Definitie Taal van een grammatica nZij grammatica G = ( T, N, R, S ) nde taal van G is { z T* | S * z } L(G)
Unieke ontleding nEen zin heeft een unieke ontleding als u er maar één ontleedboom is of equivalent: u er maar één leftmost derivation is Ambigue grammatica nEen grammatica is ambigu als uer een zin is met een niet-unieke ontleding
Grammatica-transformaties Aanpassen van de regels, zo dat De taal hetzelfde blijft Wenselijke eigenschappen ontstaan nRegels (ont)expanderen nLinksrecursie verwijderen nPrioriteiten van operatoren inbouwen
Transformaties Operatoren met prioriteiten Heeft dezelfde taal als E E + E E E * E E ( E ) E N * gaat nu voor + E T E T + E T F T F * T F ( E ) F N
Haskell datatype voor ontleedbomen nGrammatica-regelsn Haskell datatype dat ontleedboom representeert { X A B, X C d, X e } data X = A B | C d | e Een Twee Drie show :: X String show (Een a b) = show a ++ show b show (Twee c) = show c ++ “d” show (Drie) = “e” parse :: String X uit de abstracte syntax kun je concrete syntax reconstrueren
Grammatica “Expressie” Expr Term Rest Rest + Expr Rest – Expr Rest Term Getal Term ( Expr ) Expr Term ( + Term | – Term ) * Term Getal | ( Expr ) EBNF- notatie
ANTLR-notatie Expr:Term ( PLUS Term | MINUS Term ) * ; Term :Getal | LPAREN Expr RPAREN ; PLUS : ‘+’ ; MINUS : ‘–’ ; LPAREN : ‘(’ ; class ExprParser extends Parser class ExprLexer extends Parser
ANTLR genereert Java Expr: Term ( PLUS Term | MINUS Term ) * ; Term : INT | LPAREN Expr RPAREN ; public void expr () { term (); loop1: while (true) { switch(sym) { case PLUS: match(PLUS); term (); break; case MINUS: match(MINUS); term (); break; default: break loop1; } public void term() { switch(sym) { case INT: match(INT); break; case LPAREN: match(LPAREN); expr (); match(RPAREN); break; default: throw new ParseError(); }
ANTLR-notatie Expr :Term ( PLUS Term | MINUS Term ) * ; Term :GETAL | LPAREN Expr RPAREN ; returns [int x=0] { int y; } returns [int x=0] x=x= y=y= y=y= x=x= { x += y; } { x –= y; } n:n: { x = str2int(n.getText(); }
ANTLR-Architectuur Expr. g ExprMain. java ExprLexer. java ExprParser. java ANTLR *. class Java compiler Antlr. jar Java interpreter zin
Haskell Parser Combinator Architectuur Expr. hsParseLib. hs Haskell interpreter zin
ANTLR vs. ParserCombinators nGrammatica schrijven in apart taaltje nGenereert Java-code nGroot, ingewikkeld nGeen linksrecursie nGeen ambiguiteit n1-symbool lookahead nJava n Grammatica schrijven met Haskell-operatoren n Is gewone Haskell-library n Kort n Geen linksrecursie n Wel ambiguiteit n Onbeperkt lookahead n Haskell
Type van parsers parse :: String X type Parser = String X type Parser b = String b polymorf resultaattype type Parser b = String (b, String) restant-string type Parser a b = [a] (b, [a]) polymorf alfabet type Parser a b = [a] [ (b, [a]) ] lijst resultaten i.v.m. ambiguïteit
Simpele parsers X a symbola :: Parser Char Char type Parser a b = [a] [ (b, [a]) ] symbola [ ] = symbola (x:xs) | x==’a’ = | otherwise = [ (’a’, xs) ] [ ]
Simpele parsergeneratoren X a symbol :: Parser a a symbol a [ ] = [ ] symbol a (x:xs) | x==a = [ (a,xs) ] | otherwise= [ ] symbola :: Parser Char Char symbola [ ] = [ ] symbola (x:xs) | x==’a’ = [ (’a’,xs) ] | otherwise= [ ] a a Eq a te herkennen symbool is nu parameter
Andere parsergeneratoren token :: Eq a [a] Parser a [a] satisfy :: (a Bool) Parser a a token t xs where n = length t | t == take n xs= | otherwise = [(t, drop n xs)] [ ] satisfy p [ ] = satisfy p (x:xs) | p x = | otherwise = [ ] [(x, xs)] [ ]
Publieksvraag satisfy :: (a Bool) Parser a a satisfy p [] = [ ] satisfy p (x:xs) | p x = [ (x,xs) ] | otherwise= [ ] symbol :: Eq a a Parser a a symbol a [] = [ ] symbol a (x:xs) | x==a = [ (a,xs) ] | otherwise= [ ] nAls satisfy al bestaat, kun je symbol ook maken. Hoe? symbol a = satisfy (==a)
Triviale parsers X epsilon :: Parser a () epsilon xs = [ ( (), xs ) ] succeed :: b Parser a b succeed r xs = [ ( r, xs ) ] failp :: Parser a b failp xs = [ ]
Publieksvraag X epsilon :: Parser a () epsilon xs = [ ( (), xs ) ] succeed :: b Parser a b succeed r xs = [ ( r, xs ) ] nAls succeed al bestaat, kun je epsilon ook maken. Hoe? epsilon = succeed ()
Gebruik van parsergeneratoren nMaar wat moet je daar nou mee? … symbol ’a’ … token “public” … … satisfy isDigit … … succeed 1 … > satisfy isDigit “1ab” [ (‘1’, “ab”) ]
Parser combinatoren X Y | Z of :: Parser a b Parser a b Parser a b of p q xs =p xs q xs ++ voegt succes- lijsten samen nLeuker: notatie als operator infixr 4 ( ) :: Parser a b Parser a b Parser a b (p q) xs =p xs ++ q xs
Parser combinatoren X Y Z infixl 6 ( ) :: Parser a b Parser a c Parser a (b,c) (p q) xs = p xs q ys (b,ys) [|,][|,] (c,zs) (, ) (b,c) zs nDit is nog niet de definitieve versie Hoe de resultaten combineren?
infixl 6 ( ) :: Parser a b Parser a c Parser a (b,c) Parser combinatoren X Y Z infixl 6 ( ) :: Parser a b Parser a c (b c d) Parser a d (, ) (p q) xs = p xs q ys (b,ys) [|,][|,] (c,zs) (b,c) zs nDit is nog steeds niet de definitieve versie ff b c
infixl 6 ( ) :: Parser a b Parser a c (b c d) Parser a d Parser combinatoren X Y Z infixl 6 ( ) :: Parser a (c d) Parser a c Parser a d (, ) (p q) xs = p xs q ys (b,ys) [|,][|,] (c,zs) (b,c) zs f f c
Parser nabewerking infixl 7 ( ) :: (b c) Parser a b Parser a c (f p) xs = p xs (b,ys) [|][|] ( f b, ys )
Gebruik parsercombinators: controleer geneste haakjes nGrammatican Abstracte syntax { H , H ( H ) H } data H =Leeg |Paar H H haakjes :: Parser Char H nParser haakjes = epsilon open haakjes sluit haakjes where open = symbol ’(’ sluit = symbol ’)’ (\x Leeg) (\a b c d Paar b d)
Publieksvraag nMaak een parser voor booleans waarheid :: Parser Char Bool nHint: gebruik token, en bewerk na waarheid = token “true” token “false” (\x True) (\x False)
Eigenschappen van de ontleedboom bepalen nAbstracte syntax data H =Leeg |Paar H H nGrammatica { H , H ( H ) H } aantal :: H Int nEigenschappen diepte :: H Int aantal Leeg = aantal (Paar x y)= aantal x + aantal y diepte Leeg = diepte (Paar x y)= 0 max (1+ diepte x) (diepte y)
aantalP :: Parser Char Int aantalP = open aantalP sluit aantalP epsilon Eigenschappen al bepalen tijdens het ontleden haakjes :: Parser Char H haakjes = epsilon open haakjes sluit haakjes (\x Leeg) (\a b c d Paar b d) nParser (\x 0) (\a b c d 1+b+d) nParser die aantal meteen uitrekent
Eigenschappen al bepalen tijdens het ontleden haakjes :: Parser Char H haakjes = epsilon open haakjes sluit haakjes (\x Leeg) (\a b c d Paar b d) nParser diepteP :: Parser Char Int diepteP = epsilon open diepteP sluit diepteP (\x 0) (\a b c d max (1+b) d) nParser die diepte meteen uitrekent
Samenwerking van en ( ) :: (b c) Parser a b Parser a c ( ) :: Parser a (c d) Parser a c Parser a d open, sluit :: Parser Char Char open = symbol ‘(’ sluit = symbol ‘)’ test = open sluit (\x y [x,y]) nWat is het type van test ? nHoe associeert f p q eigenlijk, wil dit überhaupt kunnen?
Samenvatting hst. 3 sec. 1-3 nType van parsers nElementaire parsers nParser-combinators type Parser a b = [a] [ (b, [a]) ] lijst resultaten i.v.m. ambiguïteit satisfy :: (a Bool) Parser a a succeed :: b Parser a b failp :: Parser a b ( ) :: Parser a b Parser a b Parser a b ( ) :: Parser a (b c) Parser a b Parser a c ( ) :: (b c) Parser a b Parser a c
Werkcollege nHoofdstuk 3: geselecteerde opgaven nDownload ParseLib.hs en run met hugs nDefinieer ontleedboomtype en maak parse-functie voor Java If-statement nVindt-ie de ambiguïteit? { Expr …, Stat Var = Expr, Stat while ( Expr ) Stat, Stat if ( Expr ) Stat Rest, Rest | else Stat }
Practicum nSchrijf een ANTLR-grammatica voor Haskell- data types nLever String als resultaat op, met daarin Haskell-programma voor een fold -functie voor dat datatype nInleveren: vrijdag 30 november 2007