Análise Léxica Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife ‹#› Contatos Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/gtalk: [email protected] [email protected] Site: http://www.alexandrecordel.com.br/fbv Celular: (81) 9801-1878 JFlex É um gerador de analisadores léxicos escrito em Java, baseado no flex para C • Também é uma melhoria do Jlex • Pode ser encontrado em http://jflex.de/ Constrói o analisador léxico a partir de um arquivo de especificação dado como entrada • Processo visto nos slides da aula anterior • Recebe arquivo de entrada normalmente com extensão .lex ou .flex • A partir desse arquivo vai ser gerado um analisador léxico capaz de reconhecer os caracteres de determinada linguagem Gera uma classe que faz a análise léxica 3 JFlex Gerador automático de analisadores léxicos na linguagem Java Especificação JFlex Classe do Lexer 4 Especificando um Lexer Especificando um Lexer A especificação é dividida em 3 partes que são separadas por “%%” Código do usuário %% Opções do JFlex + Declarações de Macros %% Regras léxicas 6 Parte 1 – Código do Usuário É inserido diretamente no topo do arquivo gerado (não é inserido dentro da classe) package br.fbv.examples.jflex; import java.util.Hashtable; %% ... 7 Parte 1 – Código do Usuário Por exemplo, pode ser usado para: • Definir o pacote ao qual o lexer vai pertencer • Definir imports • Definir a classe Token ou qualquer outra classe, desde que não seja pública - Não recomendo • Comentários de documentação 8 Parte 2 – Diretivas e Macros Situada entre o primeiro sinal “%%” e o segundo sinal “%%” Pode conter opções do JFlex ou macros de expressões regulares •Podem vir alternadas e em qualquer ordem Veremos separadamente... 9 Parte 2.1 – Opções Geralmente definem detalhes de como será a classe gerada (para funcionar como lexer) •Nome da classe, atributos adicionais, etc. ... %% %class Lexer %% ... 10 Parte 2.1 – Algumas Opções •%class <name> – define o nome da classe que vai ser gerada - Se não definir a classe se chamará Yylex •%{ e }% – delimitam código Java a ser inserido dentro da classe do lexer - Ex: Atributos e métodos adicionais (ex.: main) •%cup – torna o arquivo gerado compatível com o gerador de parsers CUP 11 Parte 2.1 – Algumas Opções • %function <name> – define o nome da função que retorna o próximo token - Se não for definida, será yylex() • %type <class-name> – define qual classe (já existente) irá representar os tokens - Ou seja, qual será o tipo de retorno da função acima • %line– ativa o contador de linhas (no atributo yyline) • %column – ativa o contador de colunas (yychar) 12 Parte 2.1 – Outras Opções Existem também opções para: •Tratamento de exceção •Criação de estados léxicos •Tornar a classe pública •etc. 13 Parte 2.2 – Macros Definem nomes para expressões regulares particulares ... %% %class Lexer ALPHA=[A-Za-z_] DIGIT=[0-9] %% ... 14 Parte 2.2 – Macros As macros são definições auxiliares, mas não representam tokens • Podem ser usadas na definição deles, na parte 3 Para usar a definição de uma macro, deve-se delimitar seu nome por chaves • Exemplo de uma macro definida a partir de outra ALPHA_NUMERIC={ALPHA}|{DIGIT} 15 Parte 3 – Regras Seção após o segundo “%%” que especifica regras léxicas no formato •<expressão regular> { <código Java> } ... %% ... %% [0-9] {System.out.println(“Digito encontrado”);} 16 Parte 3 – Regras As regras podem ser criadas com uma expressão regular pura ou usar macros A ação associada à expressão regular pode ser qualquer código Java •Atenção: Esse código (assim como o da opção “%{“ na segunda parte) não é verificado pelo JFlex – ele é apenas copiado fielmente para a classe! 17 Parte 3 – Regras Para expressões que representam tokens, a regra deve ter um “return” passando o token Se for uma expressão que representa comentários ou espaço em branco, a ação não deve retornar valor Se for preciso recuperar o lexema (como um objeto String), basta chamar a função yytext() 18 Parte 3 – Regras Exemplo ... %% "+" { return new Symbol(sym.MAIS); } [0-9]+ { return new Symbol(sym.NUMERO, yytext()); } "//"[^\n] { /* representa um comentário portanto, não faz nada */ } 19 Gerando o Lexer Gerando o Lexer Primeiramente, deve-se salvar a especificação para um arquivo Não é necessário salvar com uma extensão específica, mas é comum usar “.flex” 21 Gerando o Lexer Baixe o JFlex no site • http://jflex.de/ • Arquivo de nome “jflex-<versão>.zip” Descompacte o arquivo Serão gerados vários subdiretórios, como • \doc – tem o manual • \examples – tem exemplos de uso do JFlex • \lib – tem a versão compilada do JFlex • \src – tem o código fonte do JFlex 22 Gerando o Lexer Basta usar a versão compilada do JFlex • Arquivo JFlex.jar na pasta \lib Para gerar o lexer a partir de um arquivo de especificação, use o comando > java -jar JFlex.jar <nome-do-arquivo> Um arquivo “.java” será criado no diretório atual 23 Gerando o Lexer Se usar o mesmo comando sem passar o arquivo, uma janela se abrirá > java –jar JFlex.jar Escolhe o arquivo de especificação (com extensão “.flex”) e o diretório de saída •Um arquivo “.java” será criado no diretório escolhido 24 Gerando o Lexer Coloque o arquivo “.java” gerado no seu projeto (do Netbeans/Eclipse, por exemplo) e compile Erros de compilação podem acontecer na classe por conta de trechos de código errados colocados na especificação • Ajuste a especificação, gere novamente a classe e compile-a novamente no seu projeto 25 Exemplo Há exemplos de uso no próprio JFlex. Implementação dos tokens da linguagem XPR-1 • Linguagem para expressões inteiras, como no exemplo: def myVar = (10 + 3) - 4; myVar * myVar; //imprime o resultado! 19 + 10 * myVar; //imprime o resultado! 26 Referências (Java) Site do JFlex - http://jflex.de Manual do JFlex - http://jflex.de/manual.html 27