ANTLR4谓词失败忽略了以下替代方案?

时间:2013-07-24 16:05:00

标签: parsing antlr text-parsing antlr4

我在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())}?

它永远不会达到第二规则替代方案,因为(我猜)它已经读了一个额外的标记。

有人能告诉我如何做到这一点吗?

1 个答案:

答案 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)应提供您想要的令牌。