如何在递归正则表达式中匹配组?

Mac*_*eus 3 regex perl regex-recursion

我正在编写一个简单的正则表达式,需要接收一对坐标和/或地图名称。

例如:

move 10 15 # should returns [[10, 15]]
move 10 15 map # should returns [[10, 15, 'map']]
move map # should returns [['map']]
move 10 15 mapA mapB # should returns [[10, 15, 'mapA'], ['mapB']] 
move 10 15 mapA mapB 33 44 # should returns [[10, 15, 'mapA'], ['mapB'], [33, 44]]
move 10 15 mapA 33 44 mapB # should returns [[10, 15, 'mapA'], [33, 44, 'mapB']]
Run Code Online (Sandbox Code Playgroud)

然后,我写了这个正则表达式:

/
  (?(DEFINE)
     (?<coord>    (?<x>\d+)\s+(?<y>\d+) )
     (?<map>      (?<mapname>[a-zA-Z]+) )
     (?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
  )
  move\s+(?&commands)
/six
Run Code Online (Sandbox Code Playgroud)

但我怎么能得到群体的价值xymap使用Perl?

我尝试了一些方法:

use strict;
use warnings;

my $command = 'move 10 15';

$command =~ /
  (?(DEFINE)
     (?<coord>    (?<x>\d+)\s+(?<y>\d+) )
     (?<map>      (?<mapname>[a-zA-Z]+) )
     (?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
  )
  move\s+(?&commands)
/six;

while (my ($k,$v) = each %+) { print "$k $v\n" }
print "$+{x}";
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 6

从问题上讲,您不能拥有它。该perlre说,这个

请注意,在递归返回后无法访问在递归内匹配的捕获组,因此捕获组的额外层是必需的。

但是此模式<x>不能再进行“额外的捕获”,因为它仅在语法内部使用。你只能拥有整个东西

if ($command =~ /
        move\s+ (?<match>(?&commands))
        (?(DEFINE)
            (?<coord>    (?<x>\d+)\s+(?<y>\d+) )
            (?<map>      (?<mapname>[a-zA-Z]+) )
            (?<commands> \s* (?: (?&coord) | (?&map) ) \s* (?&commands)? )
        )
    /six)
{
    say "got: $+{match}";
}
Run Code Online (Sandbox Code Playgroud)

?(DEFINED)根据建议,将块移动到模式末尾的位置。

请注意,这是没有意义之一:以递归的比赛,其中多的<x>应该一赠?因此,您需要重组方法,以便能够重新捕获所需的匹配项。但如果您希望将子图案深埋,我看不出该怎么做。

对于出现的问题,我会编写一个简单的解析器,不要介意所有正则表达式。或者,在您的方法中,重新处理其零件的匹配项,希望一旦获得匹配项,便会容易得多。

然后是功能强大的工具,例如Marpa :: R2Parse :: RecDescentRegexp :: Grammars