Anda di halaman 1dari 7

Anatomia de um compilador

Um compilador uma ferramenta que traduz um programa de uma lngua para outra
lngua. Um intrprete uma ferramenta que tem um programa e executa-lo. No primeiro
caso, o programa chega muitas vezes a partir de um ficheiro no disco e no segundo
programa armazenada, por vezes, em memria intermdia, de modo que as alteraes
podem ser feitas rapidamente e facilmente atravs de um editor integrado. Este
frequentemente o caso em interpretadores BASIC e programas de calculadora. Vamos
fazer referncia fonte do programa, se ele est no disco ou na memria RAM, como
o fluxo de entrada .
Independentemente de onde o programa vem ele deve primeiro passar por um Tokenizer ,
ou como s vezes chamado, um Lexer . O tokenizador responsvel por dividir o fluxo
de entrada em tokens individuais, identificando o tipo de token, e passando sinais um de
cada vez para a prxima fase do compilador.
A prxima etapa do compilador chamado o Analisador . Esta parte do compilador tem
uma compreenso da gramtica da lngua. Ele responsvel por identificar erros de
sintaxe e de traduzir um programa livre de erros nas estruturas de dados internos que
podem ser interpretadas ou escritas em outro idioma.
A estrutura de dados chamado de rvore de anlise , ou s vezes um Cdigo
representao intermediria . A rvore de anlise uma estrutura independente da
linguagem, o que d uma grande flexibilidade para o gerador de cdigo. O analisador
lxico e analisador juntos so muitas vezes referidos como front-end do compilador. O
resto do compilador chamado a extremidade traseira. Devido natureza independente
do idioma a rvore de anlise, fcil, uma vez que a extremidade da frente est no local,
para substituir a extremidade traseira com um gerador de cdigo para uma linguagem de
alto nvel diferente, ou em linguagem de mquina um diferente, ou substituir o gerador de
cdigo todos juntos com um intrprete. Esta abordagem permite que um compilador de
ser facilmente transportado para um outro tipo de computador, ou por um nico
compilador para produzir o cdigo para um nmero de computadores diferentes
(compilao cruz).
s vezes, especialmente em sistemas menores, a representao intermediria gravado
em disco. Isto permite que a extremidade da frente para ser descarregado a partir da RAM
e RAM no necessrio para a representao intermdia. Isto tem duas desvantagens:
mais lento, e isso requer que a rvore de anlise ser traduzido para uma forma que pode
ser armazenado em disco.
O passo seguinte no processo consiste em enviar a rvore de anlise ou para um
intrprete, onde executado, ou a um pr-processador de gerador de cdigo. Nem todos
os compiladores ter um pr-processador de gerador de cdigo. O pr-processador tem
dois empregos. O primeiro para quebrar qualquer expresso em seus componentes mais
simples. Por exemplo, a atribuio de um: = 1 + 2 * 3 seria quebrado em temp: = 2 *
3; a: = 1 + temp; Tais expresses so chamadas deexpresses binrias . Tais expresses
so necessrios para a gerao de cdigo de linguagem assembler. Compiladores que
traduzem de uma linguagem de alto nvel para outro, muitas vezes no contm este
passo. Outra tarefa do pr-processador gerador de cdigo para executar determinadas
otimizaes independentes de mquina.
Depois de pr-processamento, a rvore de anlise enviada para o gerador de cdigo , o
que cria um novo arquivo na lngua-alvo. s vezes, o arquivo recm-criado , ento, o
cargo foi processado para adicionar mquinas otimizaes dependentes.
A Figura 1 mostra graficamente as diferentes partes de um compilador;

Figura 1 Anatomia de um compilador
Os intrpretes so s vezes chamados de mquinas virtuais . Esta situao decorre da
idia de que a CPU realmente um intrprete nvel baixo - ele interpreta o cdigo de
mquina. Um intrprete uma simulao de alto nvel de uma CPU.
Retornar ao incio da pgina Anatomia e Tokenizer

O Tokenizer
O trabalho do tokenizador ler smbolos um de cada vez a partir do fluxo de entrada e
passar as fichas para o analisador. O corao do tokenizador do seguinte tipo:
token_type_enum = (glob_res_word,
con_res_word,
reserved_sym,
identificador,
string_type,
INT_TYPE,
real_type);

