Соответствие вашим примерам
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.Пожалуйста, используйте комментарии, если хотите получить разъяснения по любому из них.
Глядя на соответствующий исходный код Rakudo
Я написал выше, не обращаясь к исходному коду Rakudo.(Я хотел посмотреть, что я придумаю, не делая этого.)
Но теперь я посмотрел на исходный код, который imo будет более или менее обязательным для любого, кто пытается что-то сделатьвы пытаетесь серьезно задуматься над тем, насколько хорошо это может работать в общем случае.
Когда я начал, мне было особенно интересно узнать, могу ли я понять, почему я передаю этот код в rakudo (2018.12):
#`{{ {{ And don't forget the tricky repeating delimiters } }}
выдает скорее ошибку компилятора LTA (Less Than Awesome):
Starter {{ is immediately followed by a combining codepoint...
Это не выглядит напрямую относящимся к вашему вопросу, но я столкнулся с ним при попытке понятьправила вложенного разделителя.
Поэтому, когда я добрался до этой части своего ответа, я начал с поиска в репо Rakudo «сразу после».Это привело к fail-terminator
методу в грамматике P6.(Возможно, не интересует вас, но это мне.)
Вот что еще я обнаружил в стандартной грамматике, что IMO напрямую связано с тем, что вы пытаетесь сделать, или, по крайней мере, точно понимаете, чтоВ коде говорится, что правила касаются соответствия комментариев:
comment:sym<#
(...)> `token , который анализирует эти комментарии.Это приводит к:
Список открывающих .Этот список должен заменить в моем коде только три пары «открывающий / сближающий», которые просто соответствуют вашим примерам.
Маркер quibble
.Похоже, это общая вещь "parse 'quoted' (delimited)".Это приводит к:
babble
токен .Это устанавливает «старт» и «останов» с этим кодом:
$<B>=[<?before .>]
{
# Work out the delimiters.
my $c := $/;
my @delims := $c.peek_delimiters($c.target, $c.pos);
my $start := @delims[0];
my $stop := @delims[1];
Правило peek_delimiters
отсутствует в файле грамматики P6.
Поискв репо Rakudo его нет нигде в Rakudo или P6.
Поиск в NQP дает подпрограмму в грамматике nqp (от которой наследуется грамматика Perl 6, поэтому peek_delimiters
Call работает и почему я посмотрел в NQP, когда я не нашел его в Rakudo / P6).
Я остановлюсь на этом этапе, чтобы сделать вывод.
Заключение
У вас есть регулярное выражение.Это может сработать так, как вы собираетесь.Я не знаю.
Если вы в конечном итоге исследуете приведенный выше код Rakudo / NQP и понимаете его достаточно хорошо, чтобы написать обзор того, что делают придирки, лепеты, клевы и т. Д., Или обнаружите хороший существующийнаписать (я еще не искал), пожалуйста, добавьте комментарий к этому ответу, ссылаясь на него.Я сделаю так же.ТИА!