SlideShare una empresa de Scribd logo
1 de 8
Compilador
Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa
    Nota: Compilação redireciona para este artigo. Se procura por compilação musical,
veja Coletânea musical.




Uma captura de tela do compilador GCC versão 4.0.2 rodando em uma janela xterm.
Um programa simples está sendo compilado e então executado

Um compilador é um programa de computador (ou um grupo de programas) que, a
partir de um código fonte escrito em uma linguagem compilada, cria um programa
semanticamente equivalente, porém escrito em outra linguagem, código objeto.[1] Ele é
chamado compilador por razões históricas; nos primeiros anos da programação
automática, existiam programas que percorriam bibliotecas de subrotinas e as reunia
juntas, ou compilava,[Nota 1] as subrotinas necessárias para executar uma determinada
tarefa.[2][3]

O nome "compilador" é usado principalmente para os programas que traduzem o código
fonte de uma linguagem de programação de alto nível para uma linguagem de
programação de baixo nível (por exemplo, Assembly ou código de máquina). Contudo
alguns autores citam exemplos de compiladores que traduzem para linguagens de alto
nível como C.[4] Para alguns autores um programa que faz uma tradução entre
linguagens de alto nível é normalmente chamado um tradutor, filtro[5] ou conversor de
linguagem. Um programa que traduz uma linguagem de programação de baixo nível
para uma linguagem de programação de alto nível é um descompilador.[6] Um programa
que faz uma tradução entre uma linguagem de montagem e o código de máquina é
denominado montador (assembler).[5] Um programa que faz uma tradução entre o
código de máquina e uma linguagem de montagem é denominado desmontador
(disassembler).[6] Se o programa compilado pode ser executado em um computador cuja
CPU ou sistema operacional é diferente daquele em que o compilador é executado, o
compilador é conhecido como um compilador cruzado.[7]


Índice
       1 História
       2 Características
       3 Fases da compilação
          o 3.1 Análise léxica
          o 3.2 Análise sintática
o   3.3 Análise semântica
           o   3.4 Geração de código intermediário
           o   3.5 Optimização de código
           o   3.6 Geração de código final
       4 Tratamento de erros
       5 Ver também
       6 Notas
       7 Referências
       8 Bibliografia
       9 Ligações externas



História




Grace Hopper em 1984

Os softwares para os primeiros computadores foram escritos principalmente em
linguagem assembly por muitos anos. As linguagens de alto nível de programação não
foram inventadas até que os benefícios de ser capaz de reutilizar software em diferentes
tipos de CPUs passassem a ser significativamente maiores do que o custo de se escrever
um compilador. A capacidade de memória muito limitada capacidade dos primeiros
computadores também criava muitos problemas técnicos na implementação de um
compilador.

No final da década de 1950, as linguagens de programação independentes de máquina
foram propostas. Posteriormente, vários compiladores experimentais foram
desenvolvidos. O primeiro compilador foi escrito por Grace Hopper,[8] em 1952, para a
linguagem de programação A-0.[9] Antes de 1957, foram desenvolvidos esforços e
várias contribuições ao desenvolvimento de linguagens de alto nível foram feitas. Entre
estes, o desenvolvimento da Short Code (UNIVAC), Speedcoding no IBM 701,[10][11] o
Whirlwind, o BACAIC e o PRINT.[12] A equipe de desenvolvimento do FORTRAN
liderada por John Backus na IBM é geralmente creditada como tendo introduzido o
primeiro compilador completo em 1957 (embora tenha ocorrido simultaneamente o
desenvolvimento do algebraic translator de Laning e Zierler[9]). O COBOL é um
exemplo de uma linguagem da primeira geração que compilava em múltiplas
arquiteturas, em 1960.[13]
Em muitos domínios de aplicação a idéia de usar uma linguagem de alto nível
rapidamente ganhou força. Por causa da funcionalidade de expansão apoiada por
linguagens de programação recentes e a complexidade crescente de arquiteturas de
computadores, os compiladores tornaram-se mais e mais complexos.

Os primeiros compiladores foram escritos em linguagem assembly. O primeiro
compilador de auto-hospedagem - capaz de compilar seu próprio código-fonte em uma
linguagem de alto nível - foi criado para o Lisp por Tim Hart e Levin Mike no MIT em
1962.[14]