registro Token_Type
incio
infile: texto;
cur_str: array [1..80] do char;
cur_str_len: integer;

cur_line: integer;
cur_pos: integer;

type_of_token: token_type_enum;
read_string: char [1..30] do char;
cap_string: char [1..30] do char;
int_val: integer;
float_val: real;
glob_res_word: glob_res_word_type;
con_res_word: con_res_word_type;
res_sym: res_sym_type;
fim; (* Token *)
Uma varivel deste tipo usado para armazenar o token atual. O campo infile a entrada
de transmitir o programa que est sendo analisado realizado em (para aqueles que no
sabem Pascal, arquivos de texto tm o tipo de texto ). O prximo campo a linha atual
que est sendo analisado. mais eficiente para ler arquivos de um pedao de cada vez,
em vez de um personagem de cada vez, por isso uma prtica padro para adicionar um
campo para realizar uma seqncia inteira para o token. Cur_str_len d o comprimento da
string atual;
Se o fluxo a partir de uma memria RAM tampo, em seguida, esses dois domnios
pode ser substitudo com um ponteiro para a posio correcta no tampo.
Os campos cur_line e cur_pos manter o nmero da linha atual ea posio atual em que
linha. Estes dados so utilizados pelo analisador para indicar onde ocorrem erros.
Glob_res_word_type, con_res_word_type e res_sym so enumeraes. As enumeraes
no so dadas aqui, porque eles so especficos idioma (que deve o servio pelo menos
lbio pagamento a ser independente de linguagem aqui) e podem ser muito grandes. O
tokenizador trata de contexto sensveis palavras reservadas como um grupo separado de
palavras globalmente reservados. Cabe ao analisador de decidir o contexto est sendo
analisado e se uma palavra reservada sensvel ao contexto deve ser tratado como uma
palavra reservada ou um identificador.
Existe uma maneira alternativa para lidar com o contexto sensveis palavras reservadas. O
tokenizador pode lidar com todos os identificadores simplesmente como identificadores,
mas fornecer procedimentos adicionais para determinar se um identificador uma palavra
reservada ou globalmente um contexto palavra reservada sensvel. Em seguida, quando o
analisador l um identificador de consulta o tokenizador quanto ao facto de o
identificador um ou o outro. Qual o mtodo j utilizado, sensvel ao contexto palavras
reservadas significa mais trabalho para o analisador. por isso que prefervel fazer
todas as palavras reservadas global.
Read_string contm a cadeia de sinal, uma vez que foi lido a partir do fluxo de entrada,
cap_stream contm a cadeia de sinal aps ter sido capitalizados. Isso essas cadeias
conter apenas o token. Quando o tipo de token uma palavra reservada, identificador ou
seqncia o valor correto ser em um desses campos. Quando o tipo de token inteiro ou
real uma representao de cadeia de valor podem ser encontrados aqui. Desde Pascal no
case sensitive todas as cadeias sero capitalizados como eles so lidos. Isto ir facilitar a
localizao variveis e procedimentos de forma independente caso. Por vezes, no entanto,
a cadeia sem maiscula necessria, tal como quando uma constante de cadeia
encontrado no fluxo de entrada.
Int_val e float_val conter o valor correto quando um inteiro ou real so
lidos. Glob_res_word, con_res_word e res_sym so enumeraes que contm todas as
palavras possveis globalmente reservados, contexto palavras reservadas sensveis e
smbolos reservados, respectivamente.
O tokenizador prximo deve fornecer vrios procedimentos para manipular smbolos. Um
procedimento de inicializao normalmente necessrio para abrir o fluxo de entrada e
encontrar o primeiro token. O analisador vai precisar de um procedimento para ler o
prximo token no comando. Este procedimento mostrado a seguir. O procedimento
parece longo e assustador, mas muito para a frente. A maior parte do espao ocupado
com observaes, e no h nada complicado no prprio cdigo.
procedimento Advance_Token (var token: Token_Type);

var
read_str_idx: integer;
i: integer;

