在Perl 6中传递数据以形成语法规则

Eug*_*sky 7 perl6

不确定是否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中做这些事情的最佳方法是什么?

sml*_*mls 7

要匹配数组的任何元素,只需@在正则表达式中写入数组变量的名称(以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)