
- •Введение
- •Формальные грамматики. Выводы Основные понятия
- •Способы задания языков
- •Операции над языками
- •Формальные грамматики. Выводы
- •Преобразования кс-грамматик Основные понятия
- •Устранение лишних символов
- •Исключение лишних правил
- •Исключение -правил
- •Устранение цепных правил
- •Выделение нетерминала
- •Левая факторизация
- •Устранение левой рекурсии
- •Устранение правой рекурсии
- •Нормальная форма Хомского
- •Нормальная форма Грейбах
- •Операторная кс-грамматика
- •Регулярные языки и конечные распознаватели Правосторонние грамматики
- •Левосторонние грамматики
- •Связь правосторонних и левосторонних грамматик
- •Преобразование кс-грамматики произвольного вида в правостороннюю
- •Конечные распознаватели. Основные понятия
- •Преобразование недетерминированных конечных распознавателей с -переходами в детерминированные
- •Эквивалентность состояний конечных детерминированных распознавателей
- •Эквивалентность конечных детерминированных распознавателей
- •Минимизация конечных детерминированных распознавателей
- •Регулярные множества и регулярные выражения
- •Регулярные выражения и конечные распознаватели
- •Получение регулярного выражения из конечного распознавателя
- •Построение конечного распознавателя по регулярному выражению
- •Конечные распознаватели и регулярные грамматики
- •Получение грамматики из конечного распознавателя
- •Построение конечных распознавателей по регулярным грамматикам
- •Ещё один способ взаимного преобразования право- и левосторонних грамматик
- •Программная реализация конечных детерминированных распознавателей
- •Лексический анализ
- •Принципы построения лексических анализаторов
- •Определение границ лексем
- •Выполнение действий, связанных с лексемами
- •Выделение ключевых слов
- •Программная реализация лексических анализаторов
- •Глава 3. Синтаксический анализ
- •3.1. Автомат с магазинной памятью
- •3.2. Таблично-управляемый предсказывающий разбор
- •3.2.1. Алгоритм разбора сверху-вниз
- •3.2.2. Множества first и follow
- •3.2.3. Конструирование таблиц предсказывающего анализатора
- •3.2.4. Ll(1)-грамматики
- •3.2.7. Рекурсивный спуск
- •3.3. Разбор снизу-вверх типа сдвиг-свертка
- •3.3.1. Основа
- •3.3.2. Lr(k)-анализаторы
- •3.3.4. Конфликты разбора типа сдвиг-свертка
Левосторонние грамматики
Левосторонняя грамматика может иметь правила двух видов: А или АВ, где А и В – нетерминалы, а - цепочка терминалов, возможно, пустая. Грамматику, которая может иметь правила двух видов: АВt и А, где А и В – нетерминалы, а t – терминал, назовём автоматной левосторонней или левосторонней грамматикой специального вида. Левостороннюю грамматику можно преобразовать в автоматную левостороннюю.
Алгоритм преобразования левосторонней грамматики в автоматную левостороннюю.
1. Если имеются правила вида А , - непустая цепочка термина-лов, то ввести новый нетерминал Е и добавить правило Е . Затем каждое из правил вида А заменить правилом АЕ.
2. Пока в грамматике есть правила вида АВ , где - цепочка более чем из одного терминала, выполнять выделение нетерминала следующим образом: правило АВ заменить правилами АСt и СВ , где t – последний терминал в цепочке , С – новый нетерминал, - цепочка без последнего терминала.
3. Устранить цепные правила.
Пример.
Привести левостороннюю грамматику к автоматному виду.
1. SAa 4. ASab
2. Sb 5. AAc
3. SA 6. A
1. В грамматике есть правило 2 вида А, поэтому введём новый нетерминал Е , добавим правило 7 и изменим правило 2 :
1. SAa 4. ASab
2. SEb 5. AAc
3. SA 6. A
7. Е
2. Выполним выделение нетерминала в правиле 4, обозначив цепочку Sa как нетерминал В :
1. SAa 4.2. ВSa
2. SЕb 5. AAc
3. SA 6. A
4.1. ABa 7. Е
3. Устраним цепное правило 3 :
1. SAa 4.1. ABa
2. SEb 4.2. ВSb
3.1. SBa 5. AAc
3.1. SAc 6. A
3.1. S 7. E
Автоматная левосторонняя грамматика получена.
Связь правосторонних и левосторонних грамматик
Класс левосторонних грамматик эквивалентен классу правосторонних грамматик, т.е. любой язык, заданный правосторонней грамматикой, может быть задан левосторонней грамматикой и любой язык, заданный левосторон-ней грамматикой, может быть задан правосторонней грамматикой, следовательно, левосторонняя грамматика порождает регулярный язык.
Покажем, что любую левостороннюю грамматику можно преобразовать в эквивалентную ей правостороннюю грамматику и любую правостороннюю грамматику можно преобразовать в эквивалентную ей левостороннюю грамматику. Будем считать, что в исходной грамматике исключены цепные и -правила выполнением соответствующих преобразований.
Алгоритм преобразования левосторонней грамматики в правостороннюю.
1. Устранить левую рекурсию.
2. Выполнить замену края.
3. В каждом i-ом правиле вида АВ, где и - непустые цепочки терминалов, выделить новый нетерминал Ci , определяемый правилом CiВ , а правило АВ заменить на А Ci.
4. Выполнить замену края.
5. В правых частях правил грамматики подцепочки, представляющие собой правую часть правила, определяющего нетерминал Ci в правилах, полученных в п.3, заменить на Ci .
В результате устранения левой рекурсии (п.1 алгоритма) можем получить правила вида:
1. АB1 - в правой части нетерминал и цепочка терминалов;
2. А2 - в правой части цепочка терминалов;
3. B3B’ - в правой части цепочка терминалов и новый нетерминал;
4. B’4B’
5. B’
Правила вида 1-3 определяют нетерминалы исходной грамматики, а правила вида 4 и 5 определяют нетерминалы, введённые в грамматику при устранении левой рекурсии. Среди получаемых правил только правила вида 1 не соответствуют правилам правосторонней грамматики. В соответствии с п.2 алгоритма выполним замену края в правилах вида 1. В результате замены края можем получить правила вида 2 и правила вида:
6. A3B’1
Правило вида 6 не соответствует правилам правосторонней грамматики. По п.3 алгоритма выполним выделение нетерминала С и получим правила вида:
7. A3С
8. CB’1
В правилах вида 8 выполним замену края (п.4 алгоритма), используя правила вида 4 и 5. В результате вместо правил вида 8 получим правила вида:
9. С4B’1
10. С1
В правилах вида 9 есть подцепочка B’1 , соответствующая правой части правила вида 8, и, заменяя её на левую часть правила вида 8 (п.5 алгоритма), получаем правостороннюю грамматику.
Пример.
Преобразовать левостороннюю грамматику в правостороннюю.
1. ABa 3. BBca
2. Aab 4. BAc
5. Bb
1. В результате устранения левой рекурсии получим:
1. ABa 5. B’caB’
2. Aab 6. В’acB’
3. BabcB’ 7. B’
4. BbB’
2. В результате замены края в правиле 1 получим:
1. A abcB’a 4. B’caB’
2. AbB’a 5. В’acB’
3. Aab 6. B’
3. В результате выделения нетерминала С в правилах 1 и 2 получим:
1. A abcС 4. B’caB’
2. AbС 5. В’acB’
3. Aab 6. B’
7. СB’a
4. В результате замены края в правиле 7 получим:
1. A abcС 5. В’acB’
2. AbС 6. B’
3. Aab 7. С caB’a
4. B’caB’ 8. С acB’a
9. С a
5. В результате замены подцепочки B’a в правилах 7 и 8 на нетерминал С в соответствии с правилом 7. СB’a п.3 получим правостороннюю грамматику:
1. A abcС 5. В’acB’
2. AbС 6. B’
3. Aab 7. С caС
4. B’caB’ 8. С acС
9. С a
При преобразовании правосторонней грамматики в левостороннюю будем использовать операцию обращения языка.
Если язык L задан порождающей грамматикой G , то язык L-1 – обращение языка L , можно задать грамматикой G’ , полученной из грамматики G обращением правой части каждого правила (изменения порядка следования символов в правой части правила на обратный).
Если язык L задан правосторонней грамматикой G , то его обращение – язык L-1 , можно задать левосторонней грамматикой G’ . Если же язык L задан левосторонней грамматикой G , то его обращение можно задать правосторонней грамматикой G’ . Естественно, что обращение обращения языка L есть язык L, т.е. L= L-1-1. Имея алгоритм преобразования левосторонней грамматики в правостороннюю и учитывая вышесказанное, получаем простой алгоритм преобразования правосторонней грамматики в левостороннюю.
Алгоритм преобразования правосторонней грамматики в левостороннюю.
1. Получить левостороннюю грамматику G’ путём обращения правых частей правил грамматики G. Грамматика G’ порождает обращение языка, заданного исходной грамматикой.
2. Преобразовать левостороннюю грамматику G’ в эквивалентную ей правостороннюю грамматику G’’ .
3. Получить правостороннюю грамматику G’’’ путём обращения правых частей правил грамматики G’’. Грамматика G’’’ порождает обращение языка, заданного грамматикой G’’, т.е. исходный язык.
Пример.
Преобразовать правостороннюю грамматику в левостороннюю.
1. AaB 3. BacB
2. Aba 4. BcA
5. Bb
1. Получим левостороннюю грамматику путём обращения правых частей правил исходной грамматики:
1. ABa 3. BBca
2. Aab 4. BAc
5. Bb
2. В результате преобразования левосторонней грамматики в правостороннюю (процесс преобразования рассмотрен в предыдущем примере) получим:
1. A abcС 5. В’acB’
2. AbС 6. B’
3. Aab 7. С caС
4. B’caB’ 8. С acС
9. С a
3. В результате обращения правых частей правил получим левостороннюю грамматику, эквивалентную исходной правосторонней:
1. AСcba 5. В’B’ca
2. AСb 6. B’
3. Aba 7. С Сac
4. B’B’ac 8. С Сca
9. С a
Для преобразования правосторонней грамматики в левостороннюю можно использовать алгоритм, аналогичный алгоритму преобразования левосторонней грамматики в правостороннюю.
Алгоритм преобразования правосторонней грамматики в левостороннюю.
1. Устранить правую рекурсию.
2. Выполнить замену нетерминалов, занимающих самую правую позицию в правых частях правил.
3. В каждом i-ом правиле вида АВ, где и - непустые цепочки терминалов, выделить новый нетерминал Ci , определяемый правилом CiВ , а правило АВ заменить на А Ci.
4. Выполнить п.2.
5. В правых частях правил грамматики подцепочки, представляющие собой правую часть правила, определяющего нетерминал Ci в правилах, полученных в п.3, заменить на Ci .
В результате устранения правой рекурсии (п.1 алгоритма) можем получить правила вида:
1. А1B - в правой части цепочка терминалов и нетерминал;
2. А2 - в правой части цепочка терминалов;
3. BB’3 - в правой части новый нетерминал и цепочка терминалов;
4. B’B’4
5. B’
Правила вида 1-3 определяют нетерминалы исходной грамматики, а правила вида 4 и 5 определяют нетерминалы, введённые в грамматику при устранении правой рекурсии. Среди получаемых правил только правила вида 1 не соответствуют правилам левосторонней грамматики. В соответствии с п.2 алгоритма выполним замену нетерминалов, занимающих самую правую позицию в правых частях правил в правилах вида 1. В результате замены можем получить правила вида 2 и правила вида:
6. A1B’3
Правило вида 6 не соответствует правилам левосторонней грамматики. По п.3 алгоритма выполним выделение нетерминала С и получим правила вида:
7. A С 3
8. C1B’
В правилах вида 8 выполним замену нетерминала (п.4 алгоритма), используя правила вида 4 и 5. В результате вместо правил вида 8 получим правила вида:
9. С1B’4
10. С1
В правилах вида 9 есть подцепочка 1B’ , соответствующая правой части правила вида 8, и, заменяя её на левую часть правила вида 8 (п.5 алгоритма), получаем левостороннюю грамматику.
Пример.
Преобразовать правостороннюю грамматику в левостороннюю.
1. AаB 3. BасB
2. Abа 4. BсA
5. Bb
1. В результате устранения правой рекурсии получим:
1. AаB 5. B’B’ac
2. Abа 6. В’B’ca
3. BB’сba 7. B’
4. BB’b
2. В результате замены нетерминала в правиле 1 получим:
1. AaB’cba 4. B’B’ac
2. AaB’b 5. В’B’ca
3. Aba 6. B’
3. В результате выделения нетерминала С в правилах 1 и 2 получим:
1. AСcba 4. B’B’ac
2. AСb 5. В’B’ca
3. Aba 6. B’
7. СaB’
4. В результате замены нетерминала в правиле 7 получим:
1. AСcba 5. В’B’ca
2. AСb 6. B’
3. Aba 7. С aB’ac
4. B’B’ac 8. С aB’ca
9. С a
5. В результате замены подцепочки a B’ в правилах 7 и 8 на нетерминал С в соответствии с правилом 7. С aB’ п.3 получим левостороннюю грамматику:
1. AСcba 5. В’B’ca
2. AСb 6. B’
3. Aba 7. С Сac
4. B’B’ac 8. С Сca
9. С a
Грамматики, заведомо порождающие регулярные языки (определяется по виду правил), назовём регулярными. Из сказанного выше следует, что к классу регулярных грамматик относятся право- и левосторонние и право- и левосторонние автоматные грамматики.