3

我在使用 ANTLR 4 中的语义谓词时遇到了问题。我的语法在句法上是模棱两可的,需要先看一个标记来解决歧义。

例如,我想将“2012 年 1 月 19 日至晚上 9 点”解析为日期“2012 年 1 月 19 日”,将解析器的下一个标记留在“直到”。我想将“Jan 19, 7 until 9 pm”解析为日期“Jan. 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())}?

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

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

4

1 回答 1

6

In parser rules, ANTLR 4 only uses predicates on the left edge when making a decision. Inline predicates like the one you showed above are only validated.

The following modification will cause ANTLR to evaluate the predicate while it makes the decision, but obviously you'll need to modify it to use the correct lookahead token instead of calling 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: If month is always exactly one token long, then _input.LT(3) should provide the token you want.

于 2013-07-24T19:48:26.130 回答