首页 > 解决方案 > 云雀语法:转义字符串正则表达式如何工作?

问题描述

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

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

ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""

我明白_STRING_INNER。我也明白ESCAPED_STRING是怎么组成的。但我真的不明白的是_STRING_ESC_INNER

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

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

并且不要求语法只允许字符串数据中的转义双引号吗?

标签: pythonregexgrammarlark-parser

解决方案


预赛:

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

  • (?<!...)是一个“否定的后视断言”(链接):“如果字符串中的当前位置之前没有匹配 ....,则匹配”。所以.*(?<!X)Y会匹配AY但不是XY

将此应用于您的示例:

  • ESCAPED_STRING:规则说:“匹配",然后_STRING_ESC_INNER,然后"再匹配”。

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

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

    (\\\\)匹配\\。上面说“以前的(?<!\\)位置不应该有\”。所以组合的(?<!\\)(\\\\)意思是“匹配\\,但前提是它前面没有\”。

    然后下面*?会尽可能少地重复这个,这再次只有在考虑到后面出现的正则表达式时才有意义,这是"来自ESCAPED_STRING规则(可能的混淆点:the \"inESCAPED_STRING指的是"我们实际输入中的文字想要匹配,与输入中\\\\引用的方式相同\\)。所以意味着“匹配后面跟不前面(?<!\\)(\\\\)*?\"的最短数量。换句话说,只匹配前面有偶数个(包括大小为0的块)。\\"\(?<!\\)(\\\\)*?\""\

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


推荐阅读