Dieser Artikel setzt Vorkenntnisse im Bereich Theoretische Informatik und Compilerbau voraus.


Eine LL(k)-Grammatik (im Gegensatz zu LF(k)-Grammatik auch schwache LL(k)-Grammatik) ist eine spezielle kontextfreie Grammatik, welche die Grundlage eines LL(k)-Parsers bildet.

Eine kontextfreie Grammatik heißt LL(k)-Grammatik für eine natürliche Zahl k, wenn jeder Ableitungsschritt eindeutig durch die nächsten k Symbole der Eingabe (Lookahead) bestimmt ist. Das bedeutet, die Frage, welches Nichtterminalsymbol mit welcher Regel als Nächstes expandiert werden soll, kann eindeutig mit Hilfe der nächsten k Symbole der Eingabe bestimmt werden.

Generell gilt, je größer k gewählt wird, umso mächtiger wird die Sprachklasse, wobei die Ausdrucksstärke von kontextfreien Grammatiken nie erreicht wird. Damit gibt es kontextfreie Sprachen, die für kein k von einer LL(k)-Grammatik erzeugt werden.

L ( L L ( 1 ) ) L ( L L ( 2 ) ) L ( L L ( k ) ) L ( L R ( 1 ) ) = L ( D P D A ) {\displaystyle {\mathcal {L}}(\mathrm {LL} (1))\subsetneq {\mathcal {L}}(\mathrm {LL} (2))\subsetneq \dots \subsetneq {\mathcal {L}}(\mathrm {LL} (k))\subsetneq {\mathcal {L}}(\mathrm {LR} (1))={\mathcal {L}}(\mathrm {DPDA} )}

Dabei steht DPDA für die deterministischen Kellerautomaten. Diese können genau die deterministisch kontextfreien Sprachen erkennen.

Formale Definition LL(k)-Grammatik

Eine kontextfreie Grammatik G = ( N , Σ , P , S ) {\displaystyle G=(N,\Sigma ,P,S)} ist genau dann eine LL(k)-Grammatik, wenn für alle Linksableitungen der Form

