Você está na página 1de 14

Introduo

O Compilador

O compilador um software complexo que converte uma linguagem fonte, ou


linguagem origem, em uma linguagem destino, ou linguagem objeto, ou seja,
converte um programa originado de uma linguagem de programao para
uma linguagem que possa ser entendida e executada por um computador.
Durante a compilao so executadas tarefas que fazem a traduo de uma
linguagem em outra.

Existem dois princpios fundamentais na construo de compiladores:

1. O compilador deve preservar o significado do programa a ser


compilado.

2. O compilador deve melhorar o programa de entrada de alguma forma


perceptvel.

As etapas de compilao so complexas e exigiam um esforo significativo,


os primeiros compiladores eram escritos em binrio e salvos na memria
ROM, hoje ns temos um conjunto de ferramentas que facilitam a criao e
manuteno de compiladores, muitas dessas ferramentas so escritas em
linguagem como Java, C e C++ e j automatizam boa parte da construo de
um compilador.

Essas ferramentas geram cdigos que podem ser includos no projeto do


compilador. Um exemplo so os geradores de analisadores lxicos, que com
base em expresses reguladores geram uma algoritmo capaz de identificar
os elementos lxicos de uma linguagem de programao.

O compilador precisa traduzir um conjunto infinito de programas escrito em


uma linguagem de programao o resultado desse processo deve ser um
cdigo eficiente que deve ser executado em diversas arquiteturas de
processadores.
Um conceito muito importante no estudo de compiladores
a otimizao que se refere as atentivas de produzir um compilador que gere
um cdigo mais eficiente. Essa uma etapa cada vez mais importante e
complexa devida a grande variedade de arquitetura de processadores.
O tempo de compilao outro fator muito importante que deve ser levado
em considerao durante o desenvolvimento de um compilador.

Analise

Anlise lxica

A anlise lxica pode ser encarada como a primeira etapa do processo de


compilao. Nesta etapa, o programa fonte encarado como uma seqncia
de caracteres que devero ser agrupados e identificados como palavras
reservadas da linguagem (em C, por exemplo, main, int, for), constantes
(123, 0x1F, 'A'), identificadores (myvar, Str1).

Os smbolos que devero ser reconhecidos na anlise lxica so representveis


por expresses regulares ou equivalentemente por gramticas regulares .
Existe tambm uma correspondncia unvoca entre expresses (ou gramticas)
regulares e autmatos finitos, mquinas que podem ser utilizadas para
reconhecer strings de uma dada linguagem.

Um autmato finito tem um conjunto de estados, alguns dos quais so


denominados estados finais. medida que caracteres da string de entrada so
lidos, o controle da mquina passa de um estado a outro, segundo um conjunto
de regras de transio especificadas para o autmato. Se aps o ltimo
carcter o autmato encontra-se em um dos estados finais, a string foi
reconhecida (ou seja, pertence linguagem). Caso contrrio, a string no
pertence linguagem aceita pelo autmato.
Um analisador lxico, ou scanner, um programa que implementa um
autmato finito, reconhecendo (ou no) strings como smbolos vlidos de uma
linguagem.

A implementao de um analisador lxico requer uma descrio do autmato


que reconhece as sentenas da gramtica ou expresso regular de interesse.
Com essa descrio, possvel oferecer os seguintes procedimentos auxiliares
para o analisador lxico:

ESTADO-INICIAL, que recebe como argumento a referncia para o


autmato e retorna o seu estado inicial;
ESTADO-FINAL, que recebe como argumentos a referncia para o
autmato e a referncia para o estado corrente. O procedimento
retorna true se o estado especificado elemento do conjunto de estados
finais do autmato, ou false caso contrrio; e
PRXIMO-ESTADO, que recebe como argumento a referncia para o
autmato, para o estado corrente e para o smbolo sendo analisado. O
procedimento consulta a tabela de transies e retorna o prximo estado
do autmato, ou o valor nulo se no houver transio possvel.

A sentena a ser reconhecida estruturada como uma lista de smbolos, que


passada como argumento para o analisador lxico juntamente com a referncia
para o autmato.

O analisador lxico inicia sua operao definindo o estado inicial como o


