lark解析器预定义了一些常见的终端,包括一个字符串。其定义如下:
_STRING_INNER: /.*?/
_STRING_ESC_INNER: _STRING_INNER /(?<!\\)(\\\\)*?/
ESCAPED_STRING : "\"" _STRING_ESC_INNER "\""
我确实明白。我也理解ESCAPED_STRING
是如何组成的。但我真正不明白的是_STRING_ESC_INNER
如果我读对了正则表达式,它所说的就是,每当我发现两个连续的文本反斜杠时,它们不能被另一个文本反斜杠所取代
我如何将这两个组合成一个正则表达式
语法不需要在字符串数据中只允许转义双引号吗
预备工作:
.*?
非贪婪匹配,表示.
(任何符号)的最短重复次数。这只有在后面跟着其他东西时才有意义。因此,输入AAXAAX
上的.*?X
将只匹配AAX
部分,而不是一直扩展到最后一个X
(?<!...)
是一个“反向查找后断言”(link):“如果字符串中的当前位置前面没有匹配…,则匹配”。因此.*(?<!X)Y
将匹配AY
,而不是XY
将此应用于您的示例:
ESCAPED_STRING
:规则说:“匹配"
,然后_STRING_ESC_INNER
,然后再"
”_STRING_INNER
:匹配任何符号的最短重复次数。如前所述,这只有在考虑后面的正则表达式时才有意义_STRING_ESC_INNER
:我们希望它匹配不包含结束引号的尽可能短的字符串。也就是说,对于输入"abc"xyz"
,我们希望匹配"abc"
,而不是同时使用xyz"
部分。然而,我们必须确保"
实际上是一个结束语,因为它本身不应该被转义。因此,对于输入"abc\"xyz"
,我们不希望只匹配"abc\"
,因为\"
是转义的。我们注意到,结束"
之前必须有一个偶数\
(零是偶数)。所以"
是可以的,\\"
是可以的,\\\\"
是可以的,等等。但是只要"
前面有一个奇数\
,这意味着"
实际上不是一个结束引号(\\\\)
匹配\\
。{(?<!\\)(\\\\)
表示“匹配\\
,但前提是它前面没有\
”下面的
*?
然后进行尽可能小的重复,这同样只有在考虑后面的正则表达式时才有意义,这是来自ESCAPED_STRING
规则的"
(可能的混淆点:ESCAPED_STRING
中的\"
指的是文字"
在我们想要匹配的实际输入中,以相同的方式\\\\
引用输入中的\\
)。因此(?<!\\)(\\\\)*?\"
意味着“匹配紧跟在"
后面而不紧跟在\
前面的最短数量的\\
。换句话说,(?<!\\)(\\\\)*?\"
只匹配前面有偶数个\
的"
(包括大小为0的块)现在将它与前面的
_STRING_INNER
结合起来,_STRING_ESC_INNER
规则说:匹配前面有偶数个\
的第一个"
,换句话说,第一个"
中的\
本身并没有转义。相关问题 更多 >
编程相关推荐