
4.7 Обрізання основ
Неформально кажучи, основа рядка – це підрядок, який збігається з правою частиною продукції і згортання якої в ліву частину продукції являє собою один крок оберненого правого породження. У багатьох випадках крайній зліва підрядок β, що відповідає правій частині деякої продукції A→β, не є основою, оскільки згортання у відповідності з продукцією A→β приводить до рядка, який не може бути згорнутий до стартового символа. Якщо в попередньому прикладі ми замінимо у другому рядку aAbcde символ b нетерміналом A, то одержимо рядок aAAcde, який не може бути згорнутий до S. Тому нам потрібно дати більш точне визначення основи.
Кажучи
формально, основа правосентенціальної
форми γ
є продукцією A→β
і позицією рядка β
в
γ,
такими, що β
може
бути замінена нетерміналом A
для
одержання попередньої правосентенціальної
форми у правому породженні γ.
Таким чином, якщо S
αAw
αβw,
то
A→β
в позиції після α
являє собою основу рядка αβw.
Рядок w
праворуч
від основи містить тільки термінальні
символи. Відмітимо, що граматика може
бути неоднозначною, з кількома правими
породженнями αβw.
Якщо граматика однозначна, то кожна
правосентенціальна форма граматики
має тільки одну основу.
У наведеному прикладі abbcde являє собою право- сентенціальну форму, основою якої є A→β в позиції 2. Аналогічно aAbcde являє собою правосентенціальну форму, основою якої є A→Abc в позиції 2.
Розглянемо таку граматику:
E → E + E , E → E * E ,
E → ( E ) , E → id
і праве породження
E E+E E+E*E E+E* id3
E+ id2 * id3 id1 + id2 * id3 .
Для зручності тут підкреслено основи кожної правосентенціальної форми. Наприклад id1 являє собою основу правосентенціальної форми id1+ id2* id3, оскільки id є правою частиною продукції E→ id, і заміна id1 на E приведе до попередньої правосентенціальної форми E+id2* id3.
Обернене праве породження може бути отримане за допомогою повторного застосування “обрізання основ”. Ми починаємо процес з рядка терміналів w. Якщо w є словом граматики, то w=γn, де γn – правосентенціальна форма ще невідомого правого породження
S = γ0 γ1 γ2 ... γn-1 γn = w .
Щоб відновити це породження у оберненому порядку, виділяємо основу βn у γn і заміняємо βn на ліву частину деякої продукції An→βn, в результаті одержимо (n-1)-у правосентенціальну форму γn-1.
Потім повторюємо цей процес, тобто виділяємо у γn-1 основу βn-1 і згортаємо цю основу, одержуючи правосентенціальну форму γn-2. Якщо, повторюючи цей процес, ми одержимо правосентенціальну форму, що складається тільки з початкового символа S, то зупиняємося і повідомляємо про успішне завершення розбору. Обернена послідовність продукцій, використаних у згортках, є праве породження вхідного рядка.
Для вхідного рядка id1+ id2 * id3 послідовність згортань наведена в табл. 4.3.
Таблиця 4.3
Правосентенціальна форма |
Основа |
Продукція для згорання |
id1+ id2 * id3 E+ id2 * id3 E+ E * id3 E+ E * E E+ E E |
id1 id2 id3 E * E E+ E
|
E → id E → id E → id E → E * E E → E + E
|
Зручним шляхом реалізації ПЗ-аналізатора є використання стека для зберігання символів граматики і вхідного буфера для зберігання рядка, що аналізується. Для маркера дна стека ми використовуємо $, і цей самий символ буде маркером правого кінця вхідного рядка. Спочатку стек порожній, а вхідний буфер містить рядок w.
Синтаксичний аналізатор працює шляхом перенесення нуля або декількох символів у стек доти, поки на вершині стека не виявиться основа β. Потім він згортає β до лівої частини відповідної продукції. Синтаксичний аналізатор повторює цей цикл, поки не буде виявлена помилка або він не прийде в конфігурацію, коли в стеку знаходиться тільки стартовий символ, а вхідний буфер порожній.
У цій конфігурації синтаксичний аналізатор припиняє роботу і повідомляє про успішний розбір вхідного рядка.
Пройдемо по кроках всі дії, які виконуються синтаксичним аналізатором при розборі вхідного рядка id1+id2 * id3. Послідовність дій показана в табл. 4.4.
Основними операціями синтаксичного аналізатора являються перенесення і згортання, але фактично ПЗ-аналізатор може виконувати чотири дії: перенесення, згортання, допуск і виявлення помилки.
Таблиця 4.4
Стек |
Вхід |
Дія |
$ $ id1 $E $E+ $E+ id2 $E+ E $E+ E* $E+ E* id3 $E+ E*E $E+ E $E
|
id1+id2 * id3$ +id2 * id3$ +id2 * id3$ id2 * id3$ * id3$ * id3$ id3$ $ $ $ $ |
Перенесення Згортання за E → id Перенесення Перенесення Згортання за E → id Перенесення Перенесення Згортання за E → id Згортання за E → E*E Згортання за E → E+E Допуск
|
При перенесенні черговий символ переноситься на вершину стека.
При згортанні синтаксичний аналізатор розпізнає правий кінець основи на вершині стека, після чого він повинен знайти лівий кінець основи і прийняти рішення про те, яким нетерміналом замінити основу.
При допуску синтаксичний аналізатор повідомляє про успішний розбір вхідного рядка.
При помилці синтаксичний аналізатор знаходить помилку у вхідному потоці і викликає програму відновлення після помилки.