
- •Глава 1. Введение 2
- •Глава 2. Лексический анализ 6
- •2.4. Построение детерминированного конечного
- •Глава 3. Синтаксический анализ 20
- •Глава 8. Генерация кода 76
- •Глава 9. Системы автоматизации построения трансляторов 120
- •Глава 1. Введение
- •1.1. Место компилятора в программном обеспечении
- •1.2. Структура компилятора
- •Глава 2. Лексический анализ
- •2.1. Регулярные множества и регулярные выражения
- •2.2. Конечные автоматы
- •2.5. Программирование лексических анализаторов
- •2.6. Конструктор лексических анализаторов lex
- •Глава 3. Синтаксический анализ
- •3.1. Основные понятия и определения
- •3.2. Таблично-управляемый предсказывающий разбор
- •3.2.1. Алгоритм разбора сверху-вниз
- •3.2.2. Множества first и follow.
- •3.2.4. Ll(1)-грамматики
- •3.2.5. Удаление левой рекурсии
- •3.2.6. Левая факторизация
- •3.2.7. Рекурсивный спуск
- •3.2.8. Диаграммы переходов для рекурсивного спуска
- •3.2.9. Восстановление после синтаксических ошибок
- •3.3. Разбор снизу-вверх типа сдвиг-свертка
- •3.3.1. Основа
- •3.3.2. Lr(k)-анализаторы
- •3.3.4. Конфликты разбора типа сдвиг-свертка
- •3.3.5. Восстановление после синтаксических ошибок
- •Глава 4. Промежуточные представления программы
- •4.1. Представление в виде ориентированного графа
- •4.2. Трехадресный код
- •4.3. Линеаризованные представления
- •4.4. Организация информации в генераторе кода
- •4.5. Уровень промежуточного представления
- •Глава 5. Элементы теории перевода
- •5.1. Преобразователи с магазинной памятью
- •5.2. Синтаксически управляемый перевод
- •5.3. Атрибутные грамматики
- •5.3.1. Определение атрибутных грамматик
- •5.3.2. Атрибутированное дерево разбора
- •5.3.3. Язык описания атрибутных грамматик
- •Глава 6. Контекстные условия языков программирования
- •6.1. Описание областей видимости и блочной структуры
- •6.2. Структура среды Модулы-2
- •6.3. Занесение в среду и поиск объектов
- •Глава 7. Организация таблиц символов компилятора
- •7.1. Таблицы идентификаторов и таблицы символов
- •7.2. Таблицы идентификаторов
- •7.3. Таблицы символов и таблицы расстановки
- •7.4. Функции расстановки.
- •7.5. Таблицы на деревьях
- •7.7. Сравнение различных методов реализации таблиц
- •Глава 8. Генерация кода
- •8.1. Модель машины
- •8.2. Динамическая организация памяти
- •8.3. Назначение адресов
- •8.4. Трансляция переменных.
3.2. Таблично-управляемый предсказывающий разбор
3.2.1. Алгоритм разбора сверху-вниз
Основная проблема предсказывающего разбора - определение правила
вывода, которое нужно применить к нетерминалу. Процесс
предсказывающего разбора (сверху-вниз) с точки зрения построения
дерева разбора можно проиллюстрировать рис. 3.1. Фрагменты
недостроенного дерева соответствуют сентенциальным формам вывода.
Вначале дерево состоит только из одной вершины, соответствующей
аксиоме S. В этот момент по первому символу входного потока
предсказывающий анализатор должен определить правило S->X1 X2 ...,
которое должно быть применено к S. Затем необходимо определить
правило, которое должно быть применено к X1, и т.д., до тех пор, пока
в процессе такого построения сентенциальной формы, соответствующей
левому выводу, не будет применено правило Y->a .... Этот процесс затем
применяется для следующего самого левого нетерминального символа
сентенциальной формы.
S S S
/ | \ / | \
X1 X2... X1 X2...
/ / |
........... .............
/ / |
Y Y |
/|\ /|\ Z
/ ... / ... /|\
a..........$ a...........$ a........b.......$
а) б) в)
Рис. 3.1
На рис. 3.2 приведена структура предсказывающего анализатора,
который определяет очередное правило из таблицы. Такую таблицу множно
построить непосредственно из грамматики.
+---------------+
Вход | a | + | b | $ |
+---------------+
^
|
+-+ +----------------------+
|X| | Программа предсказы- | Выход
Магазин |-|<---| вающего анализатора |--->
|Y| +----------------------+
|Z| |
|-| v
|$| +---------------------+
+-+ | Таблица анализатора |
+---------------------+
Рис. 3.2
Таблично-управляемый предсказывающий анализатор имеет входной
буфер, таблицу анализа и выход. Входной буфер содержит распознаваемую
строку, за которой следует $ - правый концевой маркер, признак конца
строки. Магазин содержит последовательность символов грамматики с $ на
дне. Вначале магазин содержит начальный символ грамматики на верхушке
и $ на дне. Таблица анализа - это двумерный массив M[A,a], где A -
нетерминал, и a - терминал или символ $.
Анализатор управляется программой, которая работает следующим
образом. Она рассматривает X - символ на верхушке магазина и a -
текущий входной символ. Эти два символа определяют действие
анализатора. Имеются три возможности.
1. Если X=a=$, анализатор останавливается и сообщает об успешном
окончании разбора.
2. Если X=a#$, анализатор удаляет X из магазина и продвигает
указатель входа на следующий входной символ.
3. Если X - нетерминал, программа заглядывает в таблицу M[X,a].
По этому входу хранится либо правило для X, либо ошибка. Если,
например, M[X,a]={X->UVW}, анализатор заменяет X на верхушке магазина
на WVU {на верхушке U}. Будем считать, что анализатор в качестве
выхода просто печатает использованные правила вывода. Если
M[X,a]=error, анализатор обращается к подпрограмме анализа ошибок.
Поведение анализатора может быть описано в терминах конфигураций
автомата разбора.
Алгоритм 3.1. Нерекурсивный предсказывающий анализ.
repeat X:=верхний символ магазина;
if X - терминал или $
then if X=InSym
then удалить X из магазина;
InSym:=очередной символ;
else error()
end
else /*X = нетерминал*/
if M[X,InSym]=X->Y1Y2...Yk
then удалить X из магазина;
поместить Yk,Yk-1,...Y1 в магазин
(Y1 на верхушку);
вывести правило X->Y1Y2...Yk
else error() /*вход таблицы M пуст*/
end end
until X=$ /*магазин пуст*/
Рис. 3.3
Вначале анализатор находится в конфигурации, в которой магазин
содержит S$, (S - начальный символ грамматики), во входном буфере w$
(w - входная цепочка), переменная InSym содержит первый символ входной
строки. Программа, использующая таблицу анализатора M для
осуществления разбора, изображена на рис. 3.3.
Пример 3.1. Рассмотрим грамматику арифметических выражений:
E -> T E'
E' -> + T E' | e
T -> F T' (*)
T' -> * F T' | e
F -> ( E ) | id
Таблица предсказывающего анализатора для нее изображена на рис.
3.4. Здесь пустые клетки - входы ошибок. Непустые дают правила, по
которым делается развертка нетерминала.
---------------------------------------------------
Нетер-| Входной символ
|--------------------------------------------
минал | id | + | * | ( | ) | $
------+------+--------+--------+------+-----+------
E |E->TE'| | |E->TE'| |
E' | |E'->+TE'| | |E'->e|E'->e
T |T->FT'| | |T->FT'| |
T' | |T'->e |T'->*FT'| |T'->e|T'->e
F |F->id | | |F->(E)| |
-----------------------------------------------------
Рис. 3.4
----------------------------------
Магазин | Вход | Выход
--------+-----------+-------------
$E | id+id*id$ |
$E'T | id+id*id$ | E->TE'
$E'T'F | id+id*id$ | T->FT'
$E'T'id | id+id*id$ | F->id
$E'T' | +id*id$ | E
$E' | +id*id$ | T'->e / \
$E'T+ | +id*id$ | E'->+TE' / \
$E'T | id*id$ | T E'
$E'T'F | id*id$ | T->FT' /| / | \
$E'T'id | id*id$ | F->id F T' + T E'
$E'T' | *id$ | | / |
$E'T'F* | *id$ | T'->*FT' id / |
$E'T'F | id$ | F T'
$E'T'id | id$ | F->id | /|\
$E'T' | $ | id * F T'
$E' | $ | T'->e |
$ | $ | E'->e id
----------------------------------
Рис. 3.5 Рис. 3.6
На входе id+id*id предсказывающий анализатор совершает
последовательность шагов, изображенную на рис. 3.5. Указатель входа
указывает на самый левый символ в колонке Вход. Если внимательно
проанализировать действия анализатора, то видно, что он осуществляет
левый вывод, т.е. правила применяются в соответствии с левым выводом.
За уже просмотренными входными символами следуют символы грамматики в
магазине (сверху вниз), что соответствует левым сентенциальным формам
вывода.
Дерево разбора приведено на рис. 3.6.