LR(k)-Parser Ziele: • Effizienter (und deterministischer) Test, ob ein gegebenes Wort w in der Sprache L(G) enthalten ist. • Falls ja: Konstruktion des Syntaxbaums • Falls nein: Hinweise zum Fehler CYK-Algorithmus ist zu langsam.
596
LR(k)-Parser Bedeutung der Abkürzung: L: left-to-right scan R: rightmost derivation — Berechnung einer Rechtsableitung Der Syntaxbaum wird bottom-up aufgebaut. k: Lookahead von k Zeichen — Der Algorithmus muss anhand der nächsten k Zeichen der Eingabe entscheiden, welche Ableitungsregel anzuwenden ist. 597
Notation α β, falls β aus α mit einer Rechtsableitung in einem Schritt herleitbar ist. r
r * α β, falls β aus α mit einer endlichen Folge
von Rechtsableitungen herleitbar ist.
598
Beispiel: L={aibicjdjekfk | i,j,k≥0} S8
• Links-Rechts-Scan erzeugt Num. der Regeln in bottom-upZ X3 7 5Y Ordnung (Postorder) • Anwendung der Regeln gemäß der a X b c Yd e Zf 2 6 4 umgedrehten Nummerierung ist a X b ε Rechtsableitung. ε 1 • Lookahead nötig. ε
599
Bemerkungen • Alternative Sichtweise: Syntaxanalyse entspricht „Reduzierung“ der Eingabe auf das Startsymbol durch umgekehrtes Anwenden der Regeln der Grammatik. • Syntaxanalyse mit Hilfe von Lookahead ist nur für spezielle Grammatiken möglich siehe folgende Beispiele.
600
Beispiel T8.2.6 Grammatik G1 für a*c+a*d: SC, SD, CaC, Cc, DaD,Dd S
S
C
D
a
C
a
D
a
C
a
D
c
d
Lookahead von 0 ausreichend 601
Beispiel T8.2.7 Grammatik G2 für a*c+a*d: SCc, SDd, CCa, Cε, DDa, Dε S S C c
D d
C a
D a
C a
D a
C a
D a
ε
ε
Syntaxanalyse mit endlichem Lookahead nicht möglich. 602
Beispiel T.8.2.8 Grammatik für {aabbb,aabba}: SCD, Ca, DEF, DaG, Eab, Fbb,Gbba. S S C a
D E
C F
a b b b
a
D a G b b a
Lookahead von 2 nötig. 603
Definition von LR(k)-Grammatiken Ziel: Ein Lookahead von k soll ausreichen, um entscheiden zu können, welche Regel angewendet werden muss. Definition: FIRSTk(w1…wn):=
w1…wk, falls n≥k, w1…wn, sonst. 604
Neues Startsymbol S´ Ziel: Wir wollen einfach das Ende einer erfolgreichen Herleitung erkennen. Dazu: Modifiziere die Grammatik: Neues Startsymbol S´ und Regel S´S. Dann: Wenn diese Regel erreicht wird und die gesamte Eingabe gelesen wurde, liegt eine erfolgreiche bottom-up Herleitung vor.
605
Definition T8.2.5 Eine kontextfreie Grammatik G heißt LR(k)Grammatik, falls für alle α,β,γ∈ (V ∪T )*, alle A,B∈V und alle w,x,y∈T * gilt: r r * S´ αAw αβw r r * S´ γBx αβy
⇒ α=γ, A=B und y=x.
FIRSTk(w)=FIRSTk(y)
606
Shift-Reduce-Parser Spezieller DPDA, der zusätzlich eine Rechtsableitung berechnet. Aufbau: Eingabeband Lookahead von k
S t a c k
Steuerung mit Übergangstabelle
Ausgabe 607
Übergangstabelle Enthält das „Programm“ des Parsers. Operationen (in Abhängigkeit vom Lookahead und dem obersten Stacksymbol) • Shift: Lies nächstes Zeichen der Eingabe ein und schiebe es auf den Stack. Zusätzlich speichere „Zustand“ auf dem Stack. Aktualisiere Lookahead. • Reduce: Wende eine Regel Aα an. Dazu entferne den zu α gehörenden Stackinhalt und lege A und aktualisierten Zustand auf Stack. • Error/Accept: Rechnung verwerfend/akzeptierend beenden. 608
Reduce-Operation Anwendung der Regel Aβ1…βr • Entferne die obersten 2r Symbole vom Stack (β1,…,βr, sowie die Zustände dazwischen) Weicht vom bisherigen Modell ab, da mehrere Zeichen vom Stack entfernt werden. • Schreibe A auf Stack. • Berechne anhand Tabelle neuen Zustand und lege ihn auf dem Stack ab. 609
Bsp: S´S, SSaSb, Sεε
R0 R1 Lookahead Aktion a b ε T0 R2 error R2 T1 shift error Acc T2 R2 R2 error T3 shift shift error T4 R2 R2 error T5 R1 error R1 T6 shift shift error T7 R1 R1 error Alter Zustand
Oberstes Stacksymbol
R2 neuer Zustand a b S T1 error error error T2 error T3 error error error T4 T5 T6 error error error error error error T4 T7 error error error
610
Wie berechnet man die Tabelle? Algorithmus: • siehe Kapitel T8.3 und T8.4 oder • Aho, A., Sethi, R. und Ullman, J.D. Compilers, Principles, Techniques and Tools, Addison-Wesley, 1986. • Für LR(0)-Parser: http://en.wikipedia.org/wiki/LR_parser Zu aufwändig für diese Vorlesung.
611
Wie berechnet man die Tabelle? Praxis: Verwende Parser-Generator. Eingabe: Kontextfreie Grammatik sowie zusätzliche Befehle, die beim Anwenden der Regeln auszuführen sind. Ausgabe: Parser. Beispiele (für sog. LALR(1)-Gram.): • yacc (yet another compiler compiler) • bison
612
Beispiel: L={w| |w|0=|w|1} Besprochene Grammatik: Sε, S0S1S, S1S0S • bison liefert: shift/reduce conflicts • bedeutet: es gibt Situationen, wo nicht klar ist, ob ein Eingabezeichen zu lesen ist oder eine Regel anzuwenden ist. • Ursache: Grammatik nicht eindeutig. Satz T8.4.10: LR(k)-Grammatiken sind eindeutig. 613
Zusammenfassung • Kontextfreie Grammatiken ermöglichen die Beschreibung von vielen Konstrukten aus den gängigen Programmiersprachen. • Mit Parser-Generatoren kann man auf eine einigermaßen einfache Weise zu speziellen Grammatiken Parser erzeugen. • Die Konstruktion von Compilern, die auch sinnvolle Fehlermeldungen liefern, ist aufwändiger. 614