摘自《权威ANTLR 4参考》一书
我们的STRING规则还不够完善,因为它不允许 字符串中的双引号。为此,大多数语言定义 以反斜杠开头的转义序列。获得双引号 在双引号字符串中,我们使用
\"
。为了支持普通逃生 字符,我们需要以下内容:
STRING : '"' ( ESC |.)*? '"' ;
fragment
ESC : '\\"' | '\\\\' ; // 2-char sequences \" and \\
ANTLR本身需要转义转义字符,所以这就是为什么我们需要
\\
来转义 指定反斜杠字符。 STRING中的循环现在可以匹配 通过调用片段规则ESC
或其他任何转义字符序列 通过点通配符的单个字符。*?
子规则运算符 终止(ESC |.)*?
听起来不错,但是当我读到它时,发现ESC
和.
之间的选择存在一定的歧义。就STRING
而言,可以通过将转义字符"Hi\""
与\
匹配来匹配输入.
,并考虑以下转义的双引号作为关闭字符串。这甚至可以减少贪婪程度,因此更适合使用?
。
当然,问题在于,如果我们这样做,那么末尾会有一个多余的双引号,该双引号不会与任何内容匹配。
所以我写了以下语法:
grammar String;
anything: STRING '"'? '\r\n';
STRING: '"' (ESC|.)*? '"';
fragment
ESC: '\\"' | '\\\\';
,它在字符串之后接受一个可选的孤独双引号字符。该语法仍将"Orange\""
解析为完整字符串:
所以我的问题是:为什么这是可接受的解析,而不是将"Orange\"
用作STRING
,然后加上孤立的双引号"
?请注意,后者的贪婪程度会降低,这似乎更适合使用?
,因此人们可能会认为它更可取。