我希望grammar
做这样的事情:
> "abc" ~~ m:ex/^ (\w ** 1..2) (\w ** 1..2) $ {say $0, $1}/
「ab」「c」
「a」「bc」
或者像这样:
> my regex left { \S ** 1..2 }
> my regex right { \S ** 1..2 }
> "abc" ~~ m:ex/^ <left><right> $ {say $<left>, $<right>}/
「ab」「c」
「a」「bc」
这是我的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>;
它的输出是:
$ input: abc
$ split: ab|c
所以,<left>
只能贪婪,不能留给<right>
。我应该如何修改代码以匹配两种可能的变体?
$ input: abc
$ split: a|bc, ab|c
答案 0 :(得分:4)
语法被设计为给出零或一个答案,而不是更多,因此你必须使用一些技巧让它们做你想做的事。
由于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');
通过调用<!>
断言(总是失败)使匹配失败会强制先前的原子回溯,从而找到不同的解决方案。当然,这使得语法不再可重用,因为它在语法的常规调用约定之外工作。
请注意,对于来电者,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');
答案 1 :(得分:3)
我认为Moritz Lenz,绰号moritz,即将出版的书"Parsing with Perl 6 Regexes and Grammars"的作者,是有关此问题的人。我可能应该让他回答这个问题......
如果有人考虑尝试修改grammar.parse
以使其支持:exhaustive
,或以其他方式黑客攻击@evb想要的内容,以下文档可能会从我的洞察力中获取的潜在有用的灵感/指导相关推测文档(S05)并搜索#perl6和#perl6-dev irc日志。
7年前 Moritz添加了an edit of S05:
仅影响调用行为的[regex]修饰符,而不是正则表达式本身[例如
:exhaustive
]可能只出现在涉及调用的构造上(例如m//
[或{{1} }]),而不是grammar.parse
[或rx//
]。
([例如regex { ... }
],[或:exhaustive
]和[或grammar.parse
]位是我在此答案中添加的外推/解释/推测。它们不在链接源中。)
5年前 Moritz expressed interest in implementing :exhaustive
用于匹配(不解析)功能。不到2分钟后,肯特展示了一个单人班轮,演示了他猜测他是如何接近它的。不到30分钟后,莫里茨发布了a working prototype。 final version landed 7 days later。
1年前 Moritz在#perl6上发言(强调由我添加):"regexes and grammars aren't a good tool to find all possible ways to parse a string"。
H个。