Recursive regular expression in Perl 6?

笑着哭i 提交于 2020-02-01 01:39:29

问题


I've been trying to figure out how to do a recursive regular expression in Perl 6. For a toy example, a balanced parentheses matcher, which would match ((())()) inside (((((())()).

  • PCRE example: /\((?R)?\)/

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

I thought this would do it:

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

or the simpler

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

but that fails with

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

回答1:


You need to make explicit that you're calling a my-scoped regex:

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

Notice the & that has been added. With that:

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

While it's true that you can sometimes get away without explicitly writing the &, and indeed could when using it:

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

This only works because the compiler spots there is a regex defined in the lexical scope with the name paren so compiles the <paren> syntax into that. With the recursive case, the declaration isn't installed until after the regex is parsed, so one needs to be explicit.




回答2:


You can use the ~~ in the meta-syntax to make a recursive callback into the current pattern or just a part of it. For example, you can match balanced parenthesis with the simple regex:

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

Try it online!

Unfortunately, matching via a captured subrule (like ~~0) is not yet implemented.



来源:https://stackoverflow.com/questions/54940877/recursive-regular-expression-in-perl-6

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!