不确定是否grammars要做这样的事情:我想tokens在运行时(将来 - 使用文件中的数据)定义.所以我写了一个简单的测试代码,并且按照预期它甚至都不会编译.
grammar Verb {
token TOP {
<root>
<ending>
}
token root {
(\w+) <?{ ~$0 (elem) @root }>
}
token ending {
(\w+) <?{ ~$0 (elem) @ending }>
}
}
my @root = <go jump play>;
my @ending = <ing es s ed>;
my $string = "going";
my $match = Verb.parse($string);
.Str.say for $match<root>;
Run Code Online (Sandbox Code Playgroud)
在Perl 6中做这些事情的最佳方法是什么?
要匹配数组的任何元素,只需@在正则表达式中写入数组变量的名称(以sigil 开头):
my @root = <go jump play>;
say "jumping" ~~ / @root /; # Matches ?jump?
say "jumping" ~~ / @root 'ing' /; # Matches ?jumping?
Run Code Online (Sandbox Code Playgroud)
因此,在您的用例中,唯一棘手的部分是将数组从创建它们的代码(例如,通过解析数据文件)传递给需要它们的语法标记.
最简单的方法可能是使它们成为动态变量(由*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;
Run Code Online (Sandbox Code Playgroud)
另一种方法是Capture将数组传递给args方法的副词.parse,然后将它们传递给token TOP,然后您可以使用<foo(...)>或者<foo: ...>语法将它们传递给子规则:
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
Run Code Online (Sandbox Code Playgroud)