3.4. Przekształcenia gramatyk bezkontekstowych

Transkrypt

3.4. Przekształcenia gramatyk bezkontekstowych
3.4. Przekształcenia gramatyk bezkontekstowych
Definicje
Niech będzie dana gramatyka bezkontekstowa G = <N, T, P, Z> ∈ GBK
Symbol X ∈ (N∪T) nazywamy nieużytecznym w G∈GBK jeśli nie można w tej gramatyce
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∈GBK, jeśli X nie pojawia się w żadnej
formie zdaniowej tej gramatyki (czyli nie można go wyprowadzić z Z).
Gramatyka G∈GBK jest gramatyką bez ε-produkcji, gdy:
(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
Twierdzenie 3.4.1.
Każdą gramatykę bezkontekstową G = <N, T, P, Z> ∈ GBK można przekształcić do postaci
równoważnej G’ = <N’, T’, P’, Z> ∈ GBK (to znaczy takiej, że L(G’) = L(G) ) nie zawierającej symboli nieosiągalnych, symboli nieużytecznych oraz będącej gramatyką bez εprodukcji (w sensie powyższych definicji).
Sposoby wykonania odpowiednich przekształceń podają poniższe algorytmy. Czytelnik zechce udowodnić poprawność tych algorytmów.
Algorytm usuwania symboli nieosiągalnych
wejście:
G = <N, T, P, Z> ∈ GBK
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> ∈ GBK
wyjście:
G’ = <N’ , T’, P’, Z> ∈ GBK taka, że:
(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
wejście:
G = <N, T, P, Z> ∈ GBK
wyjście:
G’ = <N’, T, P’, Z’> ∈ GBK taka, że:
(i) L(G) = L(G’)
(ii) G’ jest gramatyką bez ε-produkcji
Metoda:
N0 := φ;
/* φ - zbiór pusty */
i := 0;
repeat
i:= i + 1;
Ni := 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
Cykle typu A ⇒+ A powstają poprzez istnienie w gramatyce produkcji łańcuchowych, np.
A → B, B → C, C → A, więc usuwając produkcje łańcuchowe – usuwamy również automatycznie wszystkie cykle.
Twierdzenie 3.4.2.
Każdą gramatykę bezkontekstową G = <N, T, P, Z> ∈ GBK można przekształcić do postaci
równoważnej G’ = <N’, T’, P’, Z> ∈ GBK (to znaczy takiej, że L(G’) = L(G) ) nie zawierającej produkcji łańcuchowych i cykli (w sensie powyższych definicji).
Algorytm usuwania produkcji łańcuchowych i cykli
wejście:
G = <N, T, P, Z> ∈ GBK ; G – bez ε-produkcji!
wyjście:
G’ = <N, T, P’, Z> ∈ GBK taka, że
(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 */
for p ∈ P do
begin
if p = (B → α) and α ∉ N then
begin
MB := {A ∈ N | B ∈ NA};
/* p nie jest łańcuchowa */
/* MB = { A : A ⇒*G B} */
for A ∈ MB do
P’ := P’ ∪ { A → α };
end;
end;
Przykład: Rozpatrujemy gramatykę:
(1)
E→E+T
(2)
E→T
(3)
T→T*F
(4)
T→F
(5)
F→(E)
(6)
F → id
Wyznaczamy odpowiednie zbiory nieterminali:
NE = { E, T, F }
NT = { T, F }
NF = { F }
ME = { E }
MT = { E, T }
MF = { E, T, F }
Analizujemy kolejno wszystkie produkcje gramatyki przekształcanej
(1)
E→E+T
(2)
wypada, bo jest łańcuchowa
(3)
E→T*F
(4)
wypada, bo jest łańcuchowa
(5)
E→(E)
T→(E)
F→(E)
(6)
E → id
T → id
F → id
T→T*F
Definicja
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)* )
Twierdzenie 3.4.3.
Dana jest gramatyka G = < N, T, P, Z > ∈ GBK oraz symbol nieterminalny A ∈ N.
Zbiór { 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 > będzie nową gramatyką, w której A’ – nowy symbol nieterminalny zaś zbiór produkcji P' jest określony jak niżej
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→β
Analizowane
słowo : βααα
α
A
α
A
A
α
β
Po modyfikacji:
A → βA’
A’ → ε
A’ → αA’
Analizowane
słowo : βααα
A
β
A’
α
A’
α
A’
α
A’
ε
Twierdzenie 3.4.4.
Każdą gramatykę bezkontekstową G = <N, T, P, Z> ∈ GBK można przekształcić do postaci
równoważnej G’ = <N’, T’, P’, Z> ∈ GBK (to znaczy takiej, że L(G’) = L(G) ) nie zawierającej (bezpośredniej i pośredniej) lewostronnej rekursji.
Algorytm usuwania (także pośredniej) rekursji lewostronnej
wejście:
G = <N, T, P, Z> ∈ GBK , G –gramatyka prawidłowa!
wyjście:
G’ = <N’, T, P’, Z> ∈ GBK taka, że
(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 */
Przykład:
A → BC | a
B → CA | Ab
C → AB | CC | a
Rodzaje rekursji lewostronnej:
1
2
A
A
C
B
3
B
C
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
i=3;j=1
C → BCB | aB | CC | a
i=3;j=2
C → CAB’CB | abB’CB | aB | CC | a
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’ | ε
rekursja
bezposrednia
Wariant drugi usuwania lewostronnej rekursji – dla potrzeb przekształcania gramatyki bezkontekstowej do postaci normalnej Greibacha
Twierdzenie 3.4.3. (wariant drugi)
Dana jest gramatyka G = < N, T, P, Z > ∈ GBK oraz symbol nieterminalny A ∈ N.
Zbiór { 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 > będzie nową gramatyką, w której A’ – nowy symbol nieterminalny zaś zbiór produkcji P' jest określony jak niżej
P’ = P – {A → Aα1 | ... | Aαm } ∪ { A → β1A’ | ... | βnA’ }
∪ { A’ → α1A’ | ... | αmA’ | α1 | ... | αm }
Wówczas zachodzi L(G) = L(G’).
Twierdzenie podaje drugi sposób usuwania bezpośredniej lewej rekursji (nie powodujący
dodawania ε–produkcji ale zwiększający liczbę nowych produkcji wprowadzanych do gramatyki).
Przykład:
A → Aα
A
A→β
Analizowane
słowo : βααα
α
A
α
A
A
α
β
Po modyfikacji:
A → βA’
A→β
A’ → αA’
A' → α
Analizowane
słowo : βααα
A
β
A’
α
A’
α
A’
α
Drugi wariant algorytmu usuwania (także pośredniej) rekursji lewostronnej
wejście:
G = <N, T, P, Z> ∈ GBK , G –gramatyka prawidłowa
wyjście:
G’ = <N’, T, P’, Z> ∈ GBK taka, że
(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 }
∪ {Ai → β1Ai’ | ... | βpAi’} ∪ {Ai’ → α1Ai’ | ... | αqAi’ | α1 | ... | αq } end;
/* q – liczba wszystkich produkcji Ai → Aiαr... (lewostr. rekurs.)
żadne z β1, ... , βp nie zaczyna się od Ai
p – liczba wszystkich produkcji Ai → βr... (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 */
Przykład:
A → BC | a
B → CA | Ab
C → AB | CC | a
I
i=1
G bez zmian
II
i=2;j=1
B → CA | BCb | ab
I
i=2
B → CAB’ | abB’ | CA | ab
B’ → CbB’ | Cb
II
I
i=3;j=1
C → BCB | aB | CC | a
i=3;j=2
C → CAB’CB | abB’CB | CACB | abCB | aB | CC | a
i=3
C → abB'CBC' | abCBC' | aBC' | aC' | abB'CB | abCB | aB | a
C’ → AB'CBC' | ACBC' | CC' | AB'CB | ACB | C
Ostatecznie: A → BC | a
B → CAB’ | abB’ | CA | ab
B’ → CbB’ | Cb
C → abB'CBC' | abCBC' | aBC' | aC' | abB'CB | abCB | aB | a
C’ → AB'CBC' | ACBC' | CC' | AB'CB | ACB | C

Podobne dokumenty