
- •Отчет по лабораторной работе №1
- •Описание набора команд, переменных, их типов:
- •Часть 2: Результат аналитического задания («Регулярные выражения»).
- •Недетерминированные конечные автоматы.
- •Детерминированные конечные автоматы.
- •Построение нка по регулярному выражению
- •Преобразование нка в дка.
- •Часть 3: Описание архитектуры разработанного компилятора.
- •Часть 4: Примеры работы компилятора.
Часть 2: Результат аналитического задания («Регулярные выражения»).
Конечный автомат – это математическая модель, которая задается множествами состояний Q, входных символов , функций переходов , начальное состояние , и конечных состояний Z.
Распознавателем (recognizer) языка называется программа, которая получает на вход строку х и отвечает "да", если х — предложение языка, или в противном случае "нет". Мы компилируем регулярное выражение в распознаватель путем построения обобщенной диаграммы переходов, называемой конечным автоматом.
Такой автомат может быть двух видов: детерминированный и недетерминированный. И тот и другой вид конечного автомата может распознавать точные регулярные выражения. То есть они могут распознавать все, что могут обозначать регулярные выражения. Детерминированные конечные автоматы (ДКА) распознают значительно быстрее, хотя значительно больше эквивалентных недетерминированных (НКА).
Недетерминированные конечные автоматы.
НКА представляет собой математическую модель, которая состоит из:
множества состояний S;
множества входных символов (символы входного алфавита);
функций переходов , каждая из которых отображает пары символ-состояние на множество состояний;
состояния - начальное состояние;
множества конечных состояний Z.
Для изображения НКА можно использовать помеченный ориентированный граф переходов. Узлы этого графа – состояния, а дуги – функции переходов. Этот граф будет похож на диаграмму переходов, но один символ может помечать два и более переходов из одного состояния, а некоторые переходы могут быть помечены символом ε, как обычным входным символом.
Граф переходов для языка (a|b)*a(a|b)(a|b) представлен на рисунке 1.
Рисунок 1. Граф НКА для языка (a|b)*a(a|b)(a|b).
Входной алфавит данного языка – {a, b}, состояния НКА – {0, 1, 2, 3}. 0 – начальное состояние, 3 – конечное, представлено двойным кружком.
Недетерминированный конечный автомат M, допускающий данный язык:
M = {{0, 1, 2, 3}, {a, b}, D, 0, {3}}.
Функция переходов D определяется так:
-
D(0, a) = {0, 1},
D(1, b) = {2},
D(0, b) = {0},
D(2, b) = {3},
D(1, a) = {2},
D(2, a) = {3}
Эту же функцию можно представить в виде таблицы:
Состояние |
Входной символ | |
a |
b | |
0 1 2
|
{0, 1} {2} {3} |
{0} {2} {3} |
Такое представление обеспечивает быстрый доступ к переходам из одного состояния по конкретному символу в другое. Однако такая таблица занимает много место (особенно если большой алфавит и есть множество пустых переходов). Представление в виде списка более компактно, но замедляет доступ к переходам. Оба представления с легкостью преобразуются друг в друга.
НКА принимает входную строку х только если в графе переходов существует путь из начального состояния к какому-либо из заключительных, соответствующий строке х.
Стоит заметить также, что в заключительное состояние может приводить более чем одна последовательность перемещений. Начальное состояние может быть и конечным. Язык, определяемый НКА, представляет собой множество допускаемых им входных строк. Например, НКА на рисунке 2 допускает строки ab*|ba*.
Рисунок 2. НКА, допускающий строки ab*|ba*.
Такой НКА допускает, например, строчку abb перемещениями по состояниям 0, 1, 2, 2. Метками соответствующих дуг являются ε, а, а, b. Стоит заметить что ε-переход не влияет на строчку, то есть символ ε в строке отсутствует.