Perl 6 Regex匹配Perl 6分隔注释

zos*_*tay 7 regex perl6

任何人都有一个Perl 6正则表达式,它将匹配Perl 6分隔的注释?我更喜欢那些短而不是完整语法的东西,但我不排除任何东西.

作为我正在寻找的一个例子,我想要一些可以在这里解析注释的东西:

#`{ foo {} bar }
#`« woo woo »
say #`(
This is a (
long )
multiliner()) "You rock!"
#`{{ { And don't forget the tricky repeating delimiters }}
Run Code Online (Sandbox Code Playgroud)

我的总体目标是能够获取源文件并删除pod和注释,然后使用剩下的代码执行有趣的操作.剥线注释和pod非常简单,但分隔注释需要额外的技巧.我也希望这个解决方案很小,只使用Perl 6核心,所以我可以将它粘贴在我的dotfiles repo中而不需要外部依赖.

rai*_*iph 5

匹配你的例子

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> /
Run Code Online (Sandbox Code Playgroud)

显示:

?{ foo {} bar }?
?« woo woo »?
?(
This is a (
long )
multiliner())?
?{{ { And don't forget the tricky repeating delimiters }}?
Run Code Online (Sandbox Code Playgroud)

如果您知道 P6 正则表达式,希望代码是不言自明的。如果您想澄清其中的任何内容,请使用评论。

查看相关的乐堂源代码

我在没有参考乐堂的源代码的情况下写了上面的内容。(我想看看我想出了什么而不这样做。)

但是我现在查看了源代码,对于任何尝试做您想做的事情并认真了解它在一般情况下可能工作得如何的人来说,imo 或多或少都是强制性的。

作为我的起点,我特别想知道我是否能弄清楚为什么要将此代码提供给 rakudo (2018.12):

#`{{ {{ And don't forget the tricky repeating delimiters  } }}
Run Code Online (Sandbox Code Playgroud)

产生相当 LTA (Less Than Awesome) 编译器错误:

Starter {{ is immediately followed by a combining codepoint...
Run Code Online (Sandbox Code Playgroud)

这看起来与您的问题没有直接关系,但我在尝试理解嵌套分隔符规则时遇到了它。

因此,当我得到答案的这一部分时,我首先在 Rakudo 存储库中搜索“立即关注”。这导致了 P6 语法中的一种fail-terminator方法。(也许你不感兴趣,但我很感兴趣。)

这是我在标准语法中发现的其他内容,即 imo 与您要执行的操作直接相关,或者至少准确理解代码所说的规则是关于匹配注释的内容:

  • 解析这些评论的comment:sym<#`(...)>令牌。这将导致:

  • 叹为观止的名单。此列表应替换我的代码中仅与您的示例匹配的微不足道的 3 个开启器/关闭器对。

  • quibble令牌。这似乎是一个通用的“解析'引用'(分隔)的东西”。它导致:

  • 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];
    
    Run Code Online (Sandbox Code Playgroud)

该规则peek_delimiters不在 P6 语法文件中。

Rakudo repo 中的搜索显示它不在 Rakudo 或 P6 中的任何地方。

在 NQP 中搜索会产生nqp 语法中的一个例程(Perl 6 语法从中继承,这就是peek_delimiters调用有效的原因以及为什么我在 Rakudo/P6 中没有找到它时我在 NQP 中查找它的原因)。

我将在这一点上停下来得出结论。

结论

你有一个正则表达式。它可能会如您所愿。我不知道。

如果你最终研究了上面的 Rakudo/NQP 代码并且对它有足够的理解,可以写一篇关于 quibble、babble、nibble 等的演练,或者发现一个很好的现有文章(我还没有搜索过) ,请在此答案中添加评论并链接到它。我也会这样做。蒂亚!