
- •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. Приклади побудови спадного розпізнавача
12.6. Приклади побудови спадного розпізнавача
Приклад 1.
Побудувати спадний розпізнавач для оператора присвоювання арифметичного виразу. Арифметичний вираз містить: ідентифікатори і, :=, (, ), ;. Кількість вкладених дужок не обмежена. Приклади ланцюжків, що є операторами присвоювання:
i := і+(і+і)+(і+і);
i :=і+і;
i :=і+(і+(і+і)).
1. Будуємо правила граматики. Праву частину оператора присвоювання позначимо нетермінальним символом А. Перше правило матиме вигляд: I i := A;. Нетермінальний символ А є списком з роздільником. Елементом списку є ідентифікатор і, а роздільником є знак «+». Окрім того, список А може бути розміщеним в дужках. Нетермінальний символ С використовуємо для рекурсії. Таким чином, маємо:
I i := A; (1)
A iC (2)
C +A (3)
A (А)C (4)
C $. (5)
2. Визначаємо, чи містить наша граматика непродуктивні символи, а саме знайдемо правило, в правій частині якого розташовано термінальний символ або символ $. {C} – продуктивний символ. Знайдемо правила, в правій частині котрих містяться символи, що вже занесені в список. Якщо такі правила існують, то додаємо в список нетермінальні символи, які розміщені в лівій частині правила:
{C A}
{C A}
{C A I}
Таким чином, у список потрапили всі нетермінальні символи, отже непродуктивних символів немає.
3. Шукаємо недосяжні символи.
Заносимо в список початковий символ граматики {I}.
Шукаємо правило, ліва частина якого вже занесена в список. Додаємо нетермінальні символи правої частини:
{I A}
{I A C}
У список потрапили всі нетермінальні символи, отже недосяжних символів немає.
4. Дана граматика містить правила, що анулюють, та правила, права частина котрих починається з нетермінального символу, отже вона не може бути розділеною та слабко-розділеною граматикою. Визначимо належність даної граматики до LL(1)-граматики.
Аналізуючи складені нами правила, дійдемо висновку, що ліво-рекурсивних правил немає.
5. Побудуємо функцію ПЕРШ:
ПЕРШ (I і:= A;) = {і}
ПЕРШ (A iC) = {і}
ПЕРШ (C +A) = {+}
ПЕРШ (A (А)C) = {(}
ПЕРШ (C $) = {$}.
6. Побудуємо функцію СЛІД:
Згідно першого правила СЛІД(А) ={;}. Згідно чевертого правила СЛІД(А) ={)}. Згідно другого правила СЛІД(С) = СЛІД (А). Згідно третього правила СЛІД(А) = СЛІД (С). Має місце зацикленість. Отже СЛІД(А) = СЛІД (С) = {;} {)} = {;, )}.
7. Побудуємо множину ВИБІР. Для всіх правил, крім правила що анулює, множина ВИБІР дорівнює функції ПЕРШ. Для правила, що анулює, множина ВИБІР дорівнює функції СЛІД.
ВИБІР(I і:= A;) = ПЕРШ (I і:= A;) = {і}
ВИБІР(A iC) = ПЕРШ (A iC) = {і}
ВИБІР(C +A) = ПЕРШ (C +A) ={+}
ВИБІР(A (А)C) = ПЕРШ (A (А)C) = {(}
ВИБІР(C $) = СЛІД(C) {$} = СЛІД(A) {$} = {;, )}
Дана граматика є LL(1)-граматикою, тому що для правил, які починаються з однакових нетермінальних символів, множина ВИБІР не містить однакових термінальних символів.
10. Будуємо команди магазинного автомата (розпізнавача):
1) f(s, i, I) = (s, ;A:=) 7) f(s, ;, ;) = (s, $)
2) f(s, i, A) = (s, C) 8) f(s, ), )) = (s, $)
3) f(s, +, C) = (s, A) 9) f(s, :=, :=) = (s, $)
4) f(s, (, A) = (s, C)А) 10) f(s, $, h0) = (s, $)
5) f*( s, ;, C) = (s, $)
6) f*( s, ), C) = (s, $)
Кількість команд для кожного правила визначається числом елементів множини ВИБІР. Оскільки п’яте правило є правилом що анулює, то команди магазинного автомата 5 – 6 виконуються без зрушення вхідної головки. Команди 8 – 9 будуються для термінальних символів « ; », « ) » та « := », які розташовані в середині та в кінці правил. Команда 10 використовується для переходу в заключний стан.
11. Розпізнаємо ланцюжок i:=i+(i+i); відповідно до побудованих правил:
(s,i:=i+(i+i);$,h0I) ├1
(s, :=i+(i+i);$,h0;A:=) ├10
(s,i+(i+i);$,h0;A) ├2
(s, +(i+i);$,h0;C) ├3
(s, (i+i);$,h0;A) ├4
(s,i+i);$,h0;C)A) ├2
(s, +i);$, h0;C)С) ├3
(s, i);$, h0;C)A) ├2
(s, );$,h0;С)C) ├6
(s, );$,h0;C)) ├9
(s, ;$,h0;C) ├5
(s, ;$,h0;) ├8
(s,$, h0) ├11
(s,$,$)
Ланцюжок розпізнано.
Приклад 2.
Побудувати спадний розпізнавач для оператора виведення write або writeln. Оператор може містити в дужках список ідентифікаторів і та коментарів ‘t‘. Приклади ланцюжків:
write(‘t’,і);
writeln(‘t’,і, і);
write(і, і).
1. Будуємо правила граматики. Нетермінальним символом А позначимо частину ланцюжка яка знаходиться після термінальних символів write або writeln. Нетермінальним символом В позначимо список операторів і та коментарів ‘t‘ з роздільником «,». Нетермінальний символ С використаємо для рекурсії.
I write A; (1)
I writeln A; (2)
A (B) (3)
A $ (4)
B ’t’C (5)
B iC (6)
C , B (7)
C $ (8)
2. Дана граматика не містить марних символів та ліворекурсивних правил.
3. Дана граматика містить правила, що анулюють, та правила, права частина яких починається з нетермінального символу, отже, вона не може бути розділеною та слабко-розділеною граматикою. Визначимо належність даної граматики до LL(1)-граматики.
ВИБІР(I write A;) = ПЕРШ(I write A;) = {write}
ВИБІР(I writelnA;) = ПЕРШ(I writelnA;) = {writeln}
ВИБІР(A (B)) = ПЕРШ (A (B)) = {(}
ВИБІР(A $) = СЛІД(А) = {$,;}
ВИБІР(B ’t’C) = ПЕРШ (B ’t’C) = {‘}
ВИБІР(B iC) = ПЕРШ(B iC) = {i}
ВИБІР(C , B) = ПЕРШ(C , B) = {,}
ВИБІР(C $) = СЛІД(С) = СЛІД(В) = {),$}
Дана граматика є LL(1)-граматикою, тому що множина ВИБІР для правил, які починаються з однакових лівих нетермінальних символів, не містить однакових термінальних символів.
4. Будуємо команди розпізнавача:
1) f (s, write, I) = (s, h0;A)
2) f (s, writeln, I) = (s, h0;A)
3) f (s, (, A) = (s, h0)B)
4) f *(s, ; , A) = (s, $)
5) f *(s, $, A) = (s, $)
6) f (s, ‘, B) = (s, C’t)
7) f (s, i, B) = (s, C)
8) f (s, , , C) = (s, B)
9) f *(s, ),C) = (s, $)
10) f *(s, $, C) = (s, $)
11) f (s, ; , ;) = (s, $)
12) f (s, ) , )) = (s, $)
13) f (s, ’, ‘) = (s, $)
14) f (s, t, t) = (s, $)
15) f (s, $, h0) = ($, $)
5. Розпізнаємо заданий ланцюжок:
(s, writeln(‘t’,і, і);$ h0I) ├1
(s, (‘t’,і,і);$ h0;A) ├3
(s, ‘t’,і,і); $ h0;)B) ├6
(s, t’,і,і);$ h0;)C’t) ├14
(s, ’,і,і);$ h0;)C’) ├13
(s, ,і,і);$ h0;)C) ├8
(s, і,і);$ h0;)B) ├7
(s, ,і);$ h0;)C) ├8
(s, і);$, h0;)B) ├7
(s, );$, h0;)C) ├9
(s, );$, h0;) ) ├12
(s, ; $, h0;) ├11
(s, $, h0) ├15
($, $, $)
Ланцюжок розпізнано.
Контрольні запитання
1. Як працює спадний розпізнавач?
2. Яка граматика називається розділеною або простою?
3. Які типи команд розпізнавача можуть бути зіставлені з кожним правилом граматики?
4. Яка граматика називається слабкорозділеною?
5. Як будується функція ПЕРШ(µ)?
6. Як будується функція СЛІД(µ)?
7. Як будується множина ВИБІР(B µ)?
8. Які граматики називаються LL(K)–граматиками?
9. Як будуються команди розпізнавача для LL(K)–граматик?
10. Побудувати спадний розпізнавач для фрагмента програми, яка описує список змінних цілого і символьного типів.