Transformace a normální formy bezkontextových gramatik
Derivace a derivační stromy
Gramatika (N, Σ, P, S)
Vlastní gramatika
Rekurzivní pravidla
Rekurzivní zleva: A → Aα
Rekurzivní zprava: A → αA
Rekurzivní: A → αAβ
Každý bezkontextový jazyk lze generovat gramatikou bez levé rekurze
Všechna pravidla s levou rekurzí lze nahradit pravidly s pravou rekurzí
Odstranění nedostupných symbolů
Převod gramatiky (N, Σ, P, S) na gramatiku bez nedostupných stavů (N′, Σ′, P′, S)
Najdeme všechny dostupné terminály a nonterminály
i = 0
V₀ = {S} (tj. v nultém kroku je dostupný pouze počáteční stav)
repeat
Vᵢ₊₁ = Vᵢ ∪ {X | A → αXβ ∈ P ∧ A ∈ Vᵢ} (tj. do množiny dostupných přidáme všechny terminály a nonterminály, kterlé lze získat přepisem z některého nonterminálu z množiny dostupných z předchozího kroku)
i++ (tj. přejdeme k dalšímu kroku)
until
Vᵢ₊₁ = Vᵢ₋₁ (tj. končíme pokud se nám v posledním kroku množina dostupných nezměnila)
Novou gramatiku sestavíme jako:
N′ = Vᵢ ∩ N (tj. použijeme pouze dosažitelené nonterminály)
Σ′ = Vᵢ ∩ Σ (tj. použijeme pouze dosažitelené terminály)
P′ ⊂ P obsahuje pouze pravidla používající pouze symboly z Vᵢ
Odstranění zbytečných symbolů
Převod gramatiky (N, Σ, P, S) na gramatiku bez nedostupných stavů (N′, Σ, P′, S)
Nalezení nonterminálů, které produkují terminální řetězce
i = 0
N₀ = ∅ (tj. v nultém kroku začínáme s prázdnou množinou nonterminálů generujících terminální řetězce)
repeat
Nᵢ₊₁ = Nᵢ ∪ {A | A → α ∈ P ∧ α ∈ (Nᵢ ∪ Σ)*} (tj. do množiny všechny terminály, které lze přepsat na řetězce skladádající se pouze z terminálů nebo nonterminálů, které jsou již v množině nonterminálů generujících terminální řetězce)
i++ (tj. přejdeme k dalšímu kroku)
until Nᵢ₊₁ = Nᵢ₋₁ (tj. končíme pokud se nám v posledním kroku množina nezměnila)
Vytvoříme gramatiku bez nonterminálů, které neprodukují terminální řetězce:
Odstraníme nedostupné symboly z gramatiky
Odstranění ε-pravidel
Převod gramatiky (N, Σ, P, S) na gramatiku bez ε-pravidel (N′, Σ′, P′, S′)
Sestavení množiny nonterminálů, které mohou generovat ε Nε
Sestavíme novou množinu přepisovacích pravidel P′
Jestliže A → α₀B₁α₁…Bₖαₖ ∈ P, k ≥ 0 a všechna Bᵢ jsou v Nε a žádný symbol αᵢ není v Nε pak k P′ přidej všechny prvidla tvaru A → α₀X₁α₂X₂…Xₖαₖ kde Xᵢ je buď Bᵢ nebo ε. Nepřidává se pravidlo A → ε.
Tj. od každého pravidla sestavíme všechny možné kombinace, kde jsou jednotlivé částí přepsatelné na ε vynechány
Zavedeme nový počáteční nonterminál S′
Jestliže je S v Nε pak přidáme do P′ pravidla S′ → ε a S′ → S
Odstranění jednoduchých pravidel
Převod gramatiky bez ε-pravidel (N, Σ, P, S) na gramatiku bez jednoduchých pravidel (N, Σ, P′, S)
Pro každé A ∈ N sestrojíme množinu NA = {B | A ⇒* B}
i = 0
N₀ = {A}
repeat
Nᵢ₊₁ = Nᵢ ∪ {C | B → C ∈ P ∧ B ∈ Nᵢ}
i++
until
Nᵢ = Nᵢ₋₁ (tj. končíme pokud se nám v posledním kroku množina nezměnila)
NA = Nᵢ
Sestavíme novou množinu P′
Pro všechna nejednoduchá pravidla B → α přidáme do P′ pravidla A → α pro všechna A pro něž platí B ∈ NA, tj. pro každého nejednoduché pravidlo najdeme všechny nonterminály A, které jdou jednoduchými pravidly přepsat na B, a vytvoříme všechny varianty pravidla, kde levou stranu nahradíme za A.
Odstranění levé rekurze
Převod vlastní gramatiky (N, Σ, P, S) na gramatiku bez levé rekurze (N′, Σ, P′, S).
Nonterminály vyjádříme jako N = {A₁, A₂, …, Aₙ} tj. zvolíme pořadí jednotlivých nonterminálů.
Gramatiku budeme transformovat tak, že je-li Aᵢ → α pravidlo pak α začíná buď terminálem nebo nonterminálem Aj, který je v pořadí až za Aᵢ (j > i).
i = 1 (tj. začneme prvním nonterminálem v pořadí)
Vezmeme všechna Aᵢ-pravidla, která jsou buď ve tvaru Aᵢ → Aᵢαₓ nebo Aᵢ → βₓ, kde β nezačíná nonterminálem, který je v pořadí před Aᵢ
Přidáme nový nonterminál Aᵢ′ do N′
Všechna Aᵢ-pravidla nahradíme za:
Aᵢ → β₁ | β₂ | … | βₓ (tj. přepisy na β zachováme)
Aᵢ → β₁Aᵢ′ | β₂Aᵢ′ | … | βₓAᵢ′ (tj. pro všechny přepisy na β vytvoříme pravidla s vpravo přidaným Aᵢ′)
Aᵢ′ → α₁ | α₂ | … | αₓ (tj. u přepisů na Aᵢα vytvoříme pravidla pouze s α)
Aᵢ′ → α₁Aᵢ′ | α₂Aᵢ′ | … | αₓAᵢ′ (tj. u přepisů na Aᵢα vytvoříme pravidla s odstraněným Aᵢ a vpravo přidaným Aᵢ′
Tím dosáhneme toho, že všechna Aᵢ-pravidla začínají buď terminálem nebo nonterminálem, který je v pořadí až za Aᵢ)
Pokud jsme již prošli všechny nontermínály (i = n) končíme
i++
Pro všechny dosud procházené nonterminály Aj (1 < j < i)
Pravidlo Aᵢ → Ajα odstraníme
Pro každé Aj-pravidlo (Aj → β) vytvoříme Aᵢ → βα, tj. vezmeme všechna Aᵢ-pravidla, jejichž pravá strana začíná nonterminálem Aj, který je v pořadí před Aᵢ, a nahradíme je za pravidla ve kterých je Aj nahrazeno všemi řetězci na které jej lze přepsat.
Jdeme na krok 2
Chomsky normal form
Přepisovací pravidla jsou pouze ve tvaru:
Převod vlastní gramatiky bez jednoduchých pravidel (N, Σ, P, S) na gramatiku v CNF (N′, Σ, P′, S′)
Množina P′ obsahuje všechny pravidla z P ve tvaru A → BC a A → a, případně S → ε.
Každé pravidlo tvaru A → X₁X₂…Xₖ (k > 2) přepíšeme do P′ jako sérii pravidel:
A → X₁X₂′
X₂′ → X₂X₃′
…
Xₖ₋₁′ → Xₖ₋₁Xₖ
Zavedeme nové non-terminální symboly A → X₂′…Xₖ₋₁′ (tj. pravidla mající pravou stranu delší než dva prvky rozdělíme na navazující sérii pravidel majících napravo jen dva prvky)
Ve všech pravidlech v P′ které nejsou ve tvaru A → a, kde se vyskytují na pravé straně terminály, nahradíme tyto terminály a za nové non-terminály A′ a přidáme pravidlo A′ → a (tj. nepovolená pravidla s terminály na pravé straně upravíme tak, že terminál nahradíme nonterminálem, který se přepisuje na původní terminál)
Greibach normal form
Převod vlastní gramatiky bez levé rekurze (N, Σ, P, S) na gramatiku v GNF (N′, Σ, P′, S′):
Seřadíme všechny nonterminály tak, aby pravá strana žádného přepisovacího pravidla nezačínala nonterminálem, který je v pořadí před přepisovaným nonterminálem. (v podstatě stejná pořadí v jakém máme nonterminály během algoritmu odstranění levé rekurze): N = {A₁, A₂, …, Aₙ}
Postupně pro všechny nonterminály Aᵢ od Aₙ₋₁ sestupně po A₁:
Pro každé pravidlo Aᵢ → Ajα:
Odstraň toto pravidlo
Pro všechna Aj-pravidla (Ajα → β) vytvoř nová pravidla ve tvaru Aᵢ → βα (tj. všechna pravidla jejichž pravé strana začíná nonterminálem rozepíšeme tento nonterminál na všechny možnosti na jaké jej lze přepsat)
Po dokončení tohoto kroku všechny pravidla mají pravou stranu začínající terminálem.
Ve všech pravidlech v P′ ve kterých se na pravé straně vyskytují terminály na jiné než první pozici nahradíme tyto terminály a za nové non-terminály A′ a přidáme pravidlo A′ → a (tj. nepovolená pravidla s terminály na pravé straně upravíme tak, že terminál nahradíme nonterminálem, který se přepisuje na původní terminál)