Escolar Documentos
Profissional Documentos
Cultura Documentos
Introdução - Continuação
Introdução
12/3/2008 Introdução 2 de 57
1
Introdução
12/3/2008 Introdução 3 de 57
Introdução
12/3/2008 Introdução 4 de 57
2
Definição
12/3/2008 Introdução 5 de 57
Definição
Programa Programa
Fonte Alvo
Compilador
(linguagem (linguagem
(compiler)
fonte) alvo)
Mensagens
de erro
12/3/2008 Introdução 6 de 57
3
Definição
Tipos de Compiladores
Single-Pass: efetuam a compilação numa
única leitura do programa fonte.
Multi-Pass: efetuam a compilação através
de várias leituras do programa fonte.
Load-And-Go: efetuam a compilação e a
execução do programa fonte.
Debugging: efetuam a compilação
permitindo a depuração do programa fonte.
Optimizing: efetuam a compilação e a
otimização do programa alvo.
12/3/2008 Introdução 8 de 57
4
Modelo Análise-Síntese
Análise Síntese
Programa
Fonte
Significado
12/3/2008 Introdução 9 de 57
Modelo Análise-Síntese
Análise:
z Inclui possíveis mecanismos de pré-
processamento.
z Divide o programa fonte em suas partes
constituintes.
z Cria uma representação intermediária do
programa fonte.
z É uma tarefa relativamente simples.
12/3/2008 Introdução 10 de 57
5
Modelo Análise-Síntese
Síntese:
z Constrói o programa alvo a partir da
representação intermediária produzida pela
análise.
z É uma tarefa relativamente complexa.
z Utiliza a maior parte das técnicas
especializadas.
12/3/2008 Introdução 11 de 57
Modelo Análise-Síntese
Grande parte das técnicas se aplicam a
maioria das linguagens fonte e alvo.
Existem várias ferramentas que facilitam o
desenvolvimento de novos compiladores
ou softwares que usem as mesmas técnicas.
Dá origem aos conceitos de:
z front-end, relacionado com a linguagem a ser
processada;
z back-end: relacionado com a linguagem a ser
produzida.
12/3/2008 Introdução 12 de 57
6
Sistema de Processamento
de Linguagem
Pré-processador
Módulos (preprocessor)
fonte
Compilador
Programa (compiler)
Fonte
Montador
Assembly (assembler)
Alvo
Loader/Link
Código Editor
Relocável
Código
Absoluto
12/3/2008 Introdução 13 de 57
Fases da Compilação
7
Fases da Compilação
Análise
Programa Léxica
Fonte
Análise
Sintática
Análise
Semântica
Tabela de Detecção
Símbolos de Erros
Geração de
Pseudo-Código
Otimização
de Código
Programa
Alvo
Geração
de Código
12/3/2008 Introdução 15 de 57
8
Análise Léxica ou Linear
void main( ) {
int total = 0;
println(“Total = %d.”, total + 10);
}
9
Análise Léxica ou Linear
12/3/2008 Introdução 19 de 57
Análise Sintática ou
Hierárquica (parsing)
Envolve o agrupamento dos tokens obtidos
do programa fonte em frases ou unidades
lógicas.
As frases/unidade devem ser
gramaticalmente aceitas pela linguagem
fonte para possibilitar sua síntese.
Usualmente as frases/unidades são
representadas por árvores sintáticas (parsing
trees).
12/3/2008 Introdução 20 de 57
10
Análise Sintática ou
Hierárquica
Um outro exemplo:
subtotal = 10 + valorUnitario * quantidade;
atribuição
=
identificador expressão
subtotal +
expressão expressão
10 identificador identificador
valorUnitario quantidade
12/3/2008 Introdução 21 de 57
Análise Sintática ou
Hierárquica
Note que:
z identificador = expressão é uma unidade lógica
z assim como valorUnitario*quantidade
z mas 10+valorUnitario não são agrupados
como unidade lógica porque as multiplicações
devem ser executadas antes das adições
z ou seja, a precedência das operações deve ser
respeitada apesar da ordem em que os tokens
originalmente aparecem no programa fonte.
12/3/2008 Introdução 22 de 57
11
Análise Sintática ou
Hierárquica
A estrutura hierárquica de uma linguagem é
usualmente expressa por regras:
(1) Um identificador é uma expressão
(2) Um número é uma expressão
(3) Se expr1 e expr2 são expressões então
também são expressões:
expr1 + expr2
expr1 * expr2
( expr1 )
12/3/2008 Introdução 23 de 57
Análise Sintática ou
Hierárquica
Uma outra forma de expressar-se as
mesmas regras:
(1) expr → id
(2) expr → number
(3) expr → expr + expr
| expr * expr
| ( expr )
12/3/2008 Introdução 24 de 57
12
Análise Sintática ou
Hierárquica
As regras (1) e (2) são regras básicas não
recursivas.
A regra (3) define expressões em termos de
operadores aplicados a outras expressões,
ou seja, é uma regra recursiva.
É frequente o uso de regras recursivas na
definição (da gramática) de linguagens.
12/3/2008 Introdução 25 de 57
Análise Sintática ou
Hierárquica
Diretivas de linguagens de programação são
exemplos típicos de regras recursivas:
(1) Se id1 é um identificador e expr1 é uma
expressão então é também uma diretiva:
id1 = expr1
(2) Se expr1 é uma expressão e stmt1 e stmt2 são
diretivas então são também diretivas:
while (expr1) stmt1
if (expr1) stmt1 else stmt2
12/3/2008 Introdução 26 de 57
13
Análise Léxica versus
Análise Sintática
A divisão entre análise léxica e sintática é
arbitrária.
Geralmente tal divisão é pensada para
simplificar a etapa de análise como um
todo.
O fator determinante é a recursão, isto é, se
a linguagem fonte é inerentemente
recursiva ou não.
12/3/2008 Introdução 27 de 57
14
Análise Semântica ou de
Contexto
Nesta fase verifica-se se cada unidade lógica
pode efetivamente ser aplicada dentro do
contexto onde foi encontrada.
Relaciona portanto se as operações
indicadas são aplicáveis (tem significado
semântico) aos operandos utilizados.
Só pode ser realizada após a análise léxica e
sintática.
12/3/2008 Introdução 29 de 57
Análise Semântica ou de
Contexto
Um exemplo:
A=0
Da análise léxica e sintática temos:
zA é um identificador
z= é o operador de atribuição
z0 é um valor numérico (uma expressão)
Equivale assim a:
identificador = expressão
12/3/2008 Introdução 30 de 57
15
Análise Semântica ou de
Contexto
Embora sintaticamente correto pode ser
semanticamente inválido se:
identificador A não foi declarado;
identificador A corresponder a uma função,
método ou classe;
o tipo do identificador de variável A for
incompatível com o valor numérico 0 (zero);
operação de atribuição for inadequada dentro do
contexto em que ocorre (p.e. expressão condicional
de um laço).
12/3/2008 Introdução 31 de 57
Análise Semântica ou de
Contexto
Realiza a verificação de tipos e, quando
permitido pela linguagem, efetua a coerção
de operandos:
int a = 1; float b = 2.5, c;
c = a + b;
Sintaticamente correto. Se permitido a
operação de inteiros com reais ocorre a
coerção:
c = inttoreal(a) + b;
12/3/2008 Introdução 32 de 57
16
Tabela de Símbolos
Função essencial de qualquer compilador
que consiste no registro de todos os
identificadores encontrados no programa
fonte e também seus atributos.
Como atributos temos:
tipo,
escopo,
local de armazenamento,
número e tipo dos argumentos (se função),
método de passagem dos argumentos (se função) e
valor de retorno (se função).
12/3/2008 Introdução 33 de 57
Tabela de Símbolos
12/3/2008 Introdução 34 de 57
17
Tabela de Símbolos
Síntese
Implementa procedimentos de avaliação
para o programa-fonte em termos de
primitivas de um computador-alvo.
Para prover maior independência e
flexibilidade do projeto do compilador
divide-se geralmente em:
z geração de pseudo-código (target independent)
z otimização do pseudo-código
z geração do código-alvo
z otimização do código-alvo
12/3/2008 Introdução 36 de 57
18
Geração de Código
Intermediário (pseudocode)
Muitos compiladores geram uma
representação intermediária antes do
código-alvo.
Esta representação intermediária pode ser
entendida como um programa para uma
máquina abstrata (virtual).
Tal representação deve ser facilmente
gerada e traduzida no programa-alvo.
12/3/2008 Introdução 37 de 57
Geração de Código
Intermediário (pseudocode)
Uma forma típica é a three-address code onde
o trecho de programa abaixo:
montante = depInicial + taxaJuros*60
Poderia originar o seguinte pseudo-código:
temp1 = intoreal(60)
temp2 = id3 * temp1
temp3 = id2 + temp2
id1 = temp3
12/3/2008 Introdução 38 de 57
19
Geração de Código
Intermediário (pseudocode)
O three-address code tem como características:
z cada posição de memória é tratada como um
registrador;
z sequências de instruções possuem no máximo
três operandos;
z possui assim um único operador além da
atribuição
z precedência é resolvida através da ordem de
execução;
z posições temporárias são geradas e usadas para
armazenar valores intermediários.
12/3/2008 Introdução 39 de 57
Geração de Código
Intermediário (pseudocode)
Embora gere sequências de código mais
longas que aparentemente necessário,
facilita futuras otimizações e traduções
devido sua simplicidade.
Modificando-se apenas as etapas seguintes
pode-se obter compiladores para diferentes
linguagens-alvo, i.e., diferentes arquiteturas.
12/3/2008 Introdução 40 de 57
20
Otimização de Código
Procura melhorar o código intermediário
gerado em termos de:
z velocidade de execução
z quantidade de armazenamento utilizado
É uma tarefa relativamente complexa que
usualmente toma tempo significativo da
compilação, entretanto algumas otimizações
simples podem melhorar muito o tempo de
execução sem retardar demais a
compilação.
12/3/2008 Introdução 41 de 57
Geração de Código
21
Geração de Código
12/3/2008 Introdução 43 de 57
Detecção de Erros
22
Transformações do Código
12/3/2008 Introdução 45 de 57
Transformações do Código
a=b+c*3
Tabela de Símbolos
# id info
Análise Léxica 1 a
2 b
3 c
Id1 = id2 + id3 * number
Análise Sintática =
id1 +
Id2 *
id3 Number
12/3/2008 Introdução 46 de 57
23
Transformações do Código
=
id1 +
Análise Semântica
Id2 *
id3 Number
id1 +
Id2 *
id3 Intoreal(3)
12/3/2008 Introdução 47 de 57
Transformações do Código
=
Otimização Código
id1 + Intermediário
Id2 *
temp1 = id3 * 3.0
id3 Intoreal(3) id1 = id2 + temp1
Geração de Código
Geração Código Alvo
Intermediário
MOV id3, R2
MUL #3.0, R2
temp1 = intoreal(3)
MOV id2, R1
temp2 = id3 * temp1
ADD R2, R1
temp3 = id2 + temp2
MOV R1, id1
id1 = temp3
12/3/2008 Introdução 48 de 57
24
Softwares Auxiliares
Pré-processadores
z produzem a entrada para os compiladores
z efetuam o processamento de macros
#define MAX 30
z realizam a inclusão de arquivos
#include “global.h”
z permitem adicionar extensões a linguagem
z permitem realizar compilação condicional
12/3/2008 Introdução 49 de 57
Softwares Auxiliares
Assemblers
z Convertem assembly em linguagem de máquina
z Assembler de 2 passos é o mais simples
Carregadores e Link-Editors
z efetuam o carregamento do programa na
memória efetuando a substituição dos
endereços relocáveis.
z permitem a união de arquivos compilados
separadamente
12/3/2008 Introdução 50 de 57
25
Agrupamento de Fases
Agrupamento de Fases
12/3/2008 Introdução 52 de 57
26
Agrupamento de Fases
Agrupamento de Fases
27
Fases versus Passagens
12/3/2008 Introdução 55 de 57
28
Fases versus Passagens
Caso comum:
z Numa primeira passagem o analisador sintático
comanda tanto o analisador léxico para
obtenção de tokens como o analisador
semântico para geração de código
intermediário.
z Numa segunda passagem são determinados
gerados os endereços finais de variáveis e
procedimentos cujo código foi previamente
gerado.
12/3/2008 Introdução 57 de 57
29