Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Glava_5a.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
546.3 Кб
Скачать

5.1.5 Побудова таблиць предиктивного аналізу

Для побудови таблиці предиктивного аналізу даної граматики G може використатися наведений далі алгоритм. Ідея, що лежить в основі алгоритму, полягає в наступному. Припустимо, що А::=α являє собою продукцію, у якої a FIRST(α). Тоді синтаксичний аналізатор замінить нетермінал A рядком α при поточному вхідному символу α. Єдина складність виникає при α::=ε або α →* ε. У цьому випадку ми знову повинні замінити А на α, якщо поточний вхідний символ є в FOLLOW(A) або із вхідного потоку отримано $, що входить в FOLLOW(A).

Алгоритм 5.2. Побудова таблиці предиктивного аналізу

Вхід. Граматика G.

Вихід. Таблиця аналізу М.

Метод.

  1. Для кожної продукції граматики А::=α виконуємо кроки 2 – 4.

  2. Для кожного термінала а з FIRST(α) додаємо А::=α в комірку M[A,а].

  3. Якщо в FIRST(α) входить ε, для кожного термінала b з FOLLOW(A) додаємо А::=α в комірку M[A,b].

  4. Якщо ε входить в FIRST(α), а $ – в FOLLOW(A), додаємо А::=α в комірку M[A,$].

  5. Зробимо кожну невизначену комірку таблиці M такою, що вказує на помилку.

Приклад 5.5. Застосуємо алгоритм 5.2 до граматики (4.11),

(1) Е ::= ТЕ' (2) Е' ::= +TЕ' (3) Е' ::= ε (4) T ::= FТ'

(5) Т' ::= * FТ' (6) Т' ::= ε (7) F ::= (Е) (8) F ::= id

множини FIRST() і FOLLOW() для яких були визначені вище.

FIRST(E)=FIRST(T) = FIRST(F)

=

{(, id}

FIRST(E')

=

{+, ε}

FIRST(T')

=

{*, ε}

FOLLOW(E) = FOLLOW(E')

=

{), $}

FOLLOW(T) = FOLLOW(T')

=

{+, ), $}

FOLLOW(F)

=

{+,*,),$}

a) Розглянемо нетермінал E ::= ТE', для якого α=ТE'. Оскільки FIRST(α)= FFIRST(TE')= FIRST(T)= {(, id}, продукція E::=ТE' приводить, за правилом #2, до розміщення в комірках М[Е,(] і M[E,id] запису E ::= ТE'.

b) Для продукції E' ::= + ТE' FIRST(ТE')={+}, що дозволяє, за правилом #2, внести її в комірку M[E',+].

c) Продукція E'::=ε приводить, з урахуванням FOLLOW(E') = {), $} та правилом #3, до внесення E'::= ε до комірок M[E', )] і M[E', $].

d) Розглянемо нетермінал T ::= FТ'. Оскільки FFIRST(FТ')= FIRST(F)= {(, id}, продукція T ::= FТ' приводить, за правилом #2, до розміщення в комірках М[Т,(] і M[Т,id] запису T ::= FТ'.

e) Для продукції Т' ::= *FТ' FIRST(*FТ')={*}, що дозволяє, за правилом #2, внести її в комірку M[Т',*].

f) ) Продукція Т'::=ε приводить, з урахуванням FOLLOW(Т') = {+, ), $} та правилом #3, до внесення Т'::= ε до комірок M[Т', +] M[Т', )] і M[E', $].

g) Розглянемо F ::= (Е). Оскільки FIRST((Е))= {(}, то за правилом #2 в комірці М[F,(] розміщуємо F ::= (Е).

h) Розглянемо F ::= id. Оскільки FIRST(id)= {id}, то за правилом #2 в комірці М[F, id] розміщуємо F ::= id.

Повністю таблицю предиктивного аналізу, побудована за алгоритмом 5.4 для грамматики (4.11), було наведено на рис. 5.7.

