我想做grammar
这样的事情:
> "abc" ~~ m:ex/^ (\w ** 1..2) (\w ** 1..2) $ {say $0, $1}/
?ab??c?
?a??bc?
Run Code Online (Sandbox Code Playgroud)
或像这样:
> my regex left { \S ** 1..2 }
> my regex right { \S ** 1..2 }
> "abc" ~~ m:ex/^ <left><right> $ {say $<left>, $<right>}/
?ab??c?
?a??bc?
Run Code Online (Sandbox Code Playgroud)
这是我的grammar
:
grammar LR {
regex TOP {
<left>
<right>
}
regex left {
\w ** 1..2
}
regex right {
\w ** 1..2
}
}
my $string = "abc";
my $match = LR.parse($string);
say "input: $string";
printf "split: %s|%s\n", ~$match<left>, ~$match<right>;
Run Code Online (Sandbox Code Playgroud)
其输出为:
$ input: abc
$ split: ab|c
Run Code Online (Sandbox Code Playgroud)
因此,<left>
只能贪婪而已<right>
。如何修改代码以匹配两种可能的变体?
$ input: abc
$ split: a|bc, ab|c
Run Code Online (Sandbox Code Playgroud)
语法的设计目的是给出零个或一个答案,但不多于此,因此您必须使用一些技巧使它们执行您想要的操作。
由于Grammar.parse
仅返回一个Match
对象,因此您必须使用另一种方法来获取所有匹配项:
sub callback($match) {
say $match;
}
grammar LR {
regex TOP {
<left>
<right>
$
{ callback($/) }
# make the match fail, thus forcing backtracking:
<!>
}
regex left {
\w ** 1..2
}
regex right {
\w ** 1..2
}
}
LR.parse('abc');
Run Code Online (Sandbox Code Playgroud)
通过调用<!>
断言使匹配失败(总是失败)将迫使先前的原子回溯,从而找到不同的解决方案。当然,这会使语法的可重用性降低,因为它在语法的常规调用约定之外起作用。
请注意,对于调用者而言,LR.parse
似乎总是失败。您将所有匹配项作为对回调函数的调用。
稍微好一点的API(但下面使用相同的方法)是使用gather
/ take
获得所有匹配项的序列:
grammar LR {
regex TOP {
<left>
<right>
$
{ take $/ }
# make the match fail, thus forcing backtracking:
<!>
}
regex left {
\w ** 1..2
}
regex right {
\w ** 1..2
}
}
.say for gather LR.parse('abc');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
207 次 |
最近记录: |