БНФ грамматики для левой ассоциативностью

у меня есть следующие EBNF грамматика простых арифметических выражений с левой ассоциативностью:

expression:
    term {+ term}

term:
    factor {* factor}

factor:
    number
    ( expression )

Как я могу преобразовать это в BNF грамматика без изменения ассоциативности оператора? Следующие БНФ грамматики не работает для меня, потому что теперь операторы стали правоассоциативны:

expression:
    term
    term + expression

term:
    factor
    factor * term

factor:
    number
    ( expression )

в Википедии написано:

несколько решений:

  1. перепишите грамматику, чтобы оставить рекурсивной, или
  2. перепишите грамматику с более нетерминалами, чтобы заставить правильный приоритет / ассоциативность, или
  3. при использовании YACC или Bison существуют объявления операторов, %left, %right и %nonassoc, которые сообщают генератору синтаксического анализатора, какую ассоциативность заставить.

но он не говорит как переписать грамматику, и я не использую никаких инструментов синтаксического анализа, таких как YACC или Зубр, просто рекурсивный спуск. Возможно ли то, о чем я прошу?

2 ответов


expression
    : term 
    | expression + term;

просто. Вам, конечно, нужен парсер ЛР описания признать леворекурсивная грамматика. Или, если рекурсивный спуск, распознавание таких грамматик возможно, но не так просто, как правоассоциативные. Вы должны свернуть небольшую рекурсивную подъем парсер для такого матча.

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

этот псевдокод следует признать леворекурсивная грамматика в этом стиле.


то, что предлагает щенок, также может быть выражено следующей грамматикой:

expression: term opt_add
opt_add: '+' term opt_add
       | /* empty */

term:  factor opt_mul
opt_mul: '*' factor opt_mul
       | /* emtpty */

factor: number
      | '(' expression ')