LR(0)-разбор — различия между версиями
Margarita (обсуждение | вклад) (→Заполнение управляющей таблицы) |
Margarita (обсуждение | вклад) (→LR(0)-разбора конкретной строки) |
||
Строка 234: | Строка 234: | ||
!style="background-color:#EEE"| Строка | !style="background-color:#EEE"| Строка | ||
!style="background-color:#EEE"| Стек | !style="background-color:#EEE"| Стек | ||
− | !style="background-color:#EEE"| <tex> | + | !style="background-color:#EEE"| <tex>curState</tex> |
− | !style="background-color:#EEE"| <tex> | + | !style="background-color:#EEE"| <tex>curToken</tex> |
− | !style="background-color:#EEE"| <tex> | + | !style="background-color:#EEE"| <tex>T[curState,curToken]</tex> |
!style="background-color:#EEE"| Комментарий | !style="background-color:#EEE"| Комментарий | ||
|- | |- | ||
Строка 244: | Строка 244: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>(</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>(</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 4</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 4</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"("</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"("</tex>. Переход в <tex>4</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_1+n_2)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_1+n_2)+n_3\$</tex> | ||
Строка 251: | Строка 251: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>n_1</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>n_1</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_1"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_1"</tex>. Переход в <tex>3</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | ||
Строка 258: | Строка 258: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex>. Удаление из стека <tex>n_{1}3</tex>. Переход в <tex>4</tex> состояние. Добавление в стек <tex>T2</tex>. Переход в <tex>2</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | ||
Строка 265: | Строка 265: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 2</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 2</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to T</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to T</tex>. Удаление из стека <tex>T2</tex>. Переход в <tex>4</tex> состояние. Добавление в стек <tex>E6</tex>. Переход в <tex>6</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_2)+n_3\$</tex> | ||
Строка 272: | Строка 272: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 5</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 5</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"+"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"+"</tex>. Переход в <tex>5</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_2)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_2)+n_3\$</tex> | ||
Строка 279: | Строка 279: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>n_2</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>n_2</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_2"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_2"</tex>. Переход в <tex>3</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | ||
Строка 286: | Строка 286: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3 </tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3 </tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex>. Удаление из стека <tex>n_{2}3</tex>. Переход в <tex>5</tex> состояние. Добавление в стек <tex>T7</tex>. Переход в <tex>7</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | ||
Строка 293: | Строка 293: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 1 </tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 1 </tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to E + T</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to E + T</tex>. Удаление из стека <tex>E6\ +5\ T7</tex>. Переход в <tex>4</tex> состояние. Добавление в стек <tex>E6</tex>. Переход в <tex>6</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>)+n_3\$</tex> | ||
Строка 300: | Строка 300: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>)</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 8</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 8</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>")"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>")"</tex>. Переход в <tex>8</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | ||
Строка 307: | Строка 307: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 4</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 4</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to (E)</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to (E)</tex>. Удаление из стека <tex>(4\ E6\ )8</tex>. Переход в <tex>0</tex> состояние. Добавление в стек <tex>T2</tex>. Переход в <tex>2</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | ||
Строка 314: | Строка 314: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 2</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 2</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to T</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to T</tex>. Удаление из стека <tex>T2</tex>. Переход в <tex>0</tex> состояние. Добавление в стек <tex>E1</tex>. Переход в <tex>1</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>+n_3\$</tex> | ||
Строка 321: | Строка 321: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>+</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 5</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 5</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"+"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"+"</tex>. Переход в <tex>5</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_3\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>n_3\$</tex> | ||
Строка 328: | Строка 328: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>n_3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>n_3</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>shift\ 3</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_3"</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Перенос <tex>"n_3"</tex>. Переход в <tex>3</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | ||
Строка 335: | Строка 335: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 3</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>T \to \bf n</tex>. Удаление из стека <tex>n_33</tex>. Переход в <tex>5</tex> состояние. Добавление в стек <tex>T7</tex>. Переход в <tex>7</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | ||
Строка 342: | Строка 342: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 1</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 1</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to E + T</tex> | + | |style="background-color:#FFF;padding:2px 20px"| Свертка: <tex>E \to E + T</tex>. Удаление из стека <tex>E1\ +5\ T7</tex>. Переход в <tex>0</tex> состояние. Добавление в стек <tex>E1</tex>. Переход в <tex>1</tex> состояние. |
|- | |- | ||
|style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px;text-align: right;"| <tex>\$</tex> | ||
Строка 349: | Строка 349: | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>\$</tex> | ||
|style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 0</tex> | |style="background-color:#FFF;padding:2px 20px"| <tex>reduce\ 0</tex> | ||
− | |style="background-color:#FFF;padding:2px 20px"| | + | |style="background-color:#FFF;padding:2px 20px"| Так как свертка по нулевому правилу {{---}} осуществляем допуск. |
|} | |} | ||
Версия 18:04, 30 августа 2015
LR(0)-разборщик это частный случай LR(k)-разборщикa. Заметим, что в данном случае , то есть решение о своих действиях принимается только на основании содержимого стека, не учитывая символы входной цепочки.
Содержание
Построение автомата и управляющей таблицы
Как было сказано в статье про LR(k)-разборщик, управляющая программа одинакова для всех LR-анализаторов, а таблица и автомат изменяются от одного анализатора к другому. Надо заметить, что алгоритм LR-разбора похож на Алгоритм Эрли.
Автомат
Каждое состояние автомата будет состоять из LR(0)-ситуации.
Определение: |
Пусть | — КС-грамматика и . Композицию назовем LR(0)-ситуацией (англ. LR(0)-item)
В начале работы стек пуст, и указатель входной цепочки находится перед ее первым символом. Этому состоянию соответствует ситуация
, где — нетерминал, добавленный при пополнении грамматики, — стартовый нетерминал. Назовем это состояние . Входная цепочка может начинаться с любого терминального символа, с которого начинается правая часть любого правила с левой частью . Построим соответствующий переход по следующей схеме:
Теперь мы должны выяснить, что произойдет, если анализатор выполнит перенос. Предположим, что мы выполним перенос
или перенос :
Таким образом, мы определяем новые состояния, в которое автомат перейдет после переноса того или иного терминала или нетерминала.
Заметим, что хранить в каждом состоянии только по одной ситуации не имеет смысла, поэтому пусть в каждое стостояние будет представлять множество ситуаций, а переходы — термилалы и нетермилалы. Для этого определим базовые операции
и , где – множество ситуаций, – символ грамматики (терминал или нетерминал). Операция добавляет ситуации к множеству ситуаций, у которых точка стоит слева от нетерминала. Добавляются те ситуации, которые получаются из правил, в левой части которого находится этот нетерминал.
[] closure (I) do for каждой ситуации [Aw.Xv] из I for каждого правила грамматики X u I += [X .u] // Операция += добавляет элемент к множеству while I изменилось return I
|
Операция
"переносит" точку после символа . Это означает переход из одного состояния в другое под воздействием символа .
[] goto (I, X) J={} // {} обозначает пустое множество for каждой ситуации [Aw.Xv] из I J += [A wX.v] return closure (J)
|
Теперь обсудим алгоритм построения конечного автомата. Обозначим
множество состояний, – множество переходов.
E, T build() E = {} T = {closure ([S'.S])} do for каждого состояния I из T for каждой ситуации [A w.Xv] из I J = goto(I, X) T += {J} // ко множеству состояний добавляется новое состояние E += (I J) // ко множеству ребер добавляется ребро, идущее из состояния I в состояние J. Этот переход осуществляется по символу X while E или T изменились return E, T
|
Управляющая таблица
После того, как автомат построен, можно построить управляющую таблицу.
Обращение к таблице происходит следующим образом
, где- — состояние автомата,
- — входной символ;
В соответствии со структурой управляющей таблицы будем действовать следующим образом:
- Для каждого ребра
- (сокр. от shift) , если — терминал,
- , если — нетерминал.
(из состояния в состояние по ) мы поместим в позицию
- Для состояния
- Поместим (сокр. от reduce), где — это номер правила в изначальной грамматике.
, содержащего ситуацию в позицию для каждого терминала
- Запись означает допуск.
- Пустая ячейка означает ошибочную ситуацию.
Пример
Для иллюстрации алгоритма LR(0)-разборщика мы будем использовать грамматику:
Обратим внимание, что данная грамматика является леворекурсивной, поэтому нисходящий разборщик не сможет осуществить разбор слова из этой грамматики.
Пополнение грамматики
Для начала переходим к Пополненной грамматике:
Построение автомата
НКА:
состоянию будет соответствует ситуация . Добавляем остальные состояния и получаем следующийТеперь в одно состояние перемещаем все ситуации, в которые идут ДКА:
-переходы. ПолучаемЗаполнение управляющей таблицы
Пронумеруем правила для выполнения свертки:
Управляющая таблица будет выглядеть так:
LR(0)-разбора конкретной строки
Пример будет для строки
Строка | Стек | Комментарий | |||
---|---|---|---|---|---|
Перенос | . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Перенос | . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Свертка: | . Удаление из стека . Переход в состояние. Добавление в стек . Переход в состояние.|||||
Так как свертка по нулевому правилу — осуществляем допуск. |
См. также
Источники информации
- Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. Стр. 301 - 326.
- Терехов Ан.А., Вояковская Н., Булычев Д., Москаль А. - Разработка компиляторов на платформе .NET - Восходящие анализаторы
- Б.К.Мартыненко. Языки и трансляции. Стр. 198 - 223
- Лекции по теории формальных языков, LR(0)-, SLR(1)-, LR(1)- и LALR(1)-анализ