Post on 06-Feb-2018
Compiladores 1
http://erinaldosn.wordpress.com
Anlise Lxica
A varredura, ou anlise lxica, a fase de um compilador que l o programa-
fonte como um arquivo de caracteres e o separa em marcas. Essas marcas so como
palavras em uma linguagem natural.
Exemplos de smbolos lxicos so as palavras reservadas, os identificadores, a
constantes e os operadores da linguagem. Durante o processo de anlise lxica, so
desprezados caracteres no significativos como espaos em branco e comentrios.
Alm de reconhecer os smbolos lxicos, o analisador tambm realiza outras
funes, como armazenar alguns desses smbolos (identificadores e constantes) em
tabelas internas e indicar a ocorrncia de erros lxicos.
Para implementar um analisador lxico mo, importante comear com um
diagrama ou outra descrio para os lexemas de cada token. Podemos escrever cdigo
para identificar a cada ocorrncia de cada lexema na entrada e retoranr informaes
sobre o token identificado.
A tarefa efetuada pelo sistema de varredura um caso especial de casamento de
padres. Os mtodos de especificao e reconhecimento de padres que se aplicam no
processo de varredura so basicamente os de expresses regulares e autmatos finitos.
Podemos produzir um analisador lxico automaticamente especificando os
padres dos lexemas para um gerador de analisador lxico e compilando esses padres
em cdigo que funciona como um analisador lxico.
O papel do analisador lxico A tarefa principal do analisador lxico ler os caracteres da entrada do programa
fonte, agrup-los em lexemas e produzir como sada uma sequncia de tokens para cada
lexema no programa fonte.
Token: um par consistindo em um nome e um valor de atributo opcional.
Padro: uma descrio da forma que os lexemas de um token podem assumir
Lexema: uma sequncia de caracteres no programa fonte que casa com o padro para um token e identificado pelo analisador lxico como uma instncia desse
token.
O fluxo de tokens enviado ao analisador sinttico para que a anlise seja
efetuada
Interaes entre o analisador lxico e o analisador sinttico:
O analisador lxico a parte do compilador que l o texto fonte, ele pode
realizar outras tarefas, como remover comentrios e o espao em branco. Outra tarefa
correlacionar as mensagens de erro geradas pelo compilador com o programa fonte.
Os motivos que separam as fases de anlise lxica e anlise sinttica so:
1. Simplicidade do projeto.
Programa
fonte
Analisador
lxico
Analisador
sinttico
para anlise
semntica
token
obter
token
Tabela de
smbolos
Expresses Regulares
http://erinaldosn.wordpress.com
2. A eficincia do compilador melhorada. 3. A portabilidade do compilador melhorada.
Os analisadores lxicos so divididos em uma cascata de dois processos:
1. O escandimento consiste no processo simples de varredura da entrada sem se preocupar com a remoo de comentrios e a compactao de espaos em branco
consecutivos em apenas um caractere.
2. A anlise lxica, onde o analisador lxico produz a sequncia de tokens como sada.
Atributos de tokens Quando mais de um lexema casar com um padro, o analisador lxico precisa
oferecer s fases subsequentes do compilador informaes adicionais sobre qual foi o
lexema em particular casado.
Exemplo: o padro para o token number casa com 0 e 1.
Assim, em muitos casos, o analisador lxico retorna ao analisador sinttico o
nome do token e um valor de atributo que descreve o lexema representado pelo token. O
nome do token influencia as decises durante a anlise sinttica, enquanto o valor do
atributo influencia a traduo dos tokens aps o reconhecimento sinttico.
Normalmente as informaes sobre um identificador (associa muitas
informaes ao token) so mantidas na tabela de smbolos. Assim, o valor de atributos
apropriado para um identificador um apontador para a sua entrada na tabela de
smbolos.
Em certos pares (operadores, pontuao e palavras chave) no h necessidade de
um valor de atributo.
Um compilador tpico armazena uma cadeia de caracteres representando uma
constante e como valor de atributo um apontador para essa cadeia.
Erros lxicos difcil para um analisador lxico saber, sem o auxlio de outros componentes,
que existe um erro no cdigo fonte.
Por exemplo, um analisador lxico no tem como saber se fi a palavra-chave
if escrita errada ou um identificador de funo no declarada. Como fi um lexema
vlido para o token id, o analisador lxico precisa retornar o token id ao analisador
sinttico e deixar que alguma outra fase do compilador trate o erro devido
transposio das letras.
O processo de varredura As unidades lgicas geradas pela varredura so denominadas marcas (tokens).
As marcas so entidades lgicas, usualmente definidas como um tipo enumerado. typedef enum {
if, then, else, plus, minus, num, id,...
} TokenType;
Em uma linguagem sem tipos enumerados, como em C, temos que definir as
marcas diretamente como valores numricos simblicos. # define IF 256
# define THEN 257
# define ELSE 258
Esses nmeros comeam em 256 para evitar confuso com valores numricos da
tabela ASCII.
Compiladores 3
http://erinaldosn.wordpress.com
Um sistema de varredura deve computar pelo menos tantos atributos de uma
marca quanto necessrio para possibilitar a continuidade do processamento. Como o
sistema de varredura precisar possivelmente computar diversos atributos para cada
marca, frequentemente til coletar todos os atributos em um nico tipo de dado
estruturado, denominado registro marca (TokenRecord).
Esse registro poderia ser declarado em C como: typedef struct {
TokenType tokenval;
char * stringval;
int numval;
} TokenRecord;
Um arranjo mais comum o sistema de varredura retornar apenas o valor da
marca e colocar os outros atributos em variveis que possam ser acessadas por outras
partes do compilador.
A varredura no converte todo o programa fonte em uma sequncia de tokens de
uma vez. A varredura ocorrer sob o controle de uma analisador sinttico, retornando a
marca seguinte demandada por meio de uma funo com a seguinte declarao em C: TokenType getNextToken(void);
A funo getNextToken retornara a prxima marca fornecida, bem como
computadr aributos adicionais, como o valor em caracteres da marca. A cadeia de
caracteres de entrada geralmente armazenada em um repositrio ou fornecida pelos
recursos de entrada do sistema.
Exemplo: considere a seguinte linha de cdigo fonte em C: a[index] = 4 + 2;
Suponha que essa linha de cdigo seja armazenada em um repositrio de
entrada, com o prximo caractere de entrada indicado pela seta:
a [ i n d e x ] = 4 + 2
A ativao de getNextToken precisar saltar o quatro brancos seguintes,
reconhecer a cadeia de caracteres a como a prxima marca, e retornar o valor de marca
ID como prxima marca.
a [ i n d e x ] = 4 + 2
Uma chamada subsequente de getNextToken iniciar o reconhecimento a partir
do caractere de colchete esquerda.
Bufferes de entrada Devido quantidade de tempo necessria para processar caracteres e o grande
nmero de caracteres que precisam ser processados durante a compilao de um
programa fonte grande, foram desenvolvidas tcnicas especializadas de buffering para
reduzir o custo exigido no processamento em um nico caractere de entrada.
Um esquema importante envolve dois bufferes que so recarregados
alternadamente.
E = M * C * * 2 EOF
forward
lexemeBegin
Expresses Regulares
http://erinaldosn.wordpress.com
Cada buffer possui o mesmo tamanho N, e N normalmente corresponde ao
tamanho de um bloco de disco (4096 bytes).
Usando um sistema de leitura do sistema, podemos ler N caracteres para um
buffer. Se restarem menos de N caracteres no arquivo de entrada, ento um caractere
especial, representado por eof, marca o fim do arquivo fonte.
So mantidos dois apontadores para a entrada:
lexemeBegin marca o incio do lexema corrente;
forward l adiante, at que haja casamento de padro
Uma vez que o prximo lexema determinado, forward configurado para
apontar para o seu ltimo caractere direita, e lexemeBegin configurado para apontar
para o caractere imediatamente aps o lexema recm-encontrado.
Sentinelas Se usarmos o esquema de pares de buffer precisaremos verificar, sempre que
avanarmos o apontador forward, se o movemos para fora de um dos buffers; nesse
caso tambm precisaremos recarregar o outro buffer.
Para cada caractere lido fazemos dois testes: um para o fim do buffer e o outro
para determinar qual caractere foi lido.
Sentinela um caractere especial que no pode fazer parte do programa fonte, e
uma escolha natural o caractere de fim de arquivo, eof.
E = M * EOF C * * 2 EOF EOF
forward
lexemeBegin switch (* forward++) {
case eof:
if (forward est no fim do primeiro buffer){
recarrega segundo buffer;
forward = incio do segundo buffer;
}
else if (forward est no fim do segundo buffer){
recarrega primeiro buffer;
forward = incio do primeiro