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