Синтаксический анализ Владимир Васильевич Романенко, к.т.н., доцент каф.АСУ ТУСУР Введение Основные понятия: Алфавит Σ – множество символов, из которых состоят цепочки символов (предложения) анализируемого языка. Символ – элемент алфавита (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); • q0Q – начальное состояние; • FQ – множество заключительных состояний. Формальное описание КА Способы записи функции переходов: В виде отображения: δ(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; • q0Q – начальное состояние; • FQ – множество заключительных состояний. Формальное описание ДКА Способы записи функции переходов: В виде отображения: δ(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; • q0Q – начальное состояние. Формальное описание ДКА Новые обозначения: • – маркер конца цепочки (должен присутствовать в конце каждой анализируемой цепочки); • 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 = , qF); • 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, ), где qF; такт работы ДКА 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 или qF: 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 или qF. Часто используемые приёмы Приём 7. Итерация конкатенации …e…, …ab…, …abab…, …ababab… и т.д. q a b q' или qF.