
Примеры грамматик и языков
Примеры грамматик и языков, иллюстрирующие классы иерархии Хомского, приведем в порядке, обратном классификации, т. е. будем идти от простого к сложному.
Регулярные
1) Грамматика S → aS | a является праволинейной (неукорачивающей) грамматикой. Она порождает регулярный язык {an | n > 0}. Этот язык может быть порожден и леволинейной грамматикой: S → Sa | a. Заметим, что обе эти грамматики являются автоматными.
2) Грамматика S → aS | a является праволинейной и порождает регулярный язык {an | n ≥ 0}. Для любого регулярного языка существует неукорачивающая регулярная грамматика. Построим неукорачивающую регулярную грамматику для данного языка:
S → aA | a | ε
А → a | aA
В самом деле, правило с пустой правой частью может применяться только один раз и только на первом шаге вывода; остальные правила таковы, что их правая часть не короче левой, т. е. грамматика неукорачивающая.
3) Грамматика
S → A⊥ | B⊥
A → a | Ba
B → b | Bb | Ab
леволинейная; она порождает регулярный язык, состоящий из всех непустых цепочек в алфавите {a, b}, заканчивающихся символом ⊥ (маркер конца) и не содержащих подцепочку aa. То есть в цепочках этого языка символ a не может встречаться два раза подряд, хотя бы один символ b обязательно присутствует между любыми двумя a. С помощью теоретико-множественной формулы данный язык описывается так: {ω⊥ | ω ∈ {a, b}+, aa ⊄ ω }.
Контекстно-свободные
4) Грамматика
S → aQb | accb
Q → cSc
является контекстно-свободной (неукорачивающей) и порождает КС-язык {(ac)n (cb)n | n >0}, который, как и язык {anbn | n ≥ 0}, не является регулярным, т. е. не может быть порожден ни одной регулярной грамматикой.
5) Грамматика
S → aSa | bSb | ε
порождает КС-язык {xxR, x∈{a, b}. Данный язык не является регулярным. Грамматика не удовлетворяет определению неукорачивающей, но для нее существует эквивалентная неукорачивающая грамматика. Приведем такую грамматику:
S → A | ε
A → aAa | bAb | aa | bb
Неукорачивающие и контекстно-зависимые
6) Грамматика:
S → aSBC | abC
CB → BC
bB → bb
bC → bc
cC → cc
неукорачивающая и порождает язык {anbncn | n > 0}, который является языком типа 1, но не является языком типа 2.
Правило CB → BC не удовлетворяет определению КЗ-грамматики. Однако, заменив это правило тремя новыми CB→ СD, CD → BD, BD → BC (добавляем новый символ D в множество нетерминалов Vn ), мы получим эквивалентную серию контекстно-зависимых правил, которые меняют местами символы C и B. Таким образом, получаем эквивалентную КЗ-грамматику:
S → aSBC | abC
CB → CD
CD → BD
BD → BC
bB → bb
bC → bc
cC → cc
Без ограничений на вид правил (тип 0)
7) В грамматике типа 0
S → SS
SS → ε
второе правило не удовлетворяет ограничениям неукорачивающей грамматики. Существует бесконечно много выводов в данной грамматике, однако порождаемый язык конечен и состоит из единственной цепочки: {ε}.
Следующая грамматика также не является неукорачивающей и порождает пустой язык, так как ни одна терминальная цепочка не выводится из S (для обозначения пустого языка используется ∅ — знак пустого множества):
S → SS
SS → Sa | S
Заметим, что языки Lε = {ε} и L∅ = ∅ (пустой язык) могут быть описаны грамматиками. Кроме того, отметим, что Lε ≠ L∅, так как L∅ не содержит цепочек вообще, а Lε — язык, состоящий из одной цепочки (пустая цепочка ε по определению равноправна с остальными цепочками в алфавите).
Языки типа 0 (рекурсивно перечислимые множества) можно задавать с помощью распознавателей: НАМ (нормальные алгоритмы Маркова) или МТ (машина Тьюринга). Существуют алгоритмы, позволяющие по НАМ или МТ построить эквивалентную грамматику типа 0, задающую тот же язык, что и исходный распознаватель.
Грамматики непосредственно составляющих (НС-грамматики)
Опр. Порождающая грамматика называется неукорачивающей, если для каждого правила (α→β) Р выполняется неравенство |α|≤|β|.
Грамматики НС – это грамматики, правила которых имеют вид: αAβ→αγβ, где AVn, α,β,γV (контекстное преобразование) или A→γ (бесконтекстное).
Различают левоконтекстные и правоконтекстные грамматики. Соответственно, их языки называются лево(право)контекстными.
Теорема. Класс лево(право)контекстных языков не совпадает с классом КС-языков.
Контекстно-свободные грамматики и разбор цепочек
Цепочка принадлежит языку, порождаемому грамматикой, только в том случае, если существует ее вывод из цели этой грамматики. Процесс построения такого вывода (а, следовательно, и определения принадлежности цепочки языку) называется разбором.
С практической точки зрения наибольший интерес представляет разбор по контекстно-свободным (КС и УКС) грамматикам. Их порождающей мощности достаточно для описания большей части синтаксической структуры языков программирования, для различных подклассов КС-грамматик имеются хорошо разработанные практически приемлемые способы решения задачи разбора.
Рассмотрим основные понятия и определения, связанные с разбором по КС-грамматике.
Опр: вывод цепочки β (VT)* из S ∈ VN в КС-грамматике G = (VT, VN, Р, S), называется левым (левосторонним), если в этом выводе каждая очередная сентенциальная форма получается из предыдущей заменой самого левого нетерминала.
Опр: вывод цепочки β (VT)* из S ∈ VN в КС-грамматике G = (VT, VN, Р, S), называется правым (правосторонним), если в этом выводе каждая очередная сентенциальная форма получается из предыдущей заменой самого правого нетерминала.
В грамматике для одной и той же цепочки может быть несколько выводов, эквивалентных в том смысле, что в них в одних и тех же местах применяются одни и те же правила вывода, но в различном порядке.
Например, для цепочки a+b+а в грамматике G = ({a,b,+}, {S,T},{S → Т | T+S; Т → а|b}, S) можно построить выводы:
-
S→T+S→T+T+S→T+T+T→a+T+T→a+b+T→a+b+a
-
S→T+S→a+S→a+T+S→a+b+S→a+b+T→a+b+a
-
S→T+S→T+T+S→T+T+T→T+T+a→T+b+a→a+b+a
Здесь (2) - левосторонний вывод, (3) - правосторонний, а (1) не является ни левосторонним, ни правосторонним, но все эти выводы являются эквивалентными в указанном выше смысле.
Для КС-грамматик можно ввести удобное графическое представление вывода, называемое деревом вывода, причем для всех эквивалентных выводов деревья вывода совпадают.
Опр: дерево называется деревом вывода (или деревом разбора) в КС-грамматике G = (VT, VN, Р, S), если выполнены следующие условия:
-
каждая вершина дерева помечена символом из множества (VNVT), при этом корень дерева помечен символом S; листья - символами из (VTε);
-
если вершина дерева помечена символом А ∈ VN, а ее непосредственные потомки - символами a1, а2, ... , аn, где каждое аi ∈ (VT VN), то А → a1a2...an -правило вывода в этой грамматике;
(3)если вершина дерева помечена символом А ∈ VN, а ее единственный непосредственный потомок помечен символом ε, то А → ε - правило вывода в этой грамматике.
Пример дерева вывода для цепочки a+b+а в грамматике G:
Опр: КС-грамматика G называется неоднозначной, если существует хотя бы одна цепочка α ∈ L(G), для которой может быть построено два или более различных деревьев вывода.
Это утверждение эквивалентно тому, что цепочка α имеет два или более разных левосторонних (или правосторонних) выводов.
Опр: в противном случае грамматика называется однозначной.
Опр: язык, порождаемый грамматикой, называется неоднозначным, если он не может быть порожден никакой однозначной грамматикой.
Однако это не означает, что язык L(G) обязательно неоднозначный. Определенная нами неоднозначность - это свойство грамматики, а не языка, т.е. для некоторых неоднозначных грамматик существуют эквивалентные им однозначные грамматики.
Если грамматика используется для определения языка программирования, то она должна быть однозначной.
Проблема, порождает ли данная КС-грамматика однозначный язык (т.е. существует ли эквивалентная ей однозначная грамматика), является алгоритмически неразрешимой.
Теорема. Для языков типа 3 существует алгоритм для установления однозначности грамматики. Для языков остальных типов данная задача является алгоритмически неразрешимой.
Поиск ответа на вопрос, неоднозначна или однозначна заданная грамматика – это искусство поиска цепочки с двумя различными деревьями вывода, или доказательство того, что таких цепочек не существует. Универсального способа решения этой задачи, к сожалению, нет.
Пример неоднозначной грамматики:
G = <{if, then, else, a, b}, {S}, P, S >, где P = {S → if b then S else S | if b then S | a}.
В этой грамматике для цепочки if b then if b then a else a можно построить два различных дерева вывода.
Дерево вывода можно строить нисходящим либо восходящим способом.
При нисходящем разборе дерево вывода формируется от корня к листьям; на каждом шаге для вершины, помеченной нетерминальным символом, пытаются найти такое правило вывода, чтобы имеющиеся в нем терминальные символы «проектировались» на символы исходной цепочки.
Метод восходящего разбора заключается в том, что исходную цепочку пытаются «свернуть» к начальному символу S; на каждом шаге ищут подцепочку, которая совпадает с правой частью какого-либо правила вывода; если такая подцепочка находится, то она заменяется нетерминалом из левой части этого правила.
Если грамматика однозначная, то при любом способе построения будет получено одно и то же дерево разбора.
Опр. Языком Дика над 2n буквами называется контекстно-свободный язык над алфавитом {a1, b1, a2, b2, . . . , an, bn}, порождаемый грамматикой S → ε, S → a1Sb1S, ..., S → anSbnS.
Замечание. Словами этого языка являются последовательности правильно вложенных скобок n типов. При любом положительном целом n грамматика является однозначной.
Опр. Языком Лукасевича над n + 1 буквами называется контекстно-свободный язык над алфавитом {a0, a1, . . . , an}, порождаемый грамматикой S → a0, S → a1S, S → a2SS, ..., S → anSn.
Замечание. При любом n ∈ N грамматика является однозначной.
Опр. Грамматика в нормальной форме Хомского (грамматика в бинарной нормальной форме, квадратичная грамматика) — контекстно-свободная грамматика G=<Vt,Vn,P,S>, в которой каждое правило имеет один из следующих трёх видов: S → ε, A → a, A → BC, где A ∈ Vn, B ∈ Vn − {S}, C ∈ Vn − {S}, a ∈ Vt.
Пример. Грамматика S → RR, S → AB, R → RR, R → AB, A → a, B → RB, B → b — грамматика в нормальной форме Хомского.
Теорема. Каждая контекстно-свободная грамматика эквивалентна некоторой грамматике в нормальной форме Хомского.
Пример. Грамматика S → ε, S → aUbU , U → S, U → ba эквивалентна следующей грамматике в нормальной форме Хомского: S0 → ε, S0 → AD, D → UC, D → BU, D → b, C → BU, C → b, U → BA, U → AD, A → a, B → b.
Теорема. Если контекстно-свободный язык не содержит пустого слова, то он порождается некоторой грамматикой, в которой каждое правило имеет один из следующих двух видов: A → a, A → BC, где A ∈ Vn, B ∈ Vn − {S}, C ∈ Vn − {S}, a ∈ Vt.
Опр. Грамматика в нормальной форме Грейбах — контекстно-свободная грамматика G=<Vt,Vn,P,S>, в которой каждое правило имеет один из следующих четырёх видов: A → ε, A → a, A → aB, A → aBC, где A ∈ Vn, B ∈ Vn, C ∈ Vn, a ∈ Vt.
Пример. Грамматика S → aST, S → aT, T → bS, T → b — грамматика в нормальной форме Грейбах.
Замечание. Некоторые авторы разрешают в грамматиках в нормальной форме Грейбах использовать также правила вида A → aβ, где A ∈ Vn, a ∈ Vt, β ∈ Vn*.
Теорема. Каждая контекстно-свободная грамматика эквивалентна некоторой грамматике в нормальной форме Грейбах.
Теорема. Пусть язык L контекстно-свободный. Тогда язык L−{ε} порождается некоторой грамматикой в нормальной форме Грейбах без ε-правил.
Пример. Грамматика S → aR, R → bRT , R → ε, T → cSR, T → ε эквивалентна следующей грамматике в нормальной форме Грейбах без ε-правил: S → aR, S → a, R → bRT , R → bT , R → bR, R → b, T → cSR, T → cS.
Контекстно-свободные грамматики имеют ряд характеристик, для которых справедливы следующие положения.
1) Каноническая форма
а) Каждая КС-грамматика эквивалентна (т.е. генерирует тот же язык) грамматике в нормальной форме Хомского;
б) Каждая КС-грамматика эквивалентна грамматике в нормальной форме Грейбаха;
2) Самовложение
Если в грамматике G есть нетерминал A, для которого A ⇒ α1Aα2 (здесь α1 и α2 являются непустыми строками терминалов и/или нетерминалов), то о такой грамматике говорят, что она содержит самовложение. Например, две приведенные ниже грамматики содержат самовложение:
1) G1 = <{a, b}, {S}, P, S>, где элементы P:
S → aSb
S → ε
2) G2 = <{begin, end,[,]}, {S, A}, P, S>, где элементы P:
S → begin A end
S → ε
A → [S]
Теоретически любая КС-грамматика, не содержащая самовложения, эквивалентна регулярной грамматике и генерирует регулярный язык.