estado corrente. Obtm ento o prximo smbolo (que inicialmente o
primeiro smbolo) da sentena . Se no houver prximo smbolo, preciso
verificar se o estado corrente um estado final. Se for, o procedimento
retorna true, indicando que a sentena foi reconhecida pelo autmato. Se o
estado corrente no for um estado final e no houver mais smbolos na
sentena, ento no houve reconhecimento e o procedimento retorna false.

Se houver smbolo a ser analisado, ento o procedimento deve continuar o


processo de reconhecimento. Para tanto, obtm o prximo estado
correspondente transio do estado atual pelo smbolo sob anlise. Se no
houver transio possvel, ento a sentena no foi reconhecida e o
procedimento deve encerrar, retornando false.
Anlise sinttica

A sintaxe a parte da gramtica que estuda a disposio das palavras na


frase e das frases em um discurso. Essa etapa no processo de compilao
deve reconhecer as forma do programa fonte e determinar se ele valido ou
no.

Esse modelo pode ser definido utilizando gramticas livres de contexto que
representam uma gramtica formal e pode ser escrita atravs de algoritmos
fazem a derivao de todas as possveis construes da linguagem.

As derivaes tem como objetivo determinar se um fluxo de palavras se


encaixa na sintaxe da linguagem de programao.

Alguns termos utilizados na definio de linguagens de programao.

Smbolo: so os elementos mnimos que compe uma linguagem. Na


linguagem humana so as letras.

Sentena: um conjunto ordenado de smbolos que forma uma


cadeia ou string. Na linguagem humana so as palavras.

Alfabeto: um conjunto de smbolos. Na linguagem humana o


conjunto de letras {a, b, c, d, ...}
Linguagem: o conjunto de sentenas, Na linguagem humana so os
conjuntos de palavras {compiladores, linguagem, ...}

Gramtica: uma forma de representar as regras para formao de


uma linguagem.

Dada uma gramtica G e uma sentena s o objetivo do analisador sinttico


verificar se a sentena s pertence a linguagem G. O analisador sinttico
recebe do analisador lxico a sequncia de tokens que constitui a
sentena s e produz uma arvore de derivao se a sentena vlida ou
emite um erro se a sentena invlida.
O analisador lxico desenvolvido para reconhecer cadeias de caracteres
fazendo uma leitura dos caracteres e obtendo a sequncia de tokens, esse
analisador v o texto como uma sequncia de palavras de uma linguagem
regular e reconhece ele atravs de autmatos finitos determinsticos e no
determinsticos.

J o analisador sinttico v o mesmo texto como uma sequncia de


sentenas que deve satisfazer as regras gramaticais. atravs da gramtica
que podemos validar expresses criadas na linguagem de programao.

Gramtica Livre de Contexto - GLC

As linguagens de programao em geral pertencem a uma categoria


chamada de Linguagens Livres de Contexto. Umas das formas de
representar essas linguagens atravs de Gramticas Livres de Contexto
que so a base para a construo de analisadores sintticos. Elas so
utilizadas para especificar as regras sintticas de uma linguagem de
programao, uma linguagem regular pode ser reconhecida por uma
automato finitos determinsticos e no determinsticos, j uma Gramatica
Livre de Contexto pode ser reconhecida por um automato de pilha.

Outra aplicao de GLC so os DTD - Definio de Tipos de Documentos -


utilizados por arquivos XML que descreve as tags de uma forma natural, as
tags deve estar aninhas afim de lidar com o significado do texto.
Ambiguidade:

Certas gramaticas permitem que uma mesma sentena tenha mas de uma
rvore de derivao, isso torna a gramtica inadequada para a linguagem de
programao, pois o compilador no pode determinar a estrutura desse
programa fonte. Duas derivaes podem gerar uma unica rvore sinttica,
mas duas rvores sintticas no podem ser geradas por uma derivacao.

Uma ambiguidade por ser evitada de duas formas:

1. Reescrevendo a gramatica afim de remover a ambiguidade, isso pode tornar


a gramatica mais complexa.

2. Definir ordens de prioridade durante a derivao.

Geradores de analisadores sintticos

Da mesma forma que ocorre na construo de analisadores lxicos os


analisadores sintticos podem ser construdos atravs de ferramentas que
auxiliam esse trabalho.

O funcionamento semelhante aos analisadores lxicos. Um arquivo com as


