P. 1
Fases da compilação

Fases da compilação

|Views: 495|Likes:

More info:

Published by: brunosantosmonteiro2084 on May 09, 2012
Direitos Autorais:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as DOCX, PDF, TXT or read online from Scribd
See more
See less

08/28/2014

pdf

text

original

Fases da compilação Análise léxica Ver artigo principal: Análise léxica A análise léxica é a primeira fase do compilador.

[21] 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.[22] É 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.[23] Existem disponíveis uma série de geradores automáticos de analisadores léxicos, como por exemplo, o lex. O objetivo dos geradores automáticos é limitar o esforço de programação de um analisador léxico especificando-se apenas os tokens a ser reconhecidos.[24]

Análise léxica - A fase de análise léxica (varredora) tem por objetivo ler o programa fonte e transformar seqüências de caracteres em uma representação interna, denominada itens léxicos. A saída é um fluxo do símbolo. As expressões regulares são usadas para definir o símbolo reconhecido por um varredor (ou pelo analisador lexical). Por exemplo, suponha a expressão abaixo, descrita em Pascal: Exp := (A + B) * 1.5; Os itens léxicos contidos nesta expressão, são: Exp, :=, (, A, +, B, ), *, 1.5 e ;. Os itens léxicos a serem reconhecidos pelo analisador léxico são determinados pela gramática da linguagem-fonte. Deste modo, caso um item léxico não seja definido por esta gramática, um erro léxico é gerado. Por exemplo, suponhamos que uma linguagem só suporte valores inteiros. Então o valor 1.5 iria ocasionar um erro, o qual deverá ser tratado.

Análise sintática

Ver artigo principal: Análise sintática (computação) A análise sintática, ou análise gramatical é o processo de se determinar se uma cadeia de símbolos léxicos pode ser gerada por uma gramática.[25] O analisador sintático é o cerne do compilador, responsável por verificar se os símbolos contidos no programa fonte formam um programa válido, ou não.[26] No caso de analisadores sintáticos top-down, temos a opção de escrevê-los à mão ou gerá-los de forma automática, mas os analisadores bottom-up só podem ser gerados automaticamente.[27] A maioria dos métodos de análise sintática, cai em uma dessas duas classes denominadas top-down e bottom-up.[28] Entre os métodos top-down os

seu programa passará pela análise léxica (writeln e identificador existem).mais importantes são a análise sintática descendente recursiva e a análise sintática preditiva não-recursiva.[33] A análise semântica .[30] As gramáticas livres de contexto não são suficientemente poderosas para descrever uma série de construções das linguagens de programação. Análise Sintática . funções e procedimentos. que informa a necessidade de um abre-parênteses logo após esta procedure. O papel do analisador semântico é prover métodos pelos quais as estruturas construídas pelo analisador sintático possam ser avaliadas ou executadas. análise sintática LR canônico. regras de visibilidade e consistência de tipos. os conflitos entre tipos.responsabiliza-se por traduzir os Tokens. um espaço.[31] É papel do analisador semântico assegurar que todas as regras sensíveis ao contexto da linguagem estejam analisadas e verificadas quanto à sua validade. a ausência de declarações de variáveis. É nesta fase que são detectadas. e descobrir a relação de uns com os outros. Geração de código intermediário Exemplo de código de três endereços e um DAG correspondente para uma expressão aritimética Ver artigo principal: Geração de código . Uma das tarefas mais importantes é a verificação de tipos. o Yacc. gerada pelo analisador sintático em busca de inconsistências semânticas. por exemplo.[25] Existem disponíveis uma série de geradores automáticos de analisadores sintáticos. Análise semântica Ver artigo principal: Análise semântica As análises léxica e sintática não estão preocupadas com o significado ou semântica dos programas que elas processam. análise sintática LALR e análise sintática SLR. Um exemplo de tarefa própria do analisador semântico é a checagem de tipos de variáveis em expressões. e um identificador. ou análise de contexto. mas não passará pela análise sintática.[29] como por exemplo. como por exemplo regras de escopo. Entre os métodos de análise sintática bottom-up os mais importantes são a análise sintática de precedência de operadores.analisa a árvore sintática para a informação context-sensitive. o Bison e o JavaCC. que consiste em uma gramática livre de contexto acrescentada de um conjunto finito de atributos e um conjunto finito de predicados sobre estes atributos. Se você escreve writeln.[32] Um dos mecanismos comumente utilizados por implementadores de compiladores é a Gramática de Atributos.

