如何理解 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 版本。
我正在用简单的输入字符串测试一个简单的语法(如下所示),并从 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 版本。