especificaes sintticas criado e atravs de comandos o analisador
sinttico gerado.

A sada um arquivo de cdigo com a implementao do analisador


sinttico.
Analise Semntica

At o momento vimos as etapas de anlise lxica, que quebra o programa


fonte em tokens e a analise sinttica, que valida as regras a sintaxe da
linguagem de programao.

No possvel representar com expresses regulares ou com uma gramtica


livre de contexto regras como: todo identificador deve ser declarado antes de
ser usado. Muitas verificaes devem ser realizadas com meta-informaes e
com elementos que esto presentes em vrios pontos do cdigo fonte,
distantes uns dos outros. O analisador semntico utiliza a rvore sinttica e a
tabela de smbolos para fazer as analise semantica.

A analise semntica responsavel por verificar aspectos relacionados ao


significado das instrues, essa a terceira etapa do processo de
compilao e nesse momento ocorre a validao de uma serie regras que
no podem ser verificadas nas etapas anteriores( importante ressaltar que
muitos dos erros semanticos tem origem de regras dependentes da
linguagem de programacao.).

As validaes que no podem ser executadas pelas etapas anteriores devem


ser executadas durante a anlise semntica a fim de garantir que o programa
fonte estaja coerente e o mesmo possa ser convertido para linguagem de
mquina.

A anlise semntica percorre a rvore sinttica relaciona os identificadores


com seus dependentes de acordo com a estrutura hierarquica.

Essa etapa tambm captura informaes sobre o programa fonte para que as
fases subsequentes gerar o cdigo objeto, um importante componente da
analise semntica a verificao de tipos, nela o compilador verifica se cada
operador recebe os operandos permitidos e especificados na linguagem
fonte.

Um exemplo que ilustra muito bem essa etapa de validao de tipos a


atribuio de objetos de tipos ou classe diferentes. Em alguns casos, o
compilador realiza a converso automtica de um tipo para outro que seja
adequado aplicao do operador.

Inferncia de tipos

O sistema de tipos de dados podem ser divididos em dois grupos: sistemas


dinmicos e sistemas estticos. Muitas das linguagens utilizam o sistema
esttico, esse sistema predominante em linguagens compiladas, pois essa
informao utilizada durante a compilao e simplifica o trabalho do
compilador.

Sistema de tipo esttico: Linguagem como C, Java, Pascal obrigam o


programador a definir os tipos das variveis e retorno de funes, o compilador
pode fazer varias checagens de tipo em tempo de compilao.

Sistema de tipo dinmico: Variveis e retorno de funes no possuem


declarao de tipos, como exemplo temos linguagens como Python , Perl e PHP.

Algumas linguagens utilizam um mecanismo muito interessantes chamado


inferncia de tipos, que permite a uma variavel assumir varios tipos durante o
seu ciclo de vida, isso permite que a ela possa ter varios varios valores.
Linguagens de programao como Haskel tira proveito desse mecanismo.
Nesses casos o compilador infere o tipo da varivel em tempo de execuo,
esse tipo de mecanismos esta diretamente relacionado ao mecanismo
de Generics do Java e Delphi Language. A validao de tipos passa a ser
realizada em tempo de execucao.

Principais erros semnticos:

Escopo dos identificadores

O compilador deve garantir que variveis e funes estejam declaradas em


locais que podem ser acessados onde esses identificadores esto sendo
utilizados.

Uma classe com funes declaradas como privadas e essas funes sendo
utilizadas fora da classe.

Compatibilidade de tipos:

Verificar se os tipos de dados declarado nas variveis e funes esto sendo


utilizados e atribuidas corretamente, por exemplo: operaes matemticas devem
ser realizadas com nmeros, atribuies de valores para varivies.

Detectar unicidade de nomes de identificadores:


Essa verificao muito importante pois ele deve garantir que os
identificadores sejam unicos no havendo na tabela de simbolos uma entrada
para o mesmo identificador: Isso implica em:

diferentes identificadores podem ter o mesmo nome;

o mesmo identificadores pode estar em um escopo diferente;

sobrecarga de metodos deve gerar novas entradas na tabela de


simbolos;

Detectar o uso correto de comandos de controle de fluxo:

Comandos como continue e break executam saltos na execucao de cdigos, esse


comandos deve ser utilizados em instrues que permitem os saltos.

