为什么令牌显示为“结束”类型而不是STRING?

时间:2018-11-21 16:06:29

标签: antlr antlr4

我的目标是保存这样一个注释,该注释以任何单词开头,以“ end”单词结尾,

  

ANYWORD bla bla bla 结束

我有这个语法:

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

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

enter image description here

当我检出词法分析器令牌时,是相同的:

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

提前谢谢

1 个答案:

答案 0 :(得分:2)

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

PLUS示例中当然是有意义的,但在您的示例中却没有任何意义,因为由于more,您的STRING规则实际上并不仅仅是匹配end,但匹配整个字符串。因此,在解析器语法中编写'end'来匹配一个完整的begin-end部分将完全令人困惑(尽管它可以工作),并且它被用作令牌名称也是事实。但是ANTLR并没有意识到,因为它没有意识到只能通过调用STRING的规则才能达到more

请注意,您仍然可以使用STRING来引用标记,因此这实际上不会以任何方式破坏您的语法。但是,这将导致错误消息混乱(当它应为“ STRING”时为“ missing'end'”)。

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

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

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