190 likes | 375 Views
ANTLR. ANother Tool for Language Recognition www.antlr.org Jobson Ronan (jrjs) Renato Viana (rvf). Motivação. Parsers criados com YACC tendem a ter baixa qualidade de mensagens de erro
E N D
ANTLR ANother Tool for Language Recognition www.antlr.org Jobson Ronan (jrjs)Renato Viana (rvf)
Motivação • Parsers criados com YACC tendem a ter baixa qualidade de mensagens de erro • Erros em gramáticas do YACC são difíceis de entender. YACC informa um erro de "shift/reduce" ou "reduce/reduce" associado a uma dada regra da gramática • Possibilidade de gerar Parsers para várias linguagens (C++, Java, C# e Python) • Open-source
Características • ANTLR gera recursive decentparsers e possui uma boa reportagem de erros. • Parsers gerados pelo ANTLR são razoavelmente legíveis. Facilitando a depuração • Possui boa documentação e grande quantidade de exemplos • Apesar disso, a curva de aprendizagem ainda é grande.
Aprendendo por exemplo • Exp: Linguagem de expressões aritméticas • Suporta soma, subtração e multiplicação de inteiros • Suporta parêntesis para definir prioridades • Ex: • 2+3 • 1 • 5*(3+7)
Gramática • Todas as gramáticas do ANTLR são subclasses de Lexer, Parser, or TreeParser • As regras são específicadas em uma notação EBNF class ExprParser extends Parser; expr: mexpr ((PLUS|MINUS) mexpr)* ; mexpr : atom (STAR atom)* ; atom: INT | LPAREN expr RPAREN ;
Lexer class ExprLexer extends Lexer; options { k=2; // needed for newline junk charVocabulary='\u0000'..'\u007F'; // allow ascii } LPAREN: '(' ; RPAREN: ')' ; PLUS : '+' ; MINUS : '-' ; STAR : '*' ; INT : ('0'..'9')+ ; WS : ( ' ' | '\r' '\n' | '\n' | '\t' ) {$setType(Token.SKIP);} ;
Gerando • Executar ferramenta de geração $ java antlr.Tool expr.g • Resultado ExprLexer.java ExprParser.java ExprParserTokenTypes.java
Testando • Executar o parser import antlr.*; public class Main { public static void main(String[] args) throws Exception { ExprLexer lexer = new ExprLexer(System.in); ExprParser parser = new ExprParser(lexer); parser.expr(); } }
Avaliando Expressões • Avaliando expressões on-the-fly class ExprParser extends Parser; expr returns [int value=0] {int x;} : value=mexpr ( PLUS x=mexpr {value += x;} | MINUS x=mexpr {value -= x;} )* ; mexpr returns [int value=0] {int x;} : value=atom ( STAR x=atom {value *= x;} )* ; atom returns [int value=0] : i:INT {value=Integer.parseInt(i.getText());} | LPAREN value=expr RPAREN ;
Testando • Alterações no método expr() import antlr.*; public class Main { public static void main(String[] args) throws Exception { ExprLexer lexer = new ExprLexer(System.in); ExprParser parser = new ExprParser(lexer); int x = parser.expr(); System.out.println(x); } }
Problemas • Mistura de interesses • Código de definição da gramática • Código de definição das ações • Código da linguagem alvo (Java) • Solução • Gerar uma AST
Gerando ASTs • Pequenas alterações na definição da gramática • Indica-se açucares sintáticos • Indica-se nomes dos nós • Define-se um TreeParser
Alterações na gramática • “^” Índica as raízes das sub-arvores • “!” Índica os açucares sintáticos class ExprParser extends Parser; options { buildAST=true; } expr: mexpr ((PLUS^|MINUS^) mexpr)* ; mexpr : atom (STAR^ atom)* ; atom: INT | LPAREN! expr RPAREN! ;
Definindo TreeParser class ExprTreeParser extends TreeParser; options { importVocab=ExprParser; } expr returns [int r=0] { int a,b; } : #(PLUS a=expr b=expr) {r = a+b;} | #(MINUS a=expr b=expr) {r = a-b;} | #(STAR a=expr b=expr) {r = a*b;} | i:INT {r = (int)Integer.parseInt(i.getText());} ;
Testando import antlr.*; import antlr.collections.*; public class Main { public static void main(String[] args) throws Exception { ExprLexer lexer = new ExprLexer(System.in); ExprParser parser = new ExprParser(lexer); parser.expr(); AST t = parser.getAST(); System.out.println(t.toStringTree()); ExprTreeParser treeParser = new ExprTreeParser(); int x = treeParser.expr(t); System.out.println(x); } }
Exercícios • 1. Adicionar a linguagem de expressões o comando print print(4+3*6) • 2. Adicionar a linguagem de expressões suporte a varáveis v1 = 3+5print(v1+10) *Não tente fazer os dois ao mesmo tempo
ANTLR ANother Tool for Language Recognition www.antlr.org Jobson Ronan (jrjs)Renato Viana (rvf)