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

3.3 Видалення лівої рекурсії

Граматика ліворекурсивна, якщо в ній є нетермінал A такий, що існує породження A для деякого рядка α. Ліворекурсивні граматики не можуть аналізуватися методами “зверху-вниз”, тому необхідне видалення лівої рекурсії.

Ліворекурсивна пара продукцій A→Aα | β може бути замінена неліворекурсивними продукціями:

A → βA' ,

A' → αA' | ε

без зміни кількості рядків, що породжуються з A. Цього правила достатньо для багатьох граматик.

Розглянемо таку граматику для арифметичних виразів:

E E+T | T ,

F T*F | F ,

F (E) | id .

Після видалення рекурсії з продукцій для E і T одержимо:

E TE' , E’ +TE' | ε ,

T FT ' , T’ *FT ' | ε , (3.1)

F (E) | id .

Неважливо, яка загальна кількість A-продукцій. Ми можемо видалити безпосередню ліву рекурсію з них за допомогою такої технології. Спочатку групуємо A-продукції:

A → Aα1 | Aα2 | ... | Aαm | β1 | β 2 | .... | β n ,

де βi не починається з A. Потім заміняємо ці A-продукції на

A → β1A' | β 2A' | .... | β n A' ,

A'→ α1A' | α2A' | .... | αmA' | ε .

Нетермінал A породжує ті самі рядки, що і раніше, але тепер немає лівої рекурсії. За допомогою цієї процедури видаляються всі безпосередні ліві рекурсії, але не видаляється ліва рекурсія, що включає два або більше кроків породження. Розглянемо, наприклад, граматику:

S → Aa | b ;

A→ Ac | Sd | ε .

Нетермінал S ліворекурсивний, оскільки S Aa Sda, але ця рекурсія не є безпосередньою.

Наведений нижче алгоритм дозволяє видалити всі ліві рекурсії з граматики.

Алгоритм 3.1 Видалення лівої рекурсії

Крок 1 Упорядковуємо нетермінали в довільному порядку A1, A2, …, An.

Крок 2

for і:=1 to n do begin

for j:=1 to і -1 do begin

Замінити всі продукції вигляду Ai → Ajγ

продукціями Ai → δ1γ | δ2γ | ... | δkγ,

де Aj → δ1 | δ2 | ... | δk – всі поточні Aj-продукції

end

Видалити безпосередню ліву рекурсію серед

Ai- продукцій

end

Обґрунтування працездатності алгоритму базується на тому, що після і-1 ітерації зовнішнього циклу for кроку 2 для будь-якої продукції вигляду Ak→Al α, k < i, повинно бути l >k. У результаті на наступній ітерації внутрішнього циклу (за j) послідовно збільшується нижня границя m всіх продукцій A i→ Amα, поки не буде досягнуто m≥і. Потім, видаляючи безпосередню ліву рекурсію для Ai-продукцій, одержуємо m>і.

Розглянутий алгоритм гарантовано працює з граматиками, які не мають циклів (породжень типу A A) і ε-продукцій (продукцій типу A → ε). Як цикли, так і ε-продукції можуть бути вилучені попередньо.

3.4 Ліва факторизація

Ліва факторизація являє собою перетворення граматики у форму, придатну для предиктивного аналізу.

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

Наприклад, якщо є дві продукції

stmt if expr then stmt else stmt

| if expr then stmt ,

то, після знаходження у вхідному потоці if, ми не можемо відразу вибрати ні одну з них. У загальному випадку, якщо A→αβ1 | αβ2 – дві A-продукції і вхідний потік починається з непорожнього рядка, виведеного з α, ми не можемо сказати, буде використовуватися перша чи друга продукція. Однак можна відкласти рішення, розширивши A до αA'. У цьому випадку, після розгляду вхідного потоку, що виводиться з α, ми працюємо з A', розширюючи його до β1 або до β2. Таким чином, лівофакторизовані продукції наберуть вигляду:

A → αА' ,

А' → β1 | β2 .

Алгоритм 3.2 Ліва факторизація граматики

Для кожного нетермінала A шукаємо найдовший префікс α, спільний для двох або більше його альтернатив. Якщо α ≠ ε, тобто існує нетривіальний спільний префікс, заміняємо всі A-продукції A → αβ1 | αβ 2 | ... | αβ n | γ, де γ представляє всі альтернативи, які не починаються з α, продукціями:

A → αА' | γ ,

А' → β1 | β2 | ... | βn .

Тут А' – новий нетермінал. Повторно застосовуємо це перетворення, поки ніякі дві альтернативи не будуть мати спільний префікс.

Розглянемо знову граматику умовних операторів:

S → iEtS | iEtSeS | a ,

Eb .

Тут i, t, e означають if, then, else, E і S відповідають expr і stmt.

Після лівої факторизації граматика набере такого вигляду:

S → iEtSS' | a ,

S'eS | ε ,

E b .

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