
- •Теория вычислительных процессов и структур
- •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. Ошибки, связанные с нарушением ограничений
7.3. Таблица видов
В современных языках программирования число видов (абстрактных типов данных) потенциально бесконечно. Естественно, что в этом случае вид нельзя представить целым числом. В этой связи возникает проблема – найти приемлемый (с точки зрения разработчиков компилятора) способ представления любого возможного вида.
В существующих языках существует 5-7 вариантов видов:
основные виды, напримерint, real, char, bool и др.;
длинные и короткие виды, которые содержат символыlong илиshort, появляющиеся перед основными видами;
указателина адрес ячейки памяти, выделенной для данного вида;
структурныевиды, типаstruct и последовательностью полей; каждое поле имеет вид и селектор, обычно заключенные в скобки;
виды массивов;
объединенные виды, состоящие из символовunionилиvoid, используемых для выражения значений, которые могут принадлежать нескольким видам;
виды процедур, представленные символамиprocedure, function и др., используемых для выражения значений, являющихся процедурами.
Естественно было бы представить все виды каким-нибудь одним типом, например, структурой. Для представления вида можно использовать массив или список, причем список более удобен, так как компилятор обычно строит структуру вида слева направо при просмотре программы, и необходимое для представления каждого вида пространство неизвестно, когда встречается его первый символ.
Описатель
proc(real, int) bool,
выражающий значение вида «процедура-с-вещественными-и-целочисленными-параметрами-дающая-логический-результат» может быть представлена структурой с отдельными указателями на список параметров и результат (рис. 7.3).
|
|
|
|
Real |
|
|
int |
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
|
|
|
|
Рис. 7.3. Структура процедуры
Аналогичным образом вид
struct(int(i), struct(int j, bool y), real r)
может быть представлен так, как показано на рис. 7.4.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
i |
|
|
struct |
|
|
|
real |
r |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int |
J |
|
|
bool |
y |
|
Рис 7.4. Структура типа struct
Каждая ячейка имеет два (возможно пустых) указателя; вертикальный указатель используется в случае структурных, объединенных и процедурных видов.
С помощью рассмотренного метода представления видов компилятор может легко выполнять следующие операции:
нахождение вида результата процедуры;
выбор структуры поля;
разыменование значения, т.е. замену адреса значением в адресе;
векторизацию, т.е. построение линейной структуры для любого массива.
Контрольные вопросы
Понятие прохода компилятора, необходимость использования нескольких проходов при компиляции.
Назначение таблицы символов.
Методы организации таблицы символов.
Хеширование, разрешение конфликтов при хешировании.
Сцепление элементов и бинарное дерево.
Назначение таблицы видов.
Способы организации таблицы видов.