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

4.1. Нисходящий разбор с возвратами

В алгоритме используется два магазина L1 и L2 и счетчик с текущей позицией входного указателя. Для описания алгоритма воспользуемся стилизованными обозначениями, похожими на описания конфигурации МП-автомата.

Алгоритм 4.1. Алгоритм нисходящего разбора с возвратами.

Вход. Не леворекурсивная КС-грамматика G = (N, , P, S) и входная цепочка = a1, a2, , an (n 0). Предполагается что правила из P пронумерованы числами 1, 2 , , p.

Выход. Левый разбор цепочки , если он существует, или слово “ошибка” в противном случае.

Метод.

(1) Для каждого нетерминала А N упорядочить его альтернативы. Пусть А j - индекс j-ой альтернативы нетерминала А.

(2) Четверкой (q, i, , ) будем обозначать конфигурацию алгоритма, где:

(а) q - состояние алгоритма;

(б) i - позиция входного указателя (предполагается, что (n+1)-ым “входным символом” служит правый концевой маркер $);

(в) - содержимое первого магазина (L1);

(г) - содержимое второго магазина (L2).

Будем считать, что верх первого магазина расположен справа, а второго - слева.

Магазин L2 служит для представления “текущей” левовыводимой цепочки, то есть той сентенциальной формы, которая получилась к данному моменту разбора в результате развертки нетерминалов. Верхний символ в L2 будет символом, помечающим активную вершину порожденного к данному моменту частично дерева левого выхода. В L1 представлена текущая история проделанных выборов альтернатив и входные символы, по которым прошла входная головка. Алгоритм имеет три состояния: q- нормальной деятельности, b-возврата, t заключительное состояние.

(3) Начальная конфигурация алгоритма: (q, 1, , S$).

(4) Существует шесть типов шагов. Эти шаги будут описаны в терминах их воздействия на конфигурацию алгоритма. Запись (q, i, , ) (q, i, , ) означает что если (q, i, , ) - текущая конфигурация, то нужно перейти в следующую конфигурацию (q, i, , ). Если не оговорено противное, то и i - число от 1 до (n+1), (I)*, где I - множество индексов альтернатив, (N)*.

Шесть шагов определяется так:

(а) Разрастание дерева

(q, i, , A) (q, i, A1, 1), где A1 правило из P и 1 - первая альтернатива нетерминала A, а A1 – ее индекс. Этот шаг соответствует разрастанию частичного дерева вывода, при котором применяется первая альтернатива самого левого нетерминала дерева.

(б) Успешное сравнение входного символа с порожденным символом

(q, i, , a) (q, i+1, а, ), при условии, что а i= а (i n). Если i-ый входной символ совпадает с очередным порожденным терминалом, то терминал передается из L2 в L1, а позиция указателя увеличивается на единицу.

(в) Успешное завершение

(q, n+1, , $) (t, n+1, , ). Достигнут конец входной цепочки и найдена левовыводимая цепочка, совпадающая с входной. Левый разбор входной цепочки восстанавливается по цепочке с помощью гомоморфизма h, где h(a)=, для всех а и h(A j)=p, где p - номер правила А и - j-ая альтернатива нетерминала А.

(г) Неудачное сравнение входного символа с порожденным символом

(q, i, , а) (b, i, , a), при условии, что а i а. Надо перейти в состояние возврата b, как только обнаружится, что порожденная левовыводимая цепочка не совпадает с входной цепочкой.

(д) Возврат по входу

(b, i, a, ) (b, i1, , a) для всех а. В состоянии возврата входные символы переносятся назад из L1 в L2.

(е) Испытание очередной альтернативы

(b, i, Aj, j)

(е1) (q, i, Aj+1, j+1), если j+1 - (j+1)-ая альтернатива нетерминала А. (j в L2 заменяется на j+1).

(е2) Следующая конфигурация невозможна, если i=1, A=S и S имеет только j альтернатив. (Это условие указывает, что все возможные левовыводимые цепочки, совместимые с входной цепочкой , уже исчерпаны, а ее разбор не найден).

(е3) (b, i, , A) в оставшихся случаях. (Здесь исчерпаны все альтернативы нетерминала A и дальнейший возврат происходит путем удаления Aj из L1 и замены в L2 цепочки j на A).

Алгоритм выполняется следующим образом:

Шаг 1: Исходя из начальной конфигурации, вычислить последующие конфигурации C0 C1 Ci  , пока их можно вычислить.

Шаг 2: Если последняя конфигурация (t, n+1, , ), - выдать h() и остановиться, иначе выдать сообщение об ошибке.

Пример 4.1.

Рассмотрим работу алгоритма на примере грамматикой G для упрошенных арифметических выражений с правилами:

(1)

Е ТE

(E1) -

индекс для альтернативы ТE

(2)

Е Т

(E2)

(3)

T FТ

(T1)

(4)

T F

(T2)

(5)

F a

(F1)

Для входа aa алгоритм вычислит следующую последовательность конфигураций (над символом перехода указан индекс шага алгоритма) :

(q, 1, , E$) a (q, 1, E1, TE$) a (q, 1, E1T1, FTE$)

a (q, 1, E1T1F1, aTE$) б (q, 2, E1T1F1а, TE$)

г (b, 2, E1T1F1а, TE$) д (b, 1, E1T1F1, аTE$)

е3 (b, 1, E1T1, FTE$) е1 (q, 1, E1T2, FE$)

а (q, 1, E1T2F1, aE$) б (q, 2, E1T2F1a, E$)

б (q, 3, E1T2F1a, E$) а (q, 3, E1T2F1aE1, ТE$)

а (q, 3, E1T2F1aE1T1, FТE$) а (q, 3, E1T2F1aE1T1F1, aТE$)

б (q, 4, E1T2F1aE1T1F1a, ТE$) г (b, 4, E1T2F1aE1T1F1a, ТE$)

д (b, 3, E1T2F1aE1T1F1, aТE$) е3 (b, 3, E1T2F1aE1T1, FТE$)

е1 (q, 3, E1T2F1aE1T2, FE$) а (q, 3, E1T2F1aE1T2F1, aE$)

б (q, 4, E1T2F1aE1T2F1a, E$) г (b, 4, E1T2F1aE1T2F1a, E$)

д (b, 3, E1T2F1aE1T2F1, aE$) е3 (b, 3, E1T2F1aE1T2, FE$)

е3 (b, 3, E1T2F1aE1, TE$) е1 (q, 3, E1T2F1aE2, T$)

а (q, 3, E1T2F1aE2T1, FТ$) а (q, 3, E1T2F1aE2T1F1, аТ$)

б (q, 4, E1T2F1aE2T1F1а, Т$) г (b, 4, E1T2F1aE2T1F1а, Т$)

д (b, 3, E1T2F1aE2T1F1, aТ$) е3 (b, 3, E1T2F1aE2T1, FТ$)

е1 (q, 3, E1T2F1aE2T2, F$) а (q, 3, E1T2F1aE2T2F1, a$)

б (q, 4, E1T2F1aE2T2F1a, $) в (t, 4, E1T2F1aE2T2F1a, )

В результате получается левый разбор h(E1T2F1aE2T2F1a)=145245.

Корректность приведенного алгоритма можно строго доказать [1].