匹配你的例子
my %openers-closers = < { } « » ( ) >; # (many more in reality)
my @openers = %openers-closers.keys; # { « ( ...
my ($open, $close); # possibly multiple chars
my token comment { '#`' <&open> <&middle> <&close> }
my token open {
# Store first delimiter char: Slurp as many as are repeated:
( ( @openers ) $0* )
# Store the full (possibly multiple character) delimiters:
{ $open = ~$0; $close = %openers-closers{$0[0]} x $0.chars }
}
my token middle {
:my $nest-level; # for tracking nesting
[
# Continue if nested: or if not at unnested end delimiter:
[ <?{$nest-level}> || <!&close> ]
# Match either a nested delimiter: or a single character:
( $open || $close || . )
# Keep track of nesting:
{ $_ = ~$0.tail; # set topic to latest match in list
$nest-level++ when $open; $nest-level-- when $close }
]*
}
my token close { $close }
.say for $your-examples ~~ m:g / <.&comment> /
显示:
「{ foo {} bar }」
「« woo woo »」
「(
This is a (
long )
multiliner())」
「{{ { And don't forget the tricky repeating delimiters }}」
如果您知道 P6 正则表达式,希望代码是不言自明的。如果您想澄清任何问题,请使用 cmets。
查看相关的 Rakudo 源代码
我在上面写的时候没有参考 Rakudo 的源代码。 (我想看看我不这样做的结果。)
但是我现在已经查看了源代码,对于任何试图做你想做的事情并认真了解它在一般情况下的工作情况的人来说,这或多或少是强制性的事情案例。
作为我的起点,我特别想看看我是否能弄清楚为什么将此代码提供给 rakudo (2018.12):
#`{{ {{ And don't forget the tricky repeating delimiters } }}
产生相当 LTA(Less Than Awesome)编译器错误:
Starter {{ is immediately followed by a combining codepoint...
这看起来与您的问题没有直接关系,但我在尝试理解嵌套分隔符规则时遇到了它。
因此,当我得到答案的这一部分时,我首先在 Rakudo 存储库中搜索“立即跟进”。这导致了 P6 语法中的fail-terminator method。 (也许你不感兴趣,但我很感兴趣。)
以下是我在标准语法中发现的其他内容,即 imo 与您正在尝试做的事情直接相关,或者至少准确理解代码所说的规则是关于匹配 cmets 的内容:
规则peek_delimiters不在P6语法文件中。
在 Rakudo 存储库中的搜索显示它不在 Rakudo 或 P6 中的任何位置。
在 NQP 中的搜索在 nqp 的语法中产生 a routine(Perl 6 语法继承自它,这就是 peek_delimiters 调用有效的原因以及我在 Rakudo/P6 中没有找到 NQP 时查看 NQP 的原因) .
我将在这一点上停下来得出一个结论。
结论
你有一个正则表达式。它可能会如你所愿。我不知道。
如果您最终调查了上述 Rakudo/NQP 代码并充分理解了它,可以写出关于 quibble、babble、nibble 等的演练,或者发现一个很好的现有文章(我没有搜索过一个),请在链接到它的答案中添加评论。我也会这样做。蒂亚!