我的语言中包含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.
但是最后一句话在这个语法中没有用。单词hello
是hello
类型的标记,而不是ID
类型的标记。看起来lexer抓住所有的hellos并将它们变成这种类型的标记。
这是一种疯狂的方式来解释我想要的东西:
sentence : 'hello' ID PERIOD
| INT crazyID PERIOD;
crazyID : ID | 'hello' ;
但是用我的真实语言,有很多像hello要处理的关键字,所以,是的,这种方式看起来很疯狂。
是否有合理,紧凑,与目标语言无关的方式来处理这个问题?
答案 0 :(得分:2)
处理关键字的标准方法:
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 ;
基于KEYWORD
规则之前列出的ID
规则,解决了KEYWORD
和ID
规则之间看似模棱两可的问题。
在解析器SentenceContext中,将生成TerminalNode变量key
和id
,并且在解析时,将有效地保存匹配的标记,从而可以轻松识别位置。