PLP – JavaCC Java Compiler Compiler Joabe Jesus - [email protected] Prof. Augusto Sampaio Agenda • Compiladores – Analisadores léxicos e sintáticos (Parsers) • Parser generators • JavaCC Compiladores • Analisadores léxicos – Verificam se os símbolos terminais e palavras estão de acordo com as restrições da linguagem • Há identificadores inválidos? • Há símbolos (caracteres) inválidos • Analisadores sintáticos (Parsers) – Programas que recebem como entrada um arquivo fonte e diz se ele está correto sintaticamente, segundo uma gramática pré-definida. Parsers • Há dois grupos de parsers – Top-down – Bottom-up Parsers • Por que usar um parser generator? – Implementar um parser ‘manualmente’ (passo-apasso) pode ser uma tarefa muito trabalhosa... Parsers generators • Um Parsers generator é um programa que recebe como entrada um arquivo de especificação da gramática a ser aceita pelo parser e retorna um parser que reconhece esta gramática – O formato do arquivo de especificação da gramática depende muito do tipo de parser gerado (top-down ou bottom-up) Parsers generators • Existem vários geradores de parser – – – – – JavaCC JLex & Cup AntLR SableCC … É um dos mais populares na comunidade Java, sendo suportado hoje pela comunidade java.net Tem um dos melhores suportes a gramáticas em EBNF (Extended Backus Naur Form) e gera estrutura OO da AST (Abstract Syntax Tree) além de classes utilitárias usando o padrão Visitor. JavaCC JavaCC • Gerador de parser 100% Java – O mais utilizado pela comunidade Java • Desenvolvido inicialmente pela Sun – Hoje é mantido pela java.net • É um parser top-down – Mais fácil de depurar • Utiliza uma sintaxe muito próxima de Java JavaCC • Desvantagens – Mistura código Java com a gramática – Não checa a corretude do código Java inserido – Pode gerar classes que não compilam JavaCC • Inclui um pré-processador para geração de árvores sintáticas (jjTree) • Possui um repositório de gramáticas bastante extenso disponível – inclui linguagens como Java, C, C++, Perl, etc • Possui uma interface gráfica fácil de usar • Definições léxicas e sintáticas em um único arquivo • Não aceita ambigüidades. – Ex: A gramática não pode possuir recursão à esquerda.(ex: expr:= expr ‘+’ expr) Gramáticas em JavaCC • Uma gramática JavaCC possui a seguinte estrutura: – Opções do Parser (Não obrigatório) – Definição da classe do Parser – Definição dos Tokens (Componente Léxico) • Terminais – Definição das Produções (Componente Sintático) • Ações semânticas associadas • Não-Terminais Opções do parser • STATIC – diz se os métodos do parser serão estáticos (default: true) • LOOKAHEAD – informa o nível de profundidade do lookahead (default: 1) • DEBUG_PARSER – instrui o parser a registrar todas as informações durante o parsing do arquivo (default: false) • DEBUG_LOOKAHEAD – instrui o parser a registrar também as tentativas de lookahead (default: false) Mais opções • UNICODE_INPUT – informa se a entrada usa a codificaçõo UNICODE • OUTPUT_DIRECTORY – seta o diretório onde os arquivos java serão gerados (o default é o atual) • FORCE_LA_CHECK- força a checagem do lookahead em todos os “choice points”, independente da especificação explícita do lookahead (default: false) Definição do Parser • Este trecho define a classe do Parser. Nesta classe, podem ser definidos métodos e variáveis auxiliares. O formato é o seguinte: PARSER_BEGIN(parser_name) ... class parser_name ...{ ... } ... PARSER_END(parser_name) Definição dos tokens • Serve para especificar os tipos de tokens e as expressões regulares associadas • Nesta seção são descritas as palavras reservadas TOKEN: { < NUMBER: (<DIGIT>)+ ( "." (<DIGIT>)+ )? > | < DIGIT: ["0"-"9"] > | < EOL: "\n" > } Definição das produções • Obedecem o seguinte formato: tipoRetorno nomeProducao(listaParametros): { Declaração de variáveis, código Java invocação de métodos, etc } { subProducao1() { ação semântica correspondente } [lista de subProducoes] } Código Java. Em geral, corresponde a montagem da árvore Exemplo: EBNF • Dada a gramática na forma EBNF expr := | | | | | number expr '+' expr '-' expr '*' expr '/' - expr expr expr expr expr number := digit+ ('.' digit+)? digit := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7‘ | '8' | '9' Exemplo: Gramática options { LOOKAHEAD=2; STATIC=false; } Lembre-se de que o JavaCC não permite recursão à esquerda, por isso, é necessário modificar a gramática antes de traduzí-la. PARSER_BEGIN(Arithmetic) public class Arithmetic { } PARSER_END(Arithmetic) Exemplo: JavaCC SKIP: { " " | "\r" | "\t" } TOKEN: { < NUMBER: (<DIGIT>)+ ( "." (<DIGIT>)+ )? > | < DIGIT: ["0"-"9"] > } Exemplo: JavaCC double expr(): {} { term() ( "+" expr() | "-" expr() )* } double term(): {} { unary() ( "*" term() | "/" term() )* } Exemplo: JavaCC double unary(): { } { "-" a=element() | } double element(): {} { <NUMBER> } a = element() Exercício • Altere o exemplos dados para que estes possam reconhecer as seguintes expressões: – parênteses “(“ , “)” -> expr ::= (expr) – exponenciação -> expr ::= expr ^ expr • Onde a ordem de precedência é: parênteses > exponenciação Referências • • • • • • https://javacc.dev.java.net/ https://javacc.dev.java.net/doc/docindex.html http://www.cs.aau.dk/~bt/SPOF07/Lecture4.htm http://www.antlr.org/works/index.html http://en.wikipedia.org/wiki/Top-down_parsing http://en.wikipedia.org/wiki/Bottom-up_parsing PLP – JavaCC Java Compiler Compiler Joabe Jesus - [email protected] Prof. Augusto Sampaio