Upload
phamquynh
View
223
Download
2
Embed Size (px)
Citation preview
Prof José Rui
Compiladores 04Analise léxica
Jflex
Prof José Rui
Sumário
● Análise Léxica
– Definição: Lexema, tokens
– Tabela símbolos
– Expressões regulares, automatos
– JFlex
Prof José Rui
Análise léxica
● Exemplo
– Soma = a + b * 40;<IDENT, 1>, <OP_IGUAL>, <IDENT, 3>, <OP_SOMA>, <IDENT, 5>, <OP_MULT>,<NUM, valor 40>
Tabela de simbolos
Lexema (lido) token valor
1 soma <IDENT> -
2 = <OP_IGUAL> -
3 a <IDENT> -
4 + <OP_SOMA> -
5 b <IDENT> -
6 * <OP_MULT> -
7 40 <NUM> 40
Analisadorléxico
Prof José Rui
Análise léxica
● A partir dai o compilador une os caracteres de acordo com os tokens da linguagem
● Os tokens são definidos por meio de expressões regulares
int gcd (int a, int b){while(a != b){
if(a > b)a = b;
elseb = a;
}return a;
}
i n t sp g c d sp ( i n t sp a sp , sp i n t sp b ) { nl w h i l e (a ! = b ) nl { i f sp ( a > b ) nla = b ; nl e l s e nl b = a ; nl } nlr e t u r n sp a ; nl }
Prof José Rui
Análise léxica
● Para fazer o reconhecimento do token o analisador lexico utiliza autômato finito
– letra → [A – Z] [a – z]
– digito → [0 – 9]
– digitos → digito digito*
– ident → letra (letra | digito)*
Prof José Rui
Análise léxica
● Note que:
– O AL ignora os espaços em branco
– Além de espaços ele ignora comentários, newLine...
– Fica apenas os tokens
int gcd (int a, int b){while(a != b){
if(a > b)a = b;
elseb = a;
}return a;
}
Prof José Rui
Análise Sintática
● Só para se ter uma idéia da análise sintática
– Cria-se uma arvore com os tokens
– Formalismo BNF
int gcd (int a, int b){while(a != b){
if(a > b)a = b;
elseb = a;
}return a;
}
Prof José Rui
Análise léxica
● Diagrama scanner-parser:
Analisador léxico(Scanner)
Analisador sintático(Parser)
getNextToken()
Programafonte
token
Tabela de símbolos(identificadores e
constantes)
semântico
Prof José Rui
Análise léxica
● Diagrama scanner-parser:
● Jflex e Jcup
Lex
AnalisadorLéxico
regrasléxicas
entrada
AnalisadorSintático
saída
Expressões regulares
Geradores automáticosJflex e jcup
Classes geradas
Prof José Rui
Gerador de analisador léxico - JFLEX
● Ajuda escrever programas cuja entrada é descrita por meio de expressões regulares
Prof José Rui
Gerador de analisador léxico - JFLEX
● Ajuda escrever programas cuja entrada é descrita por meio de expressões regulares
● Principais utilizações
– Transformações simples;
– Extração de padrões em textos;
– Separação da entrada em unidades léxicas; (preparando para o analisador sintático)
Prof José Rui
Gerador de analisador léxico - JFLEX
● Ajuda escrever programas cuja entrada é descrita por meio de expressões regulares
● Principais utilizações
– Transformações simples;
– Extração de padrões em textos;
– Separação da entrada em unidades léxicas; (preparando para o analisador sintático)
● Um texto fonte para LEX é composto de:
– Lista de expressões regulares
– Fragmentos de programas associados a cada expressão
Prof José Rui
JFLEX – Esquema de funcionamento
LexFonte(Expressões regulares)
Prof José Rui
JFLEX – Esquema de funcionamento
● Quando o fonte é submetido ao LEX, um programa yylex é gerado
LexFonte(Expressões regulares)
Yylex(programa gerado)
Prof José Rui
JFLEX – Esquema de funcionamento
● Quando o fonte é submetido ao LEX, um programa yylex é gerado
● Esse programa Yylex:
– Lê um arquivo de entrada
Lex
Yylex
Fonte(Expressões regulares)
Yylex(programa gerado)
entrada
Prof José Rui
JFLEX – Esquema de funcionamento
● Quando o fonte é submetido ao LEX, um programa yylex é gerado
● Esse programa Yylex:
– Lê um arquivo de entrada
– Particiona a entrada em cadeias que “casam” com as expressões regulares definidas → Tokens
– Executa executa os fragmentos de programa associados às expressões “casadas”
Lex
Yylex
Fonte(Expressões regulares)
Yylex(programa gerado)
entrada
Prof José Rui
JFLEX – Esquema de funcionamento
● Quando o fonte é submetido ao LEX, um programa yylex é gerado
● Esse programa Yylex:
– Lê um arquivo de entrada
– Particiona a entrada em cadeias que “casam” com as expressões regulares definidas → Tokens
– Executa executa os fragmentos de programa associados às expressões “casadas”
– Escreve no arquivo de saída
Lex
Yylex
Fonte(Expressões regulares)
Yylex(programa gerado)
entrada saída
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
● Os arquivos LEX são divididos em 3 seções, separadas por %%
● No jflex as seções são:
1. Código do usuário a ser incluído
2. Opções e declarações
3. Regras e ações associadas
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex1
2
3
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
Essa opção indica que o programa gerado poderá serexecutado diretamente (não será usado dentro de um analisador sintático).
Essa opção indica que o programa gerado poderá serexecutado diretamente (não será usado dentro de um analisador sintático).
ex1.lex
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
Uma regraUma regra
ex1.lex
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
Expressão regularExpressão regular
ex1.lex
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
Ação (fragmento de programa) associada a expressão
Ação (fragmento de programa) associada a expressão
ex1.lex
Prof José Rui
Lex – exemplo com Jflex
● Exemplo 1
● Esta regra “casa” com o caractere “\t” (tabulação)
● Se isso ocorrer, o código entre chaves é executado
● Senão o default é escrever o próprio caractere na saída
● Ou seja, o programa serve para ler um arquivo de entrada e trocar o caractere “\t” pela palavra TAB
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flex
Comando jflex para construir o analisador léxico
Comando jflex para construir o analisador léxico
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flexReading "ex1.flex"Constructing NFA : 6 states in NFAConverting NFA to DFA : ..4 states before minimization, 3 states in minimized DFAWriting code to "Yylex.java"
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flexReading "ex1.flex"Constructing NFA : 6 states in NFAConverting NFA to DFA : ..4 states before minimization, 3 states in minimized DFAWriting code to "Yylex.java"
Note que ele constrói um AFNdepois o converte em AFDe por fim o minimiza
Note que ele constrói um AFNdepois o converte em AFDe por fim o minimiza
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flexReading "ex1.flex"Constructing NFA : 6 states in NFAConverting NFA to DFA : ..4 states before minimization, 3 states in minimized DFAWriting code to "Yylex.java"
Ele gerou pra você o código em Java. Agora é só compilá-lo
Ele gerou pra você o código em Java. Agora é só compilá-lo
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flexReading "ex1.flex"Constructing NFA : 6 states in NFAConverting NFA to DFA : ..4 states before minimization, 3 states in minimized DFAWriting code to "Yylex.java"
> javac Yylex.java
Comando de compilação JAVA
javac nomearquivo.java
Comando de compilação JAVA
javac nomearquivo.java
Prof José Rui
Lex – usando o Jflex
● Exemplo 1
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex
> jflex ex1.flexReading "ex1.flex"Constructing NFA : 6 states in NFAConverting NFA to DFA : ..4 states before minimization, 3 states in minimized DFAWriting code to "Yylex.java"
> javac Yylex.java>
Pronto!
● Gerou o Yylex.class
● Agora é só executá-lo
Pronto!
● Gerou o Yylex.class
● Agora é só executá-lo
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 1
● Suponha o arquivo de entrada chamado teste.txt
Bla bla bla...Esta linha inicia com tabulação
Esta com duas tabulações
teste.txt
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 1
● Suponha o arquivo de entrada chamado teste.txt
Bla bla bla...Esta linha inicia com tabulação
Esta com duas tabulações
teste.txt
Voce pode ate não está vendo, mas aqui
tem uma tabulação
Voce pode ate não está vendo, mas aqui
tem uma tabulação
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 1
● Suponha o arquivo de entrada chamado teste.txt
Bla bla bla...Esta linha inicia com tabulação
Esta com duas tabulações
teste.txt
> java Yylex teste.txt
Ao executar o Yylex passando o arquivo teste.txtcomo parâmetro
Ao executar o Yylex passando o arquivo teste.txtcomo parâmetro
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 1
● Suponha o arquivo de entrada chamado teste.txt
Bla bla bla...Esta linha inicia com tabulação
Esta com duas tabulações
teste.txt
> java Yylex teste.txt
Bla bla blaTABEsta linha inicia com tabulaçãoTABTABEsta com duas tabulações
Temos como saídaTemos como saída
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 1
● Suponha o arquivo de entrada chamado teste.txt
● Se quisermos jogar a saida para uma arquivo
Bla bla bla...Esta linha inicia com tabulação
Esta com duas tabulações
teste.txt
> java Yylex teste.txt
Bla bla blaTABEsta linha inicia com tabulaçãoTABTABEsta com duas tabulações
Temos como saídaTemos como saída
> java Yylex teste.txt > saida.txt
Prof José Rui
Lex – Expressões regulares
● Basicamente:
– Caraceteres de texto: ● letras, dígitos, caracteres especiais como '\t','\n'...
– Operadores: ● Usados como funções especiais das expressões regulares
● Na maioria das versões LEX:
● " \ [ ] ˆ - ? . * + | ( ) $ / { } % < >
– Atenção: ● Nada impede de utilizar os operadores como caracteres, desde que venham
precedidos de espace('\')
● Ou se estiverem entre aspas duplas
Prof José Rui
Lex – Expressões regulares
^ → caracter que o segue inicia o elemento
$ → caracter que o antecede finaliza o elemento
. → caracter é um símbolo qualquer (exceto nova linha)
| → enumerador de alternativas
( ) → agrupador
[ ] → especificificador de classes
* → caracter ocorre 0 ou mais vezes
+ → caracter ocorre 1 ou mais vezes
? → caracter ocorre 1 ou 0 vezes
{n} → caracter ocorre exatamente "n" vezes
{n,} → caracter ocorre pelo menos "n" vezes
{n,m} → caracter ocorre pelo menos "n" vezes e não mais que "m" vezes
Prof José Rui
Lex – Expressões regulares● Especificador de classes
[abc] casa com um dos caracteres a, b ou c
[a-zA-Z]casa com letras maiúsculas ou minúsculas
[^a-zA-Z] casa com qualquer coisa, exceto letras
● ^ na expressao regular
^ab* inicia com a
● ^ na classe
[^a-zA-Z] nega o que tem dentro da classe
● $ , o que antecede finaliza a palavra
(1|0)*(000)$ casa com tudo que finaliza com 000
Prof José Rui
Lex – Expressões regulares
● Expressão opcional (? corresponde a uma ou zero ocorrências ao que vem, antes)
ab?c casa ac ou abc (b pode ocorrer uma ou zero vezes)
(ab|cd+)?(ef)* casa com abef, abefef, efefef, cddddd
● Macros
{digito} casa com a definição da expressão regular digito definido previamente
● Repetição
a{n} casa com n vezes a concatenação de a
Prof José Rui
Lex - Precedência
● Forma de escolha das regras para casamento
1. À medida que a entrada é lida, o analisador procura a regra que possui a cadeia mais longa
2. Se mais de uma regra possibilita o casamento com a seqüência mais longa, a escolha é feita pela ordem em que as regras aparecem na fonte
Prof José Rui
Lex – Relembrando
● Seções
● Os arquivos LEX são divididos em 3 seções, separadas por %%
● No jflex as seções são:
1. Código do usuário a ser incluído
2. Opções e declarações
3. Regras e ações associadas
%%
%standalone
%%
\t { System.out.print(“TAB”); }
ex1.lex1
2
3
Prof José Rui
Lex – Precedência
● Exemplo 2
● Ao encontrar “abcd”, o compilador vai casar com “abc” ou com “ident”?
%%
% standaloneIdent = [a-zA-Z][a-zA-Z0-9]*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
Prof José Rui
Lex – Precedência
● Exemplo 2
● Ao encontrar “abcd”, o compilador vai casar com “abc” ou com “ident”?
%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
Observação
● Crie Macros!
● Fica mais organizado!
Observação
● Crie Macros!
● Fica mais organizado!
Prof José Rui
Lex – Precedência
● Exemplo 2
● Ao encontrar “abcd”, o compilador vai casar com “abc” ou com “ident”?
R: Vai casar com “ident”. É a maior!
%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
Prof José Rui
Lex – Precedência
● Exemplo 2
● Ao encontrar “abcd”, o compilador vai casar com “abc” ou com “ident”?
R: Vai casar com “ident”. É a maior!
%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
Vamos conferir!Vamos conferir!
Prof José Rui
Lex – Precedência
● Exemplo 2%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
> jflex ex2.flex
Comando jflex para construir o analisador léxico Yylex.java
Comando jflex para construir o analisador léxico Yylex.java
Vamos conferir!Vamos conferir!
Prof José Rui
Lex – Precedência
● Exemplo 2%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
> jflex ex2.flexReading "ex2.flex"Constructing NFA : 16 states in NFAConverting NFA to DFA : ......8 states before minimization, 6 states in minimized DFAWriting code to "Yylex.java"
Comando jflex para construir o analisador léxico Yylex.java
Comando jflex para construir o analisador léxico Yylex.java
Prof José Rui
Lex – Precedência
● Exemplo 2%%
% standaloneDigito = [0-9]Letra = [a-zA-Z]Ident = {Letra} ({Letra} | {Digito})*
%%abc { System.out.println("-----\"abc\""); }{Ident} { System.out.println("-----id"); }
ex2.lex
> jflex ex2.flexReading "ex2.flex"Constructing NFA : 16 states in NFAConverting NFA to DFA : ......8 states before minimization, 6 states in minimized DFAWriting code to "Yylex.java"
> javac Yylex.java● Agora basta compilá-lo e
usar● Este comando gera o
Yylex.class
● Agora basta compilá-lo eusar
● Este comando gera o Yylex.class
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 2
● Suponha o arquivo de entrada chamado teste.txt
● O que será impresso?
abcdeabcabc123123abcd123abc
teste.txt
> java Yylex teste.txt
Prof José Rui
Lex – executando o analisador gerado
● Exemplo 2
● Suponha o arquivo de entrada chamado teste.txt
● O que será impresso?
abcdeabcabc123123abcd123abc
teste.txt
> java Yylex teste.txtid
abc
id
123id
123abc
Prof José Rui
JFlex
● Exercício:
– Faça o exemplo anterior no computador
● Orientações para instalação e configuração
– Linux
● http://www.skenz.it/compilers/installLinux.html
– Windows
● http://www.skenz.it/compilers/installWindows.html
Prof José Rui
Análise léxica
Exercícios
● Seja as seguintes linguagens abaixo. Construa o autômato(caso necessário) e depois crie a EXPRESSÃO REGULAR de cada linguagem e adicione no arquivo ex1.flex
a) {w {0,1}* | w tem tamanho 3}
b) {w {0,1}* | w tem tamanho maior que 4}
Depois rode para os seguinte arquivo teste.txt informando a qual linguagem cada linha pertence.
010 011001110101010010001101111001
Teste.txt
> jflex ex1.flex //Gerar o Yylex.java
> javac Yylex.java //Compilar o Yylex.java
>java Yylex teste.txt //Rodar o Yylex.class
Prof José Rui
Análise léxica
Exercícios
● Seja as seguintes linguagens abaixo. Construa o autômato(caso necessário) e depois crie a EXPRESSÃO REGULAR de cada linguagem e adicione no arquivo ex1.flex
a) {w {0,1}* | w tem tamanho 3}
b) {w {0,1}* | w tem tamanho maior que 4}
Depois rode para os seguinte arquivo teste.txt informando a qual linguagem cada linha pertence.
010 011001110101010010001101111001
Teste.txt
> jflex ex1.flex //Gerar o Yylex.java
> javac Yylex.java //Compilar o Yylex.java
>java Yylex teste.txt //Rodar o Yylex.class
Ling. a Ling. bLing. aLing. bLing. aLing. aLing. aLing. b
Saída.txt