S l w A γ l { w α γ l w x w β γ l w y {\displaystyle S\Rightarrow _{l}^{*}wA\gamma \Rightarrow _{l}\left\{{\begin{array}{l}w\alpha \gamma \Rightarrow _{l}^{*}wx\\w\beta \gamma \Rightarrow _{l}^{*}wy\end{array}}\right.}

mit ( w , x , y Σ ; α , β , γ ( N Σ ) ; A N ) {\displaystyle \quad (w,x,y\in \Sigma ^{*};\alpha ,\beta ,\gamma \in (N\cup \Sigma )^{*};A\in N)} und f i r s t k ( x ) = f i r s t k ( y ) {\displaystyle {\mathit {first}}_{k}(x)={\mathit {first}}_{k}(y)^{\,}} gilt: α = β {\displaystyle \alpha =\beta ^{\,}}

Für die in der Definition benutzte Funktion zur Bestimmung der FIRST-Mengen gilt:

Anwendung

Aktuelle LL-Parser benutzen meist nur einen Lookahead von 1. Daher kann in den folgenden Ausführungen k = 1 {\displaystyle k=1} gesetzt werden.

Bei der praktischen Anwendung ist nur mit großem Aufwand überprüfbar, ob die vorliegende Grammatik die Definition einer LL(k)-Grammatik erfüllt. Es wird stattdessen ein abgewandelter Ansatz benutzt.

Erklärung: Das Startsymbol der kontextfreien Grammatik S {\displaystyle S} wurde (in eventuell mehreren Schritten) nach w A α {\displaystyle wA^{\,}\alpha } expandiert. Gemäß der Linksableitung wird das Nichtterminalsymbol A {\displaystyle A} als Nächstes ersetzt. Dazu gibt es in der kontextfreien Grammatik aber zwei verschiedene Regeln; A β {\displaystyle A\to \beta } und A γ {\displaystyle A\to \gamma } . Die Frage, mit welcher Regel A {\displaystyle A} expandiert wird, bestimmt sich aus der Berechnung von f i r s t k ( β α ) {\displaystyle first_{k}\left(\beta \alpha \right)} und f i r s t k ( γ α ) {\displaystyle first_{k}\left(\gamma \alpha \right)} . Um die Frage eindeutig beantworten zu können, müssen beide Mengen disjunkt sein.

Im Allgemeinen hängt f i r s t k ( β α ) {\displaystyle first_{k}\left(\beta \alpha \right)} aber vom Rechtskontext α {\displaystyle \alpha } ab (wenn β ϵ {\displaystyle \beta \Rightarrow ^{*}\epsilon } ). Das Ziel ist die Bestimmung von f i r s t k ( β α ) {\displaystyle first_{k}\left(\beta \alpha \right)} nur aus den Produktionen, d. h. aus β {\displaystyle \beta } und aus den Strings, die einem Vorkommen von A {\displaystyle A} folgen können. Für diesen Zweck wird die Funktion f o l l o w k ( A ) {\displaystyle follow_{k}\left(A\right)} definiert, die die Menge aller A {\displaystyle A} folgenden Symbole berechnet.

Damit kann die eingangs geforderte Bedingung umformuliert werden:

Achtung: Dieser Satz kann auf Fälle k > 1 {\displaystyle k>1} nicht angewandt werden.

Die zu einer Produktion A β {\displaystyle A\to \beta } berechnete Menge l a ( A , β ) = f i r s t 1 ( { β } f o l l o w 1 ( A ) ) {\displaystyle la(A,\beta )=first_{1}\left(\{\beta \}follow_{1}(A)\right)} wird als Lookahead-Menge bezeichnet.

Beispiel

Für die folgende Grammatik G {\displaystyle G} wird geprüft, ob sie eine LL(1)-Grammatik ist. Dazu müssen die Lookahead-Mengen aller Produktionen mit gleichen linken Regelseiten disjunkt sein.

G = ( { E , E , T , T , F } , { a , ( , ) , , } , P , E ) {\displaystyle G=\left(\{E,E',T,T',F\},\{a,(,), ,*\},P,E\right)} und die Menge der Produktionen ist:
E T E {\displaystyle E\to TE'}
E T E | ϵ {\displaystyle E'\to TE'|\epsilon }
T F T {\displaystyle T\to FT'}
T F T | ϵ {\displaystyle T'\to *FT'|\epsilon }
F ( E ) | a {\displaystyle F\to (E)|a}

Zunächst werden die first- bzw. follow-Mengen der Nichtterminalsymbole bestimmt, da diese für die Berechnung der Lookahead-Mengen nötig sind.

Es folgt der Vergleich der Lookahead-Mengen für alle Produktionen mit gleichen linken Regelseiten.

Als erstes für die beiden Produktionen T E {\displaystyle TE'} und ϵ {\displaystyle \epsilon } von E T E | ϵ {\displaystyle E'\to TE'|\epsilon }

f i r s t 1 ( { T E } ) f i r s t 1 ( { ϵ } ) = { } { ϵ } = {\displaystyle first_{1}(\{ TE'\})\cap first_{1}(\{\epsilon \})=\{ \}\cap \{\epsilon \}=\emptyset }
f i r s t 1 ( { T E } ) f o l l o w 1 ( E ) = { } { $ , ) } = {\displaystyle first_{1}(\{ TE'\})\cap follow_{1}(E')=\{ \}\cap \{\$,)\}=\emptyset }

Als Nächstes für die beiden Produktionen F T {\displaystyle *FT'} und ϵ {\displaystyle \epsilon } von T F T | ϵ {\displaystyle T'\to *FT'|\epsilon }

f i r s t 1 ( { F T } ) f i r s t 1 ( { ϵ } ) = { } { ϵ } = {\displaystyle first_{1}(\{*FT'\})\cap first_{1}(\{\epsilon \})=\{*\}\cap \{\epsilon \}=\emptyset }
f i r s t 1 ( { F T } ) f o l l o w 1 ( T ) = { } { , $ , ) } = {\displaystyle first_{1}(\{*FT'\})\cap follow_{1}(T')=\{*\}\cap \{ ,\$,)\}=\emptyset }

Als letztes für die beiden Produktionen ( E ) {\displaystyle (E)} und a {\displaystyle a} von F ( E ) | a {\displaystyle F\to (E)|a}

f i r s t 1 ( { ( E ) } ) f i r s t 1 ( { a } ) = { ( } { a } = {\displaystyle first_{1}(\{(E)\})\cap first_{1}(\{a\})=\{(\}\cap \{a\}=\emptyset }

Da alle betrachteten Schnittmengen leer sind, handelt es sich bei der Grammatik G {\displaystyle G} um eine LL(1)-Grammatik.

Siehe auch

  • LR(k)-Grammatik
  • LR-Parser

Literatur

  • Donald E. Knuth: Top-down syntax analysis. In: Acta Informatica 1, 1971, ISSN 0001-5903, S. 79–110, (Neuabdruck einer erweiterten Fassung in: Donald E. Knuth: Selected Papers on Computer Languages. Center for the Study of Language and Information, Stanford CA 2003, ISBN 1-575-86381-2, (CSLI lecture notes 139), Kapitel 14).
  • LR(k)-Analyse für Pragmatiker von Andreas Kunert

g oder k

Rechtschreibung k oder ck

Lückenwörter G oder K Therapiematerial Artikulation, LRS/Dyskalkulie

k oder ck

Königspaket Rechtschreibung k oder ck? (Deutsch, 1. & 2. Klasse)