百灵鸟语法:转义字符串正则表达式如何工作?

lark grammar: How does the escaped string regex work?

lark解析器预定义了一些常用的终端,包括字符串。定义如下:

_STRING_INNER: /.*?/
_STRING_ESC_INNER: _STRING_INNER /(?<!\)(\\)*?/ 

ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""

我明白_STRING_INNER。我也明白 ESCAPED_STRING 是如何组成的。但是我不太明白的是 _STRING_ESC_INNER.

如果我正确阅读正则表达式,它只是说每当我发现两个连续的文字反斜杠时,它们前面不能有另一个文字反斜杠?

如何将这两个组合成一个正则表达式?

语法是否只允许在字符串数据中使用转义双引号?

预赛:

  • .*?非贪婪匹配,意思是.(任意符号)的尽可能短的重复次数。这只有在后面跟着其他东西时才有意义。因此 .*?X 输入 AAXAAX 将只匹配 AAX 部分,而不是一直扩展到最后 X.

  • (?<!...) 是 "negative look-behind assertion" (link): "Matches if the current position in the string is not preceded by a match for ...."。所以 .*(?<!X)Y 会匹配 AY 但不会匹配 XY.

将此应用于您的示例:

  • ESCAPED_STRING:规则说:"Match ", then _STRING_ESC_INNER, and then " again".

  • _STRING_INNER:匹配任何符号的尽可能短的重复次数。如前所述,这仅在考虑其后的正则表达式时才有意义。

  • _STRING_ESC_INNER:我们希望它匹配不包含右引号的最短字符串。也就是说,对于输入 "abc"xyz",我们希望匹配 "abc",而不是同时消耗 xyz" 部分。但是,我们必须确保 " 确实是一个结束引号,因为它本身不应该被转义。所以对于输入 "abc\"xyz",我们不想只匹配 "abc\",因为 \" 被转义了。我们观察到结束 " 必须直接在偶数 \ 之前(零是偶数)。所以 " 可以,\" 可以,\\" 可以等等。但是只要 " 前面有奇数个 \,这意味着" 并不是真正的收盘价。

    (\\) 匹配 \(?<!\) 表示 "the position before should not have \"。所以合并 (?<!\)(\\) 意味着 "match \, but only if it is not preceded by \".

    接下来的 *? 会尽可能重复此操作,这只有在考虑紧随其后的正则表达式时才有意义,即 [=20= 中的 " ] 规则(可能的混淆点:ESCAPED_STRING 中的 \" 指的是我们要匹配的实际输入中的文字 ",与 \\ 指的方式相同到输入中的 \)。所以 (?<!\)(\\)*?\" 的意思是“匹配最短的 \ 后跟 " 并且前面没有 \。所以换句话说,(?<!\)(\\)*?\" 只匹配 " 前面有偶数个 \(包括大小为 0 的块)。

    现在将它与前面的 _STRING_INNER 结合起来,_STRING_ESC_INNER 规则然后说:匹配前面有偶数的 first " \ 的,所以换句话说,\ 本身没有转义的第一个 "