Parser LexML João Lima Tópicos Parser Aplicações Tipos Ferramentas ANTLR Implementação Próximos passos Parser - Aplicações Filtros Traduz uma entrada em uma saída Validadores Verifica se uma entrada obedece a uma gramática Processadores Valida e Processa (sem re-escrita) sem considerar uma gramática Ações: cálculos, atualizar banco de dados, etc. Tradutores Valida e Traduz a entrada em outro formato Parser - Tipos LL(k) Top-down parser Left-to-right Derivação à esquerda (da entrada) Impossibilita regras com recursividade à esquerda Mais fácil para entender e depurar LR(k) Bottom-up parser Left-to-right Derivação à direita (da entrada) Ferramentas Qual ferramenta utilizar? Perl, awk? Tradução léxica (não gramatical) Lexer/Parser YACC/Bison, Lex, GOLD, Grammatica, Spirit ANTLR ANother Tool for Language Recognition Etapas básicas caracteres Lexer tokens Parser Tabela de Símbolos Árvore sintática ANTLR v. 3.0.1 Código aberto - Licença BSD LL(*) Predicados semânticos e sintáticos Memoized Backtracking Otimiza a performance do lookahead Unicode Lexer Hierárquico extensão LL(k) Regras hierarquizadas Target Languages Java, C, C++, C#, Objective-C, Ruby, Python EBNF AST Abstract Syntax Tree Tipos adicionais de Gramática Sintaxe mais concisa que BNF Tree Grammar Lexer Grammar (filtro=true) ANTLRWorks IDE para criação de gramáticas Syntax Diagram Error Detection ANTLR Website: www.antlr.org Etapas (ANTLR) caracteres Lexer tokens Tabela de Símbolos Parser AST P(Tree) Saída (XML) ANTLR – como codificar e executar Codifica gramática utilizando a IDE (ANTLRWorks) Gera código na linguagem destino (Java) Cria programa para efetuar as chamadas aos parser PipeLexML.java Funções estáticas auxiliares Normaliza.g LexML.g GeraXML.g Linguistico.g UtilLexml Executa “PipeLexML lei8112.txt” Passos java -ms64m -mx1G org.antlr.Tool Normaliza.g java -ms64m -mx1G org.antlr.Tool LexML.g java -ms64m -mx1G org.antlr.Tool GeraXML.g java -ms64m -mx1G org.antlr.Tool Linguistico.g javac *.java java PipeLexML %1 Parser LexML (atual) Normaliza.g Lexer Parser Arq.txt Arq_ Normal.txt LexML.g Lingüístico.g GeraXML.g Arq_ LexML.xml Arq_ LexML Lang.xml Arquivo de Entrada Após Normalização Após Parser Normaliza Trata espaços, tabs, quebras de linhas repetidos Trata caracteres especiais Ordinal / Grau / “o” sobre-escrito Normaliza.g lexer grammar Normaliza; options { filter=true; } WSinterno : (' '|'\t')(' '|'\t')+ {setText(" ");}; Normaliza : ( WS* '\r'? '\n' )+ WS* // normaliza final(is) de linha(s) {setText("\r\n");} | ('\t') // troca tab por branco {setText(" ");} | ('\u0096') // troca travessao pequeno por hifen {setText("-");} | ('0'..'9') ('o'|'°') (' '|','|';'|'.') // acerta ordinal 9o {String termo = getText(); setText(termo.substring(0, 1)+"º"+termo.substring(2));} ; Resto : .; fragment WS : (' '|'\t')+; Programa “PipeLexML arq.txt” //FASE NORMALIZACAO //arquivo de entrada FileInputStream fstream = new FileInputStream(args[0]); // Filtro de Normalização ANTLRInputStream input = new ANTLRInputStream(fstream); NormalizaLexer lexFiltro = new NormalizaLexer(input); TokenStream tokensFiltro = new CommonTokenStream(lexFiltro); System.err.println("Fase Normalização - OK"); System.setOut(new PrintStream(new FileOutputStream(args[0]+"_Normal.txt"))); System.out.println(tokensFiltro.toString()); LexMLLexer - exemplo TITULOROT : {getCharPositionInLine()==0}? ('Título'|'TÍTULO') | ('Título'|'TÍTULO') {$type = PALAVRA;} ; CAPITULOROT : {getCharPositionInLine()==0}? ('Capítulo'|'CAPÍTULO') | ('Capítulo'|'CAPÍTULO') {$type = PALAVRA;} ; SECAOROT : {getCharPositionInLine()==0}? ('Seção'|'SEÇÃO') | ('Seção'|'SEÇÃO') {$type = PALAVRA;} ; SUBSECAOROT : {getCharPositionInLine()==0}? ('Subseção'|'SUBSEÇÃO') | ('Subseção'|'SUBSEÇÃO') {$type = PALAVRA;} ; PARTEROT : {getCharPositionInLine()==0}? ('Parte'|'PARTE') | ('Parte'|'PARTE') {$type = PALAVRA;} ; PALAVRA : ('a'..'z'|'A'..'Z'|'Ç'|'ç'|'Ã'|'ã'|'Â'|'À'|'à'|'â'|'á'|'é'|'í'|'ó'|'ô'|'ú'|'Ü' |'ü'|'Á'|'É'|'Í'|'Ó'|'Ô'|'Ú'|'ê'|'Ê'|'õ'|'Õ'|'\'')+; LexML Parser - exemplo LexMLLexer e Parser // Parser do Texto Normalizado e criação de Árvore em Memória LexMLLexer lexer = new LexMLLexer(new ANTLRStringStream(tokensFiltro.toString())); TokenRewriteStream tokens = new TokenRewriteStream(lexer); LexMLParser parser = new LexMLParser(tokens); LexMLParser.lexml_return r = parser.lexml(); System.err.println("Fase Parser - OK"); // arquivo de saída (básico) System.setOut(new PrintStream(new FileOutputStream(args[0]+"_LexML.xml"), true, "UTF-8")); // Passeio na árvore, externalizando o XML CommonTree t = (CommonTree)r.getTree(); CommonTreeNodeStream nodes = new CommonTreeNodeStream(t); nodes.setTokenStream(tokens); GeraXML walker = new GeraXML(nodes); // cria a árvore Walker GeraXML.lexml_return r2 = walker.lexml(); System.err.println("Fase Geração do LexXML - OK"); Linguistico.g lexer grammar Linguistico; options { filter=true; } //{System.err.println(" Achei "+getText() );} LinguaLa : // latin (' '|','|';'|'.'|'(') 'caput' (' '|','|';'|'.'|')') {setText(getText().substring(0, 1)+"<span lang=\"la\">"+getText().substring(1, getText().length() -1)+"</span>"+getText().substring(getText().length()-1));} ; LinguaEn : // ingles (' '|','|';'|'.'|'(') 'leasing' (' '|','|';'|'.'|')') {setText(getText().substring(0, 1)+"<span lang=\"en\">"+getText().substring(1, getText().length() -1)+"</span>"+getText().substring(getText().length()-1));} ; Resto : .; Parser LexML (final) Normaliza.g Lexer Lexer Lexer Parser Parser Parser LexML.g Ok? Não LexMLFlex.g Links.g GeraXMLF.g Lingüístico.g Sim GeraXML.g Próximos passos Considerar Alteração de Norma Reconhecer entrada html Analisador de Remissões LexML Flexível Parser Decisão Monocrática, Acórdãos Parser Semântico