Синтаксичний аналіз без повернення назад
При виводу ланцюжка ω в G на кожному кроку безпосереднього виведення коли ми беремо до уваги виділений нами нетермінал (в залежності від стратегії виведення), виникає питання, яку альтернативу для використати. З точки зору практики, нас цікавить така стратегія виведення в граматиці , коли кожний наступний крок безпосереднього виведення наближав би нас до мети. Ця стратегія дасть можливість виконати виведення в за час пропорційний , де . Зрозуміло, що не маючи інформації про структуру , досягнути вибраної нами мети в більшості випадків неможливо. Але ж тримати інформацію про весь ланцюжок також недопустимо. З точки зору практики, отримати потрібний результат розумно при наявності локальної інформації, наприклад, поточних вхідних лексем програми ( — наперед фіксоване число) достатньо для організації виведення в за час пропорційний . З точки зору синтаксичного аналізу ланцюжка мова ведеться про наступну ситуацію:
S
ω1 A ω2
ω1 X Y
Мал. 5
Зафіксуємо стратегію виводу: далі будемо розглядати лише лівосторонню стратегію виводу в . Тоді:
- ( — перший зліва направо нетермінал);
- - термінальна частина ланцюжка , яку вже виведено (проаналізована частина ланцюжка);
- результат , який потрібно ще вивести, виводиться з ланцюжка ;
- щоб зробити вірний крок виведення (без повернення назад) нам було б достатньо поточних вхідних символів з непроаналізованої частини програми .
Сформульовані нами умови забезпечує клас -граматик.
Означення. КС-граматика називається -граматикою для деякого фіксованого , якщо дія двох лівосторонніх виводів виду:
1)
2) , для яких з випливає, що , де .
Неформально, граматика буде -граматикою, якщо для ланцюжка перших символів (за умови, що вони існують) решти непроаналізованого ланцюжка визначають, що з існує не більше однієї альтернативи виведення ланцюжка, що починається з та продовжується наступними термінальними символами.
Означення.
Сформулюємо основні твердження стосовно класу -граматик:
1) Не існує алгоритма, який перевіряє належність КС-граматики класу -граматик.
2) Існує алгоритм, який для конкретного перевіряє, чи є задана граматика -граматикою.
3) Якщо граматика є -граматикою, то вона є -граматикою, ( ).
4) Клас -граматик — це підклас КС-граматик, який не покриває його.
Продемонструємо на прикладі справедливість твердження 4. Розглянемо граматику з наступною схемою :
Мова, яку породжує наведена вище граматика . Візьмемо виведення наступного ланцюжка ; за означенням LL(K)-граматики , тоді маємо
Таким чином, КС-граматика не може бути -граматикою для жодного . Як результат, КС-граматика , яка має ліворекурсивний нетермінал ( нетермінал називається ліворекурсивний, якщо в граматиці існує вивід виду ), не може бути -граматикою.
З практичної точки зору в більшості випадків ми будемо користуватися -граматиками. У класі -граматик існує один цікавий підклас - це розподілені -граматики.
Означення. -граматика називаються розподіленою, якщо вона задовольняю наступним умовам:
- у схемі граматики відсутні -правила (правила виду );
- для нетермінала праві частини -правила починаються різними терміналами.
Для подальшого аналізу означення -граматики розглянемо алгоритм обчислення функції .
Означення: Якщо , то , де — бінарна операція над словарними множинами (мовами):
.
Висновок, якщо , де , тоді
Очевидно, якщо , то при . Розглянемо алгоритм пошуку
Алгоритм. Пошук множини .
Визначимо значення функції для кожного .
П1. для всіх .
П2.
в інших випадках - невизначено.
Пn.
в інших випадках - невизначено.
Пm. для всіх .
Очевидно, що:
- послідовність — монотонно зростаюча;
- — послідовність, обмежена зверху.
Тоді покладемо для кожного .
Приклад: Знайти множину Firstk(Ai) для нетерміналів граматики з наступною схемою правил:
S -> BA
A -> +BA | ε
B -> DC
C -> *DC | ε
D -> (S) | a
Нехай k=2.
Fn\Ai | S | A | B | C | D |
F0 | -- | { ε } | -- | { ε } | {a} |
F1 | -- | { ε } | {a} | { ε, *a} | {a} |
F2 | {a} | {ε, +a} | {a, a*} | { ε, *a} | {a} |
F3 | {a, a+, a*} | {ε, +a} | {a, a*} | { ε, *a} | {a, (a} |
F4 | {a, a+, a*} | {ε, +a} | {a, a*, (a} | { ε, *a, *(} | {a, (a} |
F5 | {a, a+, a*, (a} | {ε, +a, +(} | {a, a*, (a} | { ε, *a, *(} | {a, (a} |
F6 | {a, a+, a*, (a} | {ε, +a, +(} | {a, a*, (a} | { ε, *a, *(} | {a, (a, ((} |
F7 | {a, a+, a*, (a} | {ε, +a, +(} | {a, a*, (a, ((} | { ε, *a, *(} | {a, (a, ((} |
F8 | {a, a+, a*, (a, ((} | {ε, +a, +(} | {a, a*,(a, ((} | { ε, *a, *(} | {a, (a, ((} |
F9 | {a, a+, a*, (a, ((} | {ε, +a, +(} | {a, a*, (a, ((} | { ε, *a, *(} | {a, (a, ((} |
Скористаємося означенням сформулюємо необхідні й достатні умови, за яких КС-граматика буде -граматикою:
для довільного виводу в граматиці G виду та правила :
(1)
Вище сформульована умова для -граматик може бути перефразована з урахуванням визначення множини :
для довільного виводу в граматиці виду та правила :
, де (2).
Оскільки , то умова (2) є конструктивною умовою і може бути використана для перевірки, чи КС-граматика є -граматикою для фіксованого .
Означення: КС-граматика називається сильною -граматикою, якщо для А-правила виду задовольняється умова:
,
де визначається так:
Операції та можна узагальнити для словарної множини , тоді:
.
Без доведення зафіксуємо наступні твердження:
- кожна -граматика є сильною -граматикою;
- існують -граматики (k>1), які не є сильними -граматиками.
На прикладі продемонструємо останнє твердження. Нехай граматика визначена наступними правилами:
, .
Відповідні множини , , ,
.
Перевіримо умову для сильної -граматики:
а) виконаємо перевірку -умови для правила
б) виконаємо перевірку -умови для правила
Висновок: вище наведена граматика не є сильною -граматикою. Перевіримо цю ж граматику на властивість -граматики. Тут ми маємо два різні варіанти виводу з S:
а)
б)
Висновок: наведена вище граматика є -граматикою.
Алгоритм. Обчислення .
Для побудови алгоритму пошуку множини розглянемо наступні приклади на синтаксичному дереві, які дозволять перейти до узагальнень.Подивимося на синтаксичне дерево висоти 1 для правила S
ω1 A ω2
Мал. 6
Тоді .
Далі розглянемо дерево висоти 2:
S
ω1 AJ ω2
ω3 A ω4
Мал. 7.
Тоді . В силу вищесказаного, будемо знаходити значення функції , тобто будемо розглядати всілякі дерева, які можна побудувати, починаючи з аксіоми .
П0. . Очевидно, за 0 кроків ми виведемо S, після якої знаходиться . У інших випадках — невизначено .
П1. . В інших випадках — невизначено.
….
Пn . В інших випадках — невизначено.
….
Настане крок Пm, коли , .
Тоді покладемо для кожного .
Очевидно, що:
- послідовність монотонно зростаюча;
- послідовність обмежена зверху.
До того, як перевірити граматику на -властивість необхідно перевірити її на наявність ліворекурсивних нетерміналів та спробувати уникнути лівої рекурсії.
Означення: Нетермінал КС-граматики називається -нетерміналом, якщо .
Алгоритм.Пошук -нетерміналів:
….
…. Пn
Тоді множина — множина -нетерміналів.
Приклад. Для граматики G з схемою правил Р знайдемо множину -нетерміналів:
=
Таким чином, множина -нетерміналів для наведеної вище граматики -
Алгоритм.Тестування нетермінала на ліву рекурсію. Для кожного нетермінала Аi побудуємо наступну послідовність множин S0, S1, ….
, починаємо з нетерміналу Аi.
….
….
Тоді якщо , то — ліворекурсивний нетермінал.
Приклад. Для граматики G з схемою правил Р знайдемо множину ліворекурсивних нетерміналів:
1. Виконаємо процедуру тестування для кожного нетермінала окремо:
- наприклад, для нетермінала S:
Запропонуємо декілька прийомів, що дають можливість при побудові граматик уникнути лівої рекурсії. Розглянемо граматику зі схемою правил , яка має ліворекурсивний нетермінал . Замінимо схему правил новою схемою з трьома правилами
.
Приклад: Для граматики G з схемою правил Р для кожного нетермінала знайдемо множину (k=1):
S -> BA
A -> +BA | ε
B -> DC
C -> *DC | ε
D -> (S) | a
З прикладу, що наведено раніше множини First1(A) ,будуть такими:
First1(S)= First1(B)= First1(D)={(,a}, First1(A)={+, ε }, First1(C)={*, ε }.
δn\Ai | S | A | B | C | D |
δ0 | { ε } | -- | -- | -- | -- |
δ 1 | { ε } | { ε } | {+, ε } | -- | -- |
δ 2 | { ε } | {ε} | {+, ε } | {+, ε } | |
δ 3 | { ε } | {ε} | {+, ε } | {+, ε } | {*, +, ε } |
δ 4 | { ε, ) } | {ε} | {+, ε } | {+, ε } | {*, +, ε } |
δ 5 | { ε, ) } | {ε, )} | {+, ε } | {+, ε, )} | {*, +, ε } |
δ 6 | { ε, ) } | {ε, )} | {+, ε , )} | {+, ε } | {*, +, ε , )} |
δ 7 | { ε, ) } | {ε, )} | {+, ε , )} | {+, ε , )} | {*, +, ε , )} |
Таким чином, Follow1(S)= { ε, ) }, Follow1(A)= {ε, )}, Follow1(B)= {+, ε, )}, Follow1(C)= {+, ε , )}, Follow1(D)= {*, +, ε , )}.