Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УМК по СПО.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.79 Mб
Скачать

6.11.2.Распознаватель для lr(1) грамматики

Другим употребительным классом LR(k)- грамматика являются LR(1)-граммати­ки. В этих грамматиках основанием для принятия расширенным МП-автоматом решения о выполнении сдвига или свертки служит информация о содержимом стека автомата и текущий символ, обозреваемый считывающей головкой.

Рассмотрим простую КС-грамматику G({a,b}, {S}, {S→SaSb|}, S). Пополненная грамматика для нее будет иметь вид G({a,b}, {S, S'}, {S'→S, S→SaSb|}, S'). Эта грамматика является LR(1)-грамматикой. Управляющая таблица для нее приведена в табл. 6.2.

Колонка «Стек», присутствующая в таблице, в принципе не нужна для распозна­вателя. Она введена исключительно для пояснения каждого состояния стека автомата. Пустые клетки в таблице соответствуют состоянию «ошибка».

Правила в грамматике пронумерованы от 1 до 3 (при этом будем считать, что состоя­нию «успех» — свертке к нулевому символу — в пополненной грамматике всегда соответствует первое правило). Колонка «Действие» и таблице содержит пере­чень действий, соответствующих текущему входному символу, обозреваемому считывающей головкой расширенного МП-автомата.

Таблица 6.2 Пример управляющей таблицы для LR(1)-грамматики

Стек

Действие

Переход

a

b

^к

а

b

S

^и

свертка, З

свертка, 3

1

S

сдвиг

успех, 1

2

Sa

свертка, 3

свертка, 3

3

SaS

сдвиг

сдвиг

4

5

SaSa

свертка, 3

свертка, 3

6

SaSb

свертка, 2

свертка, 2

SaSaS

сдвиг

сдвиг

4

7

SaSaSb

свертка, 2

свертка, 2

Рассмотрим примеры распознавания цепочек этой грамматики но шагам, кото­рые совершает распознаватель. Конфигурацию расширенного МП-автомата бу­дем отображать в виде трех компонентов: не прочитанная еще часть входной це­почки символов, содержимое стека МП-автомата, последовательность номеров примененных правил грамматики (поскольку автомат имеет только одно состоя­ние, его можно не учитывать). В стеке МП-автомата имеете с помещенными туда символами показаны и номера строк управляющей таблицы, соответствующие этим символам » формате (символ, номер строки}.

Разбор цепочки abababb

1. (abababb^к, (^и,0), )

2. (abababb^к, {^и,0}{S,1}, 3)

3. (bababb^к, {^и,0){S,l}{a,2}, 3)

4. (bababb^к, {^и,0}(S,l}{a,2}{S,3}, 3,3)

5. (ababb^к, {^и,0}{S,l}{a,2}{S,3}{b,5}, 3,3)

6. (ababb^к, {^и,0}{S,1}, 3,3,2)

7. (babb^к, {^и,0}{S,l){a,2}, 3,3,2)

8. (babb^к, {^и,0}{S,l}{a,2}{S,3}, 3,3,2,3)

9. (abb^к, {^и,0}{S,l}{a,2}{S,3}{b,5}, 3,3,2,3)

10. (abb^к, {^и,0}{S,1}, 3,3,2,3,2)

11. (bb^к, {^и,0}{S,l}{a,2}, 3,3,2,3,2)

12. (bb^к, {^и,0}{S,l}{a.2}{S,3}, 3,3,2,3,2,3)

13. (^к, {^и,0}{S,l}{a,2}{S,3}{b.5}, 3,3,2,3,2,3)

14. Ошибка, нет данных для «b» в строке 5.

Разбор цепочки aababb.

1. (aababb^к, {^и,0}, )

2. (aababb^к, {^и,0}{S,1}, 3)

3. (аbabb^к, {^и,0}{S,1}{а,2}, 3)

4. (ababb^к, {^и,0}{S,1}{а,2}{S,3}, 3,3)

5. (bаbb^к, {^и,0){S,l}{a,2}{S,3}{a,4}, 3,3)

6. (babb^к, {^и ,0}{S,l}{a,2}{S,3}{a,4}{S,6}, 3,3,3)

7. (abb^к, {^и,0}{S,l}{a,2}{S,3}{a,4}{S,6}{b,7}, 3,3,3)

8. (abb^к, {^и,0}{S,l}{a,2}{S,3}, 3,3,3,2)

9. (bb^к, {^и,0}{S,l}{a,2}{S,3}{a,4}, 3,3,3,2)

10. (bb^к, {^и,0}{S,l}{a,2}{S,3}{a,4}{S,6}, 3,3,3,2,3)

11. (b^к, {^и,0}{S,l}{a,2}{S,3}{a,4}{S,6}{b,7}, 3,3,3,2,3)

12. (b^к, {^и,0}{S,l}{a,2}{S,3}, 3,3,3,2,3,2)

13. (^к, {^и,0}{S,l}{a,2}{S,3}{b,5}, 3,3,3,2,3,2)

14. (^к, {^и,0}{S,1}, 3,3,3,2,3,2,2)

15. (^к, {^и,0}{S',*}, 3,3,3,2,3,2,2,1) - разбор завершен.

Соответствующая цепочка вывода будет иметь вид (используется правосторон­ний вывод): S'  S  SaSb  SaSaSbb  SaSabb  SaSaSbabb  SaSababb  Saababb  aababb.

Невозможно непосредственно сравнить работу двух рассмотренных вариантов распознавателей: восходящего (LR) и нисходящего (LL). Это очевидно, посколь­ку приведенная в примере грамматика не является LL(l)- грамматикой. Соответ­ственно, она не может быть разобрана и методом рекурсивного спуска (можно убедиться в этом, построив множества FIRST и FOLLOW для символов грамма­тики: FIRST(1,S) = {a}, FOLLOW(l,S) - {α,b,}; FIRST(l,S)  FOLLOW(l,S) ≠ 0). На основании этой грамматики вообще невозможно построить нисходящий рас­познаватель, поскольку она явно содержит левую рекурсию. Устранив левую рекур­сию и выполнив ряд несложных преобразований, можно получить эквивалентную ей грамматику G"({a,b},{S},{S→|aSbS},S), которая будет относить­ся к классу LR(k) -грамматик (действительно, для нее FIRST(l,S) - {a}, FOLLOW(1,S) = {b}; FIRST(l,S)  FOLLOW(l,S) ≠ 0)1.

Теперь уже возможно сравнить ра­боту двух вариантов распознавателей — нисходящего и восходящего.

Несмотря на то что распознаватель на основе LL(1)-грамматики и в данном слу­чае имеет более простой алгоритм функционирования, нельзя сказать, что им легче воспользоваться, поскольку его создание требует дополнительных преоб­разований исходной грамматики. Для более сложных LR(1)-грамматик такие преобразования могут быть в принципе невозможны, поскольку класс языков, заданных LR(1)-грамматиками, шире, чем класс языков, заданных LL(1) -грам­матиками. Поэтому для конкретной ладанной грамматики чаще бывает проще построить восходящий распознаватель, чем нисходящий.

На практике LR(k)-грамматики при k > 1 не применяются. На это имеются две причины. Во-первых, управляющая таблица для LR(к)- грамматика при k > 1 бу­дет содержать очень большое число состояний, и распознаватель будет достаточ­но сложным и не столь эффективным2. Во-вторых, для любого языка, определяе­мого LR(k)- грамматикой, существует LR(1)-грамматика, определяющая тот же язык. То есть для любой LR(k)-грамматики c k > 1 всегда существует эквива­лентная ей LR(1)-грамматика. Более того, для любого детерминированного КС-языка существует LR(1)-грамматика (другое дело, что далеко не всегда такую грамматику можно легко построить)3.