Postać normalna Greibach

Z testwiki
Przejdź do nawigacji Przejdź do wyszukiwania

Postać normalna Greibach to postać gramatyki bezkontekstowej, w której wszystkie reguły są postaci:

AaY1...Ym,

gdzie a to dowolny symbol terminalny, Y1...Ym to (być może pusty) ciąg symboli nieterminalnych.

Specjalny przypadek produkcji gramatyki typu 1 i wyżej stanowi produkcja

Sε

generująca wyraz pusty. Produkcja ta nie jest objęta formalną definicją gramatyki bezkontekstowej, która stwierdza, że prawa strona dowolnej produkcji nie może być krótsza niż lewa strona (monotoniczność), a co w tym konkretnym aspekcie ma miejsce. Produkcja ta jest dopuszczalna pod warunkiem, że symbol startowy S nie występuje po prawej stronie żadnej produkcji danej gramatyki. W postaci normalnej Chomskiego, która stanowi podstawę dla postaci normalnej Greibach, produkcja ta zostaje przejęta bez zmian, ponieważ, wychodząc z założenia, że gramatyka nie zawiera symbolu startowego po prawej stronie, produkcja ta nie może zostać użyta w żadnej innej konfiguracji.

Nazwa wywodzi się od Sheili Greibach. W pierwotnym zamyśle w artykule definiującym tę postać normalną z roku 1965 autorka pisze: Szablon:Cytat

skąd wynika, że ten specjalny przypadek produkcji nie jest zawarty w postaci. Niektóre definicje postaci obejmują jednak również i tę produkcję.

Każdą gramatykę bezkontekstową można przedstawić w postaci normalnej Greibach.

Konstrukcja

Zakładając, że dana gramatyka bezkontekstowa znajduje się już w postaci normalnej Chomskiego, pokażemy jak można przetransformować ją do postaci normalnej Greibach. Najpierw, wszystkie symbole nieterminalne danej gramatyki ponumerujmy np. do formy Ai,1in, gdzie n to liczba symboli nieterminalnych występujących w danej gramatyce. Postać normalną Greibach można uzyskać za pomocą dwóch operacji stosowanych w odpowiedniej kolejności:

Podstawienie za pierwszy symbol po prawej

Aby zastosować tę operację, koncentrujemy naszą uwagę na pewnej regule, w której pierwszy symbol po prawej stronie jest symbolem nieterminalnym, nazwijmy go Ai. Zastąpimy tę regułę wieloma regułami, po jednej dla każdej reguły mającej Ai po lewej stronie: w naszej oryginalnej regule wymieniamy to pierwsze Ai na rezultat zastosowania tej drugiej reguły. Przykładowo, jeśli wszystkie reguły z A1 po lewej stronie to A1A2A3 i A1a, to regułę A2A1A3 możemy zastąpić regułami A2A2A3A3 i A2aA3. Zwróćmy uwagę, że taka zamiana nie zmienia języka generowanego przez gramatykę.

Zastąpienie reguł lewostronnie rekursywnych

Pod określeniem reguły lewostronnie rekursywnej rozumiane są tutaj produkcje, gdzie pierwszy symbol po prawej stronie jest taki sam jak symbol po lewej stronie. Ustalmy symbol nieterminalny Ai dla którego istnieją reguły lewostronnie rekursywne. Omawiana operacja pozbędzie się jednocześnie wszystkich reguł lewostronnie rekursywnych mających Ai po lewej stronie. Wprowadzamy nowy symbol nieterminalny, powiedzmy Bi, który nie jest jeszcze elementem danej gramatyki. Z każdej reguły lewostronnie rekursywnej mającej Ai po lewej stronie powstaną dwie produkcje:

produkcja 1: mająca nowo wprowadzony symbol Bi po lewej stronie, a po prawej pozostałość reguły rekursywnej bez pierwszego symbolu (Ai), za to na samym końcu ten nowo wprowadzony symbol nieterminalny Bi;

produkcja 2: jak produkcja pierwsza, ale bez ostatniego symbolu Bi.

Reguła rekursywna zostaje przy tym usunięta z gramatyki. Do wszystkich innych (czyli tych, które nie są lewostronnie rekursywne) reguł posiadających po lewej stronie symbol Ai dodajemy dodatkowo reguły z nowo wprowadzonym symbolem Bi na samym końcu. Można zauważyć, że opisana operacja nie zmienia języka generowanego przez gramatykę.

Przykładowo, jeśli dla A2 mieliśmy w gramatyce reguły

A2A2A3A3|A2A2|aA3,

to zostaną one zastąpione przez:

