如何获得有关ANTLR 4中缺少令牌的良好错误报告?

时间:2018-11-15 08:22:15

标签: java parsing antlr antlr4

我已经为C风格的编程语言编写了ANTLR 4语法,并且正试图改善缺少分隔符的错误消息,例如缺少逗号或函数参数列表中的右括号。

我认为ANTLR的单令牌插入机制可以准确地检测到丢失的令牌,但是相反,我经常会遇到“无可行选择”错误。这是一个示例:

root
  : expr+ EOF
  ;

expr
  : '(' expr ')'
  | '(' ')' '->' expr
  | ID
  ;

ID: [a-zA-Z0-9$_]+;

Whitespace
  : [ \t\r\n\f]+ -> skip
  ;

解析输入( -> foo会导致:

line 1:2 no viable alternative at input '(->'

相反,我想看看missing ')'。建议采用什么方法来实现这一目标?

到目前为止,我找到的唯一可行的解​​决方案是使所有定界符在语法中都是可选的,并根据访问者缺席的情况采取措施。 但是,这感觉像是一种解决方法,并且有很多我想避免的缺点。

1 个答案:

答案 0 :(得分:0)

首先要注意的是,如果删除'(' expr ')'规则,您将得到几乎完全想要的错误消息:

expr
  : '(' ')' '->' expr
  | ID
  ;

错误消息:

line 1:2 missing ')' at '->'
line 1:4 mismatched input '<EOF>' expecting {'(', ID}

我相信对于LL(1)语法和no viable alternative,当在当前位置或类似位置需要提前查找时,会出现诸如“输入X不匹配,期望Y”和“缺少X”之类的错误。

因此请记住,我们可以尝试将您的语法重写为LL(1):

expr
  : '(' ( expr ')' | ')' '->' expr )
  | ID
  ;

然后错误消息变为:

line 1:2 mismatched input '->' expecting {'(', ')', ID}

这与您想要的非常接近。