以下极其简单的示例语法并不像我预期的那样(根本)。
Declaration : 'VAR';
Letter: ('A'..'Z');
message : Declaration Letter+;
结果我期望的是,任何字母序列都将作为单个字母进行词法分析,而序列“VAR”将作为单个标记进行词法分析。
当我查看 ANTLRWorks interperter 时,我看到以下结果:
VARA
解析为 message -> "VAR", "A"
(预计)VARVA
不解析 (MismatchedTokenException(-1 != 5)。词法分析器命中第二个 VA
并尝试标记化 Declaration
。预期:message -> "VAR", "V", "A"
VARVPP
解析为 message -> "VAR", "V", "P", "P"
(预计)VARVALL
解析为 message -> "VAR", "VALL"
. 我需要一些帮助来理解这种行为,以及如何解决这个问题的建议。
具体来说:
VA
开头的所有字符串进行标记化如果后面跟着一个字母,则进入声明? V
开头的所有字符串执行此操作? ? 最佳答案
让我们来看看你所有的 4 个例子:
1“瓦拉”
一切都好。
2“天花”"VAR"
(显然)被标记为 VAR
,但随后词法分析器“看到” "VA"
并期待 "R"
,这是不存在的。它发出以下错误:
line 1:5 mismatched character '<EOF>' expecting 'R'
line 1:5 required (...)+ loop did not match anything at input '<EOF>'
并丢弃 "VA"
导致创建单个 token ,正如您在运行 ANTLRWorks 的调试器时所看到的(忽略解析中的异常,它们实际上并不存在 :)):你必须意识到的是,词法分析器永远不会放弃它已经匹配的东西。所以如果词法分析器看到
"VA"
并且不能匹配 "R"
之后,它将查看可以匹配 "VA"
的其他词法分析器规则。 .但是Letter
不匹配(它只匹配单个字母!)如果您更改 Letter
要匹配多个字符,ANTLR 将能够退回到该规则。但当它匹配单个字母时不会:词法分析器不会放弃 "A"
来自 "VA"
让Letter
规则匹配。没有办法解决它:这就是 ANTLR 的词法分析器的工作方式。这通常不是问题,因为通常会有某种
IDENTIFIER
当关键字无法匹配时,词法分析器可以依靠的规则。3“VARVPP”
一切正常:
"VAR"
变成 VAR
然后词法分析器尝试匹配 "A"
后 "V"
但这不会发生,所以词法分析器回到 Letter
单条规则"V"
.之后 "PP"
都被标记为 Letter
s。4《瓦尔瓦尔》
"VAR"
又变成了VAR
.然后是"L"
在 "VAL"
导致词法分析器产生以下错误消息:line 1:5 mismatched character 'L' expecting 'R'
然后是最后一个 "L"
变成 Letter
:我猜(或希望)前 3 个问题现在已经得到解答,剩下你的最终答案:
How should I change this grammar to parse the way I expected?
如果确实存在
"VAR"
,则强制词法分析器首先在字符流中向前看。前面,如果没有,只匹配一个 "V"
并将匹配 token 的类型更改为 Letter
, 像这样:Declaration
: ('VAR')=> 'VAR'
| 'V' {$type=Letter;}
;
正如我的回答之前提到的,请参阅此相关问答:ANTLR lexer can't lookahead at all
关于antlr - 词法分析器意外标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13679674/