análise léxica primeira fase de um compilador objetivo: ler os caracteres de entrada e produzir...
TRANSCRIPT
Análise Léxica
• Primeira fase de um compilador
• Objetivo: ler os caracteres de entrada e produzir como saida uma seqüência de tokens que o parser vai usar para análise sintática.
Analisador léxico
Analisador léxicoAnalisador léxico parserparser
getNextToken
Programafonte
token
tabela de símbolostabela de símbolos
Construindo um analisador léxico
• Especificar tokens e lexemas da linguagem
• Implementar (ou gerar através de ferramenta) o analisador a partir da especificação
Outras possíveis tarefas do analisador léxico
• Tratamento de espaços em branco e comentários
• Tratamento de mensagens de erro (localização/impressão)
• Tratamento de macros
Organização
• Às vezes dividido em– scanning – remoção de comentários e espaços
em branco duplicados– Análise léxica propriamente dita – parte mais
complexa, onde o scanner produz a sequencia de tokens
Analisador léxico x Parser
• Design mais simples – misturar análise léxica com sintática torna o parser bem mais complicado
• Eficiência – separação possibilita construir processadores léxicos e sintáticos mais eficientes.
• Portabilidade – variações de dispositivos podem ficar restritas ao analisador léxico.
Tokens, Padrões e Lexemas
• Tokens: par com o nome do token e atributos opcionais.
• Padrão: descrição da forma dos lexemas que um token pode ter
• Lexema: sequencia de caracteres que casam com o padrão de um token. Uma instância de um token.
Tokens, padrões e lexemas
• Existem conjuntos de strings na entrada que geram o mesmo token.
• Elas são descritas por padrões associados ao token
• O padrão casa cada string do conjunto• Um lexema é uma seqüência de caracteres do
programa fonte que casa com um padrão de um token.
• Tokens são símbolos terminais da linguagem.
Tokens, padrões e lexemas
• Tokens normalmente são Palavras-chave, operadores, identificadores, constantes, strings literais e símbolos de pontuação, como parenteses e vírgulas.
• Padrões normalmente são especificados por expressões regulares.
• Variações de expressões regulares são usadas em vários outros contextos:– Linguagens de programação: sed, awk, perl– Shells de sistemas operacionais: sh, csh, command
Tokens, padrões e lexemastoken exemplo descrição
if if Caracteres i, f
else else Caracteres e, l, s, e
comp <,<=,=,<>,> < ou <= ou …
id pi, count, D2 Letra seguida de letras e/ou dígitos
num 3.1416, 0, 6.02E23 Constante numérica
literal “core dumped” Quaisquer caracteres entre “” exceto “ e ”
Dificuldades na implementação de um analisador léxico
• Linguagens que requerem determinados construtores em posições (colunas) específicas da linha de entrada (e.g. Fortran).
• Tratamento de espaços em branco.
• Ausência de palavras reservadas.
Dificuldades - Exemplos
• Fortran:DO 5 I = 1.25DO 5 I = 1,25IF (I,J) = 3
• PL/I:IF THEN THEN THEN = ELSE; ELSE ELSE = THEN;
Atributos de um token
• Ao reconhecer um token num é relevante saber se seu valor é zero ou um, por exemplo.
• Geralmente associado a um token existe um atributo.
• Uso da tabela de símbolos para guardar informações auxiliares sobre tokens.
Atributos de um token - Exemplo
• E = M * C ** 2• <id, apontador p/posição de E na tabela de símbolos>
<assign_op,><id, apontador p/posição de M na tabela de símbolos><mult_op,><id, apontador p/posição de C na tabela de símbolos><exp_op,><num, valor 2>
Erros de análise léxica
• Relativamente raros.
• Geralmente o analisador tenta recuperar do erro, ignorando caracteres.
Opções de Implementação de um analisador léxico
• Uso de um gerador de analisadores léxicos, como lex ou flex, que produzem um analisador léxico a partir de uma especificação em expressões regulares.
• Escrever o analisador em uma linguagem de programação convencional, usando as facilidades de E/S da linguagem para ler a entrada.
• Escrever o analisador léxico em assembler, gerenciando explicitamente a leitura.
• Uso de bufferização da entrada é importante para a eficiência de um analisador léxico!
Especificação de Tokens
• Baseado em Teoria de Linguagens:Alfabetos, strings e linguagens
• Operações sobre linguagens
• Exemplo: seja L o conjunto (de letras) {A,B,…,Z,a,b,…,z}e D o conjunto (de dígitos) {0,1,…,9}.
Operações sobre linguagens - Exemplo
• L D conjunto composto de letras e dígitos• LD conjunto de strings compostas de
letras seguidas de dígitos• L4 conjunto de todas as strings
com 4 letras• L* conjunto de todas as strings de letras,
inclusive a string vazia • D+ conjunto de strings de um ou mais dígitos.• L(L D)*
Operadores sobre linguagensOperação Definição
União de L e ML M
L M = {s | s L ou s M }
Concatenação de L e M,LM
{ st | s L e t M }
Fechamento de Kleene de L,L*
L* = i=0,Li
Fechamento positivo de L, L+ L+ = i=1,Li
Expressões regulares
• Permitem a definição de linguagens a partir de definições de expressões regulares mais simples.
• Exemplos:– Identificadores em pascal:letter (letter | digit) *
– a | b– (a | b) (a | b)– a*– (a|b)*– a | a*b
Propriedades algébricas
• | é comutativa e associativa
• Concatenação é associativa
• Concatenação distribui sobre | é o elemento identidade da concatenação
• * é idempotente (r** = r*)
Exemplo - Pascal
• letter A | B | … | Z | a | b | …| zdigit 0 | 1 | … | 9 id letter (letter | digit)*
• digits digit digit*opt_fraction . digits | opt_exponent (E (+|-|) digits) | num digits opt_fraction opt_exponent
Abreviações
• + uma ou mais instâncias.• ? Zero ou uma instância• [ ] classes de caracteres, ex: [A-Za-z][A-Za-z0-9]*
Reconhecimento de Tokens
• Gerar diagramas de transição e depois implementar uma máquina de estados.
• Implentar autômatos finitos determinísticos e não-determinísticos.
Lex
• Linguagem (e compilador) para especificar analisadores léxicos.
Organização
Compilador lex(lex ou flex)
Compilador lex(lex ou flex)
Programa fontelex.l Lex.yy.c
C compilerC compilerlex.yy.c a.out
a.outa.outEntrada Sequencia de tokens
Programas Lex - estrutura
Declarações – variáveis, constantes, defs.regulares%%regras de tradução – expr.regulares e ações em C
Padrão { Ação }%%procedimentos auxiliares
Lex - exemplo
%{ /* definição de constantes LT, LE, EQ, NE,…*/
%}delim [ \t\n]ws {delim}+letter [A-Za-z]digit [0-9]id {letter}({letter}|{digit})*number {digit}+(\.{digit}+)? (E[+\-]?{digit}+)?
%%…
Lex – exemplo (cont.)
…{ws} {/* no action and no return */}if {return(IF);}then {return(THEN);}else {return(ELSE);}{id} {yylval=install_id();return(ID);}{number} {yylval=install_num(); return(NUMBER);}
“<“ {yylval = LT; return(RELOP);}“<=“ {yylval = LE; return(RELOP);}%%…
Lex – exemplo (cont.)
…int install_id() { Copia lexema para a tabela de símbolos. Primeiro caracter do lexema é apontado pela variável yytext e o comprimento é definido pela variável yyleng.
}
Int install_num() { … }
Lex - implementação
• Transforma o programa de entrada em um programa em C que implementa um Autômato Finito
• NFA – Nodeterministic Finite Automata• DFA – Deterministic Finite Automata
• Reconhecem a mesma linguagem, linguagens regulares, expressas por expressões regulares