Описание алгоритма
Функция переноса f зависит только от верхнего символа магазина и самого левого необработанного символа входной цепочки. Поэтому f определяется на множестве (V { }) (T { }) ( за исключением правила с), которое имеет приоритет над правилами а) и b), когда Х = S и a = ):
f(X, а) = ПЕРЕНОС, если Х <• а или Х а ;
f(X, а) = СВЕРТКА, если Х •> а ;
f(S, ) = ДОПУСК;
f(X, а) = ОШИБКА в остальных случаях.
2) Функция свертки g зависит от верхней части магазинной цепочки, включающей основу и еще один символ ниже нее. Необработанная часть входной цепочки на g не влияет, поэтому g задается только на (V { })*:
g(Xk+1XkXk-1 … X1, ) = i, если Xk+1 <• Xk, Xj+1 Xj для k>j1 и
A ХkХk-1 ... Х1 – правило вывода с номером i. Заметим, что функция g определяется только тогда, когда Х1 •> a – текущий входной символ;
b) g(, ) = ОШИБКА в остальных случаях.
Пример 4.9. Построить алгоритм разбора типа “перенос-свертка” для грамматики простого предшествования с правилами вывода:
(1) S aSSb
(2) S c
Матрица простого предшествования для этой грамматики приведена на рис. 4.31.
Функцию переносов f строим непосредственно по матрице простого предшествования: f(X, a) = ПЕРЕНОС, если Х <•а или Х а, f(X, a) = СВЕРТКА, если Х •>а. После добавления строки, соответствующей правилу 1,с), получим функцию переносов f, приведенную на рис. 4.32.
Для построения функции свертки рассмотрим все возможные комбинации основ и символа, который может располагаться в магазине под основой. Грамматика содержит два основывающих правила и, следовательно, две основы: aSSb и с. По матрице предшествования определяем множества символов, которые могут находиться под каждой основой (это символы Х <•а для правила (1) и Y <•с для правила (2)). Таким образом, функция g()=1 (см. рис. 4.33) для множества цепочек { SaSSb, aaSSb, aSSb } и g()=2 для множества цепочек { Sc, ac, }. В остальных случаях g() = ОШИБКА.
В заключение отметим, что каждая грамматика простого предшествования является LR(1)-грамматикой, в то время, как обратное утверждение неверно. Доказано, что существуют LR(1)-языки, которые не могут быть определены никакой грамматикой простого предшествования.
4.3.3.Грамматики слабого предшествования
Многие грамматики, описывающие языки программирования, не являются грамматиками простого предшествования. Попытки найти для данного языка грамматику простого предшествования могут привести к довольно громоздким грамматикам. Можно расширить класс грамматик, анализируемых методом предшествования, исключив ограничение, что отношения <•ине могут пересекаться.
Отношение •> по-прежнему используется для определения правого конца основы, а для локализации левого конца основы нужно найти правило грамматики, правая часть которого совпадает с символами, находящимися непосредственно слева от правого конца основы.
При использовании такого подхода могут возникнуть трудности, связанные с тем, что среди правил вывода грамматики могут быть правила, правые части которых являются суффиксами одна другой. Например, если w – правовыводимая цепочка, в которой правый конец основы находится между символами и w, а A и В – два разных правила, то не ясно, какое из них следует выбрать для свертки.
Мы ограничимся применением самого длинного из применимых правил. Класс грамматик, для которых такое решение является правильным, образуют грамматики слабого предшествования.
Определение.
Пусть G = < T, N, S, R > – приведенная грамматика без -правил. Назовем G грамматикой слабого предшествования, если
отношение •> не пересекается с объединением отношений <• и ;
для AX и В из R, где XV, не выполняется ни Х <• В, ни Х В.
Пример 4.10. Рассмотрим грамматику G0 (см. рис. 4.14). Матрица отношений простого предшествования для этой грамматики приведена на рис. 4.30. Как следует из рисунка, конфликты возникают только между отношениями <• и , и, следовательно. условие (1) определения грамматики слабого предшествования удовлетворяется. Рассмотрим правила (1) Е Е + Т и (2) Е Т, в которых одна правая часть служит суффиксом другой. Между символами + и Е нет никакого отношения предшествования, значит, для этих правил условие (2) не нарушается. Аналогичное заключение можно сделать и для правил (3) и (4). Таким образом, G0 – грамматика слабого предшествования.
Для любой обратимой грамматики слабого предшествования можно построить алгоритм разбора типа “перенос – свертка”.
Приведем этот алгоритм.
Вход
Обратимая грамматика слабого предшествования G = < T, N, S, R >, правила которой занумерованы натуральными числами от 1 до р.
Выход
Алгоритм A = (f, g) типа “перенос – свертка” для грамматики G.