regex - 在正则表达式或语法标记中捕获嵌套结构中的内容

标签 regex grammar raku

我想捕捉 nested structure 的内部.

my $str = "(a)";
say $str ~~ /"(" ~ ")" (\w) /;
say $str ~~ /"(" ~ ")" <(\w)> /;
say $str ~~ /"(" <(~)> ")" \w /;
say $str ~~ /"(" <(~ ")" \w /;
第一个有效;最后一个有效但也捕获了右括号。其他两个失败,因此在这种情况下不可能使用捕获标记。但问题在语法上下文中更为复杂,因为捕获组似乎也不起作用,如下所示:
# Please paste this together with the code above so that it compiles.
grammar G {
    token TOP {
              '(' ~ ')' $<content> = .+?
    }
}

grammar H {
    token TOP {
              '(' ~ ')' (.+?)
    }
}

grammar I {
    token TOP {
              '(' ~ ')' <( .+? )>
    }
}

$str = "(one of us)";
for G,H,I -> $grammar {
    say $grammar.parse( $str );
}
由于既没有捕获分组也没有 capture markers似乎有效,除非它被动态分配给一个变量。但是,这会创建一个我非常想避免的额外标记。
所以有两个问题
  • 使捕获标记在嵌套结构中工作的正确方法是什么?
  • 有没有办法使用捕获组或捕获标记中的标记来获取嵌套结构的内部?
  • 最佳答案

    两个问题的一个解决方案

  • 根据 ugexe 的评论,[...] 分组构造适用于您的所有用例。
  • <()> 捕获标记不是分组构造,因此除非它们被分组,否则它们不能与正则表达式 ~ 操作一起使用。
  • frugal matching 有效时,(...) 捕获/分组构造将 ratchet 限制到其最小匹配。像 :r (.+?) 这样的模式永远不会匹配多个字符。

  • 上面最后两个要点中描述的行为并不明显,不在文档中,可能不是按照设计文档,可能是烤孔,可能是我的想象等等。这个答案的其余部分解释了我对上述三个案例的发现,并讨论了一些可以做的事情。
    口齿伶俐的解释,仿佛一切都完美无缺<()>capture markers
    它们表现为零宽度断言。每个都断言“这标志着我想要捕获的开始/结束包含此标记的正则表达式”。

    根据正则表达式 ~ 运算符的文档:

    it mostly ignores the left argument, and operates on the next two [arguments]


    (文档说“原子”,我写了“参数”。实际上,它对接下来的两个原子 或组 进行操作。)
    在正则表达式模式 "(" ~ ")" <(\w)> 中:
  • ")"~ 之后的第一个原子/组。
  • <(~ 之后的第二个原子/组。
  • ~ 忽略 \w)>

  • 解决方案是使用 [...] :
    say '(a)' ~~ / '(' ~ ')' [ <( \w )> ] /; # 「a」
    
    同样,在语法中:
    token TOP { '(' ~ ')' [ <( .+? )> ] }
    
    (...) 分组不是您想要的,原因有二:
  • 这不可能是你想要的。它将创建一个额外的 token 捕获。你写道你想避免这种情况。
  • 即使您想要额外的捕获,当棘轮有效时使用 (...) 会在括号内进行节俭匹配。

  • 捕获标记“不工作”可以做什么?
    我认为文档更新可能是最好的做法。但是 imo 想要提交关于某个问题或准备 PR 的人,最好使用以下内容。
    是否已知是预期行为或错误?
    在 GH 存储库中搜索“捕获标记”:
  • raku/old-design-docs
  • raku/roast
  • raku/old-issue-trackerrakudo/rakudo
  • raku/docs

  • 术语“捕获标记”来自文档,而不是旧的设计文档,它只是说:

    A <( token indicates the start of the match's overall capture, while the corresponding )> token indicates its endpoint. When matched, these behave as assertions that are always true, but have the side effect of setting the .from and .to attributes of the match object.


    (也许您可以从中找出要在问题等中搜索哪些字符串...)
    在撰写本文时,所有 GH 搜索 <()> 都会绘制空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有任何存储库,例如 this

    我很好奇并尝试了这个:
    my $str = "aaa";
    say $str ~~ / <(...)>* /;
    
    它无限循环。 * 仅作用于 )> 。这证实了捕获标记被视为原子的感觉。

    正则表达式 ~ 运算符适用于 [...] 和其他一些分组原子结构。解析它们中的任何一个都有一个正则表达式模式的开始和结束。
    捕获标记的不同之处在于它们不一定成对——开始或结束可以是隐式的。
    考虑到开始( /{ )和结束( /} )发生在俚语边界,并且 Raku 是单 channel 解析,因此这可能会让 Raku 像我们希望的那样难以处理

    我认为文档修复可能是对您的 SO 的此捕获标记方面的适当响应。
    如果正则表达式 ~ 是唯一一个关心左右捕获标记都是一个单独的原子的正则表达式构造,那么提到这种皱纹的最佳位置可能是正则表达式 ~ 部分。
    但是考虑到多个正则表达式构造的关心(量词按照上面的无限循环示例进行),那么也许最好的地方是捕获标记部分。
    或者最好在两者中都提到它。 (虽然那是个滑坡……):r (.*?)“不工作”怎么办?
    我认为文档更新可能是最好的做法。但是 imo 想要提交关于某个问题或准备 PR 的人,最好使用以下内容。
    是否已知是预期行为或错误?
    搜索 ratchet frugal 的 GH 存储库:
  • braid
  • raku/old-design-docs
  • raku/roastraku/old-issue-tracker
  • rakudo/rakudo

  • 术语“棘轮”和“节俭”都来自旧的设计文档,并且仍在最新的文档中使用并且似乎没有别名。因此,对它们的搜索应该与所有相关提及相匹配。
    上面的搜索是针对这两个词的。一次搜索一个可能会发现重要的相关提及,而碰巧没有提及另一个。
    在撰写本文时,所有 GH 搜索 .*? 或类似的绘图空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有。

    也许这里的问题比棘轮、节俭和捕获的组合更广泛?
    也许使用“棘轮”、“节俭”和“捕获”等词来提出问题?

    关于regex - 在正则表达式或语法标记中捕获嵌套结构中的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62728827/

    相关文章:

    parsing - 具有运算符优先级规则的 Perl 6 语法示例

    python - 如何从文本文件中删除花括号?

    regex - htaccess 将所有图像重定向到不同的位置并将图像名称放入新的 url

    java - ANTLR 语法第 1 行 :6 mismatched input '<EOF>' expecting '.'

    python - 使用 pyparsing 分析时如何使两个语法等效部分的第一部分可选

    raku - 在Perl 6中声明一个属于用户定义类的变量

    javascript - 检查字符串是否以标点符号开头(Javascript)

    Javascript正则表达式在文件末尾提取计数

    grammar - 将歧义语法转换为明确的语法

    raku - 将非标量分配给标量有什么好处?