Синтаксический анализ Владимир Васильевич Романенко, к.т.н., доцент каф.АСУ ТУСУР

advertisement
Синтаксический анализ
Владимир Васильевич Романенко,
к.т.н., доцент каф.АСУ ТУСУР
Введение
Основные понятия:
 Алфавит Σ – множество символов, из которых
состоят цепочки символов (предложения)
анализируемого языка.
 Символ – элемент алфавита (aΣ).
Примеры:
 Двоичный алфавит Σ = {0, 1}.
 Алфавит русского языка Σ = {а б в … я А Б В … Я 0
1 2 … 9 . , ! ? …} или {а-я А-Я 0-9 . , ! ? …}
Введение
Основные понятия:
 Цепочка α – последовательность из 0 и более
символов алфавита Σ: αΣ*.
 Пустая цепочка – цепочка, состоящая из 0
символов (α = e).
 Цепочка из 1 и более символов – αΣ+.
Пример: пусть Σ = {0, 1}, тогда:
 α = 010Σ+ и α = 010Σ*;
 α = eΣ+ и α = eΣ*;
 α = e1e1e = 11Σ+ и α = e1e1e = 11Σ*.
Введение
Основные понятия:
 Язык L – множество правильных цепочек
(предложений) в алфавите Σ: LΣ* или LΣ+.
Примеры:
 Двоичные числа: Σ = {0, 1},
L=Σ+ = {0, 1, 00, 01, 10, 11, 001, 010, 011, 100, …}.
 Двоичные числа без незначащих нулей: Σ = {0, 1},
LΣ+ = {0, 1, 10, 11, 100, 101, 110, 111, 1000, …}.
Введение
Основные понятия:
 Язык L – множество правильных цепочек
(предложений) в алфавите Σ: LΣ* или LΣ+.
Примеры:
 Русский язык: Σ = {а-я А-Я 0-9 . , ! ? …},
