是否可以在插值正则表达式中进行捕获



我想从现有的值列表中生成regex,但当我试图在其中使用捕获时,匹配中没有捕获。是否不可能使用插值进行捕捉,或者我做错了什么?

my @keys = <foo bar baz>;
my $test-pattern = @keys.map({ "<$_>" }).join(' || ');
grammar Demo1 {
token TOP {
[
|| <foo>
|| <bar>
|| <baz>
] ** 1..* % s+
}
token foo { 1 }
token bar { 2 }
token baz { 3 }
}
grammar Demo2 {
token TOP {
[ <$test-pattern> ] ** 1..* % s+
}
token foo { 1 }
token bar { 2 }
token baz { 3 }
}
say $test-pattern, "n" x 2, Demo1.parse('1 2 3'), "n" x 2, Demo2.parse('1 2 3');
<foo> || <bar> || <baz>
「1 2 3」
foo => 「1」
bar => 「2」
baz => 「3」
「1 2 3」

确定形式为<...>的原子是否捕获而无需进一步操作的规则是它是否以字母或下划线开头。

如果断言以字母或下划线开头,则需要/解析一个标识符,并使用该标识符作为封闭匹配对象中的键来捕获匹配。例如,<foo::baz-bar qux>以一个字母开头,并在关键字foo::baz-bar下捕获。

如果断言不是以字母或下划线开头,那么默认情况下它不会捕获。


要捕获第一个字符是而不是字母或下划线的断言的结果,您可以将其放在括号中,也可以将其命名为:

( <$test-pattern> ) ** 1..* % s+

或者,命名断言:

<test-pattern=$test-pattern> ** 1..* % s+

或者(只是具有相同命名效果的另一种方式(:

$<test-pattern>=<$test-pattern> ** 1..* % s+

如果您所做的只是在parens中放置一个非捕获断言,那么您已经为该断言打开了而不是捕获。相反,您只需要将其封装在一个外部捕获中。断言保持非捕获状态,并且非捕获断言的任何子捕获数据都被丢弃

因此,上面显示的第一个解决方案的输出(用括号包装<$test-pattern>断言(是:

「1 2 3」
0 => 「1」
0 => 「2」
0 => 「3」

有时,这就是您想要简化解析树和/或节省内存的原因。

相反,如果您使用上面显示的任何一种命名形式名称是一个非捕获断言,那么通过这样做,您可以将其转换为捕获断言,这意味着任何捕获细节都将被保留。因此,命名的解决方案产生:

「1 2 3」
test-pattern => 「1」
foo => 「1」
test-pattern => 「2」
bar => 「2」
test-pattern => 「3」
baz => 「3」

最新更新