我尝试使用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
)?
以下是文档的节选(强调我的):
谓词可以出现在解析器规则中的任何位置,就像操作一样,但是只有那些出现在备选项左侧边缘的谓词才会影响预测(在备选项之间进行选择)。
[…]
ANTLR的一般决策策略是找到所有可行的替代方案,然后忽略当前评估为false的谓词保护的替代方案。(一个可行的替代方案是匹配当前输入的方案。)如果存在多个可行的备选方案,解析器将选择决策中首先指定的备选方案。
这基本上意味着您的谓词必须是在预测阶段要考虑的交替中的第一个项目。
当然,您将无法使用$INT
,因为它在这一点上还没有匹配,但您可以用_input.LA(1)
之类的东西代替它(提前查看一个令牌)-确切的语法取决于您的语言目标。
作为旁注,我建议您不要通过语法验证输入,在解析之后执行单独的验证传递更容易和更好。让语法处理语法,而不是语义。