Gerao de cdigo
A traduo do cdigo de alto nvel para o cdigo do processador est
associada traduzir para a linguagem-alvo a representao da rvore
gramatical obtida para as diversas expresses do programa. Embora tal
atividade possa ser realizada para a rvore completa aps a concluso da
anlise sinttica, em geral ela efetivada atravs das aes semnticas
associadas aplicao das regras de reconhecimento do analisador sinttico.
Este procedimento denominado traduo dirigida pela sintaxe.

Em geral, a gerao de cdigo no se d diretamente para a


linguagem assembly do processador-alvo. Por convenincia, o analisador
sinttico gera cdigo para uma mquina abstrata, com uma linguagem
prxima a assembly porm independente de processadores especficos. Em
uma segunda etapa de gerao de cdigo, esse cdigo intermedirio
traduzido para a linguagem assembly desejada. Dessa forma, grande parte do
compilador reaproveitada para trabalhar com diferentes tipos de
processadores.
Cdigo intermedirio
A linguagem utilizada para a gerao de um cdigo em formato intermedirio
entre a linguagem de alto nvel e a linguagem assembly deve representar, de
forma independente do processador para o qual o programa ser gerado, todas
as expresses do programa original. Duas formas usuais para esse tipo de
representao so a notao posfixa e o cdigo de trs endereos.

Cdigo de trs endereos


O cdigo de trs endereos composto por uma seqncia de instrues
envolvendo operaes binrias ou unrias e uma atribuio. O nome ``trs
endereos'' est associado especificao, em uma instruo, de no mximo
trs variveis: duas para os operadores binrios e uma para o resultado. Assim,
expresses envolvendo diversas operaes so decompostas nesse cdigo em
uma srie de instrues, eventualmente com a utilizao de variveis
temporrias introduzidas na traduo. Dessa forma, obtm-se um cdigo mais
prximo da estrutura da linguagem assembly e, conseqentemente, de mais
fcil converso para a linguagem-alvo.

Notao posfixa
A notao tradicional para expresses aritmticas, que representa uma
operao binria na forma x+y, ou seja, com o operador entre seus dois
operandos, conhecida como notao infixa. Uma notao alternativa para
esse tipo de expresso a notao posfixa, tambm conhecida como notao
polonesa3.1, na qual o operador expresso aps seus operandos.

O atrativo da notao posfixa que ela dispensa o uso de parnteses.

Expresses em formato intermedirio usando a notao posfixa podem ser


eficientemente avaliadas em mquinas baseadas em pilhas, tambm
conhecidas como mquinas de zero endereos. Nesse tipo de mquinas,
operandos so explicitamente introduzidos e retirados do topo da pilha por
instrues push e pop, respectivamente. Alm disso, a aplicao de um
operador retira do topo da pilha seus operandos e retorna ao topo da pilha o
resultado de sua aplicao.
Otimizao de cdigo
A etapa final na gerao de cdigo pelo compilador a fase de otimizao.
Como o cdigo gerado atravs da traduo orientada a sintaxe contempla
expresses independentes, diversas situaes contendo seqncias de cdigo
ineficiente podem ocorrer. O objeto da etapa de otimizao de cdigo aplicar
um conjunto de heursticas para detectar tais seqncias e substitu-las por
outras que removam as situaes de ineficincia.

As tcnicas de otimizao que so usadas em compiladores devem, alm de


manter o significado do programa original, ser capazes de capturar a maior
parte das possibilidades de melhoria do cdigo dentro de limites razoveis de
esforo gasto para tal fim. Em geral, os compiladores usualmente permitem
especificar qual o grau de esforo desejado no processo de otimizao. Por
exemplo, em gcc h opes na forma -O... que do essa indicao, desde -
O0 (nenhuma otimizao) at -O3 (mxima otimizao, aumentando o tempo
de compilao), incluindo tambm uma opo -Os, indicando que o objetivo
reduzir a ocupao de espao em memria.

As tcnicas de otimizao podem ser classificadas como independentes de


mquina, quando podem ser aplicadas antes da gerao do cdigo na
linguagem assembly, ou dependentes de mquina, quando aplicadas na
gerao do cdigo assembly.

A otimizao independente de mquina tem como requisito o levantamento


