语义谓词失败但不会转到下一个

时间:2016-10-04 07:45:05

标签: antlr antlr4

我尝试使用ANTLR4来识别范围符号<1..100>,这是我的尝试:

@parser::members {
def evalRange(self, minnum, maxnum, num):
    if minnum <= num <= maxnum:
        return True
    return False
}
range_1_100 : INT { self.evalRange(1, 100, $INT.int) }? ;

但它不适用于多个范围,例如:

some_rule : range_1_100 | range_200_300 ;

当我输入一个数字(200)时,它会停在第一个规则:

200
line 3:0 rule range_1_100 failed predicate: { self.evalRange(1, 100, $INT.int) }?
(top (range_1_100 200))

这不像我预期的那样。如何使令牌与下一个规则匹配(range_200_300)?

1 个答案:

答案 0 :(得分:0)

这里摘录自the docs(强调我的):

  

谓词可以出现在解析器规则中的任何位置,就像操作一样,但只有那些出现在备选方案左边缘的那些可以影响预测(在备选方案之间进行选择)。

     

[...]

     

ANTLR的一般决策策略是找到所有可行的替代方案,然后忽略用当前评估为假的谓词保护的替代方案。 (一个可行的替代方案是匹配当前输入的方法。)如果仍有多个可行的替代方案,解析器会选择在决策中首先指定的替代方案。

这基本上意味着你的谓词必须是预测阶段中要考虑的交替中的第一个项目。

当然,您已经无法使用my-thingy: image: my-image:latest environment: - THE_HOST_I_WANT_TO_CONNECT_TO=${LOCAL_XX_HOST} 因为此时尚未匹配,但您可以将其替换为类似$INT的内容(lookahead)一个令牌) - 确切的语法取决于您的语言目标。

作为旁注,我建议您通过语法验证输入,在<<>之后执行单独的验证传递更容易,更好/ em>解析。让语法处理语法,而不是语义。