5.1.6 LL(1)-граматики

Алгоритм 5.4 може бути застосований до будь-якої граматики G для одержання таблиці розбору М. Однак для деяких граматик M може мати кілька записів в одній комірці таблиці. Наприклад, якщо G – ліворекурсивна або неоднозначна граматика, то M буде мати як мінімум одну комірку з декількома записами.

Приклад 5.6. Звернемося знову до граматики (4.13) із приклада 4.10.

S ::= iEtSS' | a

S' ::= es | ε

E ::= b

Таблиця аналізу для цієї граматики показана на рис. 5.9.

Комірка таблиці M[S',е] містить два записи – S' ::= eS і S' ::= ε, оскільки FOLLOW(S') = {e,$}. Неоднозначність граматики проявляється у виборі продукції, яка використовується при одержанні із вхідного потоку символу е (else). Ми можемо позбутися неоднозначності вибором S' ::= eS, що означає відповідність else найближчому попередньому then. Помітимо, що вибір S' ::= ε буде перешкоджати внесенню е в стек і видаленню із вхідного потоку, що, природно, неправильно.

Нетермінал

Вхідний символ

a

b

e

i

T

$

S

Sa

SiEtSS'

S'

S'ε

SeS

S' → ε

E

E b

Рис. 5.9 Таблиця аналізу для граматики (4.13)

Граматика, таблиця аналізу якої не має множинних записів, називається LL(1). Перше "L" означає перегляд вхідного потоку зліва направо, друге "L"– ліве породження, а "1" – перегляд одного символу із вхідного потоку на кожному кроці для прийняття рішення про подальші дії. Можна показати, що алгоритм 5.2 для кожної LL(1)-граматики G будує таблицю аналізу, що розбирає всі речення G, і тільки їх.

LL(1)-граматики мають ряд відмітних властивостей. Така граматика не може бути неоднозначною або ліворекурсивною. Можна також показати, що граматика G є LL(1)-граматикою тоді й тільки тоді, коли для будь-яких двох різних її продукцій А ::= α | β виконуються наступні умови.

  1. Не існує такого термінала а, для якого і α, і β породжують рядок, що починається з а.

  2. Порожній рядок може породжувати тільки одна із продукций α або β.

  3. Якщо β * ε, то α не породжує ні один рядок, що починається з термінала із FOLLOW(A).

Ясно, що граматика (4.11) для арифметичних виразів є LL(1)-граматикою. Граматика ж (4.13), що моделює інструкції if-then-else, не є такою.

Залишається питання, що робити, якщо таблиця аналізу має комірки з декількома записами. Один вихід полягає в перетворенні граматики, що усуває ліву рекурсію, і її лівої факторизації, в надії одержати граматику, в таблиці аналізу якої відсутні комірки з декількома записами. На жаль, є граматики, ніякі зміни яких не приведуть до LL(1)-граматики. Прикладом може служити граматика (4.13). Як ми бачили, граматику (4.13) можна аналізувати за допомогою предиктивного синтаксичного аналізатора шляхом вибору M[S',е] = {S'eS}. Взагалі ж, не існує універсальних правил, за допомогою яких комірки з декількома записами можна перетворити в однозначні без певного впливу на мову, розпізнавану синтаксичним аналізатором.

Основна складність у використанні предиктивного аналізу складається в написанні для вхідної мови такої граматики, що дозволяє побудувати предиктивнй синтаксичний аналізатор. Хоча усунення лівої рекурсії й ліва факторизация прості в реалізації, вони роблять граматику нечитабельною і важкою для трансляції. Звичайна організація синтаксичного аналізатора в компіляторі полягає у використанні предиктивного синтаксичного аналізатора для керуючих конструкцій і визначення пріоритету операторів для виразів. Однак, якщо є генератор LR-аналізаторів, описаний у п. 5.2, то можна одержати всі переваги предиктивного аналізу й визначення пріоритету операторів автоматично.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]