[36]Outras representações de código intermediário comumente usadas são as triplas.[38] A fase de otimização . substituição de operações (multiplicação por shifts).permite a geração de instruções para uma máquina abstrata. Estas técnicas consistem em detectar padrões dentro do código produzido e substituí-los por códigos mais eficientes.[36] Entre as técnicas usadas estão a substituição de expressões que podem ser avaliadas durante o tempo de compilação pelos seus valores calculados.[32] Uma das técnicas de optimização mais eficazes e independente de máquina é a otimização de laços. normalmente em código de três endereços. Este esquema de representação de código intermediário é preferido por diversos compiladores. Esta forma intermediária não é executada diretamente pela máquina alvo. Esta linguagem intermediária é mais próxima da linguagem objeto do que o código fonte. A e B são operandos e op uma operação qualquer. eliminação de sub-expressões redundantes.analisa o código no formato intermediário e tenta melhorá-lo de tal forma que venha a resultar um código de máquina mais rápido em tempo de execução. pois laços internos são bons candidatos para melhorias. é possível mover estas computações para fora dos mesmos reduzindo processamento. argumento 1. argumento 2 e. entre outras. usando as réguas que denotam a semântica da linguagem-fonte. os grafos acíclicos dirigidos(DAG) e a notação polonesa. um código que execute com bastante eficiência. produzido durante a fase de geração de código com objetivo de produzir.[34] Um tipo popular de linguagem intermediária é conhecido como código de três endereços.[37] A fase de geração de código intermediário . Por exemplo. ocorre a transformação da árvore sintática em uma representação intermediária do código fonte.Na fase de geração de código intermediário.[23] Várias técnicas e várias tarefas se reúnem sob o nome de Optimização. resultado).[35] Neste tipo de código uma sentença típica tem a forma X := A op B. através de algumas técnicas.[32] O nome optimizador deve sempre ser encarado com cuidado. Uma forma prática de representar sentenças de três endereços é através do uso de quádruplas (operador. onde X. principalmente aqueles que executam extensivas otimizações de código. (similares as quádruplas exceto pelo fato de que os resultados não são nomeados explicitamente) as árvores. desmembramento de laços. uma vez que o código intermediário pode ser rearranjado de uma maneira conveniente com facilidade. mas ainda permite uma manipulação mais fácil do que se código assembly ou código de máquina fosse utilizado. Optimização de código A Otimização de código é a estratégia de examinar o código intermediário. . mais adequadas a fase de otimização. em caso de computações fixas dentro de laços. pois não se pode criar um programa que leia um programa P e gere um programa P´ equivalente sendo melhor possível segundo o critério adotado. Uma das tarefas executadas pelo otimizador é a detecção e a eliminação de movimento de dados redundantes e a repetição de operações dentro de um mesmo bloco de programa.

Um exemplo típico é o da divisão por zero. As tarefas relacionadas ao tratamento de erros consitem em detectar cada erro. ocorrem durante a execução e estão .[36] Nem todas as técnicas de optimização são independentes da arquitetura da máquina-alvo. erros de execução e erros de limite. por exemplo. O código produzido pelo compilador deve se aproveitar dos recursos especiais de cada máquinaalvo. A geração de um bom código objeto é difícil devido aos detalhes particulares das máquinas para os quais o código é gerado. Nesta etapa as localizações de memória são selecionadas para cada uma das variáveis usadas pelo programa.[41] Os erros léxicos ocorrem quando um token identificado não pertence a gramática da linguagem fonte. erros na elaboração do programa a ser compilado. Contudo é uma fase importante. etc. Os erros sintáticos ocorrem quando alguma estrutura de frase não está de acordo com a gramática. quando o programa já está sendo executado. pois uma boa geração de código pode ser.[32] Segundo Aho. Então. uma sequência de instruções de máquina relocáveis.tem como objetivo analisar o código já otimizado é a gerar o um código objeto definitivo para uma máquina alvo. traduzidas numa seqüência de instruções de máquina que realizam a mesma tarefa. Tratamento de erros Tratamento de erro de execução em uma aplicação Java no Elipse O tratamento de erros está voltado a falhas devido a muitas causas: erros no compilador. erros não independentes de contexto (semânticos). duas vezes mais rápida que um algoritmo de geração de código ineficiente.Geração de código final Ver artigo principal: Geração de código A fase de geração de código final é a última fase da compilação. reportá-lo ao usuário e possivelmente fazer algum reparo para que o processamento possa continuar. erros no ambiente (hardware. Os erros de execução ocorrem após a compilação. dados incorretos. um programa em linguagem assembly ou um programa em outra linguagem. erros sintáticos. Os erros não indepenentes de contexto em geral são associados a não declaração de objetos como variáveis e erros de tipos. o código objeto pode ser uma sequência de instruções absolutas de máquina. Os erros de limite.[40] Os erros podem ser classificados em erros léxicos. como por exemplo parênteses sem correspondência. Normalmente este código objeto é um código de máquina relocável ou um código de montagem. sistema operacional).[39] A fase de geração de código . as instruções intermediárias são. Optimizações dependentes da máquina necessitam de informações tais como os limites e os recursos especiais da máquina-alvo a fim de produzir um código mais compacto e eficiente. cada uma.

[41] Alguns compiladores encerram o processo de tradução logo ao encontrar o primeiro erro do programa-fonte. a técnica de panic-mode que procura em tabelas sintáticas em busca de símbolos válidos na entrada. estouro de pilha. porém. por exemplo. este último não sabe quais símbolos são esperados na entrada. somente os que já foram processados.[44] . detectam o maior número possível de erros visando diminuir o número de compilações.[42] A recuperação de erros em analisadores sintáticos top-down é mais fácil de implementar do que em analisadores bottom-up. por exemplo) seja encontrado. Pode-se usar neste caso técnicas como.[43] Nesta técnica se descartam símbolos da entrada até que um delimitador (como um ponto e vírgula. como por exemplo.[43] O problema é que diferente de um analisador top-down. Compiladores mais sofisticados. Esta é uma política de fácil implementação. O analisador apaga as entradas da pilha até que encontre uma entrada que permita que o processo de análise prossiga em diante.relacionados as características da máquina na qual o programa está sendo executado.

You're Reading a Free Preview

Descarregar
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->