给出以下语法:
grammar ReportAmbiguity;
unit : statements+;
statements :
callStatement+
// '.' // <- uncomment this line
;
callStatement : 'CALL' ID (argsByRef | argsByVal)*;
argsByRef : ('BY' 'REF')? ID+;
argsByVal : 'BY' 'VAL' ID+;
ID : ('A'..'Z')+;
WS : (' '|'\n')+ -> channel(HIDDEN);
解析字符串时"CALL FUNCTION BY VAL A B"
通过非根规则callStatement
一切正常,解析器正确报告歧义:
line 1:24 reportAttemptingFullContext d=6 (argsByVal), input='B'
line 1:24 reportAmbiguity d=6 (argsByVal): ambigAlts={1, 2}, input='B'
解析器正确输出树:(callStatement CALL FUNCTION (argsByVal BY VAL A B))
.
现在考虑取消上面显示的行(第七行)的注释。再次测试一切。
解析器仍然输出相同的树,但歧义性报告消失了。为什么这种明显不明确的语法和如此不明确的输入不再被报告?
(这是一个更大问题的一部分。我试图理解这一点,以便我可以确定我的语法中另一个可能的问题。)
EDIT 1
使用antlr4版本4.6。
我在github上准备了一个pet项目:https://github.com/rslemos/pet-grammars https://github.com/rslemos/pet-grammars(在模块中g
, type mvn clean test -Dtest=br.eti.rslemos.petgrammars.ReportAmbiguityUnitTest
对评论版本进行测试;取消注释第 7 行并再次运行它以查看它失败)。
EDIT 2
Changed unit: statements*;
to unit: statements+;
。此更改本身对原始问题没有任何改变。它只允许另一种体验(进一步版本待定)。
EDIT 3
触发此错误的另一种方法是更改unit: statements+;
to unit: statements+ unit;
.
就像添加时一样'.'
to statements
,这一改变也使得antlr4放弃了歧义检测。
我认为这与EOF
可能接下来argsByVal
.
第一种选择(附加'.'
to statements
) 排除EOF
就在之后出现argsByVal
.
第二个(附加unit
到它自己)使其成为非根规则(并且似乎 antlr 隐式附加EOF
每个根规则)。
我一直认为 antlr4 规则应该以我们喜欢的任何方式调用,没有任何规则给予特殊处理,根规则之所以如此命名只是因为我们(语法作者)知道哪个规则是根。
EDIT 4
可能与https://github.com/antlr/antlr4/issues/1545 https://github.com/antlr/antlr4/issues/1545.