Escolar Documentos
Profissional Documentos
Cultura Documentos
COMPILADORES
JFLEX e CUP
Introdução
Analisadores léxicos e sintáticos são construídos
a partir de especificações formais
Gramáticas Regulares / Autômatos finitos
Gramáticas Livre de contexto
Analisadores Sintáticos em C
Analisadores Sintáticos em
Java
Bison
YACC
JCup
BYACC/B
JFLex JCup
Descrição em Descrição em
gramática regular gramática livre de
javac contexto
Analisador Analisador
Léxico Sintático
http://jflex.de/index.html
JFlex
Arquivo de especificação (.jflex)
Dividido em três seções:
Código do usuário
Diretivas
Regras de Expressões Regulares
Principais diretivas:
%init{...%init}
Tudo que você escrever entre as chaves vai ser copiado diretamente para o método
construtor da classe do scanner
%eof{...%eof}
Permite declarar código que vai ser executado quando o scanner encontrar o fim do
arquivo de entrada
%char
Ativa o contador de caracteres através da variável inteira yychar
JFlex
Principais diretivas (continuação)
%line
Ativa o contador de linhas através da variável inteira yyline
%cup
Ativa a compatibilidade com o JCup. Isso significa que a classe gerada do scanner
vai implementar a interface java_cup.runtime.Scanner
%class <nome>
Muda o nome da classe do scanner (default = Yylex).
%debug
Gera o public static void main(...)
JFlex
Código incluído entre %...% é copiado literalmente na classe gerada
Declaração de variáveis
Declaração de funções
Formato:
<nome> = <definição>
Exemplos:
DIGITO = [0-9]
ALFA = [A-Za-z]
ESPACO_EM_BRANCO = [\n\r\x20\t]
NUM_NATURAL = {DIGITO}+
JFlex
Diretivas (Estados)
Permite implementar uma máquina de estados no
scanner.
Exemplo:
%state COMMENT
JFlex
Regras de expressões regulares
Formato das regras:
[<estados>] <expressão> { <ação> }
Exemplos:
{DIGITO}+ representa uma expressão que casa com os números
naturais
<ação> - obrigatório.
Uma ação é o trecho de código que deve ser executado quando uma
regra for aplicada pelo scanner
Você pode fazer uso das variáveis yytext (String), yychar (int) e yyline
(int) dentro do código de suas ações.
JFlex
Regras de expressões regulares (observações)
Se mais de uma regra casar com a string de entrada, o scanner escolhe a
regra que casa com a maior substring da string. Exemplo:
String: abcd
Regra 1: “ab” { acao1(); }
Regra 2: [a-z]+ { acao2(); }
O scanner vai escolher a regra 2.
import java.io.*;
import java.util.Scanner;
%%
%class moedas
%type String
%{
try{
System.out.println("Saída:");
scan.yylex();
}
catch (Exception e) {
}
}
%}
VALOR1 = [0-9]+
VALOR2 = [0-9]
%%
"£"{VALOR1}\.{VALOR2}{2} { System.out.println("Libra"); }
"$"{VALOR1}\.{VALOR2}{2} { System.out.println("Dollar"); }
{VALOR1}"$"{VALOR2}{2} { System.out.println("Escudo"); }
[a-zA-Z]* { }
[ \n\t\r] {}
JCup
Gerador de Analisadores Sintáticos
JCup
Dividido em quatro seções:
Seção 1: declaração de “packages” e “imports” que serão inseridos no
topo do arquivo gerado pelo JCup e diretivas do JCup
Seção 4: gramática
JCup
Seção 1 -Especificação de “packages” e “imports”. Exemplo:
package compilador.parser;
import compilador.scanner;
Diretivas
parser code {: ... :};
Permite que você declare variáveis e métodos na classe do parser. Similar à
diretiva %{...%} do JFlex
init with {: ... :};
O código entre chaves vai ser executado antes que o parser peça o primeiro
token ao scanner
scan with {: ... :};
Serve para que você escreva o código que o parser vai executar sempre que
ele quiser pedir um token ao scanner. Se essa diretiva não for utilizada, o
parser chama scanner.next_token() para receber tokens.
JCup
Seção 2 - Lista de símbolos
terminal [classe] nome0, nome1, ...;
non terminal [classe] nome0, nome1, ...;
Os nomes dos (non) terminais não podem ser palavras reservadas do JCup:
"code", "action", "parser", "terminal", "non", "nonterminal", "init", "scan",
"with", "start", "precedence", "left", "right", "nonassoc", "import", e "package"
JCup
Seção 3 - Precedência e Associatividade
precedence left terminal[, terminal...];
precedence right terminal[, terminal...];
precedence nonassoc terminal[, terminal...];