To match any of the elements of an array, just write the name of the array variable (starting with a @
sigil) in the regex:
my @root = <go jump play>;
say "jumping" ~~ / @root /; # Matches 「jump」
say "jumping" ~~ / @root 'ing' /; # Matches 「jumping」
So in your use-case, the only tricky part is passing the arrays from the code that creates them (e.g. by parsing data files), to the grammar tokens that need them.
The easiest way would probably be to make them dynamic variables (signified by the *
twigil):
grammar Verb {
token TOP {
<root>
<ending>
}
token root {
@*root
}
token ending {
@*ending
}
}
my @*root = <go jump play>;
my @*ending = <ing es s ed>;
my $string = "going";
my $match = Verb.parse($string);
say $match<root>.Str;
Another way would be to pass a Capture
with the arrays to the args
adverb of method .parse
, which will pass them on to token TOP
, from where you can in turn pass them on to the sub-rules using the <foo(...)>
or <foo: ...>
syntax:
grammar Verb {
token TOP (@known-roots, @known-endings) {
<root: @known-roots>
<ending: @known-endings>
}
token root (@known) {
@known
}
token ending (@known) {
@known
}
}
my @root = <go jump play>;
my @ending = <ing es s ed>;
my $string = "going";
my $match = Verb.parse($string, args => \(@root, @ending));
say $match<root>.Str; # go