4.4 Побудова таблиць предиктивного аналізу
Для конструювання таблиць предиктивного аналізу даної граматики G може бути використаний алгоритм, ґрунтується на такій ідеї. Припустимо, що A→α – продукція граматики і a FIRST(α). Тоді аналізатор робить розгортання A за α, якщо вхідним символом є a. Труднощі виникають, коли α=ε або α ε. У цьому випадку потрібно розгорнути A у α, якщо поточний вхідний символ належить FOLLOW(A) або якщо з вхідного потоку одержано $ і $ FOLLOW(A).
Алгоритм 4.4 Побудова таблиць предиктивного аналізу
Для кожної продукції A→α граматики виконати кроки 1 і 2.
Крок 1 Для кожного термінала a з FIRST(α) додати A→α в M[A,a].
Крок 2 Якщо ε FIRST(α), додати A→α в M[A,b] для кожного термінала b з FOLLOW(A). Якщо ε FIRST(α) і $ FOLLOW(A), додати A→α в M[A,$].
Крок 3 Прийняти, що всі невизначені входи таблиці M вказують на помилку.
Застосуємо алгоритм до граматики (4.2). Оскільки FIRST(TE')=FIRST(T)={(, id}, у відповідності з продукцією E→TE' входи M[E,(] і M[E, id] стають рівними E→TE'.
Відповідно до продукції Е'→+TE' вхід M[Е',+] дорівнює Е'→+TE'. У відповідності з продукцією Е'→ε входи M[Е',)] і M[Е',$] рівні Е'→ε, оскільки FOLLOW(Е') ={ ), $}.
Таблиця аналізу, побудована алгоритмом, була представлена вище таблицею 4.1.
4.5 Ll(1)-граматики
Алгоритм побудови таблиці M предиктивного аналізу може бути застосований до будь-якої граматики. Однак для деяких граматик M може мати неоднозначно визначені входи. Наприклад, якщо граматика ліворекурсивна або неоднозначна, M буде мати хоча б один неоднозначно визначений вхід.
Граматики, для яких таблиці аналізу не мають неоднозначно визначених входів, називаються LL(1). Перше L означає сканування входу зліва направо, друге L означає, що будується ліве породження, 1 – що на кожному кроці для прийняття рішення використовується один символ непереглянутого ланцюжка.
Можна показати, що алгоритм побудови таблиці предиктивного аналізу для кожної LL(1)-граматики G будує таблиці, за якими розпізнаються всі ланцюжки мови, визначеної граматикою G, і тільки вони.
LL(1)-граматики мають кілька відмітних властивостей.
Неоднозначна, або ліворекурсивна, граматика не може бути LL(1)-граматикою.
Можна також показати, що граматика G є LL(1)-граматикою тоді і тільки тоді, коли для двох правил вигляду A→α | β виконується таке:
1) ні для якого термінала a одночасно з α і β не виводяться рядки, що починаються з a;
2) тільки з одного рядка α або β може виводитися порожній рядок;
3) якщо β ε, то з α не виводиться ніякий рядок, що починається з терміналу з FOLLOW(A).
Мову, для якої можна побудувати LL(1)-граматику, називають LL(1)-мовою.
4.6 Висхідний аналіз
У цьому розділі розглянемо основний метод висхідного синтаксичного аналізу, відомий як “перенесення-згортання”. Далі будемо коротко називати його ПЗ-аналіз.
У процесі розбору типу “перенесення-згортання” будується дерево розбору вхідного рядка, починаючи з листів (знизу) до кореня (вгору). Цей процес можна розглядати як “згортання” рядка w до початкового символа граматики. На кожному кроці процесу згортання підрядок, який можна зіставити правій частині деякої продукції, заміняється символом з лівої частини цієї продукції, і якщо на кожному кроці вибирається правильний підрядок, то у зворотному порядку простежується праве породження.
Розглянемо граматику
S → aABe ,
A → Abc | b ,
B → d .
Рядок abbcde зводиться до S за допомогою таких кроків:
abbcde
aAbcde
aAde
aABe
S .
Ми скануємо рядок abbcde у пошуках підрядка, що відповідає правій частині якоїсь продукції. Такими підрядками є b і d . Виберемо крайнє зліва b і замінимо його нетерміналом A, що являє собою ліву частину продукції A→b; таким чином, одержимо рядок aAbcde. Тепер правим частинам продукцій відповідають підрядки Abc, b і d. Хоча b і є крайнім зліва підрядком, що відповідає правій частині однієї з продукцій, виберемо для заміни підрядок Abc і замінимо його нетерміналом A відповідно до продукції A→Abc. У результаті одержимо рядок aAde. Заміняючи d на B, ліву частину продукції B→d, одержуємо aABe, що відповідно до першої продукції заміняється стартовим символом S. Отже, послідовність з чотирьох згортань дозволяє привести рядок abbcde до стартового символа S. Ці скорочення являють собою обернене праве породження
S
aABe
aAde
aAbcde
abbcde
.
