
- •10. Формальні мови і граматики
- •10.2. Приклади, що ілюструють первинні поняття
- •I aA aаA aааA ... ,
- •I aAi aAai abAi abbI abba.
- •10.4.3. Граматики типу 2. Граматики типу 2 називають контекстно вільними (кв) граматиками, або безконтекстними граматиками.
- •I aIa abIba abaIaba ababbaba.
- •10.4.4. Граматики типу 3. Граматики типу 3 називають автоматними граматиками (а-граматиками). Правила виведення в таких граматиках мають вигляд:
- •10.5. Виведення у кв-граматиках і правила побудови дерева виведення
- •10.5.2. Ліве і праве виведення. Серед різних типів виведення найбільший інтерес становлять наступні два типи виведення.
- •10.6. Неоднозначні та еквівалентні граматики
- •10.7. Способи завдання схем граматик
- •10.7.2. Опис списків. Розглянемо побудову граматик для послідовностей символів і послідовностей символів з роздільниками, тобто для списків.
- •Cинтаксичний розбір ідентифікатора ab12 буде таким: [1, 2.1, 5.1, 2.1, 5.2, 2.2, 4.2, 2.2, 4.3, 3].
- •11. Контекстно-вільні граматики і автомати
- •11.1. Приведені граматики
- •Приклад. Маємо граматику
- •11.2. Виключення ліворекурсивних правил
- •11.3. Виключення ланцюгових правил
- •11.4. Магазинні автомати
- •12. Спадні розпізнавачі
- •12.1. Розділені граматики
- •12.2. Побудова детермінованого спадного розпізнавача
- •12.3. Слабко-розділені граматики
- •12.5. Побудова магазинного автомата
- •12.6. Приклади побудови спадного розпізнавача
11. Контекстно-вільні граматики і автомати
11.1. Приведені граматики
З чотирьох типів граматик контекстно-вільні граматики (КВ) найбільш важливі з погляду додатків до мов програмування і компіляції. За допомогою КВ-граматики можна визначити велику частину структури мови програмування. При побудові граматик, що задають конструкції мов програмування, часто доводиться вдаватися до їх перетворення, щоб породжувана мова набула потрібної структури. Тому спочатку розглянемо трохи досить простих, але важливих перетворень КВ-граматик. Перший вид перетворення пов'язаний з видаленням із граматики зайвих символів. Зайві символи в граматиці можуть виявитися в таких випадках:
а) якщо символ не може бути отриманий при виведенні;
б) якщо із символу не може бути отриманий кінцевий термінальний ланцюжок (виходить нескінченний ланцюжок або немає правил, що приводять до термінального ланцюжка).
Спочатку розглянемо алгоритм виявлення символів, з яких не можна вивести кінцеві ланцюжки.
11.1.1. Визначення непродуктивних символів. Символ X Î Va називається непродуктивним, якщо з нього не може бути виведений кінцевий термінальний ланцюжок.
Розглядаючи правила граматики, можна зробити висновок, що, коли всі символи правої частини є продуктивними, то продуктивним є і символ, що стоїть у лівій частині. Останнє твердження дозволяє написати процедуру виявлення непродуктивних символів у такому вигляді:
1. Скласти список нетермінальних символів, для яких знайдеться хоча б одне правило, права частина якого містить термінальні символи або cимвол пусто ($).
2. Якщо знайдене таке правило і всі нетермінальні символи, які стоять у його правій частині, вже занесені до списку, то додати в список нетермінальний символ, що стоїть у його лівій частині.
3. Якщо на кроці 2 список більше не поповнюється, то отримано список усіх продуктивних нетермінальних символів граматики, а всі нетермінальні символи, які не потрапили в нього, є непродуктивними.
Приклад. Маємо граматику
Г11.1: R = {I aIa (1)
I bAd (2)
I c (3)
A cBd (4)
A aAd (5)
B dAf }. (6)
На першому кроці заносимо до списку нетермінальний символ І, тому що права частина правила (3) не містить нетермінальних символів. На другому кроці, згідно з правилом (1), до списку потрібно б було занести нетермінальний символ І, але він там уже є. Тому наш список залишається без змін. Згідно з кроком три список не поповнюється, тому виявляється, що в заданій граматиці непродуктивними є символи А і B. Після виключення правил, які містять непродуктивні символи, одержуємо граматику:
R' = {I a I a, (1)
I c}. (2)
11.1.2. Визначення недосяжних символів. У КВ-граматиці Г називається недосяжним символ X Î Vт È Va, якщо X не з'являється в жодному виведеному ланцюжку.
Розглядаючи правила граматики, можна помітити, що, якщо нетермінальний символ у лівій частині правила є досяжним, то і всі символи правої частини є досяжними. Ця властивість правил є основою процедури виявлення недосяжних символів, яку можна описати так:
1. Створити одноелементний список, що складається з початкового символу граматики І.
2. Якщо знайдене правило, ліва частина якого вже є в списку, то включити до списку всі символи, які містяться в його правій частині.
3. Якщо на кроці 2 нові нетермінальні символи в список більше не додаються, то отримано список усіх досяжних нетермінальних символів, а решта нетермінальних символів, які не потрапили в список, є недосяжними.
Приклад. Маємо граматику
Г11.2: R = {I a I b (1)
I c (2)
A bI (3)
A a}. (4)
На першому кроці до списку заносимо нетермінальний символ І. На другому кроці, згідно з правилом (2), потрібно додати до списку нетермінальний символ І, але він там уже є. Через те, що більше нетермінальних символів додати до списку ми не можемо, отже, A є недосяжним символом.
КВ-граматика називається приведеною, якщо вона не містить зайвих (непродуктивних і недосяжних) символів.