如何理解ANTLRWorks 1.5.2 MismatchedTokenException80!= 21

问题描述

我正在测试具有简单输入字符串的简单语法(如下所示),并从Antlrworks解释器中获取以下错误消息:MismatchedTokenException(80!=21).

我的输入(abc45{r24})表示“将a,b,c,4和5键重复24次。”

ANTLRWorks 1.5.2 Grammar:
expr        : '(' (key)+ repcount ')' EOF;
key         : KEY | digit ;
repcount    : '{' 'r' count '}';
count       : (digit)+;
digit       : DIGIT;

DIGIT   :   '0'..'9';
KEY     :   ('a'..'z'|'A'..'Z') ;

Inputs:
(abc4{r4}) - ok
(abc44{r4}) - fails NoViableAltException
(abc4 4{r4}) - ok
(abc4{r45}) - fails MismatchedTokenException(80!=21)
(abc4{r4 5}) - ok

解析成功,输入为(abc4{r4})(仅一位数字)。 解析失败,输入为(abc44{r4})(NoViableAltException)。 解析失败,输入为(abc4{r45})(MismatchedTokenException(80!= 21))。 如果我在44或45之间放置一个空格来分隔各个数字,则解析错误就会消失。

Q1。 NoViableAltException是什么意思?如何解释它以寻找语法/输入对中的问题?

第二季度。表达式80!=21是什么意思?我可以对信息进行任何有用的操作以在语法/输入对中查找问题吗?

我不明白为什么语法在读取连续数字时会遇到问题。我以为我的表达式(key)+(digit)+指定允许使用连续数字,并将其作为连续的单个数字读取。

如果有人可以解释我在做什么错,我将不胜感激。这似乎是一个简单的问题,但是几个小时后,我仍然不明白为什么以及如何解决它。谢谢。

更新:

在我的简单语法文件中,我进一步从另一个语法复制了FLOAT的词法分析器规则。我不认为将其包括在上面(或将其检查为错误源),因为任何解析器规则均未使用它,并且永远不会匹配我的输入字符。这是FLOAT语法规则(包含DIGIT序列):

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

如果我删除整个规则,则上面所有我的测试用例都会成功解析。如果我在语法/词法分析器文件中保留三个FLOAT子句中的任何一个,则解析将失败,如上所示。

Q3。为什么FLOAT规则导致解析失败? DIGIT词法分析器规则首先出现,“ win”也应出现,并且优先于FLOAT规则使用。此外,FLOAT规则与输入流不匹配。

我冒昧地认为,即使FLOAT在输入文件中的DIGIT之后,该词法分析器仍会跳过DIGIT规则而陷入FLOAT规则。

屏幕截图

我在下面Bart的评论之后拍摄了这两个屏幕截图,以显示我遇到的解析失败。没关系,但是ANTLRWorks 1.5.2在Bart的答复中将不接受语法SPACE : [ \t\r\n]+;正则表达式语法。截图可能会有所帮助。它们在我的语法文件显示 all 规则。

两个屏幕截图中的唯一区别是,一个输入具有两组多位数字,而另一个输入字符串仅具有一组多位数字。也许这些额外的信息会有所帮助。

enter image description here

enter image description here

解决方法

如果我没记错的话,ANTLR的v3词法分析器不如v4的版本强大。当词法分析器获得输入"123x"时,词法分析器规则123将消耗前3个字符(FLOAT),但此后,当词法分析器遇到x时,它知道它无法完成FLOAT规则。但是,v3词法分析器不会放弃部分匹配,而是尝试在其下面找到另一个匹配这3个字符(123)的规则。由于没有这样的规则,因此词法分析器将引发异常。同样,不是100%肯定,这就是我记得的方式。

ANTLRv4的词法分析器 放弃部分123的匹配,并将23返回给char流以创建单个{{1 }}输入KEY的令牌。

我强烈建议您远离v3,选择功能更强大的v4版本。