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

jjm*_*elo 8 regex grammar raku

我想捕捉嵌套结构的内部。

my $str = "(a)";
say $str ~~ /"(" ~ ")" (\w) /;
say $str ~~ /"(" ~ ")" <(\w)> /;
say $str ~~ /"(" <(~)> ")" \w /;
say $str ~~ /"(" <(~ ")" \w /;
Run Code Online (Sandbox Code Playgroud)

第一个有效;最后一个有效但也捕获了右括号。其他两个失败,因此在这种情况下不可能使用捕获标记。但问题在语法上下文中更为复杂,因为捕获组似乎也不起作用,如下所示:

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

因为捕获分组或捕获标记似乎都不起作用,除非它被动态分配给一个变量。但是,这会创建一个我非常想避免的额外标记。所以有两个问题

  • 使捕获标记在嵌套结构中工作的正确方法是什么?
  • 有没有办法使用捕获组或捕获标记中的标记来获取嵌套结构的内部?

rai*_*iph 6

两个问题的一个解决方案

  • 根据 ugeexe 的评论,[...]分组结构适用于您的所有用例。

  • <()>这样他们就不会工作,与正则表达式捕获标记不分组构造~操作,除非他们分组。

  • 棘轮有效时,(...)捕获/分组构造将节俭匹配限制到其最小匹配。一种模式永远不会匹配多个字符。:r (.+?)

上面最后两个要点中描述的行为并不明显,不在文档中,可能不是根据设计文档,可能是烤孔,可能是我的想象等等。这个答案的其余部分解释了我对上述三个案例的发现,并讨论了一些可以做的事情。

口齿伶俐的解释,仿佛一切都完美无缺

<()>捕获标记

它们表现为零宽度断言。每个都断言“这标志着我想要捕获的开始/结束包含此标记的正则表达式”。


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

它主要忽略左边的参数,并对接下来的两个 [参数] 进行操作

(文档说“原子”,我写了“参数”。实际上,它对接下来的两个原子或组进行操作。)

在正则表达式模式中"(" ~ ")" <(\w)>

  • ")"是 之后的第一个原子/组~

  • <(是 之后的第二个原子/组~

  • ~忽略\w)>.


解决方案是使用[...]

say '(a)' ~~ / '(' ~ ')' [ <( \w )> ] /; # ?a?
Run Code Online (Sandbox Code Playgroud)

同样,在语法中:

token TOP { '(' ~ ')' [ <( .+? )> ] }
Run Code Online (Sandbox Code Playgroud)

(...) 分组不是你想要的,原因有两个:

  • 这不可能是你想要的。它将创建一个额外的令牌 捕获。你写道你想避免这种情况。

  • 即使您想要额外的捕获,(...)当棘轮有效时使用也会在括号内进行节俭匹配。

捕获标记“不工作”可以做什么?

我认为文档更新可能是最好的做法。但是 imo 想要提交关于某个问题或准备 PR 的人,最好使用以下内容。

是否已知是预期行为或错误?

在 GH 存储库中搜索“捕获标记”:

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

一个<(令牌指示匹配的整体捕获的开始,而相应的)>令牌指示其终点。当匹配时,它们表现为始终为真的断言,但具有设置匹配对象的.from.to属性的副作用。

(也许您可以从中找出要在问题等中搜索哪些字符串...)

在撰写本文时,所有 GH 搜索<()>绘制空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有任何存储库,例如this


我很好奇并尝试了这个:

my $str = "aaa";
say $str ~~ / <(...)>* /;
Run Code Online (Sandbox Code Playgroud)

它无限循环。在*作用于刚)>。这证实了捕获标记被视为原子的感觉。


正则表达式~运算符适用于[...]其他一些分组原子结构。解析其中的任何有开始和结束一个正则表达式。

捕获标记的不同之处在于它们不一定成对——开始或结束可以是隐式的。

考虑到开始(/{)和结束(/})发生在俚语边界并且 Raku 是单遍解析辫子,也许这使得我们可能希望 Raku 不合理地难以处理它们?


我认为文档修复可能是对您的 SO 的此捕获标记方面的适当响应。

如果正则表达式~是唯一一个关心左右捕获标记都是一个单独的原子的正则表达式构造,那么提到这种皱纹的最佳位置可能是在正则表达式~部分。

但是考虑到多个正则表达式构造的关心(量词按照上面的无限循环示例进行),那么也许最好的地方是捕获标记部分。

或者最好在两者中都提到它。(虽然那是个滑坡……)

还有什么关于做:r (.*?)“不工作”?

我认为文档更新可能是最好的做法。但是 imo 想要提交关于某个问题或准备 PR 的人,最好使用以下内容。

是否已知是预期行为或错误?

GH 存储库搜索ratchet frugal

术语“棘轮”和“节俭”都来自旧的设计文档,并且仍在最新的文档中使用,并且似乎没有别名。因此,对它们的搜索应该与所有相关提及相匹配。

上面的搜索是针对这两个词的。一次搜索一个可能会发现重要的相关提及,而碰巧没有提及另一个。

在撰写本文时,所有 GH 搜索.*?或类似的绘制空白,但这是由于当前内置 GH 搜索的弱点,而不是因为这些存储库中没有任何内容。


也许这里的问题比棘轮、节俭和捕获的组合更广泛?

也许使用“棘轮”、“节俭”和“捕获”等词来提出问题?