incio
com do smbolo
incio
(* Limpar cordas *)
(* Voc pode ter que fornecer as seguintes *)
(* Procedimento. Verifique os manuais do seu compilador *)
(* Para saber como fazer isso *)
clear_string (cur_str);
clear_string (read_string);
clear_string (cap_string);

(* Encontre incio do prximo token *)
while (cur_str [cur_pos] = '') fazer
incio
(* Se o fim da linha, obter prxima linha *)
if (cur_pos> cur_str_len), em seguida,
incio
readln (infile, cur_str);
(* Voc pode ter que fornecer as seguintes *)
(* Procedimento. Verifique os manuais do seu compilador *)
(* Para saber como fazer isso *)
find_string_length (cur_str_len, cur_str);
cur_pos: = 1;
fim; {If (cur_pos> cur_str_len)}

(* Se o fim do arquivo, o retorno final
arquivo reservados smbolo *)
if (EOF (infile)) ento
incio
type_of_token: = RESERVED_SYMBOL;
res_sym: = END_OF_FILE;
voltar;
fim; {If (EOF (infile))}
fim; {While (cur_str [cur_pos] = '')

(* Copiar token para read_string e cap_string *)
read_str_idx: = 1;
(* Voc tem que fornecer o not_delimiter funo *)
(* Simplesmente testa o carter e retorna true *)
(* Se no est no conjunto de delimitadores *)
while (not_delimiter (cur_str [cur_pos])) fazer
incio
read_str [read_str_idx]: = cur_str [cur_pos];
cap_str [read_str_idx]: =
upcase (cur_str cur_pos []);
read_str_idx: = read_str_idx + 1;
fim; {While (not_delimiter (cur_str [cur_pos]))}

(* Determinar token de tipo *)
(* token de um identificador? *)
if (cap_string [1]> = 'A') e
(Cap_string [1] <= 'Z'), ento
incio
(* smbolo de uma palavra reservada global? *)

(* Glob_res_word_table uma tabela (possivelmente um *)
(* rvore de procura binria) de palavras reservadas. *)
(* Find_in_table retorna o valor de enumerao *)
(* Associado com a palavra reservada se um *)
(* Palavra globalmente reservada. Caso contrrio, retorna *)
(* Indefinido. *)
find_in_table (glob_res_word_table,
cap_string,
glob_res_word);
Se no for (glob_res_word = indefinido), em seguida
incio
type_of_token: = GLOBAL_RES_WORD;
voltar;
fim; {If NOT (glob_res_word = indefinido)}

(* uma palavra reservada contexto sensvel smbolo? *)
find_in_table (con_res_word_table,
cap_string,
con_res_word);
Se no for (con_res_word = indefinido), em seguida
incio
type_of_token: = CONTEXT_RES_WORD;
voltar;
fim; {If NOT (con_res_word = indefinido)}

(* Se no for uma palavra reservada global ou um contexto *)
(* Palavra reservada sensvel, ele deve ser um *)
(* Identificador *)

type_of_token: = INDENTIFIER;
voltar;
fim; {If (cap_string [1]> = 'A') e
(Cap_string [1] <= 'Z')}

(* token de um nmero? *)
if ((cap_string [1]> = "0") e
(Cap_string [1] <= "9")) ou
(Cap_string [1] = '-' ento
(* um sinal real ou inteiro? *)
para i: = 2 a read_str_idx fazer
if (cap_string [i] = '.') ou
(Cap_string [i] = 'E'), ento
incio
(*, Mais uma vez, voc pode ter que fornecer *)
(* A seguinte funo de traduzir *)
(* A string para um real *)
float_val: = string_to_real (cap_string);
type_of_token: = real_type;
voltar;
fim; {If (cap_string [i] = '.') Ou
(Cap_string [i] = 'E')}
mais
incio
int_val: = string_to_int (cap_string);
type_of_token: = INT_TYPE;
voltar;
fim;

(* token de uma string? *)
if (cap_string [1] = '' ''), ento (* esta sintaxe parece
estranho, mas parece
trabalhar! *)
incio
type_of_token: = string_type;
voltar;
fim;

(* smbolo de um smbolo reservado? *)
find_in_table (res_sym_table,
cap_string,
res_sym);
Se no for (res_sym = indefinido), em seguida
incio
type_of_token: = reserved_sym;
voltar;
fim;

(*, Se o tipo de sinal no foi encontrado ainda *)
(* Ele deve ser um tipo desconhecido *)
(* Este um erro lexical *)
type_of_token: = UNKNOWN_TOKEN_TYPE;

fim; {Com o token fazer}
fim; {Procedimento advance_token}
Este procedimento , na verdade pginas apenas cerca de dois e meio de comprimento, e
sem comentrios seria provavelmente inferior a dois. Alguns engenheiros de software
salientar que um procedimento no deve ser mais do que uma pgina de
comprimento. Esses "engenheiros" so geralmente professores universitrios que nunca
se aventuraram alm dos muros de suas torres de marfim. Na vida real, um procedimento
de dois anos e meio pgina considerada no muito longo. Enquanto todo o
procedimento o mesmo nvel lgico, ser legvel e fcil de compreender.
A lgica geral do procedimento deve ser fcil ver por l-lo (ou seus
comentrios). Primeiro, encontrar o prximo token. Isto pode envolver a leitura da
prxima linha do fluxo de entrada. Em seguida, copiar o token em read_string e
cap_string. Em seguida, partimos para determinar o tipo de token. Se o token comea
com uma letra, um identificador, palavra reservada global ou contexto palavra reservada
sensvel. Para determinar se o identificador uma palavra sensvel ou global contexto
reservados, mesas so consultados que contm cada tipo de palavra. Caso o identificador
se encontra em uma das tabelas, a enumerao associado devolvido.
Note-se que um tokenizador muito flexvel pode ser criado usando cordas em vez de
enumeraes e mantendo as palavras reservadas e smbolos em um arquivo. Quando o
tokenizador inicializado as palavras e smbolos reservados podem ser lidos nas
tabelas. Desta forma, a linguagem que o tokenizador funciona no pode ser mudado
simplesmente mudando os arquivos. No cdigo-fonte precisaria ser alterado. O
inconveniente que o analisador precisa realizar comparaes. Se as cordas so usados
em vez de enumeraes, corda menos eficiente compara teria que ser usado em vez de
comparaes mais eficientes nas contagens.
Se o primeiro caracter do token um dgito o token um nmero, ou se o primeiro
caractere um sinal de menos o token um nmero negativo. Se o token um nmero
que pode ser um real ou um inteiro. Se ele contm um ponto decimal ou a letra E (que
indica a notao cientfica), ento uma verdadeira, caso contrrio, um inteiro. Observe
que isso pode estar mascarando um erro lexical. Se o arquivo contm um smbolo "9abc"
o lxico vai transform-lo em um nmero inteiro 9 provvel que qualquer erro ir
causar um erro de sintaxe que o analisador pode pegar, no entanto, o lxico
provavelmente deve ser reforada para olhar para essas coisas . Isso far com que as
mensagens de erro mais legvel para o usurio.
Se o token no um nmero que poderia ser uma string. Cordas em Pascal so
identificadas por aspas simples. E, finalmente, se o token no uma string que deve ser
um smbolo reservados. Por convenincia, os smbolos so reservados armazenados no
mesmo tipo de mesa como as palavras reservadas sensveis globais e do contexto. Se o
sinal no encontrado nesta tabela que um erro lexical. O tokenizador no tratar os
erros em si, por isso simplesmente notifica o analisador que um tipo de token no
identificado foi encontrado. O analisador ir lidar com o erro.
==================================================
======================
Eu j mencionei o programa YACC, que converte uma gramtica a um parser. Isto
possvel porque a tarefa de converter uma gramtica de analisadores de cdigo muito
mecnico. Acontece que a criao de um tokenizador para uma dada lngua, tambm
bastante mecnica, e pode ser feito pelo software. O programa clssico para fazer isso
chamado de Lex . (Este link um excelente tutorial sobre o programa.) Lex e YACC
foram projetados para trabalhar em conjunto, e so muitas vezes utilizados em conjunto
para criar compiladores.

Anda mungkin juga menyukai