
- •Содержание
- •Введение
- •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.8. Оптимизация кода
- •2.9. Исправление ошибок
- •2.10. Резюме
- •Контрольные вопросы
- •3. Теория языков
- •3.1. Способы определения языков
- •3.2. Грамматики
- •3.4. Распознаватели
- •3.5. Регулярные множества, их распознавание и порождение
- •5.2. LR(1) - таблица разбора
- •5.3. Построение LR – таблицы разбора
- •5.4. Сравнение LL – и LR – методов разбора
- •Контрольные вопросы
- •6. Оптимизация кода
- •6.1. Оптимизация линейного участка
- •6.1.1. Модель линейного участка
- •6.1.2. Преобразование блока
- •6.1.3. Графическое представление блоков
- •6.1.4. Критерий эквивалентности блоков
- •6.1.5. Оптимизация блоков
- •6.1.6. Алгебраические преобразования
- •6.2. Арифметические выражения
- •6.2.1. Модель машины
- •6.2.2. Разметка дерева
- •6.2.3. Программы с командами STORE
- •6.2.4. Влияние некоторых алгебраических законов
- •6.3. Программы с циклами
- •6.3.1. Модель программы
- •6.3.2. Анализ потока управления
- •Алгоритм вычисления прямого доминирования
- •6.3.3. Примеры преобразования программ
- •Удаления бесполезных операторов
- •Замена сложных операций
- •6.3.4. Оптимизация циклов
- •Перемещение кода
- •Индуктивное перемещение
- •Замена сложных операций
- •6.4. Анализ потоков данных
- •6.4.1. Интервалы
- •6.4.2. Анализ потоков данных с помощью интервалов
- •6.4.3. Несводимые графы управления
- •7. Включение действий в синтаксис
- •7.1. Получение четверок
- •7.2. Работа с таблицей символов
- •Контрольные вопросы
- •8. Проектирование компиляторов
- •8.1. Число проходов
- •8.2. Таблицы символов
- •8.3. Таблица видов
- •Контрольные вопросы
- •9. Распределение памяти
- •9.1. Стек времени прогона
- •9.2. Методы вызова параметров
- •9.3. Обстановка выполнения процедур
- •9.4. «Куча»
- •9.5. Счетчик ссылок
- •9.6. Сборка мусора
- •Контрольные вопросы
- •10. Генерация кода
- •10.1. Генерация промежуточного кода.
- •10.2. Структура данных для генерации кода
- •10.3. Генерация кода для типичных конструкций
- •10.3.1. Присвоение
- •10.3.2. Условные зависимости
- •10.3.3. Описание идентификаторов
- •10.3.4. Циклы
- •10.3.5. Вход и выход из блока
- •10.3.6. Прикладные реализации
- •10.4. Проблемы, связанные с типами
- •10.5. Время компиляции и время прогона
- •Контрольные вопросы
- •11. Исправление и диагностика ошибок
- •11.1. Типы ошибок
- •11.2. Лексические ошибки
- •11.3. Ошибки в употреблении скобок
- •11.4. Синтаксические ошибки
- •11.5. Методы исправления синтаксических ошибок
- •11.6. Предупреждения
- •11.7. Сообщения о синтаксических ошибках
- •11.8. Контекстно-зависимые ошибки
- •11.9. Ошибки, связанные с употреблением типов
- •11.10. Ошибки, допускаемые во время прогона
- •Контрольные вопросы
- •Список литературы

189
Есть много других вариантов избежать перехеширования при создании таблиц идентификаторов. Рассмотрим некоторые из них.
·Сцепление элементов. В этом случае переполнения таблиц можно
избежать путем использования указателей (рис. 7.1.)
AGE
BAT
CAT |
|
COW |
|
|
|
CASE |
|
|
Рис. 7.1. Сцепление элементов
Для этого в таблице необходимо предусмотреть место для указателей, что ведет к увеличению объема последней.
·Бинарное дерево. Бинарное дерево (рис. 7.2.) состоит из некоторого количества вершин, каждая из которых содержит идентификатор, его тип и т.д., и двух указателей на другие вершины.
|
|
|
|
|
|
|
|
LEMON |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EGG |
|
|
|
|
|
|
MOUSE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
BUS |
|
|
|
|
|
HADDOCK |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 7.2. Бинарное дерево
Бинарное дерево, приведенное на рис. 7.2, упорядочено в алфавитном порядке слева направо(т.е. его вершины расположены в алфавитном порядке их обхода изнутри). Поддерево любой вершины обозначается с помощью указателя. Поиск осуществляется с использованием рекурсивного алгоритма обхода: пересечь левое поддерево,
пройти корень, пересечь правое поддерево. К бинарному дереву всегда можно добавить новую вершину, поместив ее в соответствующее место. Время поиска зависит от глубины дерева.
Расплачиваться за использование бинарного дерева в качестве таблицы символов приходится дополнительным объемом памяти, требуемым для указателей.
8.3. Таблица видов

190
Всовременных языках программирования число видов(абстрактных типов данных) потенциально бесконечно. Естественно, что в этом случае вид нельзя представить целым числом. В этой связи возникает проблема – найти приемлемый (с точки зрения разработчиков компилятора) способ представления любого возможного вида.
Всуществующих языках существует 5-7 вариантов видов:
1)основные виды, например int, real, char, bool и др.;
2)длинные и короткие виды, которые содержат символы long или short, появляющиеся перед основными видами;
3)указатели на адрес ячейки памяти, выделенной для данного вида;
4)структурные виды, типа struct и последовательностью полей; каждое поле имеет вид и селектор, обычно заключенные в скобки;
5)виды массивов;
6)объединенные виды, состоящие из символовunion или void, используемых для выражения значений, которые могут принадлежать нескольким видам;
7)виды процедур, представленные символами procedure, function и др., используемых для выражения значений, являющихся
процедурами.
Естественно было бы представить все виды каким-нибудь одним типом, например, структурой. Для представления вида можно использовать массив или список, причем список более удобен, так как компилятор обычно строит структуру вида слева направо при просмотре программы, и необходимое для представления каждого вида пространство неизвестно, когда встречается его первый символ.
Описатель
proc(real, int) bool,
выражающий значение вида«процедура-с-вещественными-и- целочисленными-параметрами-дающая-логический-результат» может быть представлена структурой с отдельными указателями на список параметров и результат (рис. 7.3).
proc |
|
|
|
Real |
|
|
int |
|
bool
Рис. 7.3. Структура процедуры
Аналогичным образом вид
struct(int(i), struct(int j, bool y), real r)