Compiladores
Prof. Yandre Maldonado
Compiladores - Prof. Yandre - 1
Compiladores - Prof. Yandre - 2
Introdução• Compilador
• é um programa que traduz o código fonte escrito em uma linguagem de mais alto nível para outra linguagem de mais baixo nível;
• a linguagem original é chamada de linguagem fonte, e a linguagem final é chamada de linguagem destino ou alvo;
Compiladores - Prof. Yandre - 3
Programa Linguagem
Fonte
Compilador Programa Linguagem
Alvo
Mensagens de Erro
Introdução
• VARIEDADE DE COMPILADORES
Compiladores - Prof. Yandre - 4
Linguagem Fonte
Fortran
C
Pascal
Modula
Algol
...
Máquina Alvo
Intel
Mips
Sparc
...
A máquina alvo pode estar entre um microprocessador e um supercomputador
A análise cria um
representação intermediária do código
Introdução• Estrutura Geral de um Compilador
(Modelo de compilação de Análise e Síntese)
Compiladores - Prof. Yandre - 5
Análise Léxica
Análise Sintática1. Análise
2. Síntese
Análise Estrutural
Análise Semântica
Geração de Código Intermediário
Otimização de Código
Geração de Código Alvo
Gera o código a partir
da representação
intermediária
Introdução A interação entre os módulos do compilador
Tratamento de Erros
Geração de Código Intermediário
Otimização
Código Alvo
Síntese
Léxica
Sintática
Semântica
Análise
Programa Fonte
Programa Alvo
Compiladores - Prof. Yandre - 6
Introdução Conceitos acerca da compilação:
– Tradutor: programa que transforma um programa fonte escrito numa linguagem em um programa equivalente escrito em uma linguagem diferente;
– Pré-processador: programa que transforma um programa escrito em uma linguagem estendida em um programa equivalente escrito em linguagem original;
Compiladores - Prof. Yandre - 7
Prog. Linguagem AProg. Linguagem A Prog. Linguagem BProg. Linguagem BTradutorTradutor
Prog. Linguagem Estendida
Prog. Linguagem Estendida
Prog. Linguagem Original
Prog. Linguagem OriginalPré-
processadorPré-
processador
CompiladorCompilador
Introdução– Montador: tradutor que transforma um programa
escrito em uma linguagem simbólica (de baixo nível) em instruções equivalentes em linguagem de máquina;
Compiladores - Prof. Yandre - 8
Prog. Linguagem Simbólica
Prog. Linguagem Simbólica
Instruções em Linguagem de
Máquina
Instruções em Linguagem de
Máquina
MontadorMontador
Alto nívelSimbólica Instruções em Ling. de Máquina
b := a+2;b := a+2;MOV a, R1
ADD #2, R1
MOV R1, b
MOV a, R1
ADD #2, R1
MOV R1, b
0001 0100 00000000
0011 0110 00000010
0010 0100 00000100
0001 0100 00000000
0011 0110 00000010
0010 0100 00000100
Compilação
Montagem
1xn 1x1
Introdução– Interpretador: tradutor que funciona em tempo de
execução. Estes programas traduzem programas codificados em linguagem de alto nível para um código intermediário e o coloca em execução.
• Exemplos: – o run do Pascal ou C;– Java: sitemas distribuídos, diferentes equipamentos;
(bytecode)» Cerca de 10 vezes mais lento que um código
compilado C++;» Pode ser interpretado em plataformas diferentes;
Compiladores - Prof. Yandre - 9
Programa FontePrograma Fonte Código Intermediário em Execução
Código Intermediário em Execução
InterpretadorInterpretador
Introdução• Hierarquia:
Compiladores - Prof. Yandre - 10
TRADUTORES
INTERPRETADORES
PRÉ-PROCESSADORES
COMPILADORES
MONTADORES
Regras de Produção<cmd> id := <expr>
| if <expr> then <cmd>
| if <expr> then <cmd> else <cmd>
| while <expr> do <cmd>
| begin <cmds> end.
<cmds> <cmd> <cmds>
|
<expr> <expr> + termo
| <expr> - termo
| termoCompiladores - Prof.
Yandre - 11
Análise Léxica
Realizada pelo Analisador Léxico ou SCANNER;
Identifica no arquivo fonte os símbolos pertencentes à linguagem;
Compiladores - Prof. Yandre - 12
Fluxo de Caracteres de Entrada
(Prog. Fonte)
Analisador Léxico
Fluxo de Tokens
Análise Léxica
Tarefas do Analisador Léxico:– Percorrer o programa fonte (arquivo texto),
passando por cada um de seus caracteres;
– Formar itens léxicos a partir dos caracteres consecutivos, que podem ser de vários tipos:
• palavras reservadas;• identificadores;• constantes numéricas;• símbolos especiais.
Compiladores - Prof. Yandre - 13
Análise Léxica
Atribuir um código numérico (token) a cada um dos itens léxicos encontrados;
Ignorar espaços em branco e comentários; Detectar erros léxicos:
– caracteres inválidos. Exemplo: a:=2#3;– tamanho dos identificadores;
Compiladores - Prof. Yandre - 14
Análise Léxica
Exemplo: análise léxica do seguinte programa em Pascal.
• Identificar: Token, ítem léxico, tipo.
Compiladores - Prof. Yandre - 15
program exemplo;var A, B: real;begin A:=B+0.5;end.
Tabela de Símbolos
• É uma estrutura de dados com algoritmos apropriados para a manipulação de seus dados (listas, árvores, arranjos, ...);
Guarda informações sobre os identificadores:– Nome– Endereço– Tipo
Compiladores - Prof. Yandre - 16
Tabela de Símbolos
• Uma tabela de símbolos possui um registro para cada identificador;
• A estrutura de dados que manipula esta tabela deve permitir rápido armazenamento ou recuperação dos dados.
Compiladores - Prof. Yandre - 17
Análise Sintática
• Executada pelo PARSER (Analisador Sintático);
• Procura agrupar os TOKENS obtidos pelo SCANNER em estruturas sintáticas (declarações, comandos, corpo do programa, blocos, lista de identificadores, programa, ...) verificando a sintaxe da linguagem;
Compiladores - Prof. Yandre - 18
Análise Sintática
Program Exemplo; Var A, B: byte; begin A := B + 0,5; end.
Compiladores - Prof. Yandre - 19
Lista Ident.
Declaração Comando
Expressão
Cabeçalho
Corpo Prog.
Bloco
Programa
Análise Sintática• As regras gramaticais que definem as construções da
linguagem podem ser descritas através de produções, cujos elementos incluem símbolos terminais (que fazem parte do código fonte) e símbolos não-terminais (que geram outras regras);
• As seguintes regras definem o comando WHILE, da linguagem Pascal, nas quais as palavras em maiúsculo representam terminais e as palavras em minúsculo os não-terminais:comando comandoWhile
| comandoIf| comandoAtrib,| ...
comandoWhile WHILE expr_bool DO comando;expr_bool expr_arit < expr_arit
| expr_arit > expr_arit | ...
expr_arit expr_arit * termo | termo | ...
termo expr_arit| NÚMERO| IDENTIFICADOR Compiladores - Prof.
Yandre - 20
Análise Semântica• Funções:
• Verificar se o significado das construções sintáticas possibilitam a geração de código;
• Extrair informações do programa fonte que possibilitem a geração de código;
• Por exemplo, o seguinte comando IF, sintaticamente correto, pode existir em um programa:
if a>7 then b:=5 else b:=10;• Depende dos tipos das variaveis a e b
Compiladores - Prof. Yandre - 21
Análise Semântica
• Principais verificações semânticas:• Compatibilidade de tipos
...
var A: boolean;
B: real;
...
A:=B+0,5;
Compiladores - Prof. Yandre - 22
Análise Semântica
– Duplicidade de identificadores:• Var A, A, B: integer;
– Compatibilidade entre declarações e uso de entidades:
• Var X: array[1..N] of byte;
A: byte;
...
A:=X.C1;
Compiladores - Prof. Yandre - 23
Análise Semântica
– Compatibilidade entre parâmetros formal e atual:
• procedure X (a, b: integer);
begin
...
end;
...
X(a, b, c);
Compiladores - Prof. Yandre - 24
Tratamento de Erros
• Este módulo é responsável por diagnosticar os erros (léxicos, sintáticos e semânticos) e emitir mensagens apropriadas;
• É interessante que este módulo permita recuperar o analisador a partir de uma situação de erro e analise o restante do programa fonte.
Compiladores - Prof. Yandre - 25
Geração de Código Intermediário• Gera um conjunto de instruções, equivalentes
ao programa fonte, para uma máquina hipotética.• Ex.: A:=(B+C) * (D+E)
• Gera-se quádruplas:• (+, B, C, T1)• (+, D, E, T2)• (*, T1, T2, A)
• Esta representação intermediária tem as seguintes vantagens:• Possibilita a otimização do código intermediário, a
fim de obter código objeto final mais eficiente;• Resolve, de maneira gradual, problemas da
passagem do código fonte para objeto Compiladores - Prof.
Yandre - 26
Geração de Código Intermediário A maior diferença entre o código intermediário e o
código objeto é que o intermediário não especifica detalhes de baixo nível de implementação, tais como endereços de memória e registradores, entre outros.
Para o comando: while i < 100 do i := j * i;
o seguinte código de três endereços (um dos tipos de código intermediário utilizado, no qual cada instrução deve ter, no máximo, três operandos) é gerado:
L0 : if i < 100 goto L1 goto L2L1: temp := j * i i := temp goto L0L2: ... Compiladores - Prof.
Yandre - 27
Otimização de Código Função: melhorar o código intermediário de
forma que ocupe menos espaço e/ou “execute” mais rápido.
Principais otimizações:• Agrupamento de sub-expressões comuns:
C:= (A+B) * (A+B)(+, A, B, T1)(+, A, B, T2)(*, T1, T2, C)
Ou, para o código do slide 27:L0: if i 100 goto L1 temp := j * i
i:= temp goto L0L1 ...
Compiladores - Prof. Yandre - 28
(+, A, B, T1)(*, T1, T1, C)
Compiladores - Prof. Yandre - 28
Compiladores - Prof. Yandre - 28
Otimização de Código• Eliminação de JUMPS desnecessários:
...10: JUMP 20...20: JUMP 30...
• Remoção de comandos invariantes dentro do loop:...For I:= 1 to 100 do Begin ... J:=X; {não modifica X} ... End;
Compiladores - Prof. Yandre - 29
10: JUMP 30
...J:=X; {transferir p/ cá} For I:= 1 to 100 do Begin ... End;
Geração de Código Objeto
• Sua principal função é gerar o código equivalente ao programa fonte para uma máquina real, a partir do código intermediário otimizado.
Compiladores - Prof. Yandre - 30
Análise Sintática (Parsing)
• É realizada pelo Analisador Sintático ou Parser;
• O parser é um algoritmo que, recebendo como entrada uma cadeia , emite como saída:• Aceitação de , se pertence à
linguagem, ou• ERRO, se não pertence à linguagem.
Compiladores - Prof. Yandre - 31
Análise Sintática (Parsing)
Análise sintática (parse) top-down: é uma análise onde se procura, a partir do símbolo de partida da gramática, chegar à cadeia que está sendo analisada progredindo nas regras de produção;
Esta análise equivale à seqüência dos números das regras de produção utilizadas S através de derivações mais à esquerda.
Compiladores - Prof. Yandre - 32
Análise Sintática (Parsing)
Análise sintática (parse) bottom-up: é uma análise onde se procura, a partir da cadeia que está sendo analisada, chegar ao símbolo inicial da gramática regredindo nas regras de produção;
Esta análise equivale à seqüência invertida dos números das regras de produção utilizadas S através de derivações mais à direita.
Compiladores - Prof. Yandre - 33
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 34
Descendente(Top-down)
Ascendente(Bottom-up)
Com retrocesso(back track)
Sem retrocesso(preditive)
Analisadores Sintáticossimbolo de partida para
a sentença sentença para o simbolo de partida
Análise sintática descendente:– Com retrocesso (back track): Quando a gramática permite, em um
determinado estágio da derivação, a aplicação de mais de uma regra. Isto acontece quando o mesmo símbolo terminal aparece no início do lado direito de mais de uma regra de produção.
Exemplo:
A aA a
Onde: , (VN VT)*
A VN
a VT
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 35
• Análise sintática descendente:• Sem retrocesso (preditive): Quando a gramática só permite
um caminho a ser derivado. Desta forma, olhando apenas para o próximo símbolo de entrada podemos determinar a próxima derivação.
• Requisitos:• Durante o processo de derivação, sempre haverá uma
única regra que possa levar a cadeia que está sendo analisada.
• Não pode haver recursão à esquerda.• Exemplo: A A
Onde (VN VT)* e A VN
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 36
• Preditive parser recursivo:• É executado um conjunto de procedimentos recursivos para
processar a entrada. A cada não terminal é associado um procedimento;
• Existe também um procedimento adicional para o reconhecimento dos símbolos (tokens);
• Vantagens:• Simplicidade;
• Desvantages:• Maior tempo de processamento;• Não é geral (requisitos transp. 36);• Existem linguagens que não aceitam recursividade.
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 37
Exemplo de analisador preditivo recursivo para a seguinte gramática:
<tipo> <tipo_simples>
<tipo> id<tipo> array [<tipo_simples>] of <tipo>
<tipo_simples> integer
<tipo_simples> char
<tipo_simples> num..num
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 38
1)
2)
3)
4)
5)
6)
Análise Sintática (Parsing)
procedimento reconhecer (t: token);
início
se lookahead=t então
lookahead:=próximo_token
senão erro;
fim;
Compiladores - Prof. Yandre - 39
Análise Sintática (Parsing)
procedimento tipo;início se lookahead está em {integer, char, num} então tipo_simples; senão se lookahead=‘↑’ então início reconhecer (‘↑’); reconhecer (id) fim senão se lookahead=array então início reconhecer(array); reconhecer(‘[‘);
tipo_simples; reconhecer(‘]’); reconhecer(of); tipo;
fim senão errofim; Compiladores - Prof.
Yandre - 40
Análise Sintática (Parsing)
procedimento tipo_simples;início se lookahead = integer então reconhecer (integer) senão se lookahead=char então reconhecer (char); senão se lookahead=num então início
reconhecer (num); reconhecer(pontoponto); reconhecer (num)
fim senão errofim;
Compiladores - Prof. Yandre - 41
Exemplo de processamento para a seguinte cadeia:
array [num..num] of integer
tipo: reconhecer(array); reconhecer(‘[‘); tipo_simples: reconhecer(num); reconhecer(‘..’); reconhecer(num); reconhecer(‘]’); reconhecer(of); tipo: tipo_simples: reconhecer(integer);
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 42
Cálculo do first: o cálculo do first (ou primeiro) é fundamental para verificar se a partir de um mesmo símbolo terminal existem duas possibilidades de derivação que produzam um mesmo símbolo terminal mais à esquerda (na primeira posição).
First(A) (ou Primeiro(A)) é o conjunto de tokens (símbolos) que figuram como primeiro elemento de uma ou mais cadeias geradas a partir de A.
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 43
Exemplo 1:S AS | BA
A aB | C
B bA | d
C c
First(S) = First(A) First(B) = {a, c, b, d}
First(A) = {a, c}
First(B) = {b, d}
First(C) = {c}
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 44
Exemplo 2:S ABC | A aA | B bB | ACd
C cC |
First(S) = {a, c, b, d, }
First(A) = {a, }
First(B) = {b, a, c, d}
First(C) = {c, }
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 45
• Assim, só se pode aplicar o analisador preditivo recursivo em uma gramática se para todas as regras do tipo A , A , ...(onde , (VN VT)*), os conjuntos First() e First() forem disjuntos.
Análise Sintática (Parsing)
Compiladores - Prof. Yandre - 46
Top Related