Parsing 左联想算子的BNF文法

Parsing 左联想算子的BNF文法,parsing,grammar,bnf,ebnf,associativity,Parsing,Grammar,Bnf,Ebnf,Associativity,对于带有左关联运算符的简单算术表达式,我有以下EBNF语法: expression: term {+ term} term: factor {* factor} factor: number ( expression ) 如何在不更改运算符关联性的情况下将其转换为BNF语法?以下BNF语法不适用于我,因为现在运算符已成为右关联: expression: term term + expression term:

对于带有左关联运算符的简单算术表达式,我有以下EBNF语法:

expression:
    term {+ term}
    
term:
    factor {* factor}
    
factor:
    number
    ( expression )
如何在不更改运算符关联性的情况下将其转换为BNF语法?以下BNF语法不适用于我,因为现在运算符已成为右关联:

expression:
    term
    term + expression
    
term:
    factor
    factor * term
    
factor:
    number
    ( expression )
维基百科说:

有几种解决方案:

  • 重写语法,使其保持递归,或
  • 用更多的非终结符重写语法,以强制使用正确的优先级/关联性,或
  • 如果使用YACC或Bison,则会有操作符声明、%left、%right和%nonassoc,它们告诉解析器生成器要强制哪个关联性
  • 但它没有说明如何重写语法,我也没有使用任何解析工具,比如YACC或Bison,只是简单的递归下降。我所要求的可能吗

    expression
        : term 
        | expression + term;
    
    就这么简单。当然,您需要某种描述的LR解析器来识别左递归语法。或者,如果是递归下降,识别这样的语法是可能的,但不像正确的关联语法那么简单。您必须滚动一个小的递归上升解析器来匹配这样的语法

    Expression ParseExpr() {
        Expression term = ParseTerm();
        while(next_token_is_plus()) {
            consume_token();
            Term next = ParseTerm();
            term = PlusExpression(term, next);
        }
        return term;
    }
    

    此伪代码应该识别该样式的左递归语法。

    Puppy建议的内容也可以用以下语法表示:

    expression: term opt_add
    opt_add: '+' term opt_add
           | /* empty */
    
    term:  factor opt_mul
    opt_mul: '*' factor opt_mul
           | /* emtpty */
    
    factor: number
          | '(' expression ')
    

    最后一行将我的递归下降解析器发送到一个无限递归中。正如我所说的,必须使用LR解析器(或递归上升)来识别左递归语法。这样删除左递归会使操作符右关联。