When declaring a proto, it's possible to surround the multimethod/sub code with additional code. For a silly example:
proto sub foo(|) { 'Camelia says “' ~ {*} ~ '!”' }
multi sub foo(1) { "hi" }
multi sub foo($) { "bye" }
say foo(1) # Camelia says “hi!”
I haven't come across any times (yet) where I've felt that's hugely useful, but on the flipside, I have come across some where in regex/Grammar world where I occasionally find myself repeating myself throughout all of the proto tokens — it's not that I can't shift into a separate token, but that adds an extra layer of hierarchy and actions. Compare a hypothetical
grammar Bar {
token TOP { <meta>* }
token metastart { '#' }
proto token meta { <metastart> {*} }
token meta:name { ( \w* ) }
token meta:date { (\d**6) }
}
Where they only action methods necessary besides TOP
would be meta:name
and meta:date
to
grammar Bar {
token TOP { <meta>* }
token metastart { '#' }
token meta { <metastart> <metacontent> }
proto token metacontent { * }
token metacontent:name { \w* }
token metacontent:date { \d**6 }
}
This now requires three methods: metacontent:name
, metacontent:date
and then a fairly superfluous meta
whose entire body would just be make $<metacontent>.made
.
Although I've seen documentation / comments floating around saying you can toss in code in the protos inside of a grammar, if anything is placed in the body of a proto token/regex/rule other than a single *
, then the compiler complains: Proto regex body must be {*} (or <*> or <...>, which are deprecated)
Is this an as-yet unimplemented features or is the plan to no longer allow anything in the proto? And if it's the latter, why should the proto
designator be required? (I'm guessing it's because there's something special about how proto token/regex/rule dispatches, since removing proto inside of a grammar results in runtime failures unlike in the sub/method world.
As a matter of fact, proto regexes are little more than a grouping device for several tokens. The documentation says:
the name of a group of values we'll create
They don't really declare a routine multi, and in fact, tokens that follow that proto are not declared as multis, they're simply tokens (which are regexes, which are methods) with funny names.
In your case, you can simply avoid the additional proto token by using alternation, which is actually what protos in grammars stand for:
grammar Bar {
token TOP { <meta>* }
token metastart { '#' }
token meta { <metastart> [ <name> | <date> ] }
token name { \w* }
token date { \d**6 }
}
say Bar.parse( "#Hey" );
say Bar.parse( "#3333" );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With