6.4 LL()-Grammatiken (nicht im Sommersemester 2025)
Definition 6.4.1Grenzform
Sei eine kontextfreie Grammatik.
Eine Wortform - also eine Wortform, die mit einem Nichtterminal beginnt -
heißt Grenzform, wenn es ein gibt, so dass
es eine Linksableitung
gibt.
In anderen Worten: eine Grenzform ist das, was bei einem Kellerautomaten auf dem Stack liegt,
wenn ein Nichtterminal ganz oben liegt.
Grenzformen sind also diejenigen Wortformen, bei denen der Kellerautomat eine Entscheidung
treffen muss, weil er eventuell mehrere Produktionen zur Auswahl hat.
In diesem Teilkapitel wollen wir herausarbeiten, unter welchen Umständen wir die
richtige Auswahl treffen können, auch wenn wir nur wenige weitere Zeichen unseres Inputwortes lesen
dürfen.
Definition 6.4.2
Für ein Wort und eine natürliche Zahl
sei wie folgt definiert:
In Worten: besteht aus den ersten Zeichen
von (oder aus ganz , falls es weniger als lang ist).
Definition 6.4.3LL()-Grammatiken
Eine kontextfreie Grammatik ist eine
LL()-Grammatik, wenn für jede Grenzform und für jedes Paar
verschiedener Produktionen (also ) folgendes gilt: wenn
dann müssen sich und in den ersten Zeichen unterscheiden, also
Intuitiv gesprochen: wenn wir bereits eine ersten Teil unseres Zielwortes
abgeleitet haben, dann können wir die nächste anzuwendende Produktion
eindeutig bestimmen, indem wir die nächsten Zeichen des Zielwortes lesen.
Übungsaufgabe 6.4.1
Negieren Sie die Definition, d.h., schreiben Sie eine Aussage der Form
Wenn nicht LL() ist, dann gibt es...
Beispiel 6.4.4
Die Klammern-Grammatik
ist LL(1).
Beweis.
Folgen wir der Definition von LL(1): für jedes Paar verschiedener Regeln muss etwas
gelten. Wir haben hier keine Auswahl, denn es gibt ja nur ein Paar. Also
müssen wir zeigen, dass, falls
gilt, dann auch gilt.
Offensichtlich ist "".
Was kann sein?
Behauptung. Wenn ,
dann steht jedes in entweder am Ende von oder
unmittelbar vor einem "".
Das folgt per Induktion über die Länge der Ableitung. Wenn es also für gilt
und wir die Produktion auf anwenden,
dann gilt es für jedes "alte" und auch für die beiden neu erzeugten;
wenn wir anwenden, dann verschwindet ein ,
die Behauptung gilt aber nach wie vor für alle anderen in .
Wir folgern also, dass für das den beiden obigne
Herleitungen gilt.
Keines davon ist ein Nichtterminal, und so muss auch
gelten. Zusammenfassend gesagt:
und somit sind sie verschieden.
Wir folgern, dass eine LL(1)-Grammatik ist.
Sehen Sie, dass die LL()-Bedingung der Aussage "der Backtrack-Baum hat keine langen Sackgassen"
ähnelt (aber nicht völlig äquivalent dazu ist). Wenn eine LL()-Grammatik ist
und wir den Backtrack-Baum für ein Wort bauen, dann gilt: sobald wir in einer Sackgasse
neue Terminalsymbole
am "Terminalpräfix" der Wortform hergeleitet haben, merken wir, dass wir in einer Sackgasse sind.
Mit Terminalpräfix meine ich den längsten Präfix einer Wortform, der ausschließlich aus Terminalen
besteht.
Allerdings muss nicht jeder Ableitungsschritt den Terminalpräfix wachsen lassen
(Regeln wie zum Beispiel ersetzen einfach das erste Nichtterminal),
aber "moralisch" geschieht etwas ähnliches).
Wenn umgekehrt eine Grammatik nicht LL() ist, dann muss der Backtrack-Baum
beiden Ableitungen
mindestens so lange weiterverfolgen, bis der
Terminalpräfix weitere Zeichen dazugewonnen hat. Der Baum bekommt also dementsprechend
lange Sackgassen.
Übungsaufgabe 6.4.2
(Beispiel 5.3 aus The Theory of Parsing, Translation, and Compiling von Alfred V. Aho
und Jeffrey D. Ullman).
Betrachten wir die Grammatik
Zeigen Sie, dass diese Grammatik LL(2) ist, aber nicht LL(1).
Tip. Leiten Sie erst einmal
ein Dutzend verschiedene Wörter ab und finden dann
eine "normalsprachliche" Beschreibung
dieser Sprache. Beschreiben Sie dann alle möglichen Wortformen
mit .
Übungsaufgabe 6.4.3
Schreiben Sie eine äquivalente Grammatik zu der vorherigen Sprache, die LL(1) ist.
(Warnung: Ich weiß nicht, ob das überhaupt geht).
Übungsaufgabe 6.4.4
Betrachten wir die Grammatik :
Sie erzeugt die Sprache
also Wörter, wo auf beliebig viele 's eine Folge von
höchstens so vielen 's folgt.
Geben Sie diese Grammatik in den
Parser-Simulator
ein und finden Wörter mit langen Sackgassen.
Zeigen Sie, dass diese Grammatik nicht LL ist, für kein
.
Übungsaufgabe 6.4.5
Sei eine feste, im Voraus bekannte Zahl.
Betrachten wir die Sprache
also die Wörter der Form mit
.
Schreiben Sie für eine Grammatik,
geben Sie diese im
Parser-Simulator ein
und schauen, wie lang die Sackgassen werden können.
Zeigen Sie, dass eine LL-Grammatik ist. Für welchen
Wert von ? Ist
(für im Voraus bekanntes ) eine
LL-Grammatik? Für welchen Wert von ?
LL-Grammatiken parsen
Wir wollen nun erarbeiten, wie wir für eine LL-Grammatik
einen Parser, also im Prinzip einen deterministischen Pushdown-Automaten
schreiben können.
Wir tasten uns langsam voran. Wir beginnen mit einer
Verallgemeinerung von von Wörtern auf
Wortformen (die also Nichtterminale beinhalten können).
Definition 6.4.5
Sei eine kontextfreie Grammatik und eine
Wortform gegeben.
Wir definieren
Wir können nun die LL-Bedingung äquivalent formulieren:
Definition/Beobachtung 6.4.6
Eine Grammatik ist LL genau dann, wenn
für alle Grenzformen und alle
Produktionen mit auf der linken Seite, also
die Mengen paarweise disjunkt sind (wenn also keine
zwei dieser Mengen ein gemeinsames Element enthalten).
Nehmen wir eine Momentaufnahme unseres Kellerautomaten. Er
hat den Präfix des Eingabewortes gelesen und
eine Linksableitung
durchgeführt. Die Wortform ist genau das, was im Moment
auf dem Stack des Automaten liegt (um ganz genau zu sein:
liegt auf dem Stack). Wenn mit einem Terminalsymbol
beginnt, so ist klar, was wir machen müssen: wir schauen, ob mit
beginnt. Wenn ja, lesen wir und poppen es vom Stack. Der
schwierige Fall ist, wenn mit einem Nichtterminal beginnt.
Nochmal von vorn: im schwierigen Fall liegt auf dem Stack (oberhalb vom )
eine Wortform, die mit einem Nichtterminal beginnt, also
. Das bedeutet, dass der Automat per Linksableitung
bis jetzt
hergeleitet hat. Der Automat muss sich nun zwischen allen Regeln für entscheiden:
Der Automat betrachtet nun die nächsten Eingabesymbole, also
(wir gehen
mal davon aus, dass er das kann; programmieren könnten wir das auf jeden Fall;
ob man es im strengen Framework des Kellerautomaten hinkriegt, werden wir später sehen).
Wenn eine LL-Grammatik ist, dann gibt es höchstens eine
Regel mit
da ja nach obiger Beobachtung diese Mengen disjunkt sind. Wenn
in keiner dieser Mengen enthalten ist, so
kann die Ableitung offensichtlich nicht vervollständigt werden, und wir schließen,
dass ist.
Wenn es genau ein gibt mit
, dann ist
die "richtige" Produktion.
Wir wenden sie an, ersetzen also auf dem Stack durch .
Falls es zwei oder mehr Produktionen gibt mit
, dann ist die Grammatik
nicht LL; wir beenden den Parsing-Prozess mit einer
Laufzeitfehlermeldung.
Hier ist ein Entwurf eines allgemeinen Algorithmus
für LL-Grammatiken:
Generischer Algorithmus zum Parsen von LL-Gramatiken
Lege auf den Stack.
while Stack nicht leer
Sei das Resteingabewort.
Wenn das oberste Symbol auf dem Stack ein Terminalsymbol ist:
Lies das nächste Eingabesymbol .
Wenn , poppe vom Stack;
ansonsten Reject.
Wenn das oberste Symbol auf dem Stack ein Nichtterminalsymbol
ist:
Schreibe den Stack als
Seien
alle Produktionen mit auf der linken Seite.
Berechne für alle und
schaue, welches enthält
Wenn es genau eine solche Produktion
gibt: wende Sie an; es ist die richtige
Produktion.
Wenn es keine gibt: Reject. Das Wort kann nicht
abgeleitet werden.
Wenn es mehrere gibt: ende mit einem Laufzeitfehler;
die Grammatik ist nicht LL.
Wenn das oberste Symbol ist:
wenn Eingabewort zu Ende Accept ansonsten Reject
Die rot und fett gedruckte Zeile ist das "Herz" dieses Algorithmus. Um den Algorithmus
implementieren zu können, müssen wir es schaffen,
die Menge zu berechnen.
und berechnen.
Definition 6.4.7
Seien zwei Mengen.
Mit bezeichnen wir die Menge
(Diese Definition haben Sie schon im Kapitel über reguläre Sprachen kennengelernt).
Für eine natürliche Zahl definieren wir
Weiterhin bezeichnen wir mit
die Menge
Im Allgemeinen gilt
.
In Worten: der -Operator bildet alle möglichen Kombinationen von Wörtern und nimmt
von jedem die ersten Zeichen.
Beispiel 6.4.8
Sei
Dann ist
und somit
Beobachtung 6.4.9- Wie man berechnet.
Sei eine Wortform gegeben, also
. Wir berechnen
, indem wir als erstes
aussschreiben als
wobei jedes ein Terminalsymbol oder ein Nichtterminalsymbol ist,
und berechnen dann wie folgt:
Wir können dies schön der Reihe nach tun:
Initialisiere
fordown to 1 do:
// ist jetzt
return
Wir müssen nur noch herausfinden, wie wir
für einzelne Zeichen berechnen.
Für ein Terminalsymbol ist es trivial, zu berechnen:
es ist , da sich aus natürlich nur das Wort ableiten lässt.
Für Nichtterminale müssen wir uns anstrengen. Die erste Idee ist, dass
wir für eine Gleichung schreiben können, die verwendet.
Beobachtung 6.4.10
Sei ein Nichtterminal und
die Produktionen der Grammatik mit auf der linken Seite. Dann gilt
Was ja eigentlich offensichtlich ist: wenn sich ein Wort aus ableiten
lässt, dann
muss dies mittels einer der obigen Produktionen geschehen: ,
und somit
gilt .
Die Gleichungen und leuchten zwar
ein, scheinen aber erstmal
nicht hilfreich, diese Mengen auch tatsächlich zu berechnen. Denn eventuell taucht selbst
wieder auf einer rechten
Seite auf, sagen wir . Um zu berechnen, müssen wir also laut
die
Menge kennen; um diese zu berechnen, brauchen wir laut
allerdings zuerst
unter Anderem die Menge . Wo sollen wir also anfangen?
In solchen Situationen, wo sich "die Katze in den Schwanz beißt", hilft es oft, die Definition
vorerst komplexere un
genauer zu machen. Wir führen nun, zusätzlich zu und
, noch eine feinere
Unterteilung an:
Definition 6.4.11
Sei ein Symbol und . Dann ist
Beispiel 6.4.12
Sei unsere Grammatik
Dann ist beispielsweise
ein Ableitungsbaum der Höhe 2 von , und somit gilt
Ein Baum der Höhe 1, der mit beginnt, könnte ja nur ableiten und somit gar kein
Wort. Es gilt also
Für eine Wortform definieren
wir
Eine Ableitung der Höhe maximal entspricht also einer Folge
von Ableitungsbäumen, von denen jeder Höhe maximal hat.
Mit dieser Definition können wir nun Gleichungen für und
angeben.
Seien die Produktionen mit auf der
linken Seite. Dann gilt
für :
Lemma. 6.4.13
Für gilt
Für gilt
und schließlich
Die Gleichungen sagen, dass wir, falls wir für alle Nichtterminale
kennen,
dann auch berechnen können.
Daraus folgt auch: wenn
für alle , dann auch
für alle , und somit werden die
Mengen für alle von nun an gleich bleiben.
Beobachtung 6.4.14
Falls für alle , dann gilt
für alle .
Demo. 6.4.15- Berechnung der Menge für die Nichtterminale einer Sprache.
Wir betrachten die Grammatik