LΣ+ = {мама, папа, я, …}.
 Язык C++: Σ = {_ a-z A-Z 0-9 , ; : # < > ( ) …},
LΣ* = {e, void main() {}, #include <vector>, …}.
Введение
Задачи, решаемые методами синтаксического
анализа:
1. Получение всех правильных цепочек
(предложений) языка, т.е. построение дерева
вывода.
2. Проверка принадлежности цепочки
(предложения) языку (αL или αL).
Введение
Как описать язык L?
 Если язык состоит из конечного числа цепочек
(предложений), то можно просто составить
список всех цепочек (предложений).
Пример: язык булевых констант L = {false, true}.
Пример: двоичные числа от 0 до 255 (байт).
 Если число цепочек (предложений) бесконечно,
то требуются специальные средства описания
языков.
Введение
Конечные
автоматы
Способы
описания
языков
Регулярные
выражения
Грамматики
Введение
Конечные
автоматы
Способы
описания
языков
Регулярные
выражения
Грамматики
Конечные автоматы
Классификация КА
Конечный автомат (КА)
Недетерминированный
конечный автомат
(НКА)
Детерминированный
конечный автомат
(ДКА)
ДКА с магазинной
памятью (ДМПА)
Формальное описание КА
Конечный автомат (КА):
M = (Q, Σ, δ, q0, F),
где
• Q – конечное множество состояний;
• Σ – конечное множество входных символов
(алфавит);
• δ – функция переходов, отображение множества
QΣ во множество P(Q);
• q0Q – начальное состояние;
• FQ – множество заключительных состояний.
Формальное описание КА
Способы записи функции переходов:
 В виде отображения:
δ(q0, x) = {q1}, δ(q0, y) = {q1, q2}, …
 В виде множества:
δ = {((q0, x), {q1}), ((q0, y), {q1, q2}), …}
 В виде графа:
q2
y
x
q0
q1
y
Формальное описание КА
Способы записи функции переходов:
 В виде таблицы:
x
y
q0
{q1}
{q1, q2}
q1
{}
{}
q2
{}
{}
В детерминированном автомате #δ(q, a) ≤ 1.
Данный автомат недетерминирован, т.к.
#δ(q0, y) = #{q1, q2} = 2.
Формальное описание ДКА
Детерминированный конечный автомат (ДКА):
M = (Q, Σ, δ, q0, F),
где
• Q – конечное множество состояний;
• Σ – конечное множество входных символов
(алфавит);
• δ – функция переходов, отображение множества
QΣ во множество Q;
• q0Q – начальное состояние;
• FQ – множество заключительных состояний.
Формальное описание ДКА
Способы записи функции переходов:
 В виде отображения:
δ(q0, x) = q1, δ(q0, y) = q2, …
 В виде множества:
δ = {((q0, x), q1), ((q0, y), q2), …}
 В виде графа:
q2
y
q0
x
q1
Формальное описание ДКА
Способы записи функции переходов:
 В виде таблицы:
x
y
q0
q1
q2
q1
ERROR
ERROR
q2
ERROR
ERROR
ERROR – специальный символ ошибки
синтаксического анализа (в функции переходов его
можно не указывать).
Формальное описание ДКА
Сокращенный вариант записи:
M = (Q, Σ, δ, q0),
где
• Q – конечное множество состояний;
• Σ – конечное множество входных символов
(алфавит);
• δ – функция переходов, отображение множества
Q(Σ{}) во множество Q;
• q0Q – начальное состояние.
Формальное описание ДКА
Новые обозначения:
•  – маркер конца цепочки (должен
присутствовать в конце каждой анализируемой
цепочки);
• HALT – специальный символ, означает успешное
завершение разбора.
q
Формальное описание ДКА
Таблица переходов ДКА:
a1
a2
…

q0
δ(q0, a1)
δ(q0, a2)
…
δ(q0, )
q1
δ(q1, a1)
δ(q1, a2)
…
δ(q1, )
q2
δ(q2, a1)
δ(q2, a2)
…
δ(q2, )
…
…
…
…
…
δ(q, a) :
• q';
• HALT (a = , qF);
• ERROR.
Пример описания ДКА
Пусть язык описывает двоичные числа без
незначащих нулей. Тогда:
• Q = {q0, q1, q2};
• Σ = {0, 1};
• δ = {((q0, 0), q1), ((q0, 1), q2), ((q1, 0), ERROR),
((q1, 1), ERROR), ((q2, 0), q2), ((q2, 1), q2)};
• q0 = q0.
• F = {q1, q2}.
Т.е. M = ({q0, q1, q2}, {0, 1}, {((q0, 0), q1), ((q0, 1), q2),
((q2, 0), q2), ((q2, 1), q2)}, q0, {q1, q2})
Пример описания ДКА
Или:
• Q = {q0, q1, q2};
• Σ = {0, 1};
• δ = {((q0, 0), q1), ((q0, 1), q2), ((q0, ), ERROR),
((q1, 0), ERROR), ((q1, 1), ERROR), ((q1, ), HALT),
((q2, 0), q2), ((q2, 1), q2), ((q2, ), HALT)};
• q0 = q0.
Т.е. M = ({q0, q1, q2}, {0, 1}, {((q0, 0), q1),
((q0, 1), q2), ((q1, ), HALT), ((q2, 0), q2),
((q2, 1), q2), ((q2, ), HALT), q0)
Пример описания ДКА
Функция переходов в виде графа:
0
q0
1
0
q1
1
q2
Функция переходов в виде таблицы:
0
1

q0
q1
q2
ERROR
q1
ERROR
ERROR
HALT
q2
q2
q2
HALT
Пример описания ДКА
Состояниям можно давать любые имена:
0
1

start
zero
non-zero
ERROR
zero
ERROR
ERROR
HALT
non-zero
non-zero
non-zero
HALT
Тогда:
 Q = {start, zero, non-zero};
 q0 = start;
 и т.д.
Проверка ДКА
Как проверить, что ДКА описан правильно?
1. Построить дерево вывода. Если дерево
содержит все правильные цепочки языка, и не
содержит неправильные цепочки, то автомат
описан правильно.
2. Осуществить запуск ДКА. Если для всех
правильных цепочек разбор окончится
символом HALT, а всех неправильных –
символом ERROR, то автомат описан
правильно.
Дерево вывода ДКА
0
q0
1
0
q1
1
q2
q0
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
1 q2
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
0
1 q2
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
0
1 q2
10 q2
11 q2
1
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
1 q2
0
10 q2
11 q2
100 q2
101 q2
10
1
Дерево вывода ДКА
0
q0
1
0
q1
q0
1
q2
0 q1
0
1 q2
10 q2
11 q2
1
110 q2
111 q2
11
Запуск ДКА
Основные понятия:
 конфигурация ДКА M
(q, α)QΣ*;
 начальная конфигурация – (q0, α), где αΣ*;
 заключительная конфигурация – (q, ), где qF;
 такт работы ДКА M при δ(q, a) = q', где q, q'Q,
aΣ{}:
(q, aα) (q', α)
Запуск ДКА
0
q0
1
0
q1
1
q2
 Для правильной цепочки:
(q0, «110») 1 (q2, «10»)
2 (q , «0»)
(q0, «110») •
2
3 (q , «»)
(q0, «110») •
2
4 HALT
(q0, «110») •
 Для неправильной цепочки:
(q0, «010») 1 (q1, «10»)
2 ERROR
(q0, «010») •
Алгоритм работы ДКА
Пусть α = a1a2…an – входная цепочка. Тогда:
1. q  q0, k  1.
2. Ищем δ(q, a), где a = ak.
3. Если δ(q, a) не определена, то ошибка в позиции k. Если
значений δ(q, a) несколько – таблица переходов построена
неверно. Если δ(q, a) = q', то:
3.1. q  q'.
3.2. k  k + 1.
4. Если δ(q, a) = HALT, то разбор успешно завершен.
5. Если δ(q, a) = ERROR, то имеем во входной цепочке
синтаксическую ошибку в позиции k.
6. Иначе возврат на шаг 2.
Минимизация ДКА
Цель минимизации – избавиться от лишних
состояний, которые дублируют друг друга.
Минимизация ДКА
Цель минимизации – избавиться от лишних
состояний, которые дублируют друг друга.
Способ 1. Сравним два состояния qi и qj. Поведение
автомата в этих двух состояниях идентично, если:
 Функция переходов для этих состояний дает
одинаковый результат:
δ(qi, a) = δ(qj, a) aΣ;
 Оба состояния являются конечными, либо оба не
являются таковыми:
qi, qj F или qi, qj F.
Минимизация ДКА
Пример 1.
0
q0
1
q2
1
1
q4
1
0
0
q1
q3
0
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4
HALT
q3
q3
q4
HALT
q4
q3
q4
HALT
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4
HALT
q3
q3
q4
HALT
q4
q3
q4
HALT
 q3 = q4
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4 q3
HALT
q3
q3
q4 q3
HALT
q4
q3
q4
HALT
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3
q3
HALT
q3
q3
q3
HALT
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3
q3
HALT
q3
q3
q3
HALT
 q2 = q3
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1

HALT
q2
q3 q2
q3 q2
HALT
q3
q3
q3
HALT
Минимизация ДКА
Пример 1.
q0
0
1
q1
q2
q1
q2

HALT
q2
q2
HALT
Минимизация ДКА
Пример 2.
0
q0
1
q2
q1
1
1
0
0
q4
0
q3
1
Минимизация ДКА
Пример 2.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4
HALT
q3
q3
q3
HALT
q4
q4
q4
HALT
Минимизация ДКА
Способ 2. Сравним два состояния qi и qj. Поведение
автомата в этих двух состояниях идентично, если:
 Функция переходов для этих состояний дает
одинаковый результат:
δ'(qi, a) = δ'(qj, a) aΣ.
Здесь δ'(q, a) = q', если q = qi или q = qj, в
противном случае δ'(q, a) = δ(q, a).
 Оба состояния являются конечными, либо оба не
являются таковыми:
qi, qj F или qi, qj F.
Минимизация ДКА
Пример 2.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4
HALT
q3
q'
q'
HALT
q4
q'
q'
HALT
 q3 = q4
Минимизация ДКА
Пример 2.
q0
0
1
q1
q2
q1

HALT
q2
q3
q4 q3
HALT
q3
q3
q3
HALT
q4
q'
q'
HALT
Определение функции переходов
1. Построить граф переходов, а потом преобразовать его в таблицу
переходов.
2. Построение графа начинается с начального состояния q0. Если
начальное состояние может являться также и конечным (т.е. язык
допускает пустые предложения), помечаем его двойной границей.
3. Для каждого состояния графа qi определяем, есть ли из данного
состояния такие переходы, которые соответствуют допустимому
символу a из входной цепочки, которые пока еще отсутствуют в
графе. Если есть, то проверяем, ведет ли данный переход в уже
имеющееся состояние qj. Если да, то добавляем в граф только
новый переход δ(qi, a) = qj. Если нет, то добавляем в граф новое
состояние qk и переход в него δ(qi, a) = qk. Если новое состояние
может являться конечным, помечаем его двойной границей.
4. Если в процессе выполнения шага 3 в графе появились новые
состояния или переходы, возвращаемся на шаг 3, иначе граф
переходов построен.
Определение функции переходов
Пример. Рассмотрим язык L, описывающий число
с фиксированной точкой. Такое число может
начинаться со знака «+» или «–», далее следует
мантисса числа. Разные языки программирования
допускают различные формы записи мантиссы, в
общем случае они могут быть следующими: «N.M»,
«N.», «.M», «N», где N – целая, а M – дробная
часть числа. Оба числа N и M имеют одинаковый
формат – это последовательность из одной и более
цифр в диапазоне от 0 до 9.
Определение функции переходов
q0
Определение функции переходов
2
1
0
3 4 5 6
q0
+ –
.
7
8
9
Определение функции переходов
0-9
.
q0
+, –
Определение функции переходов
0-9
.
q0
+, –
q1
Определение функции переходов
0-9
.
q0
+, –
q1
q2
Определение функции переходов
q3
0-9
.
q0
+, –
q1
q2
Определение функции переходов
q3
0-9
q2
.
q0
+, –
q1
.
Определение функции переходов
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Определение функции переходов
q4
0-9
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Определение функции переходов
q4
0-9
0-9
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Определение функции переходов
q5
q4
.
0-9
0-9
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Определение функции переходов
q5
0-9
q4
.
0-9
0-9
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Определение функции переходов
0-9
q5
0-9
q4
.
0-9
0-9
q3
0-9
q2
.
q0
0-9
+, –
q1
.
Ввод диапазонов:
+
–
.
0
1
2
3
4
5
6
7
8
q0
…
qn
+, –
q0
…
qn
.
0-9

9

Ввод диапазонов:
Σ1
Σ2
…
q0
…
qn
ΣiΣ, i = 1, 2, …, m;
ΣiΣj = , i  j;
Σ1Σ2…Σm = Σ.
Σm

Определение функции переходов
Табличное представление функции переходов:
q0
q1
+, –
.
0-9
q1
q2
q3
q2
q3
q2
q3
q4
q5
q3
q4
q4
q5
q5

HALT
Определение функции переходов
Минимизация ДКА:
q0
q1
+, –
.
0-9
q1
q2
q3
q2
q3
q2
q3
q4
q4
q4
q3
q4

HALT
Определение функции переходов
Результат:
q0
q1
+, –
.
0-9
q1
q2
q3
q2
q3
q2
q3
q4
q4
q4

HALT
q3
q4
Алфавит языка Σ = {+, –, ., 0, 1, 2, 3, 4, 5, 6, 7, 8, 9} =
{+, –, ., 0-9}.
Использование диапазонов
Пример. Язык L описывает десятичные числа в
диапазоне от 0 до 255, без ведущих нулей.
Алфавит языка Σ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} = {0-9}.
Использование диапазонов
0
q1
q0
1
3-9
2
q2
q11
0-9
0-4
5
q3
q6
0-9
0-5
q4
q9
6-9
q10
q8
0-9
q7
0-9
q5
q12
Использование диапазонов
Σ1 = {0}
Σ2 = {1}
Σ3 = {2}
Σ4 = {3-4}
Σ5 = {5}
Σ6 = {6-9}
0
q1
q0
1
3-9
2
q2
q11
0-9
0-4
5
q3
q6
0-9
0-5
q4
q9
6-9
q10
q8
0-9
q7
0-9
q5
q12
Использование диапазонов
Пример. Язык L описывает десятичные числа в
диапазоне от 0 до 255, без ведущих нулей.
Алфавит языка Σ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} = {0-9}.
Σ1 = {0}, Σ2 = {1}, Σ3 = {2}, Σ4 = {3-4},
Σ5 = {5}, Σ6 = {6-9}
Σ1Σ2Σ3Σ4Σ5Σ6 = {0-9} = Σ.
0
q0
…
q12
1
2
3-4
5
6-9

Часто используемые приёмы
Приём 1. Конкатенация
…ab…
q
a
q'
Приём 2. Объединение
…a… или …b…
a
q
b
b
Часто используемые приёмы
Приём 3. Итерация
…e…, …a…, …aa…, …aaa… и т.д.
a
q
или qF:
a
q
Часто используемые приёмы
Приём 4. Положительная итерация
…a…, …aa…, …aaa… и т.д.
a
q
a
q'
или q'F:
a
q
a
q'
Часто используемые приёмы
Приём 5. Конкатенация с итерацией
…b…, …ba…, …baa… и т.д.
a
q
b
q'
или q'F;
…b…, …ab…, …aab… и т.д.
a
q
b
Часто используемые приёмы
Приём 6. Итерация объединения
…e…, …a…, …b…, …aa…, …ab…, …ba…, …bb… и т.д.
a
q
b
или qF.
Часто используемые приёмы
Приём 7. Итерация конкатенации
…e…, …ab…, …abab…, …ababab… и т.д.
q
a
b
q'
или qF.
Download