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

前端之家收集整理的这篇文章主要介绍了perl6 – 如何使Perl 6语法产生多个匹配(如:ex和:ov)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想语法做这样的事情:

> "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 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

解决方法

语法被设计为给出零或一个答案,而不是更多,因此你必须使用一些技巧使它们做你想要的.

由于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');

猜你在找的Perl相关文章