Basically, the question is more about grammars but I think that it could be more of a interesting exercise on dynamic variables.
I have a grammar role with a prototyped token (the example is simplified to demonstrate the idea):
proto token foo {*}
token foo:sym<a> {
:my $*delimiter = q<">;
\" ~ \" <value>
}
token foo:sym<b> {
:my $*delimiter = q<'>;
\' ~ \' <value>
}
token value {
.+? <?before $($*delimeter) || $($*custom-delimiter)>
}
When the role is consumed by a grammar I want the $*custom-delimiter
to be set by the grammar. Of course, I can declare it everywhere where <foo>
is needed. But sometimes it is ok to have it pre-initialized with a universal default. Something like:
{ $*custom-delimiter //= $default-delimiter }
in the value
token would work. But external pre-declaration would still be needed.
I hoped that:
our $*custom-delimiter is export = $default-delimiter;
in the scope of module where the role is declared would work. But apparently it doesn't. So, the question is: are there any elegant solutions to this?
Actually, I also hope that the solution would allow to move declaration of $*delimiter
in foo
outside of the token definitions too.
As a side note: my first thought was about adding a parameter to the token. But having absolutely identical signatures for each variant is looking terrible too:
token foo:sym<a> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<b> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<c> ( $*custom-delimiter = $default-delimiter ) {
}
Another approach is to have something like:
token pre-foo ( $*custom-delimiter = $default-delimiter ) {
<foo>
}
In this case an additional method would be required in actions class to propagate $/<foo>.ast
one level up.
Based on some test work I've done in one of my modules for allowing scoped settings for a module, you can do this but you will need to use the EXPORT sub.
I imagine the reason is that when doing EXPORT, we can install what is explicitly a brand new dynamic variable, rather than a new symbol linked to an extant dynamic variable — the latter of which to me makes scoping very unclear.
This seems to work okay for me.
# filename: Foo.rakumod
# no 'unit module', etc
sub EXPORT {
proto token foo {*}
token foo:a { … }
token foo:b { … }
Map.new:
'&foo' => &foo,
'$*dynamic' => my $ = 'default'
}
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