Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпоры по тяпу.docx
Скачиваний:
8
Добавлен:
01.04.2025
Размер:
808 Кб
Скачать
☆

10. Левая факторизация.

LL(1)-грамматики нужны для того, чтобы выбрать нужную продукцию для разбора сверху-вниз, чтобы не произошло зацикливание.

Иногда существует возможность преобразовать грамматику к LL(1) виду, используя метод левой факторизации.

Например: S→ if B then S

│if B then S else S

Эти продукции нарушают условие LL(1)-грамматик. Эту грамматику можно преобразовать к виду LL(1).

S → if B then S Tail

Tail → else S

| ε

В общем виде это преобразование можно определить так:

A → α β1

| α β2

…

| α βN

| γ

вводим новый нетерминал В, для которого

A → α B

| γ

B → β1

| β2

…

| βN Для B можно применить левую факторизацию. Эта процедура повторяется, пока остается неопределенным выбор продукции (т.е. пока в ней можно что-нибудь изменить).

11. Построение множества first

Множество First для нетерминала определяет множество терминалов, с которых может начинаться данный нетерминал.

1. Если х - терминал, то first(x)={x}. Так как первым символом последовательности из одного терминала может являться только сам терминал.

2. Если в грамматике присутствует правило Х , то множество first(х) включает . Это означает, что Х может начинаться с пустой последовательности, то есть отсутствовать вообще.

3. Для всех продукций вида XY1 Y2 … Yk выполняем следующее. Добавляем в множество first(Х) множество first(Yi) до тех пор, пока first(Yi-1) содержит , а first(Yi) не содержит . При этом i изменяется от 0 до k. Это необходимо, так как если Yi-1 может отсутствовать, то необходимо выяснить, с чего будет начинаться вся последовательность в этом случае.

12. Построение множества follow

Множество Follow для нетерминала определяет множество терминалов, которые могут следовать непосредственно за данным нетерминалом.

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

  1. Пусть goal – стартовый нетерминал. Тогда follow(goal) = {EOF}, где EOF – символ конца входной последовательности

  2. Если есть правило A -> aBb, то follow(B) = follow(B) + first(b) - {ɛ}

  3. Если есть правило A -> aB, то в множество follow(B) = follow(B) + follow(A).

  4. Если есть продукция A -> aBb и {ɛ} принадлежит first(B), то follow(B) = follow(B) + follow(A).

  5. Если на шагах 2-4 множество follow было изменено, перейти к п.2

Алгоритм построения множества follow заключается в следующем. Вначале символ конца входной последовательности помещается в множество follow стартового нетерминала (шаг 1). Затем выполнятся шаги 2-4 до тех пор, пока можно еще что-либо добавить в множество follow(X).

2. Если есть правило АB, то в множество follow(В) добавляем множество first() без . То есть, если есть правило, утверждающее, что за В следует , то за нетеримналом будут следовать терминалы, с которых начинается последовательность .

3. Если есть правило АB, то в множество follow(B) добавляется множество follow(A). То есть, если есть правило, утверждающее, что нетерминалом В заканчивается последовательность А, то за нетрминалом В будут следовать те же терминалы, что и за всей последовательностью А.

4. Если есть продукция АB и пустая последовательность принадлежит first(), то в множество follow(B) добавляется множество follow(A). Если последовательность  не пуста, то терминалы, которые могут следовать за В уже найдены на шаге 1. Если же последовательность  пуста, то шаг 3 фактически сводится к шагу 2.