这是我在ANTLR4中的语法:
grammar Hello;
r : WORD ID ;
ID : [a-z]+ ;
WORD : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;
当我输入类似的内容时:
hello buddy
我收到以下错误消息:
line 1 missing WORD at 'hello'
但是,如果我改变
中的语法grammar Hello;
r : WORD ID ;
ID : [a-z]+ ;
WORD : [1-9]+ ;
WS : [ \t\r\n]+ -> skip ;
现在WORD是一个数字,一切都好。 我强烈怀疑,因为在第一个语法中我们有两个具有相同正则表达式的终端节点,所以解析器不知道真实单词的对应性。 所以我错了想到它吗?如果没有,你如何解决这个问题,使多个终端保持相同的正则表达式?
答案 0 :(得分:0)
您不能有两个匹配相同模式的终端。
如果您的语法实际上需要匹配两次[a-z]+
,那么请使用类似
r : WORD WORD ;
并且歧视将在解析器/树遍历级别完成。
如果WORD
或ID
可以限制为固定列表,您可以将所有可能的单词声明为终端,然后使用它们来定义例如WORD
可以是什么。
答案 1 :(得分:0)
现在WORD是一个数字,一切都很好。
不是真的:
$ alias
alias grun='java org.antlr.v4.gui.TestRig'
$ grun Hello r -tokens data.txt
[@0,0:4='hello',<ID>,1:0]
[@1,6:10='buddy',<ID>,1:6]
[@2,12:11='<EOF>',<EOF>,2:0]
line 1:0 missing WORD at 'hello'
当词法分析器可以将某些输入与两个规则匹配时,存在歧义,并且它选择第一个规则。使用hello buddy
输入,词法分析器会生成两个ID令牌
您可以使用词法分析器规则中的谓词消除歧义:
grammar Question;
/* Ambiguous input */
file
: HELLO ID
;
HELLO
: [a-z]+ {getText().equals("hello")}? ;
ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;
执行:
$ grun Question file -tokens data.txt
[@0,0:4='hello',<HELLO>,1:0]
[@1,6:10='buddy',<ID>,1:6]
[@2,12:11='<EOF>',<EOF>,2:0]
有关The Definitive ANTLR Reference中语义谓词的更多信息。