SLL(k)-Grammatik

Aus testwiki
Version vom 18. September 2024, 20:01 Uhr von imported>Aka (Halbgeviertstrich, Komma ergänzt, Links optimiert)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Vorlage:Überarbeiten

Eine SLL(k)-Grammatik (auch starke LL(k)-Grammatik) ist eine spezielle kontextfreie Grammatik, welche die Grundlage eines SLL(k)-Parsers bildet. Sie ist eine besondere Form der LL(k)-Grammatik. Im Gegensatz zu dieser kann für eine aus der Grammatik ableitbare Terminalfolge allein durch die nächsten k-Symbole der Terminalfolge (Lookahead) – ohne Berücksichtigung der vorhergegangenen Zeichen – die nächste Produktion der Produktionsfolge, die die Terminalfolge erzeugt, eindeutig gewählt werden.

Formale Definition SLL(k)-Grammatik

Eine kontextfreie Grammatik G=(N,Σ,P,S) ist genau dann eine starke LL(k) Grammatik für festes k > 0, wenn für beliebige Ableitungen der Form

Sl*μAχωαχ*ωγSl*μAχωβχ*ωγ

mit μ,μ,ω,ω,γ,γΣ*,α,β,χ,χ(ΣN)*,AN und k:γ=k:γ gilt: α=β

Dabei ist k:δ={δ#,falls|δ|<kκ,fallsδ=κηund|κ|=k

mit Sentinel #.


Es lässt sich zeigen, dass jede LL(1)-Grammatik auch eine SLL(1)-Grammatik ist. Für allgemeine k ist dies aber nicht der Fall.

Alternatives Kriterium

Der formale Nachweis der Gültigkeit obiger Definition für eine beliebige SLL(k)-Grammatik ist oft schwierig, weshalb hier ein alternatives Kriterium für eine SLL(k)-Grammatik vorgestellt wird.

Dafür seien zunächst

firstk(ω)={τ|νΣ*mitω*ν,τ=k:ν}followk(ω)={τ|ν(ΣN)*mitS*μων,τfirstk(ν)}

die First- und Followmengen. Eine intuitive Erklärung für die Firstmenge ist, dass diese für die gegebene Zeichenfolge ω die ersten k Terminale, die sich aus ω ableiten lassen, enthält. Die Followmenge hingegen enthält diejenigen Terminale, die bei einer Produktionsfolge die ω ausgehend vom Startterminal erzeugt, nach ω folgen können.

Mit den First- und Followmengen lässt sich nun das Kriterium definieren:

Eine Grammatik ist genau dann eine SLL(k)-Grammatik, wenn paarweise für alle Produktionen der Form Aα|β,αβ gilt:

firstk(αfollowk(A))firstk(βfollowk(A))=

Dabei ist die Followmenge nur relevant, falls es sich bei der entsprechenden Ableitung um eine ε-Ableitung handelt.

Auch hier findet sich eine intuitive Erklärung: Der Schnitt beider Mengen stellt gerade die Terminalsequenzen der Länge k dar, die nach der Ableitung von A aus beiden Produktionen erzeugt werden können. Wenn aber nun ein Parser den aktuellen Terminalstrom verarbeitet, muss sich dieser deterministisch für eine Produktion entscheiden. Dies kann er aber nicht wenn der gleiche Zeichenstrom aus mehreren Produktionen generiert werden kann. Genau diese Situation wird durch obige Definition verhindert: unabhängig vom vorhergegangenen Zeichen μ bzw. μ ist die nächste Produktion eindeutig. Ein Parser braucht somit bereits gelesene Zeichen nicht nochmals zu betrachten.

Siehe auch

Literatur

  • Waite, W., & Goos, G. (1984). Compiler Construction. New York, USA: Springer-Verlag, ISBN 0-387-90821-8.