Características




O processo da compilação

Normalmente, o código fonte é escrito em uma linguagem de programação de alto nível,
com grande capacidade de abstração, e o código objeto é escrito em uma linguagem de
baixo nível,[15] como uma sequência de instruções a ser executada pelo
microprocessador.

O processo de compilação é composto de análise e síntese.[16] A análise tem como
objetivo entender o código fonte e representá-lo em uma estrutura intermediária. A
síntese constrói o código objecto a partir desta representação intermediária.

A análise pode ser subdividida ainda em análise léxica, análise sintática, análise
semântica e geração de código intermediário. É também conhecida como front end.[16] A
síntese pode ter mais variações de um compilador a outro, podendo ser composta pelas
etapas de optimização de código e geração de código final (ou código de máquina),
sendo somente esta última etapa é obrigatória. É também conhecida como back end.[16]

Classicamente, um compilador traduz um programa de uma linguagem textual
facilmente entendida por um ser humano para uma linguagem de máquina, específica
para um processador e sistema operacional. Atualmente, porém, são comuns
compiladores que geram código para uma máquina virtual que é, depois, interpretada
por um interpretador.

Em linguagens híbridas, o compilador tem o papel de converter o código fonte em um
código chamado de byte code, que é uma linguagem de baixo nível. Um exemplo deste
comportamento é o do compilador da linguagem Java que, em vez de gerar código da
máquina hospedeira (onde se está executando o compilador), gera código chamado Java
Bytecode.[17]

Um compilador é chamado de Just-in-time compiler (JIT) quando seu processo de
compilação acontece apenas quando o código é chamado.[18] Um JIT pode fazer
otimizações às instruções a medida que as compila.[18]

Muitos compiladores incluem um pré-processador. Um pré-processador é um programa
separado, ativado pelo compilador antes do início do processo de tradução.[19]
Normalmente é responsável por mudanças no código fonte destinadas de acordo com
decisões tomadas em tempo de compilação. Por exemplo, um programa em C permite
instruções condicionais para o pré-processador que podem incluir ou não parte do
código caso uma assertiva lógica seja verdadeira ou falsa, ou simplesmente um termo
esteja definido ou não. Tecnicamente, pré-processadores são muito mais simples que
compiladores e são vistos, pelos desenvolvedores, como programas à parte, apesar dessa
visão não ser necessariamente compartilhada pelo usuário.