B2A3A3B2|A2B2 (zgodnie z produkcją 1.).
B2A3A3|A2 (zgodnie z produkcją 2.)

oraz

A2aA3 (pozostaje bez zmian),
A2aA3B2 (z dodanym B2).

Reguły rekursywne A2A2A3A3 i A2A2A2 zostały usunięte.

Kolejność wykonywania operacji

Przekształcanie gramatyki do postaci normalnej Greibach wykonujemy w dwóch etapach. Celem pierwszego etapu jest zapewnienie, że w gramatyce będą wyłącznie reguły, w których pierwszy symbol po prawej stronie jest symbolem nieterminalnym o indeksie wyższym niż indeks lewej strony, bądź jest symbolem terminalnym. Systematycznie przeszukujemy wszystkie reguły gramatyki, zaczynając od tego symbolu nieterminalnego po lewej stronie, który ma najniższy indeks, a kończąc na tym, którego indeks jest najwyższy. Przypuśćmy, że obsłużyliśmy już symbole od A1 do Ai1, natomiast dla Ai mamy regułę, w której pierwszy symbol po prawej stronie to jeden spośród A1,,Ai1, czyli niezgodnie z naszą docelową postacią. Wówczas w tej regule podstawiamy za pierwszy symbol po prawej stronie (pierwsza operacja powyżej). W wyniku tego dostajemy reguły, w których pierwszy symbol po prawej stronie jest terminalem bądź ma większy numer niż w oryginalnej regule. Powtarzając tę operację możemy zapewnić, że pierwszym symbolem po prawej stronie nie będzie żaden z symboli A1,,Ai1. Nadal jednak może to być Ai. Aby wyeliminować tę możliwość stosujemy drugą operację (zastąpienie reguł lewostronnie rekursywnych). Po jej zastosowaniu wszystkie reguły dla Ai mają jako pierwszy symbol prawej strony albo symbol terminalny albo symbol nieterminalny o numerze większym niż i; możemy więc przejść do poprawiania reguł dla Ai+1. Zwróćmy uwagę, że nowo wprowadzone symbole Bi nie pojawią na początku prawej strony żadnej reguły.

W przykładowej gramatyce o formie:

A1A2A3|a,
A2A1A3|A2A2,
A3A2A1|b.

najpierw podstawiamy za A1 w regule A2A1A3, następnie eliminujemy reguły lewostronnie rekursywne dla A2, a następnie podstawiamy za A2 w regule A3A2A1. Gramatyka przyjmie po tym etapie poniższą postać:

B2A3A3B2|A2B2|A3A3|A2,
A1A2A3|a,
A2aA3|aA3B2,
A3aA3A1|aA3B2A1|b.

W drugim etapie systematycznie zastępujemy wszystkie reguły zaczynające się po prawej stronie symbolem nieterminalnym. Zaczynamy przy tym od produkcji, które po lewej mają An, idąc poprzez Ai o coraz mniejszych numerach, a na koniec obsługując wszystkie Bi. Gdy obsługujemy jakąś regułę, to numer pierwszego symbolu po prawej stronie jest większy niż numer lewej strony albo po lewej mamy Bi, a po prawej Ai), czyli wszystkie reguły dla pierwszego symbolu po prawej stronie zostały już przetworzone i ich prawe strony zaczynają się od symbolu terminalnego. Zatem jednokrotne zastosowanie operacji podstawienia za pierwszy symbol po prawej stronie spowoduje, że dostaniemy wyłącznie reguły, których prawa strona zaczyna się od symbolu terminalnego. Po obsłużeniu w ten sposób wszystkich reguł dostajemy gramatykę w postaci normalnej Greibach.

W naszej przykładowej gramatyce reguły dla A2 i A3 są już w docelowej postaci. Pierwszą regułą, którą powinniśmy obsłużyć, jest A1A2A3. Zastępujemy ją przez

A1aA3A3|aA3B2A3|a.

Na koniec reguły dla B2 zastępujemy przez

B2aA3A1A3B2|aA3B2A1A3B2|bA3B2|aA3B2|aA3B2B2|aA3A1A3|aA3B2A1A3|bA3|aA3|aA3B2.

Gramatyka znajduje się w całości w postaci normalnej Greibach.

Zobacz też

Bibliografia

  • Sheila A. Greibach, A New Normal-Form Theorem for Context-Free Phrase Structure Grammars, Journal of the Association for Computing Machinery, 1965, Vol. 12, No.1, strony 42-52
  • Uwe Schöning, Theoretische Informatik – kurzgefasst, Spektrum Akademischer Verlag, 1994, Szablon:ISBN, strony 54-57