ответствует применению правила (2)).
Осталось выяснить, какие ситуации согласованы с пустым сло-
вом, то есть для каких нетерминалов K пустое слово принадлежит
Лев(K). Это определяется по следующим правилам: (1) начальный
нетерминал таков; (2) если K таков и K -> V - правило граммати-
ки, причем слово V начинается с нетерминала L, то и L таков.
14.1.10. Проделать описанный анализ для грамматики
E -> E + T
E -> T
T -> T * F
T -> F
F -> x
F -> ( E )
Решение.
Слово S Сост(S)
_________________________________________________
пустое E->_E+T;E->_T;T->_T*F;T->_F;F->_x;F->_(E)
E E->E_+T
T E->T_; T->T_*F;
F T->F_
x F->x_
( F->(_E);E->_E+T;E->_T;T->_T*F;T->_F;F->_x;F->_(E)
E+ E->E+_T;T->_T*F;T->_F;F->_x;F->_(E)
T* T->T*_F;F->_x;F->_(E)
(E F->(E_);E->E_+T;
(T = T
(F = F
(x = x
(( = (
E+T E->E+T_;T->T_*F
E+F = F
E+x = x
E+( = (
T*F T->T*F_;
T*x = x
T*( = (
(E) F->(E)_
(E+ = E+
E+T* = T*
Знак равенства означает, что множества ситуаций, являющиеся зна-
чениями функции Сост(S) на словах, стоящих слева и справа от
знака равенства, одинаковы.
Правило определения Сост(SJ), если известны Сост(S) и J (S
- слово из терминалов и нетерминалов, J - терминал или нетерми-
нал), таково:
надо найти Сост(S) в правой колонке, взять соответствующее
ему слово T в левой колонке, приписать к нему J и взять мно-
жество, стоящее напротив слова ТJ (если слово ТJ в таблице от-
сутствует, то Сост(SJ) пусто).
14.2. LR(0)-грамматики.
Напомним, что наша основная цель - это поиск вывода задан-
ного слова, или, другими словами, поиск успешного LR-процесса
над ним. Во всех рассматриваемых нами грамматиках успешный
LR-процесс (над данным словом) единствен. Искать этот единствен-
ный успешный процесс мы будем постепенно: в каждый момент мы
смотрим, какой шаг возможен следующим. Для этого на грамматику
надо наложить дополнительные требования, и сейчас мы рассмотрим
простейший случай так называемых LR(0)-грамматик.
Мы уже знаем:
(1) В успешном LR-процессе возможна свертка по правилу K->U
при содержимом стека S тогда и только тогда, когда S принадлежит
ЛевКонт(K->U) или, другими словами, когда слово S согласовано с
ситуацией K->U_.
Аналогичное утверждение про сдвиг гласит:
(2) В успешном LR-процессе при содержимом стека S
возможен сдвиг с очередным символом a тогда и только тогда, ког-
да S согласовано с некоторой ситуацией K->U_aV.
14.2.1. Докажите это.
Указание. Пусть произошел сдвиг и к стеку S добавилась бук-
ва a. Рассмотрите первую свертку, затрагивающую эту букву.
Теперь мы можем дать
Определение. Рассмотрим некоторую грамматику и произвольное
слово S из терминалов и нетерминалов. Если множество Сост(S) со-
держит ситуацию, в которой справа от подчеркивания стоит терми-
нал, то говорят, что для слова S возможен сдвиг. Если в Сост(S)
есть ситуация, в которой справа от подчеркивания ничего нет, то
говорят, что для слова S возможна свертка (по соответствующему
правилу). Говорят, что для слова S возникает конфликт типа
сдвиг/свертка, если возможен и сдвиг, и свертка. Говорят, что
для слова S возникает конфликт типа свертка/свертка, если есть
несколько правил, по которым возможна свертка.
Грамматика называется LR(0)-грамматикой, если в ней нет
конфликтов типа сдвиг/свертка и свертка/свертка ни для одного
слова S.
14.2.2. Является ли приведенная выше грамматика LR(0)-грам-
матикой?
Решение. Нет, не является. Для слов T и E+T имеются
конфликты типа сдвиг/свертка.
14.2.3. Являются ли LR(0)-грамматиками такие:
(а) T->0
T->T1
T->TT2
T->TTT3
(б) T->0
T->1T
T->2TT
T->3TTT
Решение. (а)
Слово S Сост(S)
_________________________________________
пустое Т->_0;T->_T1;T->_TT2;T->_TTT3
0 Т->0_
Т Т->Т_1;T->T_T2;T->T_TT3;Т->_0;T->_T1;T->_TT2;T->_TTT3
T1 T->T1_
TT T->TT_2;T->TT_T3;T->T_1;T->T_T2;T->T_TT3;
T->_0;T->_T1;T->_TT2;T->_TTT3
TT2 T->TT2_
TTT T->TTT_3;T->TT_2;T->TT_T3;T->T_1;T->T_T2;T->T_TT3
Т->_0;T->_T1;T->_TT2;T->_TTT3
TT0 = 0
TTT3 T->TTT3_
TTT2 = TT2
TTTT = TT
TTT0 = 0
Конфликтов нет, это LR(0)-грамматика.
(б)
Слово S Сост(S)
_______________________________________________
пустое T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
0 Т->0_
1 Т->1_T;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
2 T->2_TT;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
3 T->3_TTT;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
1T T->1T_
10 = 0
11 = 1
12 = 2
13 = 3
2T T->2T_T;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
20 = 0
21 = 1
22 = 2
23 = 3
3T T->3T_TT;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
30 = 0
31 = 1
32 = 2
33 = 3
2TT T->2TT_
2T0 = 0
2T1 = 1
2T2 = 2
2T3 = 3
3TT T->3TT_T;T->_0;T->_1Т;T->_2ТТ;T->_3ТТТ
3T0 = 0
3T1 = 1
3T2 = 2
3T3 = 3
3TTT T->3TTT_
3TT0 = 0
3TT1 = 1
3TT2 = 2
3TT3 = 3
Конфликтов нет, это LR(0)-грамматика.
Эта задача показывает, что LR(0)-грамматики могут быть как
леворекурсивными, так и праворекурсивными.
14.2.4. Пусть дана LR(0)-грамматика. Доказать, что у любого
слова существует не более одного правого вывода. Построить алго-
ритм проверки выводимости в LR(0)-грамматике.
Решение. Пусть дано произвольное слово A. Будем строить
LR-процесс над A по шагам. Пусть текущее состояние стека LR-про-
цесса равно S. Нам надо решить, делать сдвиг или свертку (и если
сертку, то по какому правилу). Согласно определнию LR(0)-грамма-
тики в нашем состоянии S возможен либо только сдвиг, либо только
свертка (причем лишь по одному правилу). Таким образом, поиск
возможных продолжений LR-процесса происходит детерминированно
(на каждом шаге можно определить, какое действие только и воз-
можно).
14.2.5. Что произойдет, если анализируемое слово не имеет
вывода в данной грамматике?
Ответ. Либо на некотором шаге не будет возможен ни сдвиг,
ни свертка, либо все возможные сдвиги будет иметь неподходящий
очередной символ.
Замечания. 1. При реализации этого алгоритма нет необходи-
мости каждый раз заново вычислять множество Сост(S) для текущего
значения S. Эти множества можно также хранить в стеке (в каждый
момент хранятся множества Сост(T) для всех начал текущего слова
S).
2. На самом деле само слово S можно не хранить - достаточно
хранить множества ситуаций Сост(T) для всех его начал T.
В алгоритме проверки выводимости в LR(0)-грамматике мы ис-
пользуем не всю информацию, которую могли бы. В этом алгоритме
для каждого состояния известно заранее, что в нем возможен
только сдвиг или только свертка (причем в последнем случае из-
вестно, по какому правилу). Более изощренный алгоритм мог бы
принимать решение о выборе между сдвигом и сверткой, посмотрев
на очередной символ (Next). Глядя на состояние, можно сказать,
при каких значениях Next возможен сдвиг (это те терминалы, кото-
рые в ситуациях этого состояния стоят непосреджственно за под-
черкиванием). Сложнее воспользоваться информацией о символе Next
для решения вопроса о том, возможна ли свертка. Для этого есть
упрощенный метод (грамматики, к которым он применим, называют
SLR(1)-грамматиками [сокращение от Simple LR(1)]) и полный метод
(более сложный, но использующий всю возможную информацию; грам-
матики, к которым он применим, называют LR(1)-грамматиками).
Есть и промежуточный класс грамматик, называемый LALR(1).
14.3. SLR(1)-грамматики
Напомним, что для любого нетерминала K мы определяли мно-
жество Послед(K) тех терминалов, которые могут стоять непос-
редственно за K в выводимом (из начального нетерминала) слове; в
это множество добавляют также специальный символ EOI, если не-
терминал K может стоять в конце выводимого слова.
14.3.1. Доказать, что если в данный момент LR-процесса пос-
ледний символ стека S равен K, причем процесс этот может в
дальнейшем успешно завершиться, то Next принадлежит Послед(K).
Решение. Этот факт является непосредственным следствием оп-
ределения (вспомним соответствие между правыми выводами и
LR-процессами).
Определение. Рассмотрим некоторую грамматику, произвольное
слово S из терминалов и нетерминалов и терминал x. Если мно-
жество Сост(S) содержит ситуацию, в которой справа от подчерки-
вания стоит терминал x, то говорят, что для пары (S,x) возможен
сдвиг. Если в Сост(S) есть ситуация K->U_, причем x принадлежит
Послед(K), то говорят, что для пары (S,x) SLR(1)-возможна
свертка (по правилу K->U). Говорят, что для пары (S,x) возникает
конфликт типа сдвиг/свертка, если возможен и сдвиг, и свертка.
Говорят, что для пары (S,x) возникает конфликт типа
свертка/свертка, если есть несколько правил, по которым возможна
свертка.
Грамматика называется SLR(1)-грамматикой, если в ней нет
конфликтов типа сдвиг/свертка и свертка/свертка ни для одной па-
ры (S,x).
14.3.2. Пусть дана SLR(1)-грамматика. Доказать, что у любо-
го слова существует не более одного правого вывода. Построить
алгоритм проверки выводимости в SLR(1)-грамматике.
Решение. Аналогично случаю LR(0)-грамматик, только при вы-
боре между сдвигом и сверткой учитывается очередной символ Next.
14.3.3. Проверить, является ли приведенная выше грамматика
(с E, T и F) SLR(1)-грамматикой.
Решение. Да, является, так как оба конфликта, мешающие ей
быть LR(0)-грамматикой, разрешаются с учетом очередного символа:
и для слова T, и для слова E+T сдвиг возможен только при Nеxt =
*, а символ * не принадлежит Послед(E) = {EOI,+,)}, и поэтому
при Next = * свертка невозможна.
14.4. LR(1)-грамматики, LALR(1)-грамматики
Описанный выше SLR(1)-подход используют не всю возможную
информацию при выяснении того, возможна ли свертка. Именно, он
отдельно проверяет, возможна ли свертка при данном состоянии
стека S и отдельно - возможна ли свертка по данному правилу при
данном символе Next. Между тем эти проверки не являются незави-
симыми: обе могут дать положительный ответ, но тем не менее
свертка при стеке S и очередном символе Next невозможна. В
LR(1)-подходе этот недостаток устраняется.
LR(1)-подход состоит вот в чем: все наши определения и ут-
верждения модифицируются так, чтобы учесть, какой символ стоит
справа от разворачивамого нетерминала (другими словами, чему ра-
вен Next при свертке).
Пусть K->U - одно из правил грамматики, а t - некоторый
терминал или спецсимвол EOI (который мы домысливаем в конце
входного слова). Определим множество ЛевКонт(K->U,t) как мно-
жество всех слов, которые являются содержимым стека непос-
редственно перед сверткой U в K в ходе успешного LR-процесса,
при условии Next = t (в момент свертки).
Если отбросить у всех слов из ЛевКонт(K->U) их конец U, то
получится множество всех слов, которые могут появиться в правых
выводах перед нетерминалом K, за которым стоит символ t. Это
множество (не зависящее от того, какое из правил для нетерминала
K выбрано) мы будем обозначать Лев(K,t).
14.4.1. Написать грамматику для порождения множеств
Лев(K,t).
Решение. Ее нетерминалами будут символы <ЛевKt> для каждого
нетерминала K и для каждого терминала t (и для t=EOI). Ее прави-