Outra parte separada do compilador que muitos usuários vêem como integrada é o
linker, cuja função é unir vários programas já compilados de uma forma independente e
unificá-los em um programa executável.[20] Isso inclui colocar o programa final em um
formato compatível com as necessidades do sistema operacional para carregá-lo em
memória e colocá-lo em execução.

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 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 mais importantes são a análise sintática
descendente recursiva e a análise sintática preditiva não-recursiva. 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, análise sintática LR canônico, análise sintática LALR e análise sintática
SLR.[25] Existem disponíveis uma série de geradores automáticos de analisadores
sintáticos,[29] como por exemplo, o Yacc, o Bison e o JavaCC.

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. O papel do analisador semântico é prover métodos pelos
quais as estruturas construídas pelo analisador sintático possam ser avaliadas ou
executadas.[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, como por exemplo
regras de escopo, regras de visibilidade e consistência de tipos.[31] É papel do analisador
semântico assegurar que todas as regras sensíveis ao contexto da linguagem estejam
analisadas e verificadas quanto à sua validade. Um exemplo de tarefa própria do
analisador semântico é a checagem de tipos de variáveis em expressões.[32] Um dos
mecanismos comumente utilizados por implementadores de compiladores é a Gramática
de Atributos, 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.[33]

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

Na fase de geração de código intermediário, ocorre a transformação da árvore sintática
em uma representação intermediária do código fonte. Esta linguagem intermediária é
mais próxima da linguagem objeto do que o código fonte, mas ainda permite uma
manipulação mais fácil do que se código assembly ou código de máquina fosse
utilizado.[34] Um tipo popular de linguagem intermediária é conhecido como código de
três endereços.[35] Neste tipo de código uma sentença típica tem a forma X := A op B,
onde X, A e B são operandos e op uma operação qualquer. Uma forma prática de
representar sentenças de três endereços é através do uso de quádruplas (operador,
argumento 1, argumento 2 e, resultado). Este esquema de representação de código
intermediário é preferido por diversos compiladores, principalmente aqueles que
executam extensivas otimizações de código, uma vez que o código intermediário pode
ser rearranjado de uma maneira conveniente com facilidade.[36]Outras representações de
código intermediário comumente usadas são as triplas, (similares as quádruplas exceto
pelo fato de que os resultados não são nomeados explicitamente) as árvores, os grafos
acíclicos dirigidos(DAG) e a notação polonesa.[37]

Optimização de código

A Otimização de código é a estratégia de examinar o código intermediário, produzido
durante a fase de geração de código com objetivo de produzir, através de algumas
técnicas, um código que execute com bastante eficiência.[32] O nome optimizador deve
sempre ser encarado com cuidado, 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.[23] Várias técnicas e várias tarefas se reúnem sob o nome de
Optimização. 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, eliminação de sub-expressões redundantes,
desmembramento de laços, substituição de operações (multiplicação por shifts), entre
outras.[32] Uma das técnicas de optimização mais eficazes e independente de máquina é
a otimização de laços, pois laços internos são bons candidatos para melhorias. Por
exemplo, em caso de computações fixas dentro de laços, é possível mover estas
computações para fora dos mesmos reduzindo processamento.[38]

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. 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. Contudo, é uma fase importante, pois uma boa geração de código pode
ser, por exemplo, duas vezes mais rápida que um algoritmo de geração de código
ineficiente.[36] Nem todas as técnicas de optimização são independentes da arquitetura
da máquina-alvo. 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. O código produzido pelo compilador deve se aproveitar dos
recursos especiais de cada máquina-alvo.[32] Segundo Aho, o código objeto pode ser
uma sequência de instruções absolutas de máquina, uma sequência de instruções de
máquina relocáveis, um programa em linguagem assembly ou um programa em outra
linguagem.[39]

Tratamento de erros




Tratamento de erro de execução em uma aplicação Java no Eclipse

O tratamento de erros está voltado a falhas devido a muitas causas: erros no compilador,
erros na elaboração do programa a ser compilado, erros no ambiente (hardware, sistema
operacional), dados incorretos, etc. As tarefas relacionadas ao tratamento de erros
consitem em detectar cada erro, reportá-lo ao usuário e possivelmente fazer algum
reparo para que o processamento possa continuar.[40]

Os erros podem ser classificados em erros léxicos, erros sintáticos, erros não
independentes de contexto (semânticos), erros de execução e erros de limite.[41] Os erros
léxicos ocorrem quando um token identificado não pertence a gramática da linguagem
fonte. Os erros sintáticos ocorrem quando alguma estrutura de frase não está de acordo
com a gramática, como por exemplo parênteses sem correspondência. Os erros não
independentes de contexto em geral são associados a não declaração de objetos como
variáveis e erros de tipos. Os erros de execução ocorrem após a compilação, quando o
programa já está sendo executado. Um exemplo típico é o da divisão por zero. Os erros
de limite, ocorrem durante a execução e estão relacionados as características da
máquina na qual o programa está sendo executado, como por exemplo, estouro de
pilha.[41]

Alguns compiladores encerram o processo de tradução logo ao encontrar o primeiro erro
do programa-fonte. Esta é uma política de fácil implementação. Compiladores mais
sofisticados, porém, 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.[43] O problema é que diferente de um analisador top-
down, este último não sabe quais símbolos são esperados na entrada, somente os que já
foram processados. Pode-se usar neste caso técnicas como, por exemplo, a técnica de
panic-mode que procura em tabelas sintáticas em busca de símbolos válidos na
entrada.[43] Nesta técnica se descartam símbolos da entrada até que um delimitador
(como um ponto e vírgula, por exemplo) seja encontrado. O analisador apaga as
entradas da pilha até que encontre uma entrada que permita que o processo de análise
prossiga em diante.[44]

Ver também

Más contenido relacionado

La actualidad más candente

Int. sistemas de informação iii
Int. sistemas de informação iiiInt. sistemas de informação iii
Int. sistemas de informação iiiRay Fran Pires
 
Material iae aula 2
Material iae   aula 2Material iae   aula 2
Material iae aula 2negasousa
 
Linguágens de programação
Linguágens de programaçãoLinguágens de programação
Linguágens de programaçãoAlbertoVach
 
Conceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoConceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoSidney Roberto
 
Jogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpJogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpPedro Vuvu Alvaro
 
Cucumber: um breve review
Cucumber: um breve reviewCucumber: um breve review
Cucumber: um breve reviewLaís Berlatto
 
055 A 094 Material Auxiliar Para Curso AvançAdo I Msp430
055 A 094   Material Auxiliar Para Curso AvançAdo I Msp430055 A 094   Material Auxiliar Para Curso AvançAdo I Msp430
055 A 094 Material Auxiliar Para Curso AvançAdo I Msp430Texas Instruments
 
Programação de Microprocessadores
Programação de MicroprocessadoresProgramação de Microprocessadores
Programação de MicroprocessadoresDiogo Silva
 
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)Leinylson Fontinele
 
