如何使用 ANTLR 4 转义转义字符?

How do I escape an escape character with ANTLR 4?

许多语言用某种引号绑定字符串,像这样:

"Rob Malda is smart."

ANTLR 4 可以用这样的词法分析器规则匹配这样的字符串:

QuotedString : '"' .*? '"';

要在字符串中使用某些字符,必须对它们进行转义,可能像这样:

"Rob \"Commander Taco\" Malda is smart."

ANTLR 4 也可以匹配这个字符串;

EscapedString : '"' ('\"|.)*? '"';

(摘自 The Definitive ANTLR 4 Reference 的 p96)

这是我的问题:假设转义字符与字符串定界符相同。例如:

"Rob ""Commander Taco"" Malda is smart."

(这在 Powershell 中是完全合法的。)

什么词法分析器规则会匹配这个?我认为这会起作用:

EscapedString : '"' ('""'|.)*? '"';

但事实并非如此。词法分析器将转义字符 " 标记为字符串定界符的结尾。

使用 ~ 运算符取反某些字符:

EscapedString : '"' ( '""' | ~["] )* '"';

或者,如果您的字符串中不能有换行符,请执行:

EscapedString : '"' ( '""' | ~["\r\n] )* '"';

您不想使用非贪婪运算符,否则 "" 将永远不会被消耗,而 "a""b" 将被标记为 "a""b"一个令牌。

(不要为这个答案投票;为@Bart Kiers 的答案投票。)

我提供这个是为了完整性,因为它是 Powershell 语法的一小部分。将 The Definitive ANTLR 4 Reference 中 p76 的转义逻辑与 Bart 的回答相结合,以下是在 Powershell 中对转义字符串进行词法分析所必需的规则:

EscapedString
    : '"'      (Escape | '""'   | ~["])* '"'
    | '\''     (Escape | '\'\'' | ~['])* '\''
    | '\u201C' (Escape | .)*? ('\u201D' | '\u2033')   // smart quotes
    ;

fragment Escape
    : '\u0060\''    // backtick single-quote
    | '\u0060"'     // backtick double-quote
    ;

这些规则处理以下四种在 Powershell 中转义字符串的方法:

'Rob ''Commander Taco'' Malda is smart.'
"Rob ""Commander Taco"" Malda is smart."
'Rob `'Commander Taco`' Malda is smart.'
"Rob `"Commander Taco`" Malda is smart."