6.8 Linker Rand, Blüten und die DK-Grammatik

In diesem Teilkapitel werden wir sehen, wie wir für eine gültige Wortform γ den korrekten Linksreduktionsschritt

γ=αβwαXw

finden. Als erstes müssen wir uns überlegen, wie die Front front(γ)=αβ überhaupt aussehen kann. Wenn wir uns den Ableitungsbaum von γ ansehen, wird das einigermaßen offensichtlich sein.

Zur Erinnerung: Zu jeder Ableitung SwΣ können wir eindeutig einen Ableitungsbaum zeichnen. Wenn die Grammatik eindeutig ist, so hängt auch der Baum nur vom Wort wL(G) ab und nicht von der Ableitung Sw. Allerdings können wir für Zwischenformen Sγw auch einen Ableitungsbaum zeichnen, und der unterscheidet sich stark, abhängig davon, ob Sγ eine Rechtsableitung, Linksableitung oder sonst was ist. Ich zeige Ihnen jetzt ein Beispiel für eine Grammatik und eine Handvoll Ableitungen samt Ableitungsbaum.

G:SABAxBS | BzByAS | Az | x | y | z

Es ist zu diesem Zeitpunkt irrelevant, ob G eindeutig oder sogar LR(0) ist. Ich interessiere mich gerade nur für Ableitungsbäume von Wortformen.

Fällt Ihnen etwas auf? Schauen Sie sich bitte noch ein weiteres Beispiel an für den Ableitungsbaum einer in einer gültigen Wortform, also von einer, die in einer Rechtsableitung vorkommen kann:

Warten Sie! Scrollen Sie erst weiter, wenn Sie den Baum oben lang genug angeschaut haben! Versuchen Sie selbst, die spezielle Form dieses Baumes möglichst formal zu beschreiben!
Auflösung. Hier sehen Sie noch einmal den gleichen Baum, nun aber gewisse Teile verschieden umrandet / eingefärbt.

Sie sehen: links vom Stamm gibt es nur Blätter. Rechts vom Stamm ist jedes Blatt ein Terminalsymbol. Wir erkennen auch, was der letzte Ableitungsschritt war, der zu diesem Baum geführt hat: die Blüte ist hinzugekommen, in diesem Fall also AxBS. Wir definieren nun eingeführten Begriffe formal:

Definition / Beobachtung 6.8.1 (Stamm, linker Rand, Blüte, Front, rechter Rest) Sei Sγ eine Rechtsableitung, γ also eine gültige Wortform, und T der Ableitungsbaum von γ. Der Stamm ist der Pfad von der Wurzel zu jenem inneren Knoten u, der von allen inneren Knoten, deren Kinder allesamt Blätter sind, am weistesten links steht. Die Kinder von u, per Definition alles Blätter, sind die Blüte. Die Menge der Knoten, die einen Stammknoten als rechtes Geschwister haben, heißt der linke Rand. Jeder Knoten v im linken Rand muss ein Blatt sein, ansonsten stünde er ja weiter links als u; die Menge der rechten Geschwisterkinder von Stammknoten sowie deren Nachkommen heißt der rechte Rand. Im rechten Rest ist jedes Blatt ein Terminalsymbol, ansonsten wäre es keine Rechtsableitung.

Die Beschriftung der Knoten im linken Rand ergibt eine Wortform α; die Blüte ergibt β. Die Blätter im rechten Rand sind ausschließlich mit Terminalen beschriftet und ergeben ein Wort wΣ. Der ganze Baum stellt also eine Rechtsableitung

SRαβw dar. Die Wortform αβ, also linker Rand plus Blüte, nennen wir die Front von T und schreiben sie als front(T). Wir sagen auch, dass β eine Blüte von γ und αβ die Front von γ ist, ohne über den Ableitungsbaum T selbst zu reden. Hierbei ist zu beachten, dass in einer mehrdeutigen Grammatik eine gültige Wortform mehrere Ableitungsbäume und somit mehrere Blüten haben kann, die Unterteilung γ=αβw also nicht eindeutig ist. Für eindeutige Grammatiken ist die Unterteilung aber eindeutig.