Aula 03 isc -softwares-hardwares-arquiteturas
Aula 03   isc -softwares-hardwares-arquiteturasAula 03   isc -softwares-hardwares-arquiteturas
Aula 03 isc -softwares-hardwares-arquiteturasFábio Andrade
 
Linguagem C Entendendo a Programação
Linguagem C Entendendo a ProgramaçãoLinguagem C Entendendo a Programação
Linguagem C Entendendo a ProgramaçãoMonike Santos
 

La actualidad más candente (19)

Linguagem da programação
Linguagem da programaçãoLinguagem da programação
Linguagem da programação
 
Int. sistemas de informação iii
Int. sistemas de informação iiiInt. sistemas de informação iii
Int. sistemas de informação iii
 
Linguagens de programação
Linguagens de programaçãoLinguagens de programação
Linguagens de programação
 
Material iae aula 2
Material iae   aula 2Material iae   aula 2
Material iae aula 2
 
Linguágens de programação
Linguágens de programaçãoLinguágens de programação
Linguágens de programação
 
Pascal 70
Pascal 70Pascal 70
Pascal 70
 
Compiladores
CompiladoresCompiladores
Compiladores
 
Conceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de ProgramaçãoConceitos Iniciais de Linguagens de Programação
Conceitos Iniciais de Linguagens de Programação
 
Jogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpJogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharp
 
Cucumber: um breve review
Cucumber: um breve reviewCucumber: um breve review
Cucumber: um breve review
 
055 A 094 Material Auxiliar Para Curso AvançAdo I Msp430
055 A 094   Material Auxiliar Para Curso AvançAdo I Msp430055 A 094   Material Auxiliar Para Curso AvançAdo I Msp430
055 A 094 Material Auxiliar Para Curso AvançAdo I Msp430
 
Lp m2(parte1)
Lp m2(parte1)Lp m2(parte1)
Lp m2(parte1)
 
Programação de Microprocessadores
Programação de MicroprocessadoresProgramação de Microprocessadores
Programação de Microprocessadores
 
Aplicativo aula01
Aplicativo aula01Aplicativo aula01
Aplicativo aula01
 
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)
Introdução à Computação Aula 09 - Algoritmos (Linguagens de Programação)
 
Auto cad visual lisp iv
Auto cad visual lisp ivAuto cad visual lisp iv
Auto cad visual lisp iv
 
Aula 03 isc -softwares-hardwares-arquiteturas
Aula 03   isc -softwares-hardwares-arquiteturasAula 03   isc -softwares-hardwares-arquiteturas
Aula 03 isc -softwares-hardwares-arquiteturas
 
Lp m2
Lp m2Lp m2
Lp m2
 
Linguagem C Entendendo a Programação
Linguagem C Entendendo a ProgramaçãoLinguagem C Entendendo a Programação
Linguagem C Entendendo a Programação
 

Similar a Compiladores: introdução e características

Construção de compiladores - introducao Compilador.pdf
Construção de compiladores - introducao Compilador.pdfConstrução de compiladores - introducao Compilador.pdf
Construção de compiladores - introducao Compilador.pdfGerhard Saboia
 
Sistemas Operacionais - Gnu/Linux Instalando Programas
Sistemas Operacionais - Gnu/Linux Instalando ProgramasSistemas Operacionais - Gnu/Linux Instalando Programas
Sistemas Operacionais - Gnu/Linux Instalando ProgramasLuiz Arthur
 
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdf
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdfparadigmasdlsksmmskskkekekekekedmmmdmdmmf.pdf
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdfAndreiaCristinaFlore
 
