- •Глава 11 Контекстно-свободные языки
- •Эквивалентность языков мп-автоматов и кс-грамматик
- •Детерминированные мп-автоматы
- •Свойства детерминированных кс-языков
- •Лемма о разрастании кс-языков
- •Устранение λ-правил
- •Алгоритм устранения λ-правил по шагам
- •Пример устранения λ-правил
- •Устранение цепных правил
- •Алгоритм преобразования грамматики в нормальную форму Хомского
- •Пример преобразования грамматики в нормальную форму Хомского
- •Алгоритм устранения левой рекурсии
- •Грамматики в нормальной форме Грейбах
- •Реализация алгоритма распознавателя с подбором альтернатив
- •Реализация распознавателя с возвратами на основе алгоритма «сдвиг-свертка»
- •Алгоритм Кока—Янгера—Касами
- •Алгоритм Эрли (основные принципы)
- •Принципы построения распознавателей кс-языков без возвратов
Алгоритм устранения левой рекурсии
Условие: дана КС-грамматика G(VT,VN,P,S), необходимо построить эквивалентную ей нелеворекурсивную грамматику G'(VN',VT,P',S'): L(G) = L(G').
Алгоритм преобразования работает с множеством правил исходной грамматики Р, множеством нетерминальных символов VN и двумя переменными счетчиками: i и j.
Шаг 1. Обозначим нетерминальные символы грамматики так: VN = {А1,А2,...,АП}. i := 1.
Шаг 2. Рассмотрим правила для символа aj. Если эти правила не содержат левой рекурсии, то перенесем их во множество правил Р' без изменений, а символ aj добавим во множество нетерминальных символов VN'.
Иначе запишем правила для aj в виде aj -» AiaI|Aiaβ|...|Aiam|β1|β2|...|Pp, где Vj I <j < β ни одна из цепочек pj не начинается с символов Аk, таких, что k < i.
Вместо этого правила во множество Р' запишем два правила вида:
Символы Ai и aj' включаем во множество VN'.
Теперь все правила для aj начинаются либо с терминального символа, либо с нетерминального символа Ak, такого, что k > i.
Шаг 3. Если i = n, то грамматика G' построена, иначе i:- i+1, j := 1 и перейти к шагу 4.
Шаг 4. Для символа aj во множестве правил Р' заменить все правила вида Aj->Aja, где aE(VTuVN)*, на правила вида Ai->Pia|β2a...|βma, причем Aj->β1|β2|...|βm — все правила для символа aj.
Так как правая часть правил Aj->β1|β2|...|βm уже начинается с терминального символа или нетерминального символа Ak, k > j, то и правая часть правил для символа aj будет удовлетворять этому условию.
Шаг 5. Если j - i-1, то перейти к шагу 2, иначе j := j+1 и перейти к шагу 4.
Шаг 6. Целевым символом грамматики G' становится символ А^, соответствующий символу S исходной грамматики G.
Рассмотрим в качестве примера грамматику для арифметических выражений над символами «а» и «b» G({+,-,/,*,а,b}, {S.T.E}, Р, S):
Эта грамматика является леворекурсивной. Построим эквивалентную ей нелеворекурсивную грамматику G'.
Шаг 1. Обозначим VN = {Аь А2, А3}. i := 1. Тогда правила грамматики G будут иметь вид:
Шаг 2. Для А1 имеем правила А1->А1+А2|А1-А2|А2. Их можно записать в виде А1-»A1a1|A1a2|β1, где a1 = + A2, a2 = -A2, βi = A2.
Запишем новые правила для множества Р':
Добавив эти правила в Р', а символы At и А1’ во множество нетерминальных символов, получим: VN' = {Aj.Aj1}.
Шаг 3. i = 1 < 3. Построение не закончено: i := i+1 = 2, j := 1.
Шаг 4. Для символа А2 во множестве правил Р' нет правила вида А2->А1а, поэтому на этом шаге никаких действий не выполняем.
Шаг 5. j = 1 = i-1, переходим опять к шагу 2.
Шаг 2. Для А2 имеем правила А2-»А2*А31А2/А31А3. Их можно записать в виде А2-» -»А2а, |А2а21 pj, где а! = *А3, а2 = /А3, pj = А3.
Запишем новые правила для множества Р':
Добавим эти правила в Р', а символы А2 и А2' во множество нетерминальных символов, получим: VN' = {А1,А1',А2(А2'}.
Шаг 3. i = 2 < 3. Построение не закончено: i := i+1 = 3, j := 1.
Шаг 4. Для символа А3 во множестве правил Р' нет правила вида A3-»Aia, поэтому на этом шаге никаких действий не выполняем.
Шаг 5. j - 1 < i-1, j := j+1 = 2, переходим к шагу 4.
Шаг 4. Для символа А3 во множестве правил Р' нет правила вида А3-»А2а, поэтому на этом шаге никаких действий не выполняем.
Шаг 5. j - 2 - i-1, переходим опять к шагу 2.
Шаг 2. Для А3 имеем правила А3 -» (А1) | а | b. Эти правила не содержат левой рекурсии. Переносим их в Р', а символ А3 добавляем в VN'. Получим: VN' = -s {А1,А1',А2,А2',Аз}.
Шаг 3. i = 3 = 3. Построение грамматики G' закончено.
В результате выполнения алгоритма преобразования получили нелеворекурсивную грамматику G({+,-,/,*,а,b}, {А1,A1’,A2,A2;,A3}, Р', A1) с правилами:
