我在ANTLR 4中遇到语义谓词的问题。我的语法在语法上是模棱两可的,需要向前看一个标记以解决歧义。
作为一个例子,我想解析“2012年1月19日至晚上9点”作为日期“2012年1月19日”,将解析器的下一个标记保留在“直到”。我想解析“1月19日,7日到9点”作为日期“1月19日”,解析器的下一个标记为“7”。
所以我需要查看第三个令牌并接受或离开它。
我的语法片段是:
date
: month d=INTEGER { isYear(getCurrentToken().getText())}? y=INTEGER
{//handle date, use $y for year}
| month d=INTEGER {//handle date, use 2013 for year}
;
当解析器在任一样本输入上运行时,我收到以下消息:
line 1:9 rule date failed predicate: { isYear(getCurrentToken().getText())}?
它永远不会达到第二规则替代方案,因为(我猜)它已经读了一个额外的标记。
有人能告诉我如何做到这一点吗?
答案 0 :(得分:3)
在解析器规则中,当做出决策时,ANTLR 4仅在左边缘使用谓词。像上面显示的内联谓词只是验证。
以下修改将导致ANTLR在做出决定时评估谓词,但显然您需要修改它以使用正确的先行令牌而不是调用getCurrentToken()
。
date
: {isYear(getCurrentToken().getText())}? month d=INTEGER y=INTEGER
{//handle date, use $y for year}
| month d=INTEGER {//handle date, use 2013 for year}
;
PS:如果month
总是只有一个令牌长,那么_input.LT(3)
应提供您想要的令牌。