Aula 03 - Interpretador [mr_@@@@@].pdf
Aula 03 - Interpretador [mr_@@@@@].pdfAula 03 - Interpretador [mr_@@@@@].pdf
Aula 03 - Interpretador [mr_@@@@@].pdfmouzinhoconcursos
 
Algoritmia para o site do 10gi marcelo e ricardo
Algoritmia para o site do 10gi marcelo e ricardoAlgoritmia para o site do 10gi marcelo e ricardo
Algoritmia para o site do 10gi marcelo e ricardozedaesquina98
 
Jogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpJogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpMarcio Chiaveli
 
Linguagen..
Linguagen..Linguagen..
Linguagen..essa
 
Execução de programas
Execução de programasExecução de programas
Execução de programasMattheusAnd07
 
Apostila de Linguagem C
Apostila de Linguagem CApostila de Linguagem C
Apostila de Linguagem CDaniel Barão
 
Módulo 5 Arquitetura de Computadores
Módulo 5 Arquitetura de ComputadoresMódulo 5 Arquitetura de Computadores
Módulo 5 Arquitetura de ComputadoresLuis Ferreira
 
Linguagens de programação 03-12-09
Linguagens de programação   03-12-09Linguagens de programação   03-12-09
Linguagens de programação 03-12-09essa
 
Linguagens de programação 03-12-09
Linguagens de programação   03-12-09Linguagens de programação   03-12-09
Linguagens de programação 03-12-09essa
 
Noções Básicas do Software dos Computadores Digitais
Noções Básicas do Software dos Computadores DigitaisNoções Básicas do Software dos Computadores Digitais
Noções Básicas do Software dos Computadores DigitaisHenry Raúl González Brito
 

Similar a Compiladores: introdução e características (20)

Paradigmas de Linguagem
Paradigmas de LinguagemParadigmas de Linguagem
Paradigmas de Linguagem
 
Construção de compiladores - introducao Compilador.pdf
Construção de compiladores - introducao Compilador.pdfConstrução de compiladores - introducao Compilador.pdf
Construção de compiladores - introducao Compilador.pdf
 
Apostila complementar
Apostila complementarApostila complementar
Apostila complementar
 
Apostila c
Apostila cApostila c
Apostila c
 
Sistemas Operacionais - Gnu/Linux Instalando Programas
Sistemas Operacionais - Gnu/Linux Instalando ProgramasSistemas Operacionais - Gnu/Linux Instalando Programas
Sistemas Operacionais - Gnu/Linux Instalando Programas
 
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdf
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdfparadigmasdlsksmmskskkekekekekedmmmdmdmmf.pdf
paradigmasdlsksmmskskkekekekekedmmmdmdmmf.pdf
 
Apostila de C# & Asp.Net
Apostila de C# & Asp.NetApostila de C# & Asp.Net
Apostila de C# & Asp.Net
 
Aula 03 - Interpretador [mr_@@@@@].pdf
Aula 03 - Interpretador [mr_@@@@@].pdfAula 03 - Interpretador [mr_@@@@@].pdf
Aula 03 - Interpretador [mr_@@@@@].pdf
 
Algoritmia para o site do 10gi marcelo e ricardo
Algoritmia para o site do 10gi marcelo e ricardoAlgoritmia para o site do 10gi marcelo e ricardo
Algoritmia para o site do 10gi marcelo e ricardo
 
Jogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharpJogos pe logica_aplicada_apostila_c_sharp
Jogos pe logica_aplicada_apostila_c_sharp
 
Linguagen..
Linguagen..Linguagen..
Linguagen..
 
Execução de programas
Execução de programasExecução de programas
Execução de programas
 
Apostila de Linguagem C
Apostila de Linguagem CApostila de Linguagem C
Apostila de Linguagem C
 
Módulo 5 Arquitetura de Computadores
Módulo 5 Arquitetura de ComputadoresMódulo 5 Arquitetura de Computadores
Módulo 5 Arquitetura de Computadores
 
Linguagens de programação 03-12-09
Linguagens de programação   03-12-09Linguagens de programação   03-12-09
Linguagens de programação 03-12-09
 
