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

flo*_*wit 4 python regex grammar lark-parser

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

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

ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

f9c*_*534 5

预赛:

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

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

将此应用于您的示例:

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

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

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

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

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

    现在,它与前面的结合_STRING_INNER,该_STRING_ESC_INNER规则接着说:比赛中的第一个 "由偶数的前面\,所以换句话说,第一个"\没有逃脱本身。