问题描述
我正在测试具有简单输入字符串的简单语法(如下所示),并从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 规则。
两个屏幕截图中的唯一区别是,一个输入具有两组多位数字,而另一个输入字符串仅具有一组多位数字。也许这些额外的信息会有所帮助。
解决方法
如果我没记错的话,ANTLR的v3词法分析器不如v4的版本强大。当词法分析器获得输入"123x"
时,词法分析器规则123
将消耗前3个字符(FLOAT
),但此后,当词法分析器遇到x
时,它知道它无法完成FLOAT
规则。但是,v3词法分析器不会放弃部分匹配,而是尝试在其下面找到另一个匹配这3个字符(123
)的规则。由于没有这样的规则,因此词法分析器将引发异常。同样,不是100%肯定,这就是我记得的方式。
ANTLRv4的词法分析器 将 放弃部分123
的匹配,并将23
返回给char流以创建单个{{1 }}输入KEY
的令牌。
我强烈建议您远离v3,选择功能更强大的v4版本。