如何理解 ANTLRWorks 1.5.2 MismatchedTokenException(80!=21)

How to understand ANTLRWorks 1.5.2 MismatchedTokenException(80!=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 之间放置一个 space 来分隔各个数字,那么解析错误就会消失。

Q1。 NoViableAltException 是什么意思?我如何解释它以在 grammar/input 对中查找问题?

Q2。表达式 80!=21 是什么意思?我可以使用这些信息做任何有用的事情来查找 grammar/input 对中的问题吗?

我不明白为什么语法在读取连续数字时有问题。我认为我的表达式 (key)+(digit)+ 指定允许连续的数字并将被读取为连续的单个数字。

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

更新:

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

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

如果我删除整个规则,我上面的所有测试用例都会成功解析。如果我在 grammar/lexer 文件中留下三个 FLOAT 子句中的任何一个,解析就会失败,如上所示。

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

我猜测词法分析器正在跳过 DIGIT 规则并卡在 FLOAT 规则中,即使 FLOAT 在输入文件中出现在 DIGIT 之后。

屏幕截图

我在下面 Bart 的评论后截取了这两个屏幕截图,以显示我遇到的解析失败。这并不重要,但 ANTLRWorks 1.5.2 将不接受 Bart 友好回复中的语法 SPACE : [ \t\r\n]+; 正则表达式语法。也许屏幕截图会有所帮助。它们显示了我的语法文件中的所有规则。

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

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

ANTLRv4 的词法分析器 放弃部分 123 匹配并将 return 23 到 char 流,为输入 1.

创建单个 KEY 标记

我强烈建议您放弃 v3 并选择更强大的 v4 版本。