
- •Теория вычислительных процессов и структур
- •1. Предварительные математические сведения
- •1.2. Операции над множествами Объединение множеств
- •Пересечение множеств
- •Разность множеств
- •1.3. Множества цепочек
- •1.4. Языки
- •1.5. Алгоритмы
- •1.6. Некоторые понятия теории графов
- •2. Введение в компиляцию
- •2.1. Задание языков программирования
- •2.2. Синтаксис и семантика
- •2.3. Процесс компиляции
- •2.4. Лексический анализ
- •2.5. Работа с таблицами
- •2.6. Синтаксический анализ
- •2.7. Генератор кода
- •Алгоритм.
- •2.8. Оптимизация кода
- •2.9. Исправление ошибок
- •2.10. Резюме
- •3. Теория языков
- •3.1. Способы определения языков
- •3.2. Грамматики
- •Пример.
- •3.3. Грамматики с ограничениями на правила
- •3.4. Распознаватели
- •3.5. Регулярные множества, их распознавание
- •3.6. Регулярные множества и конечные автоматы
- •3.7. Графическое представление конечных автоматов
- •3.8. Конечные автоматы и регулярные множества
- •3.9. Минимизация конечных автоматов
- •3.10. Контекстно-свободные языки
- •3.10.1. Деревья выводов
- •3.10.2. Преобразование кс–грамматик
- •3.10.3. Грамматика без циклов
- •3.10.4. Нормальная форма Хомского
- •3.10.5. Нормальная формула Грейбах
- •3.11. Автоматы с магазинной памятью
- •3.11.1. Основные определения
- •3.11.2. Эквивалентность мп-автоматов и кс-грамматик
- •4.1. Эквивалентность мп-автоматов и кс-грамматик
- •4.2. Ll(1)-грамматики
- •4.3. Ll(1)-таблица разбора
- •5. Синтаксический анализ снизу вверх
- •5.1. Разбор снизу вверх
- •5.2. Lr(1) - таблица разбора
- •5.3. Построение lr – таблицы разбора
- •5.4. Сравнение ll – и lr – методов разбора
- •6. Включение действий в синтаксис
- •6.1. Получение четверок
- •6.2. Работа с таблицей символов
- •7. Проектирование компиляторов
- •7.1. Число проходов
- •7.2. Таблицы символов
- •Identifier, type.
- •Int procedure rehash(int n)
- •Int procedure rehash(int n)
- •7.3. Таблица видов
- •8. Распределение памяти
- •8.1. Стек времени прогона
- •Integer a, b, X, y
- •Int table[1:10, -5:5].
- •8.2. Методы вызова параметров
- •8.3. Обстановка выполнения процедур
- •8.4. «Куча»
- •8.5. Счетчик ссылок
- •8.6. Сборка мусора
- •9. Генерация кода
- •(Тип – адреса, номер - блока, смещение).
- •9.2. Структура данных для генерации кода
- •9.3. Генерация кода для типичных конструкций
- •9.3.1. Присвоение
- •9.3.2. Условные зависимости
- •If b then c else d
- •9.3.3. Описание идентификаторов
- •9.3.4. Циклы
- •9.3.5. Вход и выход из блока
- •9.3.6. Прикладные реализации
- •9.4. Проблемы, связанные с типами
- •9.5. Время компиляции и время прогона
- •10. Исправление и диагностика ошибок
- •10.1. Типы ошибок
- •10.2. Лексические ошибки
- •10.3. Ошибки в употреблении скобок
- •Begin end
- •Case esac
- •10.4. Синтаксические ошибки
- •10.5. Методы исправления синтаксических ошибок
- •End begin
- •10.6. Предупреждения
- •10.7. Сообщения о синтаксических ошибках
- •10.8. Контекстно-зависимые ошибки
- •Identifier xyz not declared
- •Identifier blank alredy declared in block
- •10.9. Ошибки, связанные с употреблением типов
- •Int I; char c;
- •10.10. Ошибки, допускаемые во время прогона
- •10.11. Ошибки, связанные с нарушением ограничений
4.3. Ll(1)-таблица разбора
Найдя LL(1)-грамматику для языка, можно перейти к следующему этапу – применению найденной грамматики в фазе разбора. Обычно модуль компилятора, занимающийся семантическим разбором, называется драйвером. Драйвер указывает на то место в синтаксисе, которое соответствует текущему входному символу. Составной частью драйвера является стек, который служит для запоминания адресов возврата всякий раз, когда он входит в новое порождающее правило, соответствующее какому-нибудь нетерминалу.
Опишем сначала возможный вид таблицы разбора, а затем рассмотрим возможные способы ее оптимизации относительно используемых вычислительных ресурсов.
Таблица разбора в общем виде представляет собой одномерный массив структур вида:
declare 1 TABLE,
2 terminals list,
2 jump int,
2 accept bool,
2 stack bool,
2 return bool,
2 error bool;
где list
declare 1 list,
2 term string,
2 next pointer;
Кроме того, для работы драйвера нужен стек адресов возврата и указатель стека.
В таблице каждому шагу процесса разбора соответствует один элемент. В процессе разбора осуществляются следующие шаги.
Проверка предварительно просматриваемого символа, для того чтобы выяснить, не является ли он направляющим для какой-либо конкретной правой части порождающего правила. Если этот символ – не направляющий и имеется альтернативная правая часть правила, то она проверяется на следующем этапе. В особом случае, когда правая часть начинается с терминала, множество направляющих символов состоит только из одного терминала.
Проверка терминала, появляющегося в правой части порождающего правила.
Проверка нетерминала. Она заключается в проверке нахождения предварительно просматриваемого символа в одном из множеств направляющих символов для данного нетерминала, помещению в стек адреса возврата и переходу к первому правилу, относящемуся к этому нетерминалу. Если нетерминал появился в конце правой части правила, то нет необходимости помещать в стек адрес его возврата.
Таким образом, в таблицу разбора включается по одному элементу на каждое правило грамматики и на каждый экземпляр терминала или нетерминала правой части правил. Кроме того, в таблице будут находиться элементы на реализацию пустой строки в правой части правил (по одному на каждую реализацию).
Драйвер содержит процедуру, которая обрабатывает элементы таблицы разбора и определяет следующий элемент для обработки. Поле перехода обычно дает следующий элемент обработки, если значение поля возврата не окажется истиной. В последнем случае адрес следующего элемента берется из стека (что соответствует концу правила). Если же предварительно просматриваемый символ отсутствует в списке терминалов и значение поля ошибки окажется ложью, нужно обрабатывать следующий элемент таблицы с тем же предварительно просматриваемым символом (способ обращения с альтернативными правыми частями).
Рассмотрим схему построения таблицы разбора и соответствующей программы для следующей грамматики:
PROGRAM begin DECLIST comma STATLIST end
DECLIST d X
X semi DECLIST
X e
STATLIST s Y
Y semi STATLIST
Y e
Сначала представим грамматику в виде схемы (рис. 4.1). В скобках и справа на рисунке указаны номера элементов таблицы разбора.
Таблица разбора, соответствующая этой грамматике может быть представлена в виде табл. 4.6.
|
|
PROGRAM |
|
|
|
begin |
|
|
(2) | ||
|
|
|
|
|
|
|
DECLIST |
|
|
|
(3) |
|
|
|
|
|
|
|
comma |
|
|
(4) | |
|
|
|
|
|
|
|
STATLIST |
|
|
|
(5) |
|
|
|
|
|
|
|
end |
|
|
(6) | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(7) |
|
DECLIST |
|
|
|
d |
|
|
(8) | ||
|
|
|
|
|
|
|
X |
|
|
|
(9) |
|
|
|
|
|
|
|
|
|
|
|
|
(10) |
|
X1 |
|
|
|
semi |
|
|
(12) | ||
(11) |
|
X2 |
|
|
|
DECLIST |
|
|
|
(13) | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
e |
|
|
(14) | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(15) |
|
STATLIST |
|
|
|
s |
|
|
(16) | ||
|
|
|
|
|
|
|
Y |
|
|
|
(17) |
|
|
|
|
|
|
|
|
|
|
|
|
(18) |
|
Y1 |
|
|
|
semi |
|
|
(20) | ||
(19) |
|
Y2 |
|
|
|
STATLIST |
|
|
|
(21) | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
e |
|
|
(22) |
Рис. 4.1. Схема грамматики
Таблица 4.6 – Таблица разбора
|
terminals |
jump |
accept |
stack |
return |
Error |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{begin} {begin} {d} {comma} {s} {end} {d} {d} {semi, comma} {semi} {comma} {semi} {d} {comma} {s} {s} {semi, end} {semi} {end} {semi} {s} {end} |
2 3 7 5 15 0 8 9 10 12 14 13 7 0 16 17 18 20 22 21 15 0 |
false true false true false true false true false false false true false false false true false false false true false false |
false false true false true false false false false false false false false false false true false false false false false false |
false false false false false true false false false false false false false true false false false false false false false true |
True True True True True true true true true false true true true true true true true false true true true true |
Рассмотрим разбор предложения
begin d semi d comma s semi end
i |
Действия |
Стек разбора |
1. |
begin считывается и проверяется; перейти к 2 |
0 |
2. |
begin считывается и принимается; перейти к 3 |
0 |
3. |
d считывается и проверяется; 4 помещается в стек; перейти к 7 |
4 0 |
7. |
d принимается; перейти к 8 |
4 0 |
8. |
d проверяется и принимается; перейти к 9 |
4 0 |
9. |
semi считывается и проверяется; перейти к 10 |
4 0 |
10. |
semi проверяется; перейти к 12 |
4 0 |
12. |
semi проверяется и принимается; перейти к 13 |
4 0 |
13. |
d считывается и проверяется; перейти к 7 |
4 0 |
7. |
d проверяется; перейти к 8 |
4 0 |
8. |
d проверяется и принимается; перейти к 9 |
4 0 |
9. |
comma считывается и проверяется; перейти к 10 |
4 0 |
10. |
comma не совпадает с semi; ошибка ложь – перейти к 11 |
4 0 |
11. |
comma проверяется; перейти к 14 |
4 0 |
14. |
comma проверяется; возврат истина – удаляется 4; перейти к 4 |
0 |
4. |
comma проверяется и принимается; перейти к 5 |
0 |
5. |
s считывается и проверяется; 6 помещается в стек; перейти к 15 |
6 0 |
15. |
s проверяется; перейти к 16 |
6 0 |
16. |
s проверяется и принимается; перейти к 17 |
6 0 |
17. |
semi считывается и проверяется; перейти к 18 |
6 0 |
18. |
semi проверяется; перейти к 20 |
6 0 |
20. |
semi проверяется и принимается; перейти к 21 |
6 0 |
21. |
s считывается и проверяется; перейти к 15 |
6 0 |
15. |
s проверяется; перейти к 16 |
6 0 |
16. |
s проверяется и принимается; перейти к 17 |
6 0 |
17. |
end считывается и проверяется; перейти к 18 |
6 0 |
18. |
end не совпадает с semi; ошибка ложь; перейти к 19 |
6 0 |
19. |
end проверяется; перейти к 22 |
6 0 |
22. |
end проверяется; возврат истина – удалить 6; перейти к 6 |
0 |
6. |
end проверяется и принимается; возврат истина – удалить 0; i:=0 |
|
0. |
Разбор заканчивается |
|
LL(1) – метод разбора имеет ряд преимуществ.
Никогда не требует возврата, поскольку этот метод детерминирован.
Время разбора пропорционально длине программы.
Имеются хорошие диагностические характеристики, и существует возможность исправления ошибок, т.к. синтаксические ошибки распознаются по первому неприемлемому символу, а в таблице разбора есть список возможных символов предложения.
Таблица разбора меньше, чем соответствующие таблицы в других методах разбора.
LL(1) –разбор применим к широкому классу современных языков.
Контрольные вопросы
Эквивалентность МП-автоматов и КС-грамматик.
LR(k)-грамматики.
S-грамматика.
LL(1)-грамматика.
Алгоритм определения принадлежности данной грамматики к LL(1)-грамматике.
LL(1) – таблица разбора.