CodeNet / Приложения / Алгоритмы / Разбор выражений. Компиляторы и интерпретаторы. / Основы компиляции
Иерархия Хомского. Регулярные языки.
Классификация грамматик по сложности соответствующих прог-
рамм-распознавателей называется иерархией Хомского. В ней выде-
лены 4 класса грамматик (в порядке возрастания сложности):
а) регулярные (или автоматные). Правила имеют вид:
A : xB или A : x, где x - цепочка терминалов или e
Примеры - упражнение.
б) контекстно-свободные (или КС). Правила имеют вид:
A : y, где y - цепочка из терминалов и нетерминалов
Примеры - "скобочный язык" из предыдущей лекции,
язык арифметических формул
в) контекстно-зависимые (неукорачивающие). Правила имеют
вид :
z : y, где z и y - цепочки из терминалов и нетерми-
налов, z содержит нетерминал, |z| <= |y|
n n n
Пример: a b c
г) без ограничений
Класс языка определяется классом самой простой (в смысле
иерархии Хомского) из описывающих его грамматик. Следующие вло-
жения для классов языков очевидны, если не рассматривать
КС-грамматики, содержащие так называемые e-правила - правила с
пустой правой частью. (Упражнение: показать, что любой КС-язык
может быть описан грамматикой без e-правил).
а < б < в < рекурсивные множества < г = рек.перечислимые мн-ва
Для языка, определенного регулярной грамматикой, всегда мож-
но написать контекстно-свободную грамматику (и даже грамматику
без ограничений!). Тем не менее, все вложения строгие: в каждом
классе существуют языки, которые нельзя задать грамматиками бо-
лее простого класса.
Конечные автоматы
Рассмотрим другой способ задания регулярных языков. (Неде-
терминированный) конечный автомат задается:
- алфавитом входных символов E;
- множеством состояний S;
- тернарным отношением переходов на множестве { S, E U e, S };
- начальным состоянием - выделенным состоянием в S, и
- конечными состояниями - непустым подмножеством S.
Принято изображать автомат в виде ориентированного графа, узлы
которого соответствуют состояниям (конечные состояния мы будем
заключать в двойную рамку), а ребра, помеченные символами вход-
ного алфавита или е, изображают отношение переходов.
Цепочка допускается автоматом если и только если существует
пусть из начального в одно из конечных состояний, такой что,
прочитав метки ребер вдоль этого пути, мы получим исходную це-
почку (буква e, естественно, не читается). Например, автомат
--------¬ 0 --------¬ 1 -T-----T¬
¦ S +-->--+ B +-->--+¦ C ¦¦
L-------- L---T---- L+--T--+-
L------<-------0
допускает цепочки (01)+. Этот язык можно описать регулярной
грамматикой:
S : 0 B B : 1 C C : 0 B C : e
Несложно показать (упражнение), что для каждого автомата
можно построить регулярную грамматику, описывающую тот же самый
язык, и наоборот.
Детерминированный конечный автомат - частный случай неде-
терминированного, в котором:
- нет e-переходов,
- отношение переходов является однозначной функцией
f:( S x E U e ) -> S,
определенной, может быть, не для всех пар из SxEUe. В терминах
графа это означает, что из одного состояния выходит не более
одного ребра с одинаковой меткой.
Для детерминированного автомата очень просто проверять при-
надлежность цепочки из E* языку. Добавив, если нужно, еще одно
"тупиковое" состояние, можно сделать функцию переходов опреде-
ленной на всех парах из S x E.
----T------¬
¦ ¦ 0 1 ¦ s := начальное состояние
+---+------+ цикл для каждого символа цепочки c выполнить
¦ S ¦ B F ¦ . s := f( s, c )
¦ B ¦ F C ¦ конец цикла
¦ C ¦ B F ¦ ответ := s - конечное состояние
¦ F ¦ F F ¦
L---+-------
Такая интерпретация детерминированного конечного автомата
более наглядна и общепринята: KA - устройство, которое может
находится в конечном множестве состояний и переходит из одного
состояния в другоe под действием внешних событий из алфавита E.
Можно ли подобным образом интерпретировать недетерминирован-
ный автомат (или хотя бы эффективно определять принадлежность
цепочки языку)? Да, можно считать, что в том случае, когда воз-
можен более чем один переход, создается необходимое число эк-
земпляров КА, которые переводятся во все возможные в этой ситу-
ации состояния. Цепочка считается допущенной, если хотя бы один
из экземпляров оказался в конечном состоянии.
-<--------------------------¬0
----+---¬ 0 --------¬ 1 -T--+--T¬
¦ S +-->--+ B +-->--+¦ C ¦¦
L-------- L---T---- L+--T--+-
L<-------------0
Какие цепочки допускает этот автомат? - упражнение.
Заметим, что если несколько экземпляров недетерминированного
КА оказались в одном состоянии, то в дальнейшем можно рассмат-
ривать только один из них. Таким образом, максимальное коли-
чество экземпляров не превосходит числа состояний.
Проверить, допускает ли недетерминированный конечный автомат
цепочку символов, также несложно:
S := e-замыкание( { начальное состояние } )
цикл для каждого символа цепочки c выполнить
. S := e-замыкание( F( S, c ) )
конец цикла
ответ := ( S П конечные состояния ) - непусто
Здесь: S - подмножество множества состояний KA;
e-замыкание( S ) - множество состояний, достижимых из S
за 0 и более e-переходов;
F( S, c ) - множество состояний, достижимых из S
за один переход, помеченный символом c.
Упражнение по программированию: придумайте структуры данных
для представления детерминированного и недетерминированного ко-
нечных автоматов и запрограммируйте проверку допуска строки из
символов ASCII KA. Это можно (и следует) делать за время
- O(длина цепочки) для детерминированного и
- O(длина цепочки*число состояний) для недетерминированного КА.
Преобразование недетерминированного КА в детерминированный
Недетерминированный КА всегда можно преобразовать в эквива-
лентный (т.е. допускающий то же множество цепочек) детерминиро-
ванный КА. Рассмотрим новый КА, состояниями которого будут под-
множества множества состояний исходного КА (если исходный авто-
мат имел m состояний, сколько их будет у нового? - упражнение).
Исходным для нового автомата будет состояние {Начало}, конечны-
ми - все состояния, содержащие исходное конечное состояние. Пе-
реход A -> B по символу d имеется в новом автомате тогда и
только тогда, когда в исходном автомате для любого состояния b
из B, существует a из A такое, что по символу d возможен пере-
ход a -> b, и других переходов по d из A нет. Новый автомат бу-
дет детерминированным и эквивалентным исходному.
Действительно, состояние нового автомата a+b соответствуют
размещению экземпляров исходного недетерминированного КА в сос-
тояниях a и b, а переход в новом автомате соответствует перехо-
дам всех экземпляров недетерминированного КА.
Для практических целей применяется аналогичный алгоритм: На-
зовем состояния неразличимыми, если в них происходит переход из
одного и того же состояния при одном и том же входном символе.
Возьмем любое множество неразличимых состояний и добавим в спи-
сок состояний КА еще одно - их "сумму", перемещая переходы:
Было: ¦ Стало:
--¬1 --¬0 --¬ ¦ --¬1 ----¬0
¦ +->+Б+->+В¦ ¦ ¦ +->+Б+Г+>T->¬
¦А¦ L-- L-- ¦ ¦А¦ L---- ¦ ¦
¦ ¦1 --¬0 --¬ ¦ ¦ ¦ --¬0 -+¬ ¦
¦ +->+Г+->+Д¦ ¦ ¦ ¦ ¦Б+->+В¦ ¦
L-- LT- L-- ¦ L-- L-- L-- ¦
--¬1 ¦ ¦ --¬1 --¬0 -+¬
¦Е+->-- ¦ ¦Е+->+Г+->---+Д¦
L-- ¦ L-- L-- L--
Получим новый (быть может, вновь недетерминированный) КА. Будем
повторять наши действия, пока в КА остаются неразличимые состо-
яния. Этот процесс в конце концов завершится (почему? - упраж-
нение). При этом мы получим детерминированный автомат, эквива-
лентный исходному (почему? - упражнение).
Применив этот метод к недетерминированному КА из примера в
этой лекции, получим:
--<----------¬ 1
--------¬ 0 --------¬ 1 -T--+--T¬0 -----+----¬
¦ S +->--+ B +->--+¦ C ¦+-->+ S + B ¦
L-------- L---T---- L+-----+- L----T-----
L--<----------------------- 0
Минимизация конечного автомата
По конечному автомату часто можно построить автомат с мень-
шим числом состояний, эквивалентный исходному. Соответствующий
процесс называется минимизацией конечного автомата. Вначале
выбросим из автомата все состояния, недостижимые из начального.
Затем разобьем все состояния КА на классы эквивалентности сле-
дующим способом: в первый класс отнесем все конечные состояния,
а во второй - все остальные. Назовем эти состояния 0-эквива-
лентными. Теперь построим новое 1-эквивалентное разбиение, вы-
делив те состояния, которые по одинаковым символам переходят в
0-эквивалентные состояния. Последовательно строя n+1-эквива-
лентные состояния по n-эквивалентным, мы будем увеличивать чис-
ло классов эквивалентности. Прекратим этот процесс тогда, когда
n+1-эквивалентное состояние совпадет с n-эквивалентным. Каждый
полученный класс эквивалентности и будет состоянием нового ми-
нимизированного КА, эквивалентного исходному (почему? - упраж-
нение).
Рассмотрим, например, следующий КА:
--------¬1 -T-----T¬ 0--------¬
-------¬0->+ B +->--+¦ D ¦+<-+ F ¦
¦Начало+-- L-T------ -++---T-+- L---T-T--
¦ ¦ ¦ --<-----0 -->- ¦1 -->- ¦1
¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦
¦ ¦ L<-+------¬0 ¦1 -<- ¦0 -<-
¦ A +-¬ -----+--¬1 LTT+--+-T¬ 1-+--+---¬
L-------1L>+ C +->--+¦ E ¦¦<-+ G ¦
L-------- L+-----+- L--------
Состояния F и G недостижимы (это можно выяснить, например, вы-
числив транзитивное замыкание отношения "есть переход"). Пос-
троим классы n-эквивалентности для оставшихся состояний:
n Классы
0 (ABC) (DE)
1 (A) (BC) (DE)
2 (A) (BC) (DE)
Результат:
------¬0,1 ------¬1 -T---T¬
¦ A +---->+ B+C +---->+¦D+E¦¦
L------ L--T--- L+-T-+-
L-<----------0
Упражнение: докажите, что для любого КА существует и
единственен с точностью до изоморфизма минимальный эквива-
лентный ему конечный автомат. Покажите, что описанный выше ал-
горитм минимизации получает на выходе минимальный автомат.
Упражнение по программированию: придумайте структуры данных
и запрограммируйте процедуры построения детерминированного КА,
и минимизации КА. Какая временная и пространственная сложность
предложенных вами алгоритмов в терминах числа состояний исход-
ного и выходного автоматов?
Регулярные языки и регулярные выражения
Рассмотрим специальный класс операций над языками - регуляр-
ные операции, множество языков, получаемое в результате приме-
нения конечного числа регулярных операций из элементарных язы-
ков, - регулярные множества, способ их описания - регулярные
выражения и недетерминированные конечные автоматы, допускающие
цепочки из этих множеств.
---------------------T-----------T----------------------------¬
¦ Регулярное ¦Регулярное ¦ Конечный автомат ¦
¦ множество ¦ выражение ¦ ¦
+--------------------+-----------+----------------------------+
¦ Пустая цепочка ¦ e ¦ ------¬ e -T---T¬ ¦
¦ ¦ ¦ ¦ S +--->---+¦ E ¦¦ ¦
¦ ¦ ¦ L------ L+---+- ¦
+--------------------+-----------+----------------------------+
¦ Один символ a из E ¦ a ¦ ------¬ а -T---T¬ ¦
¦ ¦ ¦ ¦ S +--->---+¦ E ¦¦ ¦
¦ ¦ ¦ L------ L+---+- ¦
+--------------------+-----------+----------------------------+
¦ ¦ ¦ ----¬ e --T-----T-¬ e -T-T¬¦
¦ P U Q ¦ p|q ¦ ¦ +->-+s¦Авт.P¦e+->-+¦ ¦¦¦
¦ ¦ ¦ ¦ S ¦ L-+-----+-- ¦¦E¦¦¦
¦ ¦ ¦ ¦ ¦ e --T-----T-¬ e ¦¦ ¦¦¦
¦ ¦ ¦ ¦ +->-+s¦Авт.Q¦e+->-+¦ ¦¦¦
¦ ¦ ¦ L---- L-+-----+-- L+-+-¦
+--------------------+-----------+----------------------------+
¦ PQ (конкатенация) ¦ pq ¦ ----T-----T----T-----TT-T¬ ¦
¦ ¦ ¦ ¦ S ¦Авт.P¦ es ¦Авт.Q¦¦Е¦¦ ¦
¦ ¦ ¦ L---+-----+----+-----++-+- ¦
+--------------------+-----------+----------------------------+
¦ P* (итерация) ¦ p* ¦ ---<----¬e ¦
¦ ¦ ¦ ----¬ e -+T-----T+¬ e -T-T¬¦
¦ ¦ ¦ ¦ S +->-+s¦Авт.P¦e+->-+¦E¦¦¦
¦ ¦ ¦ L-T-- L-+-----+-- L+T+-¦
¦ ¦ ¦ eL---------->----------- ¦
+--------------------+-----------+----------------------------+
¦ P (просто скобки)¦ (p) ¦ ------T-------TT---T¬ ¦
¦ ¦ ¦ ¦ S ¦ Авт.P ¦¦ E ¦¦ ¦
¦ ¦ ¦ L-----+-------++---+- ¦
L--------------------+-----------+-----------------------------
В регулярном выражении "*" имеет больший приоритет, чем кон-
катенация, а конкатенация - больший чем "|". Примеры регулярных
выражений: (0|1)*, (0|1)(0|1)*. Какие множества они описывают?
Для регулярного выражения предложен способ построения неде-
терминированного конечного автомата, допускающего соответству-
ющее выражению регулярное множество. Предложенная конструкция
не является самой экономной (автомат обычно содержит много
"лишних" e-переходов), однако построенный автомат обладает
следующими полезными свойствами:
- у него только одно конечное состояние,
- в начальное состояние не входит ни одно ребро,
- из конечного состояния не выходит ни одно ребро.
Таким образом, мы доказали, что регулярные множества < регу-
лярные языки = языки, допускаемые КА. Покажем, что допускаемое
КА множество - регулярно. (Это утверждение называется теоремой
Клини).
Доказательство: Пусть S1,...Sn - состояния детерминированно-
го КА, S1 - начальное состояние. Рассмотрим все пути в графе
переходов с началов в Si, концом в Sj, промежуточными узлами из
множества {S1...Sk} (1<=i<=n, 1<=j<=n, 0<=k<=n) и множества це-
почек из E - L(i,j,k), соответствующие этим путям. Докажем ин-
дукцией по k, что множества L - регулярны.
L(i,j,0) - состоит из меток ребер, ведущих из Si в Sj, сле-
довательно, регулярно.
Для 0<=k<=n-1
L(i,j,k+1) = L(i,j,k) U L(i,k+1,k) L(k+1,k+1,k)* L(k+1,j,k)
получено с помощью регулярных операций из регулярных мно-
жеств, следовательно, регулярно.
Множество цепочек, допускаемых КА, представляет собой объеди-
нение цепочек L(1,j,n), таких, что Sj - конечное состояние КА,
следовательно, регулярно. (Конец доказательства).
Мы рассмотрели 4 способа описания языков:
- регулярные (автоматные, праволинейные) грамматики,
- недетерминированные КА,
- детерминированные КА,
- регулярные выражения,
и показали, что они описывают один класс языков - регулярные
языки. Этот класс языков "устроен очень хорошо" - для всех ти-
пичных вопросов известны ответы и эффективные алгоритмы. Приме-
ры таких вопросов (получение ответов - упражнение):
- является ли объединение, пересечение, дополнение регулярных
языков регулярным,
- является ли регулярный язык конечным, пустым,
- совпадают ли два регулярных языка,
- является ли один регулярный язык подмножеством другого,
и т.д.
(Замечание. Для других классов иерархии Хомского дела обстоят
значительно хуже, например, проблема эквивалентности для
КС-языков алгоритмически неразрешима.)
Лемма о разрастании для регулярных языков
Так называмые "леммы о разрастании" для классов языков -
удобный способ доказательства того, что конкретный язык не от-
носится к данному классу.
Лемма для регулярного языка: Существует такое число m, что
любую цепочку x, |x| > m, принадлежащую языку, можно разбить на
три части: x = uvw так, что 0<|v|<=m и цепочки uv*w также будут
принадлежать языку. Доказательство: построим КА для распознава-
ния языка. Пусть этот автомат имеет m состояний. Тогда при раз-
боре цепочки x хотя бы одно из состояний (например, А) прохо-
дится дважды (почему? - упражнение). Разобьем цепочку x на три
части - до состояния А, от А до А, остальное. Это и есть цепоч-
ки u,v,w (почему v можно размножать, сохраняя принадлежность
цепочки языку? - упражнение).
n n
Как показать, что язык 0 1 не является регулярным? - упраж-
нение.
Задачи и упражнения
1. Написать регулярную грамматику и регулярное выражение,
порождающие тот же язык, что и грамматика:
S : AB ; A : X|Y ; X : x|xX ; Y : y|yY ; B : b|bB
2. Построить регулярную грамматику и конечный автомат, соот-
ветствующие регулярному выражению:
(101)*(010)*
3. Постройте недетерминированный а затем детерминированный
конечные автоматы, воспринимающие регулярное выражение:
(101)*(110)*
4. Построить детерминированные конечные автоматы для следу-
ющих регулярных выражений. Для каждого полученного автомата
построить эквивалентный минимальный автомат. Убедиться в изо-
морфизме минимальных автоматов, следовательно, в эквивалентнос-
ти исходных выражений:
(a|b)* (a*|b*)* ((e|a)b*)*
5. Написать регулярное выражение, описывающее следующий язык
- слово, буквы которого расположены в алфавитном порядке
- последовательность цифр, в которой нет повторяющихся цифр
- последовательность цифр, в которой не более чем одна цифра
встречается несколько раз
- строка из нулей и единиц, в которой нет подстроки 0 0 1
- строка из нулей и единиц, в которой нет подпоследователь-
ности 0 0 1
6. Опишите регулярной грамматикой и приведите регулярное вы-
ражение для идентификатора Фортрана. (До шести букв или цифр,
первый символ должен быть буквой).
7. Напишите программу распознавания вещественных констант.
Она должна воспринимать константы вида:
1.2 -0.4 +3.14 .2 1. -1.е38 1е+2 +0.5е-23 и т.д.
8. Построить минимальные детерминированные конечные автоматы
для следующих регулярных выражений
(a|b)*a(a|b)
(a|b)*a(a|b)(a|b)
(a|b)*a(a|b)(a|b)(a|b)
Доказать, что любой детерминированный конечный автомат для вы-
ражения (a|b)a(a|b)(a|b)...(a|b), содержащего n-1 (a|b) в конце
содержит не менее чем 2**n состояний.
9. Напишите программу, которая проверяет, является ли имя
файла частным случаем разновидности регулярного выражения, в
котором метасимвол * обозначает любую (в том числе и пустую)
последовательность символов кроме ".", а метасимвол ? - любой
символ кроме "."
