Syntaktische Analyse (Parsen) Gegeben: eine kontextfreie Grammatik G und ein String w. Fragen: Vorgehen: gehört w zu L(G)? Welche Bedeutung hat w? Konstruiere Herleitungsbaum zu w P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 1
Syntaktische Analyse eines Programms Gegeben: Frage: Aufgabe: Syntax einer Programmiersprache und der Quelltext eines Programms. ist dies ein syntaktisch korrektes Programm? Was soll dieses Programm bewirken? Ermittle Bedeutung des Programms, Konstruktionsverfahren für Herleitungsbäume (bzw. Syntaxbäume) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 2
Syntaktische Analyse bzgl einer CFG Für jede CFG gibt es einen Parse-Algorithmus mit worst case Laufzeit O(n 3 ) (n : Anzahl der Eingabesymbole) CYK: Cocke, Younger, Kasami, falls Grammatik in Chomsky-Normalform (Alle Regeln von der Form N W mit W 2 oder Earley-Algorithmus CYK benutzt dynamisches Programmieren. erzeugt ein Tabelle: pro Paar (N, w) von Nichtterminal N und Wort w ein Eintrag True wenn N G w, sonst False Beschränkung: w sind Unterstrings des Eingabewortes P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 3
Syntaktische Analyse bzgl einer CFG Praxis: Für jede Programmiersprache gibt es einen Parser, der effizient arbeitet, d.h. in O(n), oder in O(n log(n)) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 4
Parse-Methoden und Beschränkungen Beschränkung in dieser Vorlesung auf einfach implementierbare oder effiziente Nur für eingeschränkte CFGs Verarbeitung des Zeichenstroms bzw. des Eingabewortes von links nach rechts evtl. auch mit Vorausschau um einige Zeichen. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 5
Parse-Methoden: Vorgehensweisen: Top-Down: Es wird versucht eine Herleitung vorwärts, vom Startsymbol aus, zu bilden ( forward-chaining ) Bottom-Up: Es wird versucht eine Herleitung rückwärts, vom Wort aus, zu bilden. ( backward-chaining ). P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 6
Parse-Methoden: Vorgehensweisen: Weiteres Unterscheidungsmerkmal: R : Konstruktion einer Rechtsherleitung L : Konstruktion einer Linksherleitung Gängige Kombinationsmöglichkeiten: Top-Down-Verfahren zur Konstruktion einer Linksherleitung Bottom-Up-Verfahren zur Konstruktion einer Rechtsherleitung P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 7
Beispiel S ::= AB A ::= 0 1 B ::= 8 9 Frage: Kann 09 aus dieser Grammatik hergeleitet werden? P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 8
09-Beispiel: Top-down: Start mit Startsymbol S Rate die Produktionen; Nutze den zu parsenden String zur Steuerung Bilde Restproblem Ziel: Eingabestring bis zum Ende verarbeiten. Ziel 09 09 9 ε NT-Wort S AB B Herleitung S AB 0B 09 Die erzeugte Herleitung ist eine Linksherleitung. Beachte 09 wird von links nach rechts bearbeitet Jedes Eingabezeichen bestimmt eindeutig die Produktion P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 9
09-Beispiel: Bottom-up: Vorgehen: Regeln rückwärts auf den gegebenen String anwenden das Startsymbol der Grammatik ist zu erreichen 09 A9 AB S Eine Rechtsherleitung wurde konstruiert Beachte: Manchmal sind mehrere Regeln anwendbar Manchmal muss man den Teilstring raten, auf den eine Produktion (rückwärts) angewendet werden soll Im Beispiel: Gleicher Herleitungsbaum P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 10
Beispiel: Suche nach der Herleitung S ::= A B A ::= 0A 1 B ::= 0B 2 Kann 002 hergeleitet werden? Ziel 002 002 02 2 NT-Wort S A A A Herleitung S A 0A 00A? 002 kann nur aus B hergeleitet werden: Ziel 002 002 02 2 NT-Wort S B B B Herleitung S B 0B 00B 002 P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 11
Beispiel: Bemerkungen Ein deterministischer Top-Down-Parser muss beim ersten Zeichen von 002 entscheiden, ob A, oder B. Diese Wahl kann falsch sein. Misslingt eine Herleitung, so muss der Parser zurücksetzen Backtracking P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 12
Rekursiv absteigende Parser Rekursiv absteigender Parser / Syntaxanalyse ist an der Form der Regeln der Grammatik orientiert Methode: Top-Down-Prüfung der Anwendbarkeit der Regeln P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 13
Struktur eines rekursiv absteigenden Parsers Top-Down bzgl. der Grammatik. Eingabewort von links nach rechts Backtracking, falls Sackgasse Konstruktion einer Linksherleitung P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 14
Struktur eines rekursiv absteigenden Parsers Pro Nichtterminal N existiert ein Parser P N der die formale Sprache zu N erkennt. Eingabe: String Ausgabe: Syntaxbaum zu Prefix der Eingabe; Reststring Parser zu G ist P σ zum Startsymbol σ Gegeben alle N-Regeln: N w 1... w n P N probiert für alle w i aus, ob diese zum Anfang des Eingabestrings passen Passt keine, dann Fehlschlag Prüfung, ob eine Regel ob N w 1 passt: w i = w i1 w i2... w im von links nach rechts durchgehen Jeweils Parser P wij aufrufen. I.a. rekursiver Aufruf, falls w ij Nichtterminal. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 15
Eigenschaften eines rekursiv-absteigenden Parsers I.a. exponentiell. Liefert alle Linksherleitungen für alle Präfixe Leicht implementierbar Leicht erweiterbar auf weitere Einschränkungen Terminiert nicht für bestimmte (linksrekursive) Grammatiken, obwohl eine Herleitung existiert: Beispiel A ::= A+A A-A 1... 9 Eingabe: 1+1 : Aber: nur die erste Regel wird (jeweils rekursiv) versucht: (A,1+1) (A+A,1+1) ((A+A)+A, 1+1)... P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 16
Rekursiv-absteigende Parser Anmerkung Programme von Programmiersprachen kann man i.a. in O(n) oder O(n log(n)) parsen, Effiziente rekursiv-absteigende Parser benötigen i.a.: Erweiterungen wie Vorausschau Umbau der Grammatik (Optimierung der Grammatik) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 17
Funktionale Kombinator-Parser Implementierung von rekursiv-absteigenden Parsern in Haskell Vorteile relativ leicht verständliche Programmierung 1-1-Übersetzung der Regeln in Programmcode Pro Nichtterminal N eine Funktion parsern:: String -> [(String, R)] Präfix der Eingabe (Rest der Eingabe, Resultat (z.b. Syntaxbaum) ) Um Backtracking zu implementieren: Liste von erfolgreichen Ergebnissen verzögerte Auswertung ergibt richtige Reihenfolge der Abarbeitung. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 18
Haskell-Implementierung der Parser-Kombinatoren Kombinator (kombiniert Parser) Z.B. Alternative, Sequenz, Resultat-Umbau module RekParsKomb where import Char infixr 6 <*>, <*, *> infixr 4 < >, <!> infixl 5 <@ type Parser a b = [a] -> [([a],b)] erkennt ein Zeichen: symbol :: Eq s => s -> Parser s s symbol a [] = [] symbol a (x:xs) a ==x = [(xs,x)] otherwise = [] P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 19
Haskell: Parser-Kombinatoren (2) erkennt einen String: token :: Eq s => [s] -> Parser s [s] -- token :: Eq s => [s] -> Parser s [s] token k xs k == (take n xs) = [(drop n xs, k)] otherwise = [] where n = length k testet ein Zeichen der Eingabe: satisfy :: (s -> Bool) -> Parser s s satisfy p [] = [] satisfy p (x:xs) = [(xs,x) p x] epsilon :: Parser s () epsilon xs = [(xs,())] P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 20
Haskell: Parser-Kombinatoren (3) immer erfolgreich: succeed :: r -> Parser s r succeed v xs = [(xs,v)] immer fehlschlagend: pfail :: Parser s r pfail xs = [] P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 21
Haskell: Parser-Kombinatoren (4) Sequenzkombinator : (<*>) :: Parser s a -> Parser s b -> Parser s (a,b) (p1 <*> p2) xs = [(xs2, (v1,v2)) (xs1,v1) <- p1 xs, (xs2,v2) <- p2 xs1] Alternativkombinator : (< >) :: Parser s a -> Parser s a -> Parser s a (p1 < > p2) xs = p1 xs ++ p2 xs Alternativkombinator-2: nur das erste Ergebnis: (<!>) :: Parser s a -> Parser s a -> Parser s a (p1 <!> p2) xs = take 1 (p1 xs ++ p2 xs) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 22
Haskell: Parser-Kombinatoren (5) ignoriert Blanks am Anfang: sp :: Parser Char a -> Parser Char a sp p = p. dropwhile isspace eliminiert alle Whitespaces: wsp :: Parser Char a -> Parser Char a wsp p = p. filter (\x -> not (isspace x)) testet, ob die ganze Eingabe konsumiert wurde : just :: Parser s a -> Parser s a just p = filter (null. fst). p P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 23
Haskell: Parser-Kombinatoren (6) Operation auf dem Ergebnis des Parse : (<@) :: Parser s a -> (a-> b) -> Parser s b (p <@ f) xs = [(ys, f v) (ys,v) <- p xs] ignoriert rechtes Ergebnis: (<*) :: Parser s a -> Parser s b -> Parser s a p <* q = p <*> q <@ fst ignoriert linkes Ergebnis: (*>) :: Parser s a -> Parser s b -> Parser s b p *> q = p <*> q <@ snd list (x,xs) = x:xs P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 24
Haskell: Parser-Kombinatoren (7) erkennt Folge. d.h. entspricht *: many :: Parser s a -> Parser s [a] many p = p <*> many p <@ list < > succeed [] many1 p = p <*> many p <@ list digit :: Parser Char Int digit = satisfy isdigit <@ f where f c = ord c - ord 0 erkennt Zahl: natural :: Parser Char Int natural = many1 digit <@ foldl f 0 where f a b = a*10 + b P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 25
Haskell: Parser-Kombinatoren (8) Nimmt nur die erste (maximale) Alternative des many: nur erlaubt, wenn die Grammatik diese Alternativen nicht benötigt manyex :: Parser s a -> Parser s [a] manyex p = p <*> many p <@ list <!> succeed [] many1ex p = p <*> manyex p <@ list option p = p <@ (\x->[x]) <!> epsilon <@ (\x-> []) Nimmt nur die erste (maximale) Alternative bei Zahlen: naturalex :: Parser Char Int naturalex = many1ex digit <@ foldl f 0 where f a b = a*10 + b P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 26
Haskell: Parser-Kombinatoren (9) Erkennt Klammerung und ignoriert den Wert der Klammern: pack:: Parser s a -> Parser s b -> Parser s c -> Parser s b pack s1 p s2 = s1 *> p <* s2 Erkennt Infix-Folge wie z.b. (1+2+3+4+5): Liste der Argumente: opseqinf psymb parg = (parg <*> many (psymb *> parg)) <@ list paarf f = \(x,y) -> f x y P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 27
Beispiel arithmetische Ausdrücke Grammatik Ex ::= Plus Plus ::= SigZ SigZ Plusrest PlusRest ::= + SigZ PlusRest eps SigZ ::= B - B B ::= Z ( Ex ) Z ::= 0... 9 P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 28
Beispiel arithmetische Ausdrücke plusausdruecke = just pariex pariex :: Parser Char Integer pariex pariplus = (wsp pariplus) = (opseqinf (symbol + ) parisigz) <@ sum Die direkte Implementierung wäre: (parisigz <*> many ((symbol + ) *> parisigz)) <@ list parizsymbol = naturalex parisigz = parib < > (symbol - ) *> parib <@ (negate) parib = parizsymbol < > (pack (symbol ( ) pariex (symbol ) )) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 29
Rekursiv-prädiktive Parser Optimierte rekursiv absteigende Parser für eingeschränkte Grammatiken ( LL(1) ). Eigenschaft Die anzuwendende Produktion ist immer eindeutig festgelegt abhängig vom aktuellen Nichtterminal und dem nächsten Symbol der Resteingabe (Lookahead-Symbol) kein Zurücksetzen notwendig, deterministisch Abarbeitung der Eingabe von links nach rechts Aber: man kann nicht für jede kontextfreie Grammatik einen rekursiv-prädiktiven Parser konstruieren. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 30
Rekursiv-prädiktive Parser Eindeutige Zuordnung: (Lookahead-Symbol, aktuelles Nichtterminal) Regel Tabellengesteuerter rekursiv-prädiktiver Parser: Die obige Tabelle inklusive Fehlereinträge reicht aus zur Steuerung des Parsers P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 31
Rekursiv-prädiktive Parser Sind A w 1... w n die Regeln zu A und im Zustand A ist a das erste Symbol der Eingabe: nur eine Regel A w i darf anwendbar sein. Beispiel: A bcd aef cg H H dabc... P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 32
Rekursiv-prädiktive Parser Sonderrolle: Es gibt Regel A w i mit w i ε: Diese wird ausgewählt, wenn: keine passende rechte Seite für das Lookahead-Symbol und das Lookahead-Symbol kann auf A folgen und es gibt nur eine solche Regel für A P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 33
Rekursiv-prädiktive Parser, ε-fall Beispiel: S AB AC A bcd aef cg H H ε... B da C ea Im Zustand A und bei Eingabesymbol d: A H wird ausgewählt. Beachte: Gesamtzustand = gesamter Aufrufstack P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 34
FIRST- und FOLLOW-Mengen Definition Sei G eine CFG mit S als Startsymbol. Für w (T N) und A N: first(w) := {x T w xv für ein Wort v T } {ε} wenn w ε follow(a) := {x T S v 1 Axv 2 für Worte v 1, v 2 T } Diese Mengen kann man in allen rekursiv-absteigenden Parsern zur Vermeidung von Backtracking verwenden. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 35
Berechnung von first : Fixpunktiteration: f 0 (A i ) := für alle i f j+1 (A i ) := i f j (w i ) wenn A i ::= w 1... w k die Regeln zu A sind. Stopp, wenn sich nichts mehr ändert. Hierbei wird verwendet: f j (aw) := {a} für jedes Terminal a f j (Aw ) := f j (A) wenn ε f j (A) f j (Aw ) := (f j (A) \ {ε}) f j (w ) wenn ε f j (A) f j (ε) := {ε} P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 36
Berechnung von follow : g 0 (A i ) := für alle i g j+1 (A i ) := Vereinigung folgender Mengen: first(w ) T g j (A k ) für jede Regel A k wa i w für jede Regel A k wa i w mit ε first(w ) Stopp, wenn g j+1 (A) = g j (A) für alle Nichtterminale A. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 37
Beispiel für first: Fixpunktberechnung Ex ::= Plus Plus ::= SigZ SigZ Plusrest PlusRest ::= + SigZ PlusRest eps SigZ ::= B - B B ::= Z ( Ex ) Z ::= 0... 9 Ex Plus Plus SigZ B Z Rest +, ε - ( 0,...,9 - +, ε -,( 0,...,9, ( 0,...,9 - -,( +, ε 0,...,9, (,- 0,...,9, (,- 0,...,9 -,( 0,...,9, (,- +, ε 0,...,9, (,- 0,...,9, (,- 0,...,9 0,...,9, (,- 0,...,9, (,- +, ε 0,...,9, (,- 0,...,9, (,- 0,...,9 P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 38
Beispiel für follow : Ex ::= Plus Plus ::= SigZ SigZ Plusrest PlusRest ::= + SigZ PlusRest eps SigZ ::= B - B B ::= Z ( Ex ) Z ::= 0... 9 Ex Plus Plus SigZ B Z Rest ) + ) ) + + ) ) ) + + + ) ) ) +,) + + ) ) ) +,) +,) + ) ) ) +,) +,) +,) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 39
Konstruktion eines rekursiv-prädiktiven Parsers Bedingungen für die Eindeutigkeit: Für jedes A mit A ::= w 1... w n falls ε first(w i ) für alle i: die Mengen first(w i ) müssen paarweise disjunkt sein. Für jedes A mit A ::= w 1... w n falls ε first(w j ) für ein j: die Mengen first(w i ), i = 1,..., n und follow(a) müssen paarweise disjunkt sein. Für jedes A mit A ::= w 1... w n gibt es maximal ein w i mit ε first(w i ) Parser benötigt Tabelle (A i, a) R j P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 40
Vorgehen des LL(1)-Parsers Gegeben a, das Symbol und das aktuelle Nichtterminal A: Ist a first(w i ) für eine Regel A ::= w i, dann nehme diese Regel. Ist a first(w i ) für alle Regeln A ::= w i, dann gibt es maximal eine Regel A ::= w mit first(w) = Falls a follow(a), dann diese Regel. Wenn auch dann keine passende Alternative existiert, wird mit Fehler abgebrochen. Vorteil: genaue und frühe Fehlererkennung P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 41
Beispiel: vereinfachte Grammatik für Ausdrücke Expr ::= Term Rest Rest ::= + Term Rest Term Rest ε Term ::= 0... 9 first(term Rest) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} first(+ Term Rest) = {+}, first( Term Rest) = { } first(expr ) = first(term ) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} first(rest) = {+,, ε} follow(expr) =. follow(rest) =. follow(term) = {+, }. Diese Grammatik hat somit die LL(1)-Eigenschaft. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 42
Beispielparser zur Grammatik E ::= T R R ::= + T R - T R ε T ::= 0... 9 Die Parsefunktionen haben als Wert: (Resteingabe, Pbaum) data Pbaum = Pblatt Int PExp Pbaum Pbaum PRest Char Pbaum Pbaum PLeer deriving (Show, Eq) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 43
Beispielparser zur Grammatik (2) parseterm [] = error "Ziffer erwartet; rest = nil" parseterm eingabe@(symbol:rest) = if not (symbol elem [ 0.. 9 ] ) then error ("Ziffer erwartet; rest = " ++ eingabe) else (rest,pblatt (fst (head (reads [symbol])))) parserest [] = ([],PLeer) parserest eingabe@(operator: rest) = if not (operator elem [ +, - ] ) then error ("+ oder - erwartet; rest = " ++ eingabe) else let (rest1,resultat1) = parseterm rest (rest2,resultat2) = parserest rest1 in (rest2, PRest operator resultat1 resultat2) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 44
Beispielparser zur Grammatik (3) parseexp :: [Char] -> (String,Pbaum) parseexp [] = error ("Ziffer erwartet; rest = nil") parseexp (eingabe@(symbol: rest)) = if not (symbol elem [ 0.. 9 ] ) then error ("Ziffer erwartet; rest = " ++ eingabe) else let (rest1,resultat1) = parseterm eingabe (rest2,resultat2) = parserest rest1 in (rest2, PExp resultat1 resultat2) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 45
Beispielparser zur Grammatik (4) Testbeispiele: test1::(string,pbaum) test1 = parseexp "1 + 2-3" test2::(string,pbaum) test2 = parseexp "1+2-3" Main> test2 ("",PExp (Pblatt 1) (PRest + (Pblatt 2) (PRest - (Pblatt 3) PLeer))) :: (String,Pbaum) P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 46
Parsebaum: Beispielparser zur Grammatik (3) PExp 1 PRest + 2 PRest 3 PLeer Er entspricht der Grammatik, aber noch nicht der gewünschten Struktur des arithmetischen Ausdrucks. Man braucht eine Nachbearbeitung des Parsebaumes. P raktische Informatik 2, SS 2005, F olien Kap.4, 2, (15. Juni2005) Seite 47