Sei weiterhin A die Beschriftung des Elternknoten der Blüte (notwenigerweise ein Nichtterminal; Terminale haben keine Kinder). Dann ist Aβ eine Produktion in der Grammatik und αAw eine gültige Wortform; wir erhalten den Ableitungsbaum von αAw, indem wir die Blüte von T entfernen. Wir schließen, dass αβwαAw ein korrekter Linksreduktionsschritt ist.

Wir können also, ausgehend von der Wortform γ, eine Linksreduktion γS finden, indem wir den Ableitungsbaum von γ zeichnen und immer wieder die Blüte abschneiden:

Um für eine Wortform γ den korrekten Reduktionsschritt zu finden, reicht es also aus, linken Rand und Blüte zu bestimmen, also α und β, so dass γ=αβw und αβwαAw korrekt ist (A steht hier für das Nichtterminal, mit dem der Elternknoten der Blüte beschriftet ist). Linken Rand und Blüte zu finden scheint keine leichte Aufgabe zu sein: schließlich müssen wir dafür doch den Ableitungsbaum von γ bilden, was selbst wieder eine Parsing-Aufgabe ist???

An dieser Stelle zeigt sich die Genialität des DK-Ansatzes: der Ableitungsbaum von γ kann beliebig verschachtelt sein, aber Stamm, linker Rand und Blüte haben zusammen eine einfache, beinahe linear anmutende Struktur. Schematisch:

Die Aussage "Stamm, linker Rand und Blüte haben eine einfache Struktur" können wir formalisieren.

Definition 6.8.2 Für eine kontextfreie Grammatik G definieren wir die Sprache Front(G)(ΣN): Front(G):={front(T) | T ist der Ableitungsbaum einer Rechtsableitung SRγ} alternativ Front(G):={αβ | SRαXwRαβw} also die Menge aller Wortformen, die Front einer gültigen Wortform sind.

Lemma 6.8.3 Die Sprache Front(G) ist regulär. Insbesondere gibt es eine erweitert reguläre Grammatik G^ für Front(G), so dass die Blüte genau die im letzen Ableitungsschritt erzeugten Terminalsymbole sind.

Hier ist etwas Mentalgymnastik vonnöten: aus Sicht der Sprache Front(G) sind ΣN Terminalsymbole. Sie können ja schließlich in den Wörtern der Sprache auftauchen. Die Grammatik G^ hat also die Terminalsymbole ΣN. Darüberhinaus hat sie die Nichtterminale N^:={X^ | XN}, also für jedes Nichtterminal X von G ein Meta-Nichtterminal X^. Das XN entspricht dem X in den obigen Bäumen, wo also N als Blatt vorkommt; das X^N^ entspricht dem , also wo W als innerer Knoten vorkommt. Bevor ich G^ formal definiere, zeige ich den obigen Ableitungsbaum (ohne rechten Rand, weil der ja bei front(G) eh fehlt) und annotiere jeden Knoten auf dem Stamm mit der entsprechenden G^-Produktion.

Definition 6.8.4 Sei G=(Σ,N,S,P) eine kontextfreie Grammatik. Die Front-Grammatik oder DK-Grammatik von G ist die erweitert reguläre Grammatik G^=(ΣN,N^,S^,P^) mit N^:={X^ | XN}, wobei P^ für jede G-Produktion Aw0A1w1A2w2wk1Akwk mit wiΣ die Produktionen A^w0A^1A^w0A1w1A^2A^w0A1w1A2w2Ak1wk1A^kA^w0A1w1A2w2wk1Akwk besitzt.
Beobachtung 6.8.5 G^ erzeugt die Sprache Front(G).
Beispiel 6.8.6 Für unsere Grammatik G oben ergeben sich folgende Produktionen P^ in G^: Produktion in GProduktion in G^S^A^SABS^AB^S^ABA^xB^AxBSA^xBS^A^xBSABzA^B^A^BzB^yA^ByASB^yAS^B^yASB^A^BAzB^AzBxB^xByB^yBzB^z

Nochmals: Produktionen wie B^yAS^ sind erweitert regulär weil y und A aus Sicht von G^ beides Terminalsymbole sind. Wir können nun unseren LR(0)-Parser beschreiben:

Algorithmus 6.8.7 - Der LR(0)-Parser. Starte mit einem leerem Stack. Sei γ der Inhalt des Stacks zu einem Zeitpunkt.
  1. Wenn γFront(G), dann betrachte die letzte angewandte G^-Produktion X^β und schreibe γ=αβ. Wende die G-Produktion Xβ rückwärts an, reduziere also αβαX Konkret: lösche β vom Stack und ersetze es durch A.
  2. Falls γFront(G), lies das nächste Eingabezeichen und lege es auf den Stack.
