Я пытаюсь узнать о разборе сдвига-уменьшения. Предположим, у нас есть следующая грамматика, использующая рекурсивные правила, обеспечивающие порядок операций, основанный на грамматике ANSI C Yacc :
S: A;
P
: NUMBER
| '(' S ')'
;
M
: P
| M '*' P
| M '/' P
;
A
: M
| A '+' M
| A '-' M
;
И мы хотим проанализировать 1 + 2, используя разбор сдвига-уменьшения. Во-первых, 1 сдвигается как НОМЕР. У меня вопрос: тогда он сводится к P, затем M, затем A, и, наконец, S? Откуда он знает, где остановиться?
Предположим, что оно сокращается до S, а затем сдвигается "+". Теперь у нас есть стек, содержащий:
S '+'
Если мы сместим '2', сокращения могут быть:
S '+' NUMBER
S '+' P
S '+' M
S '+' A
S '+' S
Теперь, по обе стороны от последней строки, S может быть P, M, A или NUMBER, и все равно будет допустимо в том смысле, что любая комбинация будет правильным представлением текста. Как парсер «знает», как сделать это
A '+' M
Так что это может уменьшить все выражение до A, а затем до S? Другими словами, как он знает, что нужно прекратить сокращение, прежде чем сдвигать следующий токен? Является ли это ключевой трудностью при создании парсера LR?
<Ч />
Редактировать: После вопроса следует добавление .
Теперь предположим, что мы анализируем 1+2*3
. Ниже перечислены некоторые операции сдвига / уменьшения:
Stack | Input | Operation
---------+-------+----------------------------------------------
| 1+2*3 |
NUMBER | +2*3 | Shift
A | +2*3 | Reduce (looking ahead, we know to stop at A)
A+ | 2*3 | Shift
A+NUMBER | *3 | Shift (looking ahead, we know to stop at M)
A+M | *3 | Reduce (looking ahead, we know to stop at M)
Правильно ли это (предоставлено, оно еще не полностью проанализировано)? Кроме того, прогнозирование на 1 символ также говорит нам не уменьшать A+M
до A
, так как это приведет к неизбежной синтаксической ошибке после чтения *3
?