处理以ANTLR4中转义引号结尾的字符串文字

处理以ANTLR4中转义引号结尾的字符串文字,antlr4,Antlr4,如何编写lexer规则来匹配不以转义引号结尾的字符串文字 这是我的语法: lexer grammar StringLexer; // from The Definitive ANTLR 4 Reference STRING: '"' (ESC|.)*? '"'; fragment ESC : '\\"' | '\\\\' ; 下面是我的java块: String s = "\"\\\""; // looks like "\" StringLexer lexer = new StringLex

如何编写lexer规则来匹配不以转义引号结尾的字符串文字

这是我的语法:

lexer grammar StringLexer;

// from The Definitive ANTLR 4 Reference
STRING: '"' (ESC|.)*? '"';
fragment ESC : '\\"' | '\\\\' ;
下面是我的java块:

String s = "\"\\\""; // looks like "\"
StringLexer lexer = new StringLexer(new ANTLRInputStream(s)); 

Token t = lexer.nextToken();

if (t.getType() == StringLexer.STRING) {
    System.out.println("Saw a String");
}
else {
    System.out.println("Nope");
}
这将输出
看到一个字符串
“\”
真的应该匹配
字符串吗

编辑:280Z28和巴特的解决方案都是很好的解决方案,不幸的是我只能接受一个。

是的,
“\”
字符串规则匹配:

            STRING: '"' (ESC|.)*? '"';
                     ^       ^     ^
                     |       |     |
// matches:          "       \     "
如果不希望
与反斜杠(和引号)匹配,请执行以下操作:

STRING: '"' ( ESC | ~[\\"] )* '"';
如果您的字符串不能跨越多行,请执行以下操作:

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

对于格式正确的输入,lexer将匹配您期望的文本。但是,使用非贪婪运算符不会阻止它将某些内容与以下形式匹配:

'"' .*? '"'
为了确保字符串是尽可能“正常”的标记,我建议使用以下规则

StringLiteral
  : UnterminatedStringLiteral '"'
  ;

UnterminatedStringLiteral
  : '"' (~["\\\r\n] | '\\' (. | EOF))*
  ;
如果您的语言允许字符串文字跨越多行,则可能需要修改
UnterminatedStringLiteral
以允许匹配行尾字符


如果不包括
UnterminatedStringLiteral
规则,lexer将通过忽略开头
字符串的字符,并继续标记字符串的内容

有没有什么理由让您使用这些解析器规则而不是lexer规则?我只是将它们作为lexer规则来实现,它们似乎工作得很好。@RepickBroom它们是lexer规则(以大写字母开头)。语法分析器规则以小写字母开始。我的阅读理解到此为止。。。我习惯于看到所有的大写字母lexer规则;那些大写的规则让我目瞪口呆。把规则一分为二的目的是什么?据我所知,lexer是无上下文的?