ANTLR ANother Tool for Language Recognition Overzicht • • • • • • • • • Inleiding: Antlr: what’s in a name? Vertalers: lexers en parsers LL parser voordelen, akkefietjes Antlrworks: debugger Productieregels voor output Boomgrammatica (Antlr tree grammar) Boomparser (Antlr tree parser) Programmatransformaties Besluit Inleiding ANTLR = ANother Tool for Language Recognition • programma om “compilers” te schrijven • genereert parser voor front-end van compiler of voor domein-specifieke toepassing ANTLRWorks = antlr programmeeromgeving • auteurs – antlr:Terence Parr (UoSF) – antlrworks: Jean Bovet (master student) • locatie:http://www.antlr.org tutorial:http://www.ociweb.com/jnb/jnbJun2008.html • boek: the definitive Antlr reference CT467 Inleiding • • • • • ANTLR v3 is geschreven in Java Genereert gramatica’s in Java, C, C#,.. Motor = LL(*) top-down parser Vgl. lex/yacc: LR bottom-up Antlr gaat extra mile: – Antlrworks: debug grammatica tijdens parsen – Tree parser: parser van interne boomvoorstelling – String template (source source herschrijven) Vertaler • Wat is een vertaler? • Een vertaler leest een invoertekst, analyseert de structuur en schrijft een uitvoertekst • Werking? • Invoertekst is een stroom bytes. Deze wordt naar “handelbare” vorm gebracht in 2 fasen: Lexicale analyse: vormt woorden alfabet Semantische analyse: vormt zinnen taal Lexicale Analyse • Doel: “uit de stroom van bytes betekenisvolle woorden en leestekens te halen die eigen zijn aan de programmeertaal.” • = tokens met attributen • Vb.: 5 = geheel getal met waarde 5 a = variabele met naam “a” Lexicale Analyse • Tokens in EBNF, in hoofdletters, vb: – NUM : ('0'..'9')+; – ALF : ‘A'..‘Z'|’a’..‘z'; – ID : ALF (ALF|NUM)*; + : ≥ 1 (herhalingsteken, minstens 1) * : ≥ 0 (herhalingsteken, minstens 0) | : “of” • Resultaat: “tokens” Grammaticale Analyse • Grammatica definieert geldige zinnen, in kleine letters, bv. expr: expr : NUM | ID | expr '+' expr; • Voldoet: 3, alfa, a+b; ander vb: var : ID; assign : var '=' expr; • Resultaat: “grammaticaregels” Grammaticale Analyse • Parsing met productieregels non-terminals terminals Grammaticale Analyse • Afleiding (derivation) = substitutie van nonterminals (ouder) door zijn productie (kinderen) parseboom Grammaticale Analyse • Rechtse of linkse afleiding substitutie van meest rechtse of meest linkse nonterminal door productie parseboom • Toepassing: a : = 7 ; b : = c + (d := 5 + 6 , d) • Lexicale tokenstroom: id : = num; id : = id + (id := num + num, id) 1 Afleiding 2 3 4 5 6 7 8 10 9 11 12 • Voorbeeld • a:=7; b := c + ( d := 5 + 6 , d) • Lexicale tokenstroom: id : = num; id : = id + ( id := num + num, id) Afleiding • Voorbeeld • a:=7; b := c + (d := 5 + 6 , d) • Lexicale tokenstroom: id : = num; id : = id + (id := num + num, id) 1 2 3 4 5 6 7 8 10 9 11 12 Linkse Afleiding • Voorbeeld • a:=7; b := c + (d := 5 + 6 , d) • Lexicale tokenstroom: id : = num; id : = id + (id := num + num, id) 1 2 4 5 3 6 Contextvrije grammatica • Contextvrij = substitutie kan uitgevoerd worden onafhankelijk van de context = symbolen voor en na de substitutie • Ambigue grammatica: waneer meerdere parsebomen mogelijk zijn Predictieve Parser (LL) • Principe: de afleidingsregel voor non-terminals wordt bepaald door het ingelezen token, d.w.z. door de ingelezen terminal. • Kan gerealiseerd worden door een Recursive descent parser Predictieve Parser (LL) • • • • Recursieve afdaling algoritme: 1 functie voor elke niet-terminaal 1 case voor elke productie Vb.: grammatica 3.2. Predictieve parsing • Recursieve afdaling algoritme: Grammatica in Antlr • TOKENS = terminals • regels = nonterminals • grammar = regels + tokens • prog = startregel grammar prog; prog assign var expr : assign+ EOF; : var '=' expr '\r\n'+; : ID; : NUM | ID | expr '+' expr; NUM ALF ID : ('0'..'9')+; : ('a'..'z'|'A'..'Z')+; : ALF (ALF|NUM)*; Grammatica in AntlrWorks • In AntlrWorks: Linkse recursie conflict • In AntlrWorks: Linkse recursie conflict • Ambiguïteit: welke regel start met dit token? bij input ID: expr ID of expr expr + expr ? beide regels kunnen met ID starten... Linkse recursie conflict • Regel E start met E • [1] E E + T [2] E T • First(X) start-tokens van regel (X) • First(E) = First(E+T) U First(T) welke productie: 1 of 2 ? Linkse recursie herschrijven • Oplossing: a) herken ET|E+T als ET +T +T + .... +T • b) herschrijf tot rechtse recursie E T (+T)* Linkse recursie herschrijven • Linkse recursie wegwerken Linkse recursie wegwerken door extra term grammar prog; prog assign var expr : assign+ EOF; : var '=' expr '\r\n'+; : ID; : NUM | ID | expr '+' expr; NUM ALF ID : ('0'..'9')+; : ('a'..'z'|'A'..'Z')+; : ALF (ALF|NUM)*; Linkse recursie herschrijven • Linkse recursie wegwerken Linkse recursie wegwerken door extra term grammar prog; prog assign var term expr : assign+ EOF; : var '=' expr '\r\n'+; : ID; : NUM | ID; : term (‘+’ term)*; NUM ALF ID : ('0'..'9')+; : ('a'..'z'|'A'..'Z')+; : ALF (ALF|NUM)*; Debuggen in AntlrWorks • Eenvoudige grammatica • Debuggen alfa=5 b=2+a Debuggen in AntlrWorks • Debuggen: input alfa=5 b=2+a Debuggen in AntlrWorks • Debuggen: input + startregel alfa=5 b=2+a Debuggen in AntlrWorks • Debuggen alfa=5 b=2+a Gegenereerde bestanden Wat genereert ANTLRWorks nu uit grammatica prog.g? 1. progLexer.java, progParser.java 2. main: __Test__.java parser lexer 3. input: __Test__input.txt Tokens en parseboom • Debuggen – tokens + parseboom alfa=5 b=2+a Gegenereerde bestanden Structuur van het testprogramma: Acties of producties toevoegen • Acties bij herkenning van tokens of regels regels: groen tokens: blauw grammatica: “token” lexer: “A”... “U” Acties of producties toevoegen • @members = helper code • actie: tel klinkers Acties of producties toevoegen • @members = helper code • actie: tel klinkers Acties: tel klinkers • Input: “aaeaiiou” • Output en Afleidingsboom Lexicale en grammaticale analyse FRONT-END • Lexicale analyse produceert tokens token = type van woord (bv. getal, “if”) Lexicale en grammaticale analyse FRONT-END • Grammaticale analyse produceert syntax. AST = abstracte syntaxboom met betekenis van programma bewaart. Meestal is er extra informatie in symbooltabellen, afhankelijkheidsgrafen ... Lexicale analyse en parsing BACK-END • De back-end loopt de AST af en genereert de output Boomgenerator • ANTLR genereert ook “CommonTree” bomen • Nut: overzichtelijke structuur, boomvoorstellingen in fasen, programmatransformaties. • CommonTree bomen kunnen gegenereerd worden met de optie {output=AST}. Boomgenerator • CommonTree bomen kunnen gegenereerd worden met de optie {output=AST}. • Boomoperaties zijn productieregels: operator om boom te maken: ^(... ...) • Vb.: ^(wortel blad_1 ... blad_n) genereert Boomgenerator • Boom-grammatica: • De output: via apart testprogramma.... Boomgenerator • Testprogramma: • ast = parser g g.prog_ast getTree() • print ast met ast.toStringTree(). Boomgenerator • Resultaat van boomgeneratiegrammatica prog_ast: • = gewone output ($prog_ast.text) + tree ouput (ast.toStringTree()). Boomgenerator • ANTLR genereert “CommonTree” bomen • Nut: programmatransformaties. • Voorbeeld: for-lus 2x ontrollen in f.g Boomgenerator • TreeRewrite.g leest “CommonTree” genereert getransformeede lus • Genererende tokens uit = f.g • Grammatica f wordt ook gebruikt voor testprogramma in AntlrWorks! Boomgenerator • TreeRewrite.g leest “CommonTree” genereert getransformeede lus • Genererende tokens uit = f.g • Grammatica f wordt ook gebruikt voor testprogramma in AntlrWorks! Boomgenerator • TreeRewrite leest “CommonTree” bomen en genereert getransformeede lus Boomgenerator • Lustransformatie: • Input: for (i=0; i < n; i++) { s = f(i); v = g(k); } Output: for (i=0; i < n; i++) { s = f(i); v = g(k); s = f(i); v = g(k); } Besluit • • • • ANTLR is zeer vriendelijk in gebruik Extra mijl: booomparsers en parser IDE Veel documentatie ( o.a. Davy…) Extra’s: refactoring, semantische predicaten, multilanguage, web-support Besluit • • • • ANTLR is zeer vriendelijk in gebruik Extra mijl: booomparsers en parser IDE Veel documentatie ( o.a. Davy…) Extra’s: refactoring, semantische predicaten, multilanguage, web-support