Der Parser endet, wenn weder Schritt 1 noch Schritt 2 möglich sind; wenn zu diesem Zeitpunkt nur noch S auf dem Stack liegt, akzeptiert er, andernfalls lehnt er das Eingabewort ab.
Theorem 6.8.8 Wenn der LR(0)-Parser akzeptiert, dann hat er eine Linksreduktion wS und somit eine Rechtsableitung konstruiert; es gilt also wL(G).

Wenn umgekehrt wL(G) gilt und G die LR(0)-Bedingung erfüllt, dann findet der Parser die Rechtsableitung Sw,

Beweis. Der erste Teil der Bedeutung ist einfach zu sehen. Jeder Reduktionsschritt ist ein Linksreduktionsschritt, und wenn man Ende S steht, waren es auch alles korrekte Linksreduktionsschritte.

Der zweite Teil ist schwieriger. Wir nehmen also an, dass G eine LR(0)-Grammatik ist. Da G eindeutig ist, hat jede gültige Wortform γ eine eindeutige Rechtsableitung und einen dazugehörigen Ableitungsbaum T; somit ist front(γ):=front(T) eindeutig bestimmt. Beachten Sie, dass rechts von front(γ) nur Terminalsymbole folgen. Betrachten wir einen Zeitpunkt während des Parsing-Prozesses. Sei γ der Stackinhalt und w der ungelesene Teil des Eingabewortes. Wir werden beweisen, dass zu jedem Zeitpunkt folgende Invariante gilt:

Behauptung. (i) γw ist eine gültige Wortform. (ii) γ ist ein Präfix von front(γw).

Beweis. Die Behauptung gilt offensichtlich am Anfang, da γ=ϵ und wL ist und somit γw=w eine gültige Wortform ist. Des weiteren ist der Stack leer, also γ=ϵ, und daher sicherlich ein Präfix von front(w). Wir zeigen nun, dass, wenn die Invariante in Schritt t gilt, sie auch im nächsten Schritt t+1 gilt. Es gibt nun zwei Möglichkeiten.

  1. Der Parser wendet Schritt 1 an, also γFront(G). Das heißt nach Definition von Front(G), dass es ein wΣ gibt, so dass γw eine gültige Wortform ist und γ=front(γw). Also SRαAwRαβw mit γ=αβ. Es sind α und β also linker Rand und Blüte von γw. Somit ist (1)αβwαAw ein korrekter Linksreduktionsschritt. Die letzte G^-Produktion in der Ableitung von S^γ war somit A^β; somit ersetzt der Parser das β auf dem Stack durch A; führt also die Linksreduktion (2)αβwαAw an. Da (1) korrekt ist und αβw nach Invariante eine gültige Wortform ist, ist nach LR(0)-Bedingung auch (2) ein korrekter Schritt; αAw ist also auch eine gültige Wortform; somit gilt Teil (i) der Invariante. Um zu sehen, dass (ii) gilt, beachten Sie, dass nun auf dem Stack oben ein Nichtterminal liegt: A; da rechts vom aktiven Teil nur Terminale stehen, muss αA ein Präfix von front(αAw) sein.
  2. Der Parser wendet Schritt 2 an, also w=cw, er liest c und legt es auf den Stack. Im nächsten Schritt ist der Stackinhalt γ:=γc und das ungelesene Wort ist w. Teil (i) der Behauptung gilt offensichtlich, da γw=γw und somit immer noch eine gültige Wortform ist. Um zu sehen, dass Teil (ii) gilt, beachten Sie erstens, dass Teil (ii) vor dem Schritt galt, also γ ein Präfix von front(γw) ist; zweitens, dass γFront(G) ist (sonst hätte der Parser Schritt 1 angewandt); somit ist γ ein echter Präfix von front(γw) und somit ist γc immer noch ein Präfix von front(γw).
Wenn das Eingabewort gelesen ist, ist nun w=ϵ und Stackinhalt γ ist selbst eine gültige Wortform, die allerdings nicht weiter reduziert werden kann. Also muss γ=S gelten und der Parser akzeptiert.