如何在 ANTLR4 中有时将关键字解析为普通词

How to parse keywords as normal words some of the time in ANTLR4

我有一种语言,其关键字如 hello 只是某些类型句子中的关键字。例如,在其他类型的句子中,这些词应该作为 ID 进行匹配。这是一个讲述故事的超级简单的语法:

grammar Hello;

file : ( sentence )* ;
sentence : 'hello' ID PERIOD
         | INT ID PERIOD;

ID  : [a-z]+ ;
INT : [0-9]+ ;
WS  : [ \t\r\n]+ -> skip ;
PERIOD : '.' ;

我希望这些句子有效:

hello fred.
31 cheeseburgers.
6 hello.

但是最后一句话在这个语法中不起作用。单词 hellohello 类型的标记,而不是 ID 类型的标记。似乎词法分析器抓住了所有的问候并将它们变成了那种类型的标记。

这里有一个疯狂的方法来解释我想要的:

sentence : 'hello' ID PERIOD
         | INT crazyID PERIOD;

crazyID : ID | 'hello' ;

但是在我的真实语言中,有很多像 hello 这样的关键字需要处理,所以,是的,这种方式看起来很疯狂。

是否有合理、紧凑、独立于目标语言的方式来处理这个问题?

处理关键字的标准方式:

file     : ( sentence )* EOF ;
sentence : key=( KEYWORD | INT ) id=( KEYWORD | ID ) PERIOD ;

KEYWORD : 'hello' | 'goodbye' ; // list others as alts
PERIOD  : '.' ;
ID      : [a-z]+ ;
INT     : [0-9]+ ;
WS      : [ \t\r\n]+ -> skip ;

KEYWORDID 规则之间看似不明确的问题已解决,因为 KEYWORD 规则列在 ID 规则之前。

在解析器 SentenceContext 中,将生成 TerminalNode 变量 keyid,并且在解析时将有效地保存匹配的标记,以便轻松识别位置。