
- •Теория вычислительных процессов и структур
- •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. Ошибки, связанные с нарушением ограничений
3.3. Грамматики с ограничениями на правила
Грамматики можно классифицировать по виду их правил: пусть G=(N, Σ, P, S) – грамматика.
Определение.ГрамматикаGназывается:
праволинейной,если каждое правило из Р имеет вид АxB или Аx, где А, В;
контекстно-свободной(илибесконтекстной), если каждое правило из Р имеет вид А, где АN,(N)*;
контекстно-зависимой(илинеукорачивающей), если каждое правило из Р имеет вид..
Грамматика, не удовлетворяющая ни одному из заданных ограничений, называется грамматикой общего вида (грамматика без ограничений).
Рассмотренный ранее пример – множество арифметических выражений, построенных из символов а+ *, является примером контекстно–свободной грамматики.
Заметим, что согласно введённым определениям, каждая праволинейная грамматика – контекстно-свободная грамматика. Контекстно-зависимая грамматика запрещает правило Ае(е– правило).
Соглашение.Если языкLпорождается грамматикой типаx, тоLназывается языком типаx. Это соглашение относится ко всем «типамx».
Определённые нами выше типы грамматик и языков называют иерархией Хомского.
3.4. Распознаватели
Второй распространённый метод, обеспечивающий задание языка конечными средствами, состоит в использовании распознавателей. В сущности, распознаватель – это схематизированный алгоритм, определяющий некоторое множество.
Распознаватель состоит из трёх частей (рис 3.1) - входнойленты,управляющего устройствас конечной памятью ивспомогательнойилирабочей, памяти.
Входную ленту можно рассматривать как линейную последовательность клеток, каждая ячейка которой содержит один символ из некоторого конечного входного алфавита. Самую левую и самую правую ячейки обычно занимают (хотя и необязательно) маркеры.
Входная головка в каждый данный момент читает (обозревает) одну входную ячейку. За один шаг работы распознавателя входная головка может двигаться на одну ячейку влево, оставаться неподвижной, либо двигаться на одну ячейку вправо.
Памятью распознавателя может быть любого типа хранилище информации. Предполагается, что алфавит памяти конечен и хранящаяся в памяти информация построена только из символов этого алфавита. Предполагается также, что в любой момент времени можно конечными средствами описать содержимое и структуру памяти, хотя с течением времени память может становиться сколь угодно большой.
Поведение вспомогательной памяти для заданного класса распознавателей можно охарактеризовать с помощью двух функций: функции доступа и функция преобразования памяти.
Рис. 3.1. Распознаватель
Функция доступа к памяти – это отображение множества возможных состояний или конфигураций памяти в конечное множество информационных символов.
Функция преобразования памяти – это отображения, описывающие её изменения. Вообще, именно тип памяти определяет название распознавателя (распознаватель магазинного типа).
Управляющее устройство – это программа, управляющая поведением распознавателя. Управляющее устройство представляет собой конечное множество состояний вместе с отображением, которое описывает, как меняются состояния в соответствии с текущим входным символом (т.е. находящимся под входной головкой) и текущей информацией, извлечённой из памяти. Управляющее устройство определяет также, в каком направлении сдвинуть головку и какую информацию поместить в память.
Распознаватель работает, проделывая некоторую последовательность шагов или тактов.
В начале такта читается текущий входной символ и с помощью функций доступа исследуется память. Текущий символ и информация, извлечённая из памяти, вместе с текущим состоянием управляющего устройства определяет, каким должен быть такт. Собственно такт состоит из следующих моментов:
входная головка сдвигается на одну ячейку влево, вправо или остаётся в исходном положении;
в памяти помещается некоторая информация;
изменяется состояние управляющего устройства.
Поведение распознавателя обычно описывается в терминах конфигураций распознавателя. Конфигурация – это «мгновенный снимок» распознавателя, на котором изображены:
состояние управляющего устройства;
содержимое входной ленты вместе с положением головки;
содержимое памяти.
Управляющее устройство может быть детерминированным либо недетерминированным.
В детерминированном устройстве для каждой конфигурации существует не более одного возможного следующего шага.
Недетерминированное устройство – это просто удобная математическая абстракция, не реализуемая на практике.
Конфигурация называется начальной, если управляющее устройство находится в начальном состоянии – входная головка обозревает самый левый символ, и память имеет заранее установленное начальное содержимое.
Конфигурация называется заключительной, если управляющее устройство находится в одном из состояний заранее выделенного множества заключительных состояний, а входная головка обозревает правый концевой маркер.
Распознаватель допускает входную цепочку , если, начиная с начальной конфигурации, в которой цепочка записана на входной ленте, распознаватель может проделать конечную последовательность шагов, заканчивающуюся конечной конфигурацией.
Язык, определяемый распознавателем – это множество входных цепочек, которые он допускает.
Для каждого класса грамматик из иерархии Хомского существует естественный класс распознавателей:
язык L праволинейный тогда и только тогда, когда он определяется односторонним детерминирванным конечным автоматом;
язык L – контекстно-свободный тогда и только тогда, когда он определяется односторонним недетерминированным автома-том с магазинной памятью;
язык L контекстно-зависимый тогда и только тогда, когда он определяется двусторонним недетерминированным линейно-ограниченным автоматом;
язык L рекурсивно перечисляемый тогда и только тогда, когда он определяется машиной Тьюринга.