360 likes | 600 Views
Definitie Taal van een grammatica. Zij grammatica G = ( T , N , R, S ) de taal van G is. L(G). { z T * | S * z }. Ambigue grammatica. Een grammatica is ambigu als er een zin is met een niet-unieke ontleding. Unieke ontleding.
E N D
DefinitieTaal van een grammatica • Zij grammatica G = ( T, N, R, S ) • de taal van G is L(G) { z T* | S * z }
Ambigue grammatica • Een grammatica is ambigu als • er een zin is met een niet-unieke ontleding Unieke ontleding • Een zin heeft een unieke ontleding als • er maar één ontleedboom is of equivalent: • er maar één leftmost derivation is
Grammatica-transformaties Aanpassen van de regels, zo dat • De taal hetzelfde blijft • Wenselijke eigenschappen ontstaan • Regels (ont)expanderen • Linksrecursie verwijderen • Prioriteiten van operatoren inbouwen
Transformaties Operatoren met prioriteiten Heeft dezelfde taal als E E + E E E * E E ( E ) E N E T E T + E T F T F * T F ( E ) F N * gaat nuvoor +
Grammatica-regels Haskell datatypedat ontleedboom representeert Een Twee Drie Haskell datatypevoor ontleedbomen { X A B ,X C d ,X e } dataX =A B |C d | e uit deabstracte syntaxkun je concrete syntaxreconstrueren show :: X String show (Een a b) = show a ++ show b show (Twee c) = show c ++ “d” show (Drie) = “e” parse :: String X
Grammatica “Expressie” • Expr Term Rest • Rest +Expr • Rest –Expr • Rest e • Term Getal • Term (Expr) • Expr Term (+Term|–Term) * • Term Getal|(Expr) EBNF-notatie
ANTLR-notatie class ExprLexer extends Parser PLUS : ‘+’ ; MINUS : ‘–’ ; LPAREN : ‘(’ ; LPAREN : ‘(’ ; class ExprParser extends Parser Expr :Term (PLUSTerm|MINUSTerm) * ; Term : Getal|LPARENExprRPAREN ;
ANTLR genereert Java Expr :Term (PLUSTerm|MINUSTerm) * ; 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 (PLUSTerm|MINUSTerm) * ; Term : GETAL|LPARENExprRPAREN ; returns[int x=0] { int y; } x= y= { x += y; } y= { x –= y; } returns[int x=0] { x = str2int(n.getText(); } n: x=
ANTLR ExprLexer. java ExprParser. java Java compiler Antlr . jar * . class Java interpreter zin ANTLR-Architectuur Expr . g ExprMain. java
Haskell Parser Combinator Architectuur ParseLib . hs Expr . hs Haskell interpreter zin
Grammatica schrijven in apart taaltje Genereert Java-code Groot, ingewikkeld Geen linksrecursie Geen ambiguiteit 1-symbool lookahead Java Grammatica schrijven met Haskell-operatoren Is gewone Haskell-library Kort Geen linksrecursie Wel ambiguiteit Onbeperkt lookahead Haskell ANTLR vs. ParserCombinators
polymorfresultaattype type Parser b = String b type Parser b = String (b, String) restant-string polymorfalfabet type Parser ab = [a] (b, [a]) type Parser ab = [a][ (b, [a]) ] lijst resultateni.v.m. ambiguïteit Type van parsers parse :: String X type Parser = String X
Simpele parsers X a type Parser ab = [a][ (b, [a]) ] symbola :: Parser CharChar [ ] symbola [ ] =symbola (x:xs) | x==’a’ = | otherwise = [ (’a’, xs) ] [ ]
Simpele parsergeneratoren X a symbola :: Parser CharChar symbola [ ] = [ ] symbola (x:xs) | x==’a’ = [ (’a’,xs) ] | otherwise = [ ] symbol :: Parser aa Eq a a symbol a [ ] = [ ]symbol a (x:xs) | x==a = [ (a,xs) ] | otherwise = [ ] te herkennensymbool is nu parameter
Andere parsergeneratoren token :: Eq a [a] Parser a[a] token t xs | t == take n xs = | otherwise = [(t, drop n xs)] [] where n = length t satisfy :: (aBool) Parser aa [ ] [(x, xs)] [ ] satisfy p [ ] = satisfy p (x:xs) | p x = | otherwise =
Publieksvraag satisfy :: (aBool) Parser aa satisfy p [] = [ ] satisfy p (x:xs) | p x = [ (x,xs) ] | otherwise = [ ] symbol :: Eq a a Parser aa symbol a [] = [ ] symbol a (x:xs) | x==a = [ (a,xs) ] | otherwise = [ ] • Als satisfy al bestaat,kun je symbol ookmaken. Hoe? symbol a = satisfy (==a)
Triviale parsers X epsilon :: Parser a() epsilon xs = [ ( (), xs ) ] succeed :: b Parser ab succeed r xs = [ ( r, xs ) ] failp :: Parser ab failp xs = [ ]
Publieksvraag X epsilon :: Parser a() epsilon xs = [ ( (), xs ) ] succeed :: b Parser ab succeed r xs = [ ( r, xs ) ] • Als succeed al bestaat,kun je epsilon ookmaken. Hoe? epsilon = succeed ()
Gebruik van parsergeneratoren … symbol ’a’ … token “public” … … satisfy isDigit … … succeed 1 … • Maar wat moet je daar nou mee? > satisfy isDigit “1ab” [ (‘1’, “ab”) ]
Parser combinatoren X Y | Z of :: Parser ab Parser ab Parser ab of p q xs = p xs ++ voegt succes-lijsten samen q xs • Leuker: notatie als operator infixr 4 <|> (<|>) :: Parser ab Parser ab Parser ab (p <|> q) xs = p xs ++ q xs
Parser combinatoren X Y Z infixl 6 <*> (<*>) :: Parser ab Parser ac Parser a(b,c) Hoe deresultatencombineren? ( , ) zs (b,c) (p <*> q) xs = [ | , ] (b,ys) p xs (c,zs) q ys • Dit is nog niet de definitieve versie
Parser combinatoren X Y Z infixl 6 <*> (<*>) :: Parser ab Parser ac Parser a(b,c) infixl 6 <*> (<*>) :: Parser ab Parser ac (bcd) Parser ad ( , ) zs (b,c) (p <*> q) xs = f [ | , ] f b c (b,ys) p xs (c,zs) q ys • Dit is nog steeds niet de definitieve versie
Parser combinatoren X Y Z infixl 6 <*> (<*>) :: Parser ab Parser ac (bcd) Parser ad infixl 6 <*> (<*>) :: Parser a (cd) Parser ac Parser ad ( , ) f c zs (b,c) (p <*> q) xs = [ | , ] (b,ys) p xs f (c,zs) q ys
Parser nabewerking infixl 7 <$> (<$>) :: (bc) Parser ab Parser ac ( f b , ys ) (f <$> p) xs = [ | ] (b,ys) p xs
Grammatica Abstracte syntax Gebruik parsercombinators:controleer geneste haakjes { He , H( H ) H } dataH = Leeg | PaarH H • Parser haakjes :: Parser Char H (\x Leeg) <$> epsilon haakjes = (\a b c d Paar b d) <$> <|> open <*> haakjes <*> sluit <*> haakjes where open = symbol ’(’ sluit = symbol ’)’
Publieksvraag • Maak een parser voor booleans waarheid :: Parser CharBool • Hint: gebruik token, en bewerk na (\x True) <$> waarheid = token “true” <|> token “false” (\x False) <$>
Eigenschappen van de ontleedboom bepalen • Grammatica • Abstracte syntax { He , H( H ) H } dataH = Leeg | PaarH H • Eigenschappen aantal :: H Int diepte :: H Int aantal Leeg = aantal (Paar x y)= diepte Leeg = diepte (Paar x y)= 0 1 + aantal x + aantal y 0 max (1+ diepte x) (diepte y)
aantalP :: Parser Char Int (\x 0) <$> epsilon aantalP = (\a b c d 1+b+d) <$> <|> open <*> aantalP <*> sluit <*>aantalP Eigenschappen al bepalentijdens het ontleden • Parser haakjes :: Parser Char H (\x Leeg) <$> epsilon haakjes = (\a b c d Paar b d) <$> <|> open <*> haakjes <*> sluit <*>haakjes • Parser die aantal meteen uitrekent
diepteP :: Parser Char Int (\x 0) <$> epsilon diepteP = (\a b c d max (1+b) d) <$> <|> open <*> diepteP <*> sluit <*> diepteP Eigenschappen al bepalentijdens het ontleden • Parser haakjes :: Parser Char H (\x Leeg) <$> epsilon haakjes = (\a b c d Paar b d) <$> <|> open <*> haakjes <*> sluit <*>haakjes • Parser die diepte meteen uitrekent
Samenwerking van <$> en <*> (<$>) :: (bc) Parser ab Parser ac (<*>) :: Parser a (cd) Parser ac Parser ad open, sluit :: Parser CharChar open = symbol ‘(’ sluit = symbol ‘)’ test = open <*> sluit (\x y [x,y]) <$> • Wat is het type van test ? • Hoe associeert f <$> p <*> q eigenlijk,wil dit überhaupt kunnen?
type Parser ab = [a][ (b, [a]) ] lijst resultateni.v.m. ambiguïteit Samenvatting hst. 3 sec. 1-3 • Type van parsers • Elementaire parsers • Parser-combinators satisfy :: (aBool) Parser aa succeed :: b Parser ab failp :: Parser ab (<|>) :: Parser ab Parser ab Parser ab (<*>) :: Parser a (bc) Parser ab Parser ac (<$>) :: (bc) Parser ab Parser ac
Werkcollege • Hoofdstuk 3: geselecteerde opgaven • Download ParseLib.hs en run met hugs • Definieer ontleedboomtype enmaak parse-functie voor Java If-statement • Vindt-ie de ambiguïteit? { Expr … , StatVar = Expr , Statwhile (Expr)Stat , Stat if ( Expr )Stat Rest , Rest e | elseStat }
Practicum • Schrijf een ANTLR-grammaticavoor Haskell- data types • Lever String als resultaat op, met daarinHaskell-programma voor eenfold -functie voor dat datatype • Inleveren: vrijdag 30 november 2007