Linguagens de programação 03-12-09
Linguagens de programação   03-12-09Linguagens de programação   03-12-09
Linguagens de programação 03-12-09
 
Noções Básicas do Software dos Computadores Digitais
Noções Básicas do Software dos Computadores DigitaisNoções Básicas do Software dos Computadores Digitais
Noções Básicas do Software dos Computadores Digitais
 
Linguagem da programação
Linguagem da programaçãoLinguagem da programação
Linguagem da programação
 
Linguagem c
Linguagem cLinguagem c
Linguagem c
 
Apostila chardwere
Apostila chardwereApostila chardwere
Apostila chardwere
 

Compiladores: introdução e características

  • 1. Compilador Origem: Wikipédia, a enciclopédia livre. Ir para: navegação, pesquisa Nota: Compilação redireciona para este artigo. Se procura por compilação musical, veja Coletânea musical. Uma captura de tela do compilador GCC versão 4.0.2 rodando em uma janela xterm. Um programa simples está sendo compilado e então executado Um compilador é um programa de computador (ou um grupo de programas) que, a partir de um código fonte escrito em uma linguagem compilada, cria um programa semanticamente equivalente, porém escrito em outra linguagem, código objeto.[1] Ele é chamado compilador por razões históricas; nos primeiros anos da programação automática, existiam programas que percorriam bibliotecas de subrotinas e as reunia juntas, ou compilava,[Nota 1] as subrotinas necessárias para executar uma determinada tarefa.[2][3] O nome "compilador" é usado principalmente para os programas que traduzem o código fonte de uma linguagem de programação de alto nível para uma linguagem de programação de baixo nível (por exemplo, Assembly ou código de máquina). Contudo alguns autores citam exemplos de compiladores que traduzem para linguagens de alto nível como C.[4] Para alguns autores um programa que faz uma tradução entre linguagens de alto nível é normalmente chamado um tradutor, filtro[5] ou conversor de linguagem. Um programa que traduz uma linguagem de programação de baixo nível para uma linguagem de programação de alto nível é um descompilador.[6] Um programa que faz uma tradução entre uma linguagem de montagem e o código de máquina é denominado montador (assembler).[5] Um programa que faz uma tradução entre o código de máquina e uma linguagem de montagem é denominado desmontador (disassembler).[6] Se o programa compilado pode ser executado em um computador cuja CPU ou sistema operacional é diferente daquele em que o compilador é executado, o compilador é conhecido como um compilador cruzado.[7] Índice 1 História 2 Características 3 Fases da compilação o 3.1 Análise léxica o 3.2 Análise sintática
  • 2. o 3.3 Análise semântica o 3.4 Geração de código intermediário o 3.5 Optimização de código o 3.6 Geração de código final 4 Tratamento de erros 5 Ver também 6 Notas 7 Referências 8 Bibliografia 9 Ligações externas História Grace Hopper em 1984 Os softwares para os primeiros computadores foram escritos principalmente em linguagem assembly por muitos anos. As linguagens de alto nível de programação não foram inventadas até que os benefícios de ser capaz de reutilizar software em diferentes tipos de CPUs passassem a ser significativamente maiores do que o custo de se escrever um compilador. A capacidade de memória muito limitada capacidade dos primeiros computadores também criava muitos problemas técnicos na implementação de um compilador. No final da década de 1950, as linguagens de programação independentes de máquina foram propostas. Posteriormente, vários compiladores experimentais foram desenvolvidos. O primeiro compilador foi escrito por Grace Hopper,[8] em 1952, para a linguagem de programação A-0.[9] Antes de 1957, foram desenvolvidos esforços e várias contribuições ao desenvolvimento de linguagens de alto nível foram feitas. Entre estes, o desenvolvimento da Short Code (UNIVAC), Speedcoding no IBM 701,[10][11] o Whirlwind, o BACAIC e o PRINT.[12] A equipe de desenvolvimento do FORTRAN liderada por John Backus na IBM é geralmente creditada como tendo introduzido o primeiro compilador completo em 1957 (embora tenha ocorrido simultaneamente o desenvolvimento do algebraic translator de Laning e Zierler[9]). O COBOL é um exemplo de uma linguagem da primeira geração que compilava em múltiplas arquiteturas, em 1960.[13]
  • 3. Em muitos domínios de aplicação a idéia de usar uma linguagem de alto nível rapidamente ganhou força. Por causa da funcionalidade de expansão apoiada por linguagens de programação recentes e a complexidade crescente de arquiteturas de computadores, os compiladores tornaram-se mais e mais complexos. Os primeiros compiladores foram escritos em linguagem assembly. O primeiro compilador de auto-hospedagem - capaz de compilar seu próprio código-fonte em uma linguagem de alto nível - foi criado para o Lisp por Tim Hart e Levin Mike no MIT em 1962.[14] Características O processo da compilação Normalmente, o código fonte é escrito em uma linguagem de programação de alto nível, com grande capacidade de abstração, e o código objeto é escrito em uma linguagem de baixo nível,[15] como uma sequência de instruções a ser executada pelo microprocessador. O processo de compilação é composto de análise e síntese.[16] A análise tem como objetivo entender o código fonte e representá-lo em uma estrutura intermediária. A síntese constrói o código objecto a partir desta representação intermediária. A análise pode ser subdividida ainda em análise léxica, análise sintática, análise semântica e geração de código intermediário. É também conhecida como front end.[16] A síntese pode ter mais variações de um compilador a outro, podendo ser composta pelas
  • 4. etapas de optimização de código e geração de código final (ou código de máquina), sendo somente esta última etapa é obrigatória. É também conhecida como back end.[16] Classicamente, um compilador traduz um programa de uma linguagem textual facilmente entendida por um ser humano para uma linguagem de máquina, específica para um processador e sistema operacional. Atualmente, porém, são comuns compiladores que geram código para uma máquina virtual que é, depois, interpretada por um interpretador. Em linguagens híbridas, o compilador tem o papel de converter o código fonte em um código chamado de byte code, que é uma linguagem de baixo nível. Um exemplo deste comportamento é o do compilador da linguagem Java que, em vez de gerar código da máquina hospedeira (onde se está executando o compilador), gera código chamado Java Bytecode.[17] Um compilador é chamado de Just-in-time compiler (JIT) quando seu processo de compilação acontece apenas quando o código é chamado.[18] Um JIT pode fazer otimizações às instruções a medida que as compila.[18] Muitos compiladores incluem um pré-processador. Um pré-processador é um programa separado, ativado pelo compilador antes do início do processo de tradução.[19] Normalmente é responsável por mudanças no código fonte destinadas de acordo com decisões tomadas em tempo de compilação. Por exemplo, um programa em C permite instruções condicionais para o pré-processador que podem incluir ou não parte do código caso uma assertiva lógica seja verdadeira ou falsa, ou simplesmente um termo esteja definido ou não. Tecnicamente, pré-processadores são muito mais simples que compiladores e são vistos, pelos desenvolvedores, como programas à parte, apesar dessa visão não ser necessariamente compartilhada pelo usuário. Outra parte separada do compilador que muitos usuários vêem como integrada é o linker, cuja função é unir vários programas já compilados de uma forma independente e unificá-los em um programa executável.[20] Isso inclui colocar o programa final em um formato compatível com as necessidades do sistema operacional para carregá-lo em memória e colocá-lo em execução. 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
  • 5. 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 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 mais importantes são a análise sintática descendente recursiva e a análise sintática preditiva não-recursiva. 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, análise sintática LR canônico, análise sintática LALR e análise sintática SLR.[25] Existem disponíveis uma série de geradores automáticos de analisadores sintáticos,[29] como por exemplo, o Yacc, o Bison e o JavaCC. 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. O papel do analisador semântico é prover métodos pelos quais as estruturas construídas pelo analisador sintático possam ser avaliadas ou executadas.[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, como por exemplo regras de escopo, regras de visibilidade e consistência de tipos.[31] É papel do analisador semântico assegurar que todas as regras sensíveis ao contexto da linguagem estejam analisadas e verificadas quanto à sua validade. Um exemplo de tarefa própria do analisador semântico é a checagem de tipos de variáveis em expressões.[32] Um dos mecanismos comumente utilizados por implementadores de compiladores é a Gramática de Atributos, 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.[33] Geração de código intermediário
  • 6. 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 Na fase de geração de código intermediário, ocorre a transformação da árvore sintática em uma representação intermediária do código fonte. Esta linguagem intermediária é mais próxima da linguagem objeto do que o código fonte, mas ainda permite uma manipulação mais fácil do que se código assembly ou código de máquina fosse utilizado.[34] Um tipo popular de linguagem intermediária é conhecido como código de três endereços.[35] Neste tipo de código uma sentença típica tem a forma X := A op B, onde X, A e B são operandos e op uma operação qualquer. Uma forma prática de representar sentenças de três endereços é através do uso de quádruplas (operador, argumento 1, argumento 2 e, resultado). Este esquema de representação de código intermediário é preferido por diversos compiladores, principalmente aqueles que executam extensivas otimizações de código, uma vez que o código intermediário pode ser rearranjado de uma maneira conveniente com facilidade.[36]Outras representações de código intermediário comumente usadas são as triplas, (similares as quádruplas exceto pelo fato de que os resultados não são nomeados explicitamente) as árvores, os grafos acíclicos dirigidos(DAG) e a notação polonesa.[37] Optimização de código A Otimização de código é a estratégia de examinar o código intermediário, produzido durante a fase de geração de código com objetivo de produzir, através de algumas técnicas, um código que execute com bastante eficiência.[32] O nome optimizador deve sempre ser encarado com cuidado, 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.[23] Várias técnicas e várias tarefas se reúnem sob o nome de Optimização. 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, eliminação de sub-expressões redundantes, desmembramento de laços, substituição de operações (multiplicação por shifts), entre outras.[32] Uma das técnicas de optimização mais eficazes e independente de máquina é a otimização de laços, pois laços internos são bons candidatos para melhorias. Por exemplo, em caso de computações fixas dentro de laços, é possível mover estas computações para fora dos mesmos reduzindo processamento.[38] 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. 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. Contudo, é uma fase importante, pois uma boa geração de código pode ser, por exemplo, duas vezes mais rápida que um algoritmo de geração de código ineficiente.[36] Nem todas as técnicas de optimização são independentes da arquitetura da máquina-alvo. 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. O código produzido pelo compilador deve se aproveitar dos
  • 7. recursos especiais de cada máquina-alvo.[32] Segundo Aho, o código objeto pode ser uma sequência de instruções absolutas de máquina, uma sequência de instruções de máquina relocáveis, um programa em linguagem assembly ou um programa em outra linguagem.[39] Tratamento de erros Tratamento de erro de execução em uma aplicação Java no Eclipse O tratamento de erros está voltado a falhas devido a muitas causas: erros no compilador, erros na elaboração do programa a ser compilado, erros no ambiente (hardware, sistema operacional), dados incorretos, etc. As tarefas relacionadas ao tratamento de erros consitem em detectar cada erro, reportá-lo ao usuário e possivelmente fazer algum reparo para que o processamento possa continuar.[40] Os erros podem ser classificados em erros léxicos, erros sintáticos, erros não independentes de contexto (semânticos), erros de execução e erros de limite.[41] Os erros léxicos ocorrem quando um token identificado não pertence a gramática da linguagem fonte. Os erros sintáticos ocorrem quando alguma estrutura de frase não está de acordo com a gramática, como por exemplo parênteses sem correspondência. Os erros não independentes de contexto em geral são associados a não declaração de objetos como variáveis e erros de tipos. Os erros de execução ocorrem após a compilação, quando o programa já está sendo executado. Um exemplo típico é o da divisão por zero. Os erros de limite, ocorrem durante a execução e estão relacionados as características da máquina na qual o programa está sendo executado, como por exemplo, estouro de pilha.[41] Alguns compiladores encerram o processo de tradução logo ao encontrar o primeiro erro do programa-fonte. Esta é uma política de fácil implementação. Compiladores mais sofisticados, porém, 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.[43] O problema é que diferente de um analisador top- down, este último não sabe quais símbolos são esperados na entrada, somente os que já foram processados. Pode-se usar neste caso técnicas como, por exemplo, a técnica de panic-mode que procura em tabelas sintáticas em busca de símbolos válidos na entrada.[43] Nesta técnica se descartam símbolos da entrada até que um delimitador (como um ponto e vírgula, por exemplo) seja encontrado. O analisador apaga as
  • 8. entradas da pilha até que encontre uma entrada que permita que o processo de análise prossiga em diante.[44] Ver também