- •Теория вычислительных процессов и структур
 - •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. Ошибки, связанные с нарушением ограничений
 
9.3.6. Прикладные реализации
Во время компиляции в соответствии с прикладной реализацией идентификатора, например х в х + 4, необходимо:
найти в таблице символов запись, соответствующую определяющей реализации (int x) идентификатора;
поместить в нижний стек статические характеристики, соответствующие идентификатору.
Подразумевается, что в нижний стек также помещаются статические характеристики констант и т.д.
9.4. Проблемы, связанные с типами
Основной проблемой для трансляторов с языков высокого уровня является приведение (автоматическое изменение) типов. Здесь можно выделить, как минимум, шесть задач.
Распроцедуривание- переход от procedure realкreal.
Разыменование, например переход от pointer realкreal.
Объединение, например переход от realкstrutct(real,char).
Векторизация, например переход от realкreal [ ].
Обобщение, например переход от intкreal.
Чистка, например переход от realкvoid.
Возможность осуществления приведения зависит от синтаксической позиции. Например, в левой части присвоения может иметь место только распроцедуривание (вызов процедур без параметров), а в правой части - любое из шести приведений. Иногда возникает необходимость нескольких приведений. Например, еслих имеет видpointer realиa–pointer int, то прежде чем производить присвоениех=а, необходимо сначала разыменовать, а затем обобщить.
В зависимости от того, какие приведения могут выполняться в синтаксических позициях, последние называются мягкими, слабыми, раскрытыми, крепкими и сильными. Например, левая часть присвоения называется мягкой (допускает только распроцедуривание), а правая часть - сильной (допускает любое приведение). Кроме ограничений типов приведений, разрешаемых в заданной синтаксической позиции, существуют правила, определяющие порядок осуществления различных приведений. Например, объединение может произойти только один раз и не должно следовать за векторизацией. Можно определить грамматику, которая генерирует все допустимые последовательности приведений в заданной синтаксической позиции, например:
SOFT => deprocedure |
deprocedure SOFT
Любое предложение, генерированное посредством SOFT, представляет собой допустимую последовательность приведений в мягкой синтаксической позиции (т.е. в левой части присвоения).
Для раскрытия позиции (например, индекса в a[i]) справедливы следующие правила:
MEEK => deprocedure |
deprocedure MEEK |
dereference |
dereference MEEK.
Другими словами, в раскрытой позиции можно выполнять распроцедуривание и разыменование любое число раз и в любом порядке, например:
pointer procedurepoiter intв видint
Для сильной позиции (например, правая часть присвоения или параметр в вызове процедуры) правила таковы:
STRONG => dereference STRONG |
deprocedure STRONG |
unit |
unit ROW |
widen |
widen widen |
widen ROW |
widen widen ROW |
ROW |
ROW => row |
row ROW
Вид данных до выполнения приведений называется априорным, а после выполнения - апостериорным. В случае сильных и раскрытых синтаксических позиций известны и априорный и апостериорный виды. Для других позиций известен лишь априорный вид и некоторая информация об апостериорном виде, например о том, что он должен начинаться со structилиpointer struct, или о том, что он не должен начинаться сproc, как в левой части присвоения.
Компилятор, применяя соответствующую грамматику, генерирует последовательность приведений из априорного вида к известному либо к подходящему апостериорному виду. Если нельзя найти никакой последовательности приведений, программа синтаксически неправильная.
С другой стороны, если подходящая последовательность существует, компилятор, применяя приведения по порядку, генерирует код времени прогона.
Еще один вид приведения - чистка. Чистка представляет собой особую форму приведения и происходит в тех местах, где стоит точка с запятой
x=y;
Еще одна сложность связана с выбирающим предложением. В предложении
x + if b then 1 else 2.3
во время компиляции необходимо знать тип (вид) правого операнда знака «+». Все варианты выбирающего предложения должны приводить к общему виду, называемому объектным. Этот процесс называется уравнением, и его правила подразумевают, что последовательность сильных приведений можно применять во всех вариантах, кроме одного, в котором используется лишь последовательность приведений, уместных лишь для синтаксической позиции выбирающего предложения. В вышеприведенном примере выбирающее предложение находиться в крепкой синтаксической позиции, которая не допускает расширения. Однако внутри выбирающего предложения один вариант допускает сильное приведение, что может повлечь за собой расширение. В этом случае объектным видом окажется real, и первый вариант следует расширить, а второй нежелательно подвергать приведению.
Действия компилятора при обращении с выбирающими предложениями заключаются в том, что статические характеристики всех вариантов выбирающего предложения помещаются в нижний стек, а затем выводятся объектный вид и различные последовательности приведения для каждого варианта. Если какая-либо последовательность вызывает необходимость генерации кода во время прогона, ее можно выделить в отдельный поток, и между двумя этими потоками ввести указатели, чтобы во время следующего прохода код можно было соединить в нужном порядке.
