如何在JavaCC中删除左递归?

时间:2018-10-18 20:13:35

标签: parsing recursion compiler-construction javacc

我试图在JavaCC中删除expr的左递归,应将其定义为:

expr ::= statement binary_op statement
| **(** expr **)**
| identifier **(** arg **)**
| statement

此代码在我的程序中导致左递归:

void expr() : { }
{

    < LPAREN > simpleExpr() < RPAREN >
    | < IDENTIFIER > <LPAREN > arg() < RPAREN >
    | statement()
}

void simpleExpr() : { }
{
    statement() binary_op() statement()
}

语句定义为:

statement ::= id | - id | number | false | true | expr

void statement() : { }
{
    < ID > | < NOT_OP > < ID >
    | < DIGIT >
    | < TRUE >
    | < FALSE >
    | expr() 
}

我在程序中遇到的错误:

Left recursion detected: "expr... --> statement... --> expr..."

我该如何解决?

2 个答案:

答案 0 :(得分:1)

根据您的语法,statement可以是expr,而expr可以是statement。因此,这两个非终结符生成的语言是相同的。您不需要两个非终结符。我建议删除statement的定义,并将expr的定义更改为此

void expr() : { }
{
      < ID >
    | < NOT_OP > < ID >
    | < DIGIT >
    | < TRUE >
    | < FALSE >
    | < LPAREN > simpleExpr() < RPAREN >
    | < IDENTIFIER > <LPAREN > arg() < RPAREN > 
}

然后选择

  • 在其余语法(包括statement的定义中)到处将expr替换为simpleExpr
  • 或添加以下规则:

    void statement() : { }
    {
        expr()
    }
    

答案 1 :(得分:0)

  1. 您对ID statement的使用非常不寻常。它看起来更像是literal
  2. 在您的statement中,应删除行| expr()。否则,statement可能是expression,而expression可能是statement ...解析器应该如何决定?