如何使Perl 6语法产生多个匹配(如:ex和:ov)?

时间:2017-10-23 20:24:18

标签: perl6

我希望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

2 个答案:

答案 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 prototypefinal 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个。