Можно ли выразить левый ассоциативный оператор таким образом, чтобы синтаксические анализаторы LL(1) могли его понять?

Я пытался реализовать нисходящий синтаксический анализатор LL(1) для языка калькулятора. Это позволяет нам только суммировать, вычитать, делить и умножать числа. Нет скобок.

S -> A

A -> B + A
   | B - A
   | B

B -> int * B
   | int / B
   | int

Поскольку эта грамматика не подходит для парсера LL(1), мне пришлось немного ее изменить:

S -> A

A -> B A'
A'-> + A
   | - A
   | λ

B -> int B'
B'-> * B
   | / B
   | λ

Проблема в том, что теперь грамматика не является ассоциативной для 4 показанных операторов, и мне нужно, чтобы это было так. Как решить эту проблему? Возможно ли это сделать?

1 ответ

Решение

Вы можете получить левую ассоциативность, заменив рекурсию итерацией. Следующий псевдокод рода непосредственно вычисляет значения просто для простоты, но вы можете сгенерировать дерево разбора, используя тот же метод.

function A() {
   val = B();
   t = peek();
   while (t=='+' || t=='-') {
     match(t);
     val1 = B();
     if (t=='+')
       val = val + val1;
     else
       val = val - val1;
     t = peek();
   }
   return(val)
}

где peek() возвращает следующий токен, не съев его, и match() ест следующий токен. Вы бы сделали то же самое для B().

Другие вопросы по тегам