3.4. Przekształcenia gramatyk bezkontekstowych
Definicje
Niech będzie dana gramatyka bezkontekstowa G = <N, T, P, Z> ∈ G
BK
Symbol X ∈ (N∪ T) nazywamy nieużytecznym w G∈ G jeśli nie można w tej gramatyce BK
przeprowadzić wyprowadzenia: Z ⇒ *G wXy ⇒ *G wxy przy czym w,x,y ∈ T* (czyli z X nie można wyprowadzić żadnego słowa w symbolach terminalnych).
Symbol X ∈ (N∪ T) nazywamy nieosiągalnym w G∈ G BK, jeśli X nie pojawia się w żadnej formie zdaniowej tej gramatyki (czyli nie można go wyprowadzić z Z).
Gramatyka G∈ G jest gramatyką bez ε-produkcji, gdy: BK
(i) P nie zawiera produkcji postaci A→ε , A∈ N, A≠ Z
(ii) jeśli (Z→ε ) ∈ P to symbol Z nie występuje w prawych stronach pozostałych produkcji
Algorytm usuwania symboli nieosiągalnych
wejście:
G = < N, T, P, Z> ∈ G
BK
wyjście:
G’ = < N’, T’, P’, Z> ∈ GBK taka, że (i) L(G’) = L(G)
(ii)
(
∀ X∈(N’∪T’) ) ( ∃ α,β∈(N’∪T’)* ) ( Z ⇒*G’ αXβ )
Metoda:
V0 := {Z};
i := 0;
repeat
i := i + 1;
Vi := Vi-1 ∪ {X ∈ (N∪T) | (A→αXβ) ∈ P ∧ A ∈ Vi-1 ∧ α,β ∈ (N∪T)* }; until Vi = Vi-1 ; /*
Vi zawiera te symbole terminalne i nieterminalne które:
- występują w produkcjach z P
- dają się wyprowadzić z Z */
N’ := Vi ∩ N;
T’ := Vi ∩ T;
P’ := {(u→v) ∈ P | u,v ∈ V*i }
/* zawiera te produkcje z P, które zbudowane są
z symboli z Vi */
G’ := <N’, T’, P’, Z>
Algorytm usuwania symboli nieużytecznych
wejście:
G = <N, T, P, Z> ∈ G
BK
wyjście:
G’ = <N’ , T’, P’, Z> ∈ G taka, że:
BK
(i) L(G’) = L(G)
(ii)
(N’∪T’) nie zawiera symboli nieużytecznych
Metoda:
N0 := φ; /* φ - zbiór pusty */
i := 0;
repeat
i := i + 1;
Ni := Ni-1 ∪ { A ∈ N | (A→α) ∈ P ∧ α ∈ (Ni-1∪T)* }
until Ni = Ni-1;
G1 := < N ∩ Ni , T, P1 , Z> gdzie
P1 := {(u→v) ∈ P | u,v ∈ (Ni∪T)* };
zastosować do G1 algorytm usuwania symboli nieosiągalnych uzyskując w wyniku tego gramatykę G’ = <N’, T’, P’, Z>
Przykład:
G = <{S, A, B}, {a, b}, {S→a ; S→A ; A→AB ; B→b}, S> G1 = <{S, B}, {a, b}, {S→a ; B→b}, S>
G’ = <{S}, {a}, {S→a}, S>
Algorytm usuwania ε-produkcji
we:
G = <N, T, P, Z> ∈ G
BK
wy:
G’ = <N’, T, P’, Z’> ∈ G taka, że: BK
(i) L(G) = L(G’)
(ii) G’ jest gramatyką bez ε-produkcji
Metoda:
N0 := φ; /* φ - zbiór pusty */
i := 0;
repeat
i:= i + 1;
N
*
i := Ni-1 ∪ { A ∈ N | (A→x) ∈ P ∧ x ∈ Ni-1 }; until Ni = Ni-1;
Ne := Ni ; /*
Ne = {A | A ∈ N ∧ A ⇒+G ε} */
P’ := P ;
for (A→x) ∈ P do
begin
przedstawiamy „x” w postaci α0B1α1B2α2 ... Bkαk, k ≥ 0, gdzie Bi ∈ Ne (1 ≤ i ≤ k), αi ∈ ((N∪T) – Ne)* (0 ≤ i ≤ k); P’ := P’ ∪ {(A → α0X1α1X2α2 ... Xkαk) : (Xi= Bi ∨ Xi = ε)}; if (A→ε) ∈ P’ then P’ := P’ – {(A→ε)};
end;
if Z ∈ Ne then
begin
N’ := N ∪ {Z’};
P’ := P’ ∪ {(Z’ → Z), (Z’ → ε)};
Z’ := Z’;
end
else
begin
N’ := N;
Z’ := Z;
end;
Przykład:
S
→ aSbS
S → bSaS
S → ε
Po usunięciu S → ε otrzymujemy
S’
→ S
S’ → ε
S → aSbS , S → aSb , S → abS , S → ab
S → bSaS , S → bSa , S → baS , S → ba
Usuwanie produkcji łańcuchowych i cykli
Produkcje łańcuchowe, to produkcje postaci: A → B ; A, B ∈ N
Gramatyka G zawiera cykle, wówczas gdy istnieją w gramatyce wyprowadzenia postaci A ⇒ +G A ; A ∈ N
Algorytm usuwania produkcji łańcuchowych i cykli
wejście:
G = <N, T, P, Z> ∈ G ; G – bez ε-produkcji!
BK
wyjście:
G’ = <N, T, P’, Z> ∈ G taka, że
BK
(i) L(G) = L(G’)
(ii) G’ – nie zawiera produkcji łańcuchowych i cykli Metoda:
for A ∈ N do
begin
N0 := {A};
i := 0;
repeat
i := i + 1;
Ni := Ni-1 ∪ { C ∈ N | (B → C) ∈ P ∧ B ∈ Ni-1 }
until Ni-1 = Ni ;
NA := Ni ;
/* NA = { B | A ⇒+G B } */
end;
P’ := φ; /* φ - zbiór pusty */
begin
if p = (B → α) and α ∉ N then
/* p nie jest łańcuchowa */
begin
MB := {A ∈ N | B ∈ NA};
for A ∈ MB do
/* MB = { A : A ⇒*G B} */
P’ := P’ ∪ { A → α };
end;
end;
Przykład:
(1) E
→ E + T
(2) E
→
T
(3) T
→ T * F
(4) T
→
F
(5) F
→ ( E )
(6) F
→ id
NE = { E, T, F }
NT = { T, F }
NF = { F }
ME = { E }
MT = { E, T }
MF = { E, T, F }
(1) E
→ E + T
(2)
wypada, bo jest łańcuchowa
(3) E
→ T * F
T → T * F
(4)
wypada, bo jest łańcuchowa
(5) E
→ ( E )
T → ( E )
F → ( E )
(6) E
→ id
T → id
F → id
Gramatyka G = < N, T, P, Z > ∈ GBK nazywa się prawidłową, jeśli: (i)
nie zawiera cykli,
(ii) jest
gramatyką bez ε-produkcji,
(iii)
nie zawiera nieużytecznych symboli.
Usuwanie lewostronnej rekursji
U ∈ N jest symbolem lewostronnie rekursywnym gramatyki G jeżeli U ⇒ +G Uβ ; β ∈ (N∪ T)*
Gramatyka G nazywa się lewostronnie rekursywną ⇔ (∃ U∈ N) ( U ⇒ +G Uβ ; β ∈ (N∪ T)* ) Tw.
G = < N, T, P, Z > ∈ G ; A ∈ N ;
BK
{ A → Aα1 | ... | Aαm | β1 | ... | βn } ⊆ P jest zbiorem wszystkich produkcji mających po lewej stronie symbol A ; żadne z βi ∈ (N∪T)* (i = 1, ... , n) nie zaczyna się od symbolu A.
Niech G’ = < N ∪ {A’}, T, P’, Z > gdzie A’ – nowy symbol nieterminalny, zaś
P’ = P – {A → Aα1 | ... | Aαm | β1 | ... | βn } ∪ { A → β1A’ | ... | βnA’ }
∪ { A’ → α1A’ | ... | αmA’ | ε }
Wówczas zachodzi L(G) = L(G’)
Twierdzenie podaje sposób usuwania lewej rekursji, ale tylko bezpośredniej.
Przykład:
A → Aα A A → β
A α
Analizowane A α
słowo : βααα A α
β
Po modyfikacji:
A → βA’
A
A’ → ε
β A’
A’ → αA’
α A’
Analizowane α A’
słowo : βααα α A’
ε
Algorytm usuwania (także pośredniej) rekursji lewostronnej wejście:
G = <N, T, P, Z> ∈ G , G –gramatyka prawidłowa!
BK
wyjście:
G’ = <N’, T, P’, Z> ∈ G taka, że
BK
(i) G’ – nie jest gramatyką lewostronnie rekursywną (ii) L(G’) = L(G)
Metoda:
numerujemy symbole nieterminalne ⇔ N := {A1, ... , An}; n := #N
N’ := N ;
P’ := P ;
i := 1 ;
repeat if ∃(Ai → Aiδ) ∈ P’ and δ ∈ (N∪T)* then begin N’ := N’ ∪ {Ai’}
P’ := P’ – {Ai → Aiα1 | ... | Aiαq | β1 | ... | βp}
∪ {Ai → β1Ai’ | ... | βpAi’} ∪ {Ai’ → α1Ai’ | ... | αqAi’ | ε} end;
/* q – liczba wszystkich produkcji Ai → Ai ... (lewostr. rekurs.) żadne z β1, ... , βp nie zaczyna się od Ai
p – liczba wszystkich produkcji Ai → ... bez lewej rekursji */
if i = n then STOP else i := i + 1 ;
for j := 1 to i –1 do
P’ := P’ – {Ai → Ajα1 | ... | Ajαx}
∪ {Ai → γkαl : l = 1, ... , x
k = 1, ... , m
γk – prawe strony produkcji
Aj → γ1 | ... | γk | ... | γm};
/* x – liczba wszystkich produkcji typu Ai → Ajα
m – liczba wszystkich produkcji typu Aj → γ1 | ... | γm */
until FALSE ;
/* w ten sposób prawa strona każdej produkcji Ai → ... zaczyna się albo od symbolu terminalnego, albo od nieterminala Aj o numerze j > i */
A → BC | a
B → CA | Ab
C → AB | CC | a
rodzaje rekursji lewostronnej:
1
2
3
A
A
C B
B
C
rekursja
bezposrednia
rekursja posrednia
I i
=
1
G bez zmian
II
i = 2 ; j = 1 B
→ CA | BCb | ab
I
i = 2
B → CAB’ | abB’
B’ → CbB’ | ε
II
i = 3 ; j = 1 C
→ BCB | aB | CC | a
i = 3 ; j = 2
C → CAB’CB | abB’CB | aB | CC | a
I
i = 3
C → abB’CBC’ | aBC’ | aC’
C’ → AB’CBC’ | CC’ | ε
Ostatecznie: A
→ BC | a
B → CAB’ | abB’
B’ → CbB’ | ε
C → abB’CBC’ | aBC’ | aC’
C’ → AB’CBC’ | CC’ | ε