Ліворекурсивна пара продукцій 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ліворекурсивний, оскільки SAaSda, але ця рекурсія не є безпосередньою.
Наведений нижче алгоритм дозволяє видалити всі ліві рекурсії з граматики.
Алгоритм 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>і.
Розглянутий алгоритм гарантовано працює з граматиками, які не мають циклів (породжень типу AA) і ε-продукцій (продукцій типу 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. Таким чином, лівофакторизовані продукції наберуть вигляду:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.