是否可以在插入的正则表达式中进行捕获?
Is it possible to have a capture within an interpolated 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」
确定<...>
形式的原子是否捕获的规则是它是否以字母或下划线开头。
如果断言以字母或下划线开头,则标识符为 expected/parsed 并且使用该标识符作为封闭匹配对象中的键来捕获匹配项。例如,<foo::baz-bar qux>
以字母开头并在键 foo::baz-bar
下捕获。
如果断言不是以字母或下划线开头,则默认情况下它不会捕获。
要捕获第一个字符 不是 字母或下划线的断言的结果,您可以将其放在括号中或将其命名为:
( <$test-pattern> ) ** 1..* % \s+
或者,命名断言:
<test-pattern=$test-pattern> ** 1..* % \s+
或(具有相同命名效果的另一种方式):
$<test-pattern>=<$test-pattern> ** 1..* % \s+
如果您所做的只是在括号中放置一个非捕获断言,那么您 not 为该断言打开了捕获。相反,您只是 将其包裹在外部捕获 中。断言保持非捕获,非捕获断言的任何子捕获数据都将被丢弃。
因此上面显示的第一个解决方案的输出(将 <$test-pattern>
断言包装在括号中)是:
「1 2 3」
0 => 「1」
0 => 「2」
0 => 「3」
有时这就是您想要简化解析树的原因and/or节省内存。
相比之下,如果您 name 使用上面显示的任何一种命名形式的其他非捕获断言,那么通过这样做您将其转换为捕获断言,这意味着任何 sub 捕获细节都将保留。因此 named 解决方案产生:
「1 2 3」
test-pattern => 「1」
foo => 「1」
test-pattern => 「2」
bar => 「2」
test-pattern => 「3」
baz => 「3」
我想从现有值列表生成正则表达式,但是当我尝试在其中使用捕获时,匹配中不存在捕获。是不是无法使用插值进行捕获,还是我做错了什么?
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」
确定<...>
形式的原子是否捕获的规则是它是否以字母或下划线开头。
如果断言以字母或下划线开头,则标识符为 expected/parsed 并且使用该标识符作为封闭匹配对象中的键来捕获匹配项。例如,<foo::baz-bar qux>
以字母开头并在键 foo::baz-bar
下捕获。
如果断言不是以字母或下划线开头,则默认情况下它不会捕获。
要捕获第一个字符 不是 字母或下划线的断言的结果,您可以将其放在括号中或将其命名为:
( <$test-pattern> ) ** 1..* % \s+
或者,命名断言:
<test-pattern=$test-pattern> ** 1..* % \s+
或(具有相同命名效果的另一种方式):
$<test-pattern>=<$test-pattern> ** 1..* % \s+
如果您所做的只是在括号中放置一个非捕获断言,那么您 not 为该断言打开了捕获。相反,您只是 将其包裹在外部捕获 中。断言保持非捕获,非捕获断言的任何子捕获数据都将被丢弃。
因此上面显示的第一个解决方案的输出(将 <$test-pattern>
断言包装在括号中)是:
「1 2 3」
0 => 「1」
0 => 「2」
0 => 「3」
有时这就是您想要简化解析树的原因and/or节省内存。
相比之下,如果您 name 使用上面显示的任何一种命名形式的其他非捕获断言,那么通过这样做您将其转换为捕获断言,这意味着任何 sub 捕获细节都将保留。因此 named 解决方案产生:
「1 2 3」
test-pattern => 「1」
foo => 「1」
test-pattern => 「2」
bar => 「2」
test-pattern => 「3」
baz => 「3」