
- •Теория вычислительных процессов и структур
- •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.6. Регулярные множества и конечные автоматы
Ещё одним удобным способом определения регулярных множеств являются конечные автоматы.
Качественное описание конечных автоматов мы сделали в разделе 3.4. Теперь дадим их математическую формулировку.
Определение. Недетерминированный конечный автомат – это пятёрка М = (Q, q0, F),
где Q – конечное множество состояний;
- конечное множество допустимых входных символов;
- отображение множества Q во множество Р(Q), определяющее поведение управляющего устройства, его обычно называют функцией переходов;
q0Q - начальное состояние управляющего устройства;
F Q - множество заключительных состояний.
Работа конечного автомата представляет собой некоторую последовательность шагов (тактов). Такт определяется текущим состоянием управляющего устройства и входным символом, обозреваемым в настоящий момент входной головкой. Сам шаг состоит из изменения состояния и сдвига входной головки на одну ячейку вправо. Для того чтобы определить будущее поведение конечного автомата, нужно знать:
текущее состояние управляющего устройства;
цепочку символов на входной ленте, состоящую из символа под головкой и всех символов, расположенных вправо от него.
Эти два элемента информации дают мгновенное описание конечного автомата, которое называется конфигурацией.
Определение.
Если М = (Q, q0, F) – конечный автомат, то пара (qw)Q называется конфигурацией автомата М.
Конфигурация (qw) называется начальной, а пара (q, е), где qF, называется заключительной.
Такт автомата М представляется бинарным отношением ⊢М, определённым на конфигурациях. Это говорит о том, что, если М находится в состоянии q и входная головка обозревает символ а, то автомат М может делать такт, за который он переходит в состояние q и сдвигает головку на одну ячейку вправо. Так как автомат М, вообще говоря, недетерминирован, могут быть и другие состояния, отличные от q, в он может перейти за один шаг.
Запись С⊢М0С' означает, что С=С', а С0⊢МкСk (для к1) – что существует конфигурация С1,… Ск-1, такая что Сi⊢МСi+1 для всех 0ik. С⊢М+С' означает, что С⊢МкС' для некоторого к0. Таким образом, отношения ⊢М+ и ⊢М* являются транзитивным и рефлексивно-транзитивным замыканием отношения ⊢М.
Говорят, что М допускает цепочку w, если (q,w) ⊢* (q, e) для некоторого qF.
Языком, определяемым автоматом М (L(M)), называется множество входных цепочек, допускаемых автоматом М, т.е.
L(M)={w | w и (q, w) ⊢* (q, e) для некоторого qF}.
Пример 1:
Пусть М = ({p, q, r}, {0, 1}, , p, {r}) конечный автомат, где задаётся в виде таблицы 3.1.
Таблица 3.1 – Таблица состояний конечного автомата
|
Вход | |
0 |
1 | |
Состояние p |
{q} |
{p} |
Q |
{r} |
{p} |
R |
{r} |
{r} |
М допускает все цепочки нулей и единиц, содержащих два стоящих рядом 0. Начальное состояние р можно интерпретировать как «два стоящих рядом нуля ещё не появились и предыдущий символ не был нулём». Состояние q означает, что «два стоящих рядом нуля ещё не появились, но предыдущий символ был нулём». Состояние r означает, что «два стоящих рядом нуля уже появились», т.е. попав в состояние r автомат остаётся в этом состоянии.
Для входа 01001 единственной возможной последовательностью конфигураций, начинающейся конфигурацией (р, 01001), будет
(р, 01001) ⊢ (q, 1001)
⊢(p,001)
⊢(q,01)
⊢ (r,1)
⊢(r, е).
Таким образом 01001L(M).
Пример 2.
Построим
недетерминированный конечный автомат,
допускающий цепочки алфавита
,
у которого последний символ цепочки
уже появлялся раньше. Иными словами 121
допускается, а 31312 – нет. Введем состояние
q0,
смысл которого в том, что автомат в этом
состоянии не пытается ничего распознать
(начальное состояние). Введем состояния
q1,
q2
и
q3,
смысл
которых в том, что они «делают предположение»
о том, что последний символ цепочки
совпадает с индексом состояния. Кроме
того, пусть будет одно заключительное
состояние
qf.
Находясь
в состоянии q0,
автомат может остаться в нем или перейти
в состояние qа,
если а
– очередной символ (табл. 3.2). Находясь
в состоянии qа
автомат может перейти в состояние qf
,
если
видит символ а.
Таблица 3.2 – Таблица состояний конечного автомата
|
Вход | ||
1 |
2 |
3 | |
Состояние q0 q1 q2 q3 qf |
{q0, q1} {q1, qf } {q2} {q3} |
{q0, q2} {q1} {q2, qf } {q3} |
{q0, q3} {q1} {q2} {q3, qf } |
Формально автомат М определяется как пятерка
Часто удобно графическое представление конечного автомата.