对于一些具体的上下文,我需要在它们的大列表中禁用一些替代方法。 我决定通过语义谓词来做到这一点,但面临着奇怪的行为。看起来我做错了,但我不明白为什么。
下面是一个最大限度简化的语法,应该可以让我展示最新的内容;
输入文字为101
,我希望将其解析为(rule1 1 0 1)
。由于谓词失败,我希望antlr为rule1
选择第二个选项,它与输入序列完全匹配。
但是Antlr会抛出异常line 1:1 no viable alternative at input '0'
并生成这样的解析树:(rule1 1 (rule2 0 1))
。
grammar Test;
rule1:
'1' rule2
| '1' '0' '1' // This branch should be checked, if predicate in rule2 fail and no viable alternative was found
;
rule2:
{false}? '0' '1'
| '1' '1' // this branch will not match
;
我试图捕捉异常并用它做smth,但我能理解如何。我想我应该以某种方式报告解析器,这个分支失败了,它应该尝试下一个。
我做错了什么,或者我只是想念琐事?
P.S。是的,这是一个黑客攻击,我最好分割我的rule2
替代方案并在rule1
中仅使用有效的列表,但它会导致问题与替代优先级并直接左递归 - 间接的我的实际语法。
答案 0 :(得分:1)
ANTLR 4 解析器规则中的语义谓词可能有两种效果:
PredicateFailedException
)。第一种情况仅在谓词出现在决策的左侧时使用。由于您的语法在'1'
的开头和rule1
中的谓词之间包含rule2
,因此不会将谓词作为在第一个和第二个选项之间进行选择的一部分进行评估。 rule1
(假设是真的)。你可以按如下方式重构你的语法,完全保留原始的解析树,同时在预测期间启用谓词。
grammar Test;
rule1:
'1' ( rule2
| '0' '1' // This branch should be checked, if predicate in rule2 fail and no viable alternative was found
)
;
rule2:
{false}? '0' '1'
| '1' '1' // this branch will not match
;