如何处理无休止的递归

时间:2015-10-04 18:20:07

标签: parsing antlr grammar antlr3 xtext

我们以下面的示例语法为例:

Model:
    m+=Main*
;

Main:
    "bla" r=Rule1
    | Rule3
    | Rule2
;

    Rule1:
        i=INT
        | "key" r=Rule2
    ;

    Rule2:
        "b" r=Rule3
    ;

    Rule3:
        "b" (r=Rule1 | r=Rule2)
    ;

当我编译它时,我收到错误消息:

error(211): ../org.xtext.example.test/src-gen/org/xtext/example/test/parser/antlr/internal/InternalTest.g:119:1: [fatal] rule ruleMain has non-LL(*) decision due to recursive rule invocations reachable from alts 2,3.  Resolve by left-factoring or using syntactic predicates or using backtrack=true option.

据我所知,这是因为Rule3的ruleCall可以无限长(因为Rule3可以调用Rule2,然后可以再次调用Rule3,依此类推......)以及RuleCall for Rule2。 /> 因此,解析器无法为这些无限规则调用创建前瞻,并且在规则Main中我们要求解析器在这些无限替代方案之间做出决定,但缺少前瞻会导致此错误消息...
(如果我错了,请纠正我)

我的问题是如何解决这个问题? 必须有一种方法来重构这个语法,以便解析器可以处理它。

最好的问候Raven

1 个答案:

答案 0 :(得分:0)

如果我查看你的语法,我看到你有一个Rule2和Rule3只能在一个规则中重构。因为rule2和3以“b”开头。所以,如果你有'Rule2:'b“r =(Rule1 | Rule2);',那将是一样的。在我看来,规则3是不必要的。我会像这样重构你的语法:

Model:
    m+=Main*
;

Main:
    "bla" r=Rule1
    | Rule2
;

Rule1:
    i=INT
    | "key" r=Rule2
;

Rule2:
    "b" r=(Rule1 | Rule2)
;