In diesem Teilkapitel werden wir sehen,
wie wir für eine gültige Wortform
den korrekten Linksreduktionsschritt
finden. Als erstes müssen wir uns überlegen,
wie die Front
überhaupt aussehen kann. Wenn wir
uns den Ableitungsbaum von ansehen,
wird das einigermaßen offensichtlich sein.
Zur Erinnerung:
Zu jeder Ableitung können wir
eindeutig einen Ableitungsbaum zeichnen. Wenn die Grammatik
eindeutig ist, so hängt auch der Baum nur vom Wort ab und
nicht von der Ableitung .
Allerdings können wir für Zwischenformen
auch einen Ableitungsbaum zeichnen,
und der unterscheidet sich stark, abhängig davon, ob eine
Rechtsableitung, Linksableitung oder sonst was ist.
Ich zeige Ihnen jetzt ein Beispiel für eine Grammatik und
eine Handvoll Ableitungen samt Ableitungsbaum.
Es ist zu diesem Zeitpunkt irrelevant, ob eindeutig
oder sogar 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 .
Wir definieren nun eingeführten Begriffe formal:
Definition / Beobachtung 6.8.1(Stamm, linker Rand, Blüte, Front, rechter Rest)
Sei eine Rechtsableitung, also
eine gültige Wortform, und
der Ableitungsbaum von .
Der Stamm ist der Pfad von der Wurzel zu jenem inneren Knoten ,
der von allen inneren Knoten, deren Kinder allesamt Blätter sind,
am weistesten links steht.
Die Kinder von , 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 im linken Rand
muss ein Blatt sein, ansonsten stünde er ja weiter links als ;
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 . Der ganze Baum stellt also eine Rechtsableitung
dar. Die Wortform , also linker Rand plus Blüte, nennen wir
die Front von und schreiben sie als .
Wir sagen auch, dass eine Blüte von und
die Front von ist,
ohne über den Ableitungsbaum 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
also nicht eindeutig ist. Für eindeutige Grammatiken ist
die Unterteilung aber eindeutig.
Sei weiterhin die Beschriftung des Elternknoten der Blüte
(notwenigerweise ein Nichtterminal; Terminale haben keine Kinder).
Dann ist eine Produktion in der Grammatik und
eine gültige Wortform; wir erhalten den Ableitungsbaum
von , indem wir die Blüte von entfernen.
Wir schließen, dass
ein korrekter Linksreduktionsschritt ist.
Wir können also, ausgehend von der Wortform ,
eine Linksreduktion 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
und korrekt ist ( 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 definieren wir
die Sprache :
alternativ
also die Menge aller Wortformen, die Front einer gültigen Wortform
sind.
Lemma 6.8.3
Die Sprache ist regulär.
Insbesondere gibt es eine erweitert reguläre Grammatik für
, so dass die Blüte genau die im letzen Ableitungsschritt
erzeugten Terminalsymbole sind.
Hier ist etwas Mentalgymnastik vonnöten: aus Sicht der Sprache
sind Terminalsymbole. Sie können
ja schließlich in den Wörtern der Sprache auftauchen.
Die Grammatik hat also die Terminalsymbole
. Darüberhinaus hat sie
die Nichtterminale ,
also für jedes Nichtterminal von ein
Meta-Nichtterminal . Das entspricht
dem in den obigen Bäumen, wo also als Blatt vorkommt;
das entspricht dem
,
also wo als innerer Knoten vorkommt. Bevor ich
formal definiere, zeige ich den obigen Ableitungsbaum
(ohne rechten Rand, weil der ja bei eh fehlt)
und annotiere jeden Knoten auf dem Stamm mit der entsprechenden
-Produktion.
Definition 6.8.4
Sei eine kontextfreie Grammatik. Die
Front-Grammatik oder DK-Grammatik von ist
die erweitert reguläre Grammatik
mit , wobei
für jede -Produktion
mit die Produktionen
besitzt.
Beobachtung 6.8.5 erzeugt die Sprache
.
Beispiel 6.8.6
Für unsere Grammatik oben ergeben sich folgende Produktionen
in :
Nochmals: Produktionen wie
sind erweitert regulär
weil und aus Sicht von beides
Terminalsymbole sind. Wir können nun unseren -Parser beschreiben:
Algorithmus 6.8.7- Der -Parser.
Starte mit einem leerem Stack. Sei
der Inhalt des Stacks zu einem Zeitpunkt.
Wenn , dann
betrachte die letzte angewandte -Produktion
und schreibe
. Wende die -Produktion
rückwärts an, reduziere also
Konkret: lösche vom Stack und ersetze es durch .
Falls ,
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 auf dem Stack liegt,
akzeptiert er, andernfalls lehnt er das Eingabewort ab.
Theorem 6.8.8
Wenn der -Parser akzeptiert, dann hat er eine Linksreduktion
und somit eine Rechtsableitung konstruiert; es gilt
also .
Wenn umgekehrt gilt und
die -Bedingung erfüllt,
dann findet der
Parser die Rechtsableitung ,
Beweis.
Der erste Teil der Bedeutung ist einfach zu sehen.
Jeder Reduktionsschritt ist ein Linksreduktionsschritt, und
wenn man Ende steht, waren es auch alles
korrekte Linksreduktionsschritte.
Der zweite Teil ist schwieriger. Wir nehmen also
an, dass eine LR(0)-Grammatik ist.
Da eindeutig ist, hat jede gültige Wortform
eine eindeutige Rechtsableitung und einen
dazugehörigen Ableitungsbaum ; somit
ist eindeutig bestimmt.
Beachten Sie, dass rechts
von nur Terminalsymbole folgen.
Betrachten wir einen Zeitpunkt während des Parsing-Prozesses.
Sei der Stackinhalt und der ungelesene
Teil des Eingabewortes. Wir werden beweisen, dass zu jedem Zeitpunkt folgende
Invariante gilt:
Behauptung.
(i) ist eine gültige Wortform. (ii)
ist ein Präfix von .
Beweis.
Die Behauptung gilt offensichtlich am Anfang, da
und ist und
somit eine gültige Wortform ist. Des weiteren
ist der Stack leer, also , und daher
sicherlich ein Präfix von .
Wir zeigen nun, dass, wenn die Invariante in Schritt gilt,
sie auch im nächsten Schritt gilt.
Es gibt nun zwei Möglichkeiten.
Der Parser wendet Schritt 1 an, also .
Das heißt nach Definition von , dass es ein gibt,
so dass eine gültige Wortform ist
und . Also
mit . Es sind und also
linker Rand und Blüte von . Somit ist
ein korrekter Linksreduktionsschritt.
Die letzte -Produktion
in der Ableitung von war somit
; somit ersetzt der Parser
das auf dem Stack durch ; führt also die Linksreduktion
an. Da () korrekt ist und
nach Invariante eine gültige Wortform ist, ist
nach LR(0)-Bedingung auch () ein korrekter
Schritt; 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: ;
da rechts vom aktiven Teil nur Terminale stehen, muss
ein Präfix von sein.
Der Parser wendet Schritt 2 an, also , er liest
und legt es auf den Stack. Im nächsten Schritt
ist der Stackinhalt und das ungelesene Wort
ist .
Teil (i) der Behauptung gilt offensichtlich, da
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 ist; zweitens, dass
ist (sonst hätte der Parser Schritt 1 angewandt); somit
ist ein echter Präfix von und somit
ist immer noch ein Präfix von .
Wenn das Eingabewort gelesen ist, ist nun und
Stackinhalt ist selbst eine
gültige Wortform, die allerdings nicht weiter reduziert werden kann.
Also muss gelten und der Parser akzeptiert.