dos blocos de comandos que compem o programa. Essa etapa da otimizao
conhecida como a anlise de fluxo, que por sua vez contempla a anlise de
fluxo de controle e a anlise de fluxo de dados. Estratgias que podem ser
aplicadas analisando um nico bloco de comandos so denominadas
estratgias de otimizao local, enquanto aquelas que envolvem a anlise
simultnea de dois ou mais blocos so denominadas estratgias de otimizao
global.

Algumas estratgias bsicas de otimizao, alm da j apresentada eliminao


de desvios desnecessrios, so apresentadas a seguir.

A estratgia de eliminao de cdigo redundante busca detectar situaes


onde a traduo de duas expresses gera instrues cuja execuo repetida
no tem efeito.
Outra estratgia bsica a eliminao de cdigo no-alcanvel, ou ``cdigo
morto''.

O uso de propriedades algbricas outra estratgia de otimizao


usualmente aplicada. Nesse caso, quando o compilador identifica que uma

expresso aritmtica foi reduzida a ou ou ou

ou ou , ento ele substitui a expresso simplesmente por . Outra


classe de propriedades algbricas que utilizada tem por objetivo substituir
operaes de alto custo de execuo por operaes mais simples.

EXTRAS

Diretivas de compilao

As diretivas so comandos que no so compilados e sempre iniciam com


o caractere #.

Uma diretiva pode ser colocada em qualquer parte do programa e cada


uma cumpre com uma tarefa (que veremos mais adiante), as principais so:

#include

#define

#undef

#ifdef

#ifndef

#if

#else

#elif

#endif

#pragma
Pr-processador

Seu papel analisar o cdigo-fonte e realizar modificaes nele antes de


pass-lo para o compilador. As diretivas dizem ao pr-processador se alguma
parte do cdigo deve ser compilada ou no, se o contedo de outro arquivo
deve ser copiado para determinado local no cdigo, se uma mensagem de erro
ser exibida em tempo de compilao, entre outras regras. Alm de lidar com
as diretivas ainda responsvel por remover comentrios, substituir espaos
em branco e junta linhas separadas por sequncias de escape.

Linker

Mas voc ainda no pode executar um arquivo objeto pois o contedo dele
estar incompleto. Por exemplo, se voc colocar um comando printf para exibir
uma mensagem na tela, apesar de seu cdigo ter sido compilado, o arquivo
objeto gerado no saber o que printf, ele s possui uma referncia a essa
funo, mas sua estrutura se encontra em uma biblioteca a parte. O linker
responsvel linkar (ligar, unir) as instrues que esto em outras bibliotecas ou
em outros arquivos objeto e gerar um nico arquivo executvel.

importante notar que um executvel no precisa conter todas as funes. Por


exemplo, o Windows utiliza bibliotecas no mesmo formato de um executvel, as
famosas DLLs (Dynamic-link library). Essas bibliotecas contm cdigos, dados,
recursos e at outras bibliotecas a parte. A vantagem que podem ser
carregadas apenas uma vez na memria e utilizadas por outros programas que
invocam suas funes, reduzindo o tamanho dos executveis.

Diretivas de pr-processamento

#include

Para incluir um arquivo usamos a diretiva include. Ela diz ao compilador para
copiar o contedo deste arquivo para alguma parte do seu cdigo.

#define

Serve para darmos nome a uma constante:

#define PI 3.1415926
Ou definir uma funo simples:

#define DIV(x,y) ((x)/(y))

Toda vez que o pr-processador encontra o nome da constante ou a expresso


no cdigo realiza a substituio.

#undef

Remove um nome criado com #define e ignora as ocorrncias subsequentes.

#ifdef e #ifndef

Essas diretivas verificam a presena (#ifdef) ou ausncia (#ifndef) de


identificadores definidos com #define antes de compilar o bloco de cdigo. So
teis para compatibilidade com verses anteriores da linguagem.

#if, #elif, #else e #endif

Compila blocos do cdigo condicionalmente.

#pragma

Os pragmas so especficos do computador ou do sistema operacional e


podem variar de um compilador para outro. Se o compilador no identificar o
nome da diretiva ir ignorar o #pragma.

Um do mais comuns o #pragma once utilizado para indicar que o arquivo


atual deve ser includo apenas uma vez durante o processo de compilao.