Analisador Léxico
Analisador Léxico
Fabiano Rodrigues
Farley J. R. Oliveira
Michel Sato
Vitor Lins Vieira
051.649-1
052.696-7
Analisador Léxico
• A análise léxica é a primeira fase do
compilador. A função do analisador léxico,
também denominado scanner, é ler o código
fonte, caracter a caracter, buscando a
separação e identificação dos elementos
componentes do programa fonte,
denominados símbolos léxicos ou tokens.
Analisador Léxico
• É também de responsabilidade desta fase a
eliminação de elementos "decorativos" do
programa, tais como espaços em branco,
marcas de formatação de texto e comentários.
Tokens
• A criação dos símbolos (tokens) é importante,
pois torna a próxima etapa de um compilador
(análise sintática, ou parsing) mais simples.
Etapas
• Na análise léxica podemos destacar três
etapas:
– Extração e classificação dos tokens
– Eliminação de delimitadores e comentários
– Recuperação de erros
Tokens
• O objetivo principal da análise léxica é
identificar sequências de caracteres que
constituem unidades léxicas ("tokens"). O
analisador léxico lê, caractere a caractere, o
texto fonte, verificando se os caracteres lidos
pertencem ao alfabeto da linguagem,
identificando tokens, e desprezando
comentários e brancos desnecessários.
Tokens
• Tokens são símbolos tais como palavras
reservadas, delimitadores, identificadores, etc.
• Os tokens (símbolos léxicos) são unidades
básicas de texto do programa. Eles são
representados internamente por três
informações: classe do token, valor do token e
posição do token.
Recuperação de Erros
• Ações possíveis:
• Remoção de sucessivos caracteres até o
reconhecimento de um token válido
(modalidade Pânico).
• Inserção de um caractere ausente.
• Substituição de um caractere incorreto por
outro correto.
• Transposição de caracteres adjacentes.
Exemplo
Exemplo: sum=3+2;
token type
sum
=
3
+
2
;
IDENT
ASSIGN_OP
NUMBER
ADD_OP
NUMBER
SEMICOLON
Exemplo de comando
•Comando em Java:
if (i== j)
z = 0; /* No work needed */
else
z= 1;
•Como o analisador léxico vê os comandos:
\tif(i== j)\n\t\tz = 0; /* No work needed */\n\telse\n\t\tz= 1;
Formação de Tokens & Expressões
Regulares
• Analisador efetua sucessivas verificações de caracteres até
encontrar um caracter de “estado morto”, como espaço,
parênteses, ponto-e-vírgula
• Retorna à ultima análise válida para extrair um lexeme
• Um lexeme classificado se torna um token
• O reconhecimento de um token é feito através de expressões
regulares
Scanner
• Após a definição dos tokens, o scanner, uma função do
analisador léxico, converte isto:
\tif(i== j)\n\t\tz = 0; /* No work needed */\n\telse\n\t\tz= 1;
• Nisto:
IF, LPAR, ID("i"), EQUALS, ID("j"), RPAR, ID("z"), ASSIGN,
INTLIT(""), SEMI, ELSE, ID("z"), ASSIGN, INTLIT(""), SEMI
que é a “expressão” a ser enviada ao analisador sintático
Classe de Scanner
• Exemplo de classe para um scanner em Java
class Token {
enum SyntacticCategory {
IF, LPAR, ID, EQUALS, RPAR, ASSIGN, ...
};
SyntacticCategory syntax;
Object value;
Location sourcePosition;
...
}
Classe de Scanner
• Exemplo de classe para um scanner em Java
class Token {
enum SyntacticCategory {
IF, LPAR, ID, EQUALS, RPAR, ASSIGN, ...
};
SyntacticCategory syntax;
Object value;
Location sourcePosition;
...
}
Geradores de Analisadores Lèxicos
• FLEX
• OOLEX
LEX / FLEX
• LEX é uma ferramenta para a geração
automática de analisadores léxicos
• Versão Free: FLEX (Fast LEX)
• Desenvolvido em 1975 em conjunto com o
YACC (Yet another compiler-compiler), por
Mike Lesk & Eric Schmidt. No Bell Laboratories
LEX / FLEX
• Free Software Foundation – GNU – FLEX:
Implementação mais rápida do FLEX (e
gratuita!!)
• O gcc (GNU C Compiler) foi desenvolvido com
LEX & YACC.
• LEX: dividir as entradas em unidades
coerentes (tokens)
• YACC: descobrir o relacionamento entre os
tokens. (análise sintática)
LEX / FLEX
• Objetivos: desenvolvida para programadores
de compiladores e interpretadores; porém
podem ser usadas também em detecção de
padrões em arquivos de dados, linguagem de
comandos, etc..
• Vantagem: Rápido desenvolvimento de
protótipos e manutenção simples do software.
LEX / FLEX
• Papel do LEX: toma um conjunto de descrições
de possíveis tokens e produz uma rotina em C
que irá identificar estes tokens
• Papel do Yacc: toma uma descrição concisa de
uma gramática e produz uma rotina em C que
irá executar a análise sintática ou parsing.
• NOTA: um analisador léxico desenvolvido
usando Lex é quase sempre mais rápido do
que um analisador léxico escrito diretamente
em C.
LEX / FLEX
LEX / FLEX
• Encontra-se em qualquer sistema Unix e pode
ser chamada usando os comandos lex ou flex;
• Transforma um arquivo contendo expressões
regulares em um programa C que reconhece
os padrões descritos no arquivo
• O Flex lê os arquivos de entrada (arquivo de
definição), obtendo assim a descrição do
scanner a ser gerado. Esse arquivo é definido
usando a linguagem lex
LEX / FLEX
LEX / FLEX
• Um arquivo de descrição Flex é dividido em três seções
separadas por %% :
• DEFINICOES
%%: Contém declarações de variáveis, constantes e definições
regulares;
• REGRAS
%%: Contém definições de rotinas em C que são chamadas
quando uma expressão é reconhecida
• CODIGO
Contém o main (início de procedure em C) e descreve como o
analisador léxico deve ser utilizado
LEX / FLEX
• SEÇÃO DE DEFINIÇÕES:
•
É opcional (pode ser vazia)
•
Contém definições léxicas, e a declaração e inicialização de variáveis
globais
•
Uma definição léxica possui a forma NOME DEFINIÇÃO
•
As definições são expressões regulares que reconhecem tokens do texto
fonte.
•
Seu conteúdo será copiado no início do arquivo C gerado na saída.
LEX / FLEX
• SEÇÃO DE DEFINIÇÕES:
• LEX define por padrão as variaveis globais:
yytext (lexema corrente) e yyleng (tamanho do lexema)
• Definições de macros:
digito [01]+ /* substituir {digito} por [01]+ ao processar as regras */
frac .[0-9]+ /* substituir {frac} por .[0-9]+ ao processar as reg
nl \n
/* substituir {nl} por \n ao processar as regras */ras */
• A inclusão das linhas de comando em C devem ser delimitadas por <%{> e
<%}>, como:
%{
#include <y.tab.h>
extern int yylval;
%}
LEX / FLEX
• SEÇÃO DE REGRAS:
• Define a funcionalidade do analisador léxico. Cada regra compreende uma
seqüência valida de caracteres (literais/expressões regulares) .
• Definido da seguinte forma:
token {AÇÃO}
• A ação pode ser nula ‘{ }’ ou conter um ou mais comandos em linguagem
C.
LEX / FLEX
• SEÇÃO DE REGRAS:
• Ao chamar a função yylex(), passando o token e seu tamanho, o
analisador executará a AÇÃO associada àquela token;
• Retornará o próprio token caso seja reconhecido pelo analisador léxico;
• Retornará brancos caso nenhuma ação seja tomada, ou caso seja
encontrados espaços em branco;
• ‘{ printf(“é isso ai\n”);} é a “ação” que consiste em imprimir uma
mensagem na tela.
LEX / FLEX
• SEÇÃO DE CODIGOS / PROCEDIMENTOS ADICIONAIS:
• Opcional (pode ser vazia)
• Possui o código C definido pelo programador (função main() , que deve
chamar a função yylex()
• Qualquer código C nessa seção será copiado diretamente no arquivo
produzido pelo Lex.
• Pode definir código para as ações complexas usadas na seção anterior.
LEX / FLEX
• UTILIZAÇÃO DO COMPONENTE GERADO
• O LEX é acoplado ao YACC, que efetua a analise sintática. É uma
ferramenta similar e complementar ao LEX.
• O LEX gera a função yylex() , que retorna o identificador de um item léxico
reconhecido.
• O YACC funciona de forma a chamar o yylex() do LEX;
• O YACC gera a função yyparse() , que analisa os itens léxicos e decide se
ele formam ou não uma sentença válida.
Analisador Léxico
OOLEX
OOLEX
• OOLEX (object-oriented lexer) é estritamente
baseada no paradigma de orientação a
objetos.
• Tese de doutorado de Bernd Kühl and AxelTobias Schreiner em Ciências da Computação
na Universidade de Osnabrück, Alemanha
OOLEX
• OOLEX pode ser estendido sem acesso para o
código fonte: símbolo recognizer pode ser
obtido por herança e um scanner de execução
pode ser reconfigurado para diferentes
contextos.
• OOLEX não precisa ser baseado em um
autômato finito e, portanto, ele pode
reconhecer símbolos que sistemas como o flex
OOLEX
• OOLEX é usado para prototipagem rápida: a
maioria dos identificadores existentes podem
ser representados como expressões regulares
para o JLex baseados em Java.
• OOLEX oferece muitas vantagens sobre
Scanners de Expressões Regulares scanners
• OOLEX tem um desempenho pior justificado
OOLEX
• OOLEX pode compilar uma expressão regular
em uma árvore de objetos recognizers
• OOLEX é muito mais fácil de usar, porque já
existe uma biblioteca de recognizers para os
símbolos mais comuns
• OOLEX em sua própria classe quando se trata
de análise léxica
Analisador Léxico
LOLO
LOLO
• LOLO (language-oriented lexer objects) é
estritamente baseada no paradigma de
orientação a objetos.
• Continuação da tese de doutorado de Bernd
Kühl and Axel-Tobias Schreiner em Ciências da
Computação na Universidade de Osnabrück,
Alemanha
LOLO
• Não necessita de autômato finito
– Modelagem de estados, transições e ações
• Reconhece diretamente símbolos que
sistemas como FLEX não
LOLO
• Não necessita de autômato finito
– Modelagem de estados, transições e ações
• Reconhece símbolos que sistemas como flex
não conseguiriam diretamente
LOLO
• Baseia-se na competição de objetos
• Que buscam reconhecer um único símbolo
LOLO
• Um input entra numa "sala" repleta de
objetos
• Caractere a caractere é verificado por cada
objeto, que caso não reconheça é retirado da
sala
• O último objeto a sair é o ganhador
– Reconheceu a maior sequência de caracteres
LOLO
• Principal desvantagem é a performance
• Cerca de 3 vezes mais lento em comparação
ao Flex
Analisador Léxico
FIM
Download

Analisador Léxico