为什么令牌显示为 'end' 类型而不是 STRING?

Why the token is displayed as 'end' type instead of STRING?

我的目标是保存以任何单词开头并以 "end" 单词结尾的评论,如下所示

ANYWORD bla bla bla end

我有这个语法:

lexer grammar JunkLexer;
WS : [ \r\t\n]+ -> skip ;
LQUOTE : 'start' -> more, mode(START) ;
mode START;
STRING : 'end' -> mode(DEFAULT_MODE) ; // token we want parser to see
TEXT : . -> more ; // collect more text for string

但不知道为什么,词法分析器生成语法中不存在的标记:

当我检查词法分析器标记时,是一样的:

WS=1
STRING=2
LQUOTE=3
'start'=3
'end'=2

提前致谢

当您使用单个字符串文字定义词法分析器规则时,该字符串文字将成为该规则的替代名称。因此,当您在词法分析器语法中定义 FOO: 'foo'; 时,您可以在解析器语法中互换使用 FOO'foo'。这允许您在语法中使用字符串文字,即使您将其拆分为解析器和词法分析器语法。所以即使你必须在词法分析器中写 PLUS: '+'; ,你仍然可以在语法中写 exp '+' exp 而不是 exp PLUS exp 。字符串文字名称也是显示令牌时使用的名称,因为它往往更具可读性。

当然这在 PLUS 示例中有意义,但在您的示例中并没有真正意义,因为,由于 more,您的 STRING 规则不实际上只是匹配end,而是一个完整的字符串。因此,在解析器语法中编写 'end' 以匹配完整的开始-结束部分将完全令人困惑(尽管它会起作用),它被用作标记名称的事实也是如此。然而 ANTLR 没有意识到这一点,因为它没有意识到 STRING 只能通过调用 more.

的规则来实现

请注意,您仍然可以使用 STRING 来引用标记,因此这实际上不会以任何方式破坏您的语法。但是,这会导致错误消息令人困惑("missing 'end'",而它应该是 "missing STRING")。

要解决此问题,您可以将 STRING 规则更改为不仅包含单个字符串文字:

STRING: 'e' 'n' 'd';

除了 'end' 不再是 STRING 的别名并且不再用作令牌的显示名称外,这在各个方面都是等效的。