Perl 6中的递归正则表达式?

时间:2019-03-01 08:44:19

标签: regex perl6

我一直试图找出如何在Perl 6中执行递归正则表达式。对于一个玩具示例,一个平衡的括号匹配器将与((())())中的(((((())())匹配。

  • PCRE示例:/\((?R)?\)/

  • Onigmo示例:(?<paren>\(\g<paren>*\))

我认为这可以做到:

my regex paren {
  '(' ~ ')' <paren>*
}

或更简单

my regex paren {
  '(' <paren>* ')'
}

但是失败

No such method 'paren' for invocant of type 'Match'
in regex paren at ...

2 个答案:

答案 0 :(得分:15)

您需要明确说明您正在调用my范围的正则表达式:

my regex paren {
    '(' ~ ')' <&paren>*
}

请注意已添加的&。这样:

say "(()())" ~~ /^<&paren>$/    # 「(()())」
say "(()()" ~~ /^<&paren>$/     # Nil

虽然确实可以有时通过显式编写&而逃脱,但确实可以在使用时使用它:

say "(()())" ~~ /^<paren>$/    # 「(()())」
say "(()()" ~~ /^<paren>$/     # Nil

这仅起作用,因为编译器发现在词法范围内定义了一个名称为paren的正则表达式,因此将<paren>语法编译为该正则表达式。对于递归情况,直到解析正则表达式后才安装该声明,因此需要明确声明。

答案 1 :(得分:1)

您可以在元语法中使用~~来对当前模式或其一部分进行递归回调。例如,您可以将平衡括号与简单的正则表达式匹配:

say "(()())" ~~ /'(' <~~>* ')'/;    # 「(()())」
say "(()()"  ~~ /'(' <~~>* ')'/;    # 「()」

Try it online!

不幸的是,尚未通过捕获的子规则(如~~0)进行匹配。