ANTLR4消除终端令牌的歧义

时间:2017-02-01 11:42:39

标签: grammar antlr4

这是我在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是一个数字,一切都好。 我强烈怀疑,因为在第一个语法中我们有两个具有相同正则表达式的终端节点,所以解析器不知道真实单词的对应性。 所以我错了想到它吗?如果没有,你如何解决这个问题,使多个终端保持相同的正则表达式?

2 个答案:

答案 0 :(得分:0)

您不能有两个匹配相同模式的终端。

如果您的语法实际上需要匹配两次[a-z]+,那么请使用类似

的制作
r   : WORD WORD ;

并且歧视将在解析器/树遍历级别完成。

如果WORDID可以限制为固定列表,您可以将所有可能的单词声明为终端,然后使用它们来定义例如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令牌

  • 使用第一个语法,因为它不明确且ID首先出现
  • 使用第二个语法,输入只能与ID WS 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中语义谓词的更多信息。