Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto...

19
Slide 1 Compiladores I CP 5017.9 – Compiladores I CP 5017.9 – Compiladores I Prof. Msc. Carlos de Salles Prof. Msc. Carlos de Salles 1 - EMENTA O Processo de Compilação. Deteção e Recuperação de Erros. Introdução à geração de Código Intermediário. Geração de Código de Máquina. Otimização. Uma visão sobre alguns compiladores. A construção de um compilador. 2 - O PROCESSO DE COMPILAÇÃO 2.1 - Introdução 2.2 - Aspectos do Processo de Compilação 3 - DEFINIÇÃO DE LINGUAGEM 3.1 - Introdução 3.2 - Sintaxe e Semântica 3.3 - Gramáticas - Definição Formal de Linguagem de Programação 3.4 - O Problema da Análise 4 - ANÁLISE LÉXICA 4.1 - Introdução 4.2 - Construção Manual de Analisadores 4.3 - Construção Sistemática de Analisadores 4.4 - Saídas do Analisador Léxico 4.5 - Implementação 4.6 - Erros 5 - GRAMÁTICAS LIVRES DO CONTEXTO 5.1 - Sintaxe e Semântica 5.2 - Gramáticas - Definição Formal de Linguagens de Programação 5.3 - Gramáticas Livres do Contexto

Transcript of Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto...

Page 1: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 1 Compiladores I

CP 5017.9 – Compiladores ICP 5017.9 – Compiladores IProf. Msc. Carlos de SallesProf. Msc. Carlos de Salles

1 - EMENTAO Processo de Compilação. Deteção e Recuperação de Erros. Introdução à geração de Código Intermediário. Geração de Código de Máquina. Otimização. Uma visão sobre alguns compiladores. A construção de um compilador.

2 - O PROCESSO DE COMPILAÇÃO 2.1 - Introdução 2.2 - Aspectos do Processo de Compilação

3 - DEFINIÇÃO DE LINGUAGEM 3.1 - Introdução 3.2 - Sintaxe e Semântica 3.3 - Gramáticas - Definição Formal de Linguagem de Programação 3.4 - O Problema da Análise

4 - ANÁLISE LÉXICA 4.1 - Introdução 4.2 - Construção Manual de Analisadores 4.3 - Construção Sistemática de Analisadores 4.4 - Saídas do Analisador Léxico 4.5 - Implementação 4.6 - Erros

5 - GRAMÁTICAS LIVRES DO CONTEXTO 5.1 - Sintaxe e Semântica 5.2 - Gramáticas - Definição Formal de Linguagens de Programação 5.3 - Gramáticas Livres do Contexto

Page 2: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 2 Compiladores I

CP 5017.9 – Compiladores I CP 5017.9 – Compiladores I Prof. Msc. Carlos de SallesProf. Msc. Carlos de Salles

Ementa (continuação)

6 - ANÁLISE SINTÁTICA DESCENDENTES 6.1 - Formalização 6.2 - Análise com Recuperação 6.3 - Análise sem Recuperação 6.3.1 - Analisadores Recursivos 6.3.2 - Analisadores Preditivos

7 - ANÁLISE SNTÁTICA ASCENDENTE 7.1 - Formalização 7.2 - Analisadores de Precedência

8 - TRADUÇÃO DIRIGIDA POR SINTAXE 8.1 - Esquemas da Tradução Dirigida por Sintaxe 8.2 - Implementação de Tradutores Dirigidos por Sintaxe

9 - TABELA DE SÍMBOLOS 9.1 - Os Conteúdos da Tabela de Símbolo 9.2 – Organizações de Tabelas de Símbolos

10 - ORGANIZAÇÃO DE MEMÓRIA11 - CONSTRUÇÃO AUTOMÁTICA DE

ANALISADORES EFICIENTES

Bibliografia• GRUNE, DICK et al. Projeto Moderno de Compiladores.

Editora Campus.• AHO, Alfred; SETHI, Ravi; ULLMAN, Jeffrey D. Compiladores

– Princípios, Técnicas e Ferramentas. Editora Guanabara. Editora LTC.

Page 3: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 3 Compiladores I

Paradigma análise/síntese

código fonte interface devanguarda

código intermediário geradorde código

código alvo

Estrutura básica de um compilador

Page 4: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 4 Compiladores I

Interface de vanguarda do compilador

• Engloba as fases de análise• Gera uma representação semântica intermediária

• Análise léxica– Converte uma seqüência de caracteres no(s)

arquivo(s) de entrada com o código fonte em uma seqüência de tokens equivalente;

– Cada token representa um elemento atômico da linguagem;

• Análise sintática– Transforma a seqüência de tokens em uma árvore

sintática que representa o código fonte;– É dividido em dois grupos de métodos: os top-down

e os bottom-up;

• Tratamento de contexto– Avalia erros de tipagem e nos identificadores;– Baseia-se em informações coletadas numa

estrutura chamada tabela de símbolos.

Page 5: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 5 Compiladores I

Geração de código X Interpretação

• Geração de código– Transforma a representação semântica intermediária em

código executável em uma linguagem alvo;– Características:

• Processamento considerável;• A forma intermediária resultante, que é de código binário

específico da máquina, é de baixo-nível;• O mecanismo de interpretação é o próprio hardware da

CPU;• A execução do programa é relativamente rápida;

• Interpretação– Ao invés de traduzir para uma linguagem alvo, realiza as

ações semânticas diretamente;– Vantagens:

• Geralmente um interpretador é escrito em uma linguagem de mais alto nível, portanto irá rodar em várias máquinas diferentes. Um gerador de código é voltado para uma máquina específica;

• Escrever um interpretador exige esforço bem menor;• Executar as ações diretamente da representação semântica

permite tanto uma melhor verificação quanto informação de erros;

• Melhor segurança (explorado por Java)– Características:

• O processamento do programa é de mínimo a moderado;• A forma intermediária resultante, alguma estrutura de dados

específica de sistema, de médio a alto nível;• O mecanismo de interpretação é um programa;• A execução do programa é relativamente lenta.

Page 6: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 6 Compiladores I

Por que estudar Compiladores?

• Estruturação eficaz do problema– Compiladores analisam sua entrada, constroem uma

representação semântica intermediária e sintetizam sua saída a partir disso;

– Esse paradigma análise-síntese é muito poderoso e amplamente aplicável;

– Usando a mesma representação semântica intermediária, um compilador pode ser escrito para L linguagens e M máquinas, bastando escrever as L interfaces de vanguarda diferentes e os M sintetizadores diferentes;

• Uso eficiente de formalismos– Expressões regulares – análise léxica– Gramáticas livres de contexto – análise sintática– Gramáticas de atributo – tratamento de contexto e

extensão para geração de código e interpretação– Casamento de padrões e técnicas de programação

dinâmica – geração de código• Uso de ferramentas de geração de programas

– A entrada para um gerador de programas é de um nível de abstração mais alto que de uma linguagem de programação;

– Flexibilidade e mutabilidade ampliadas;– Código pré-construído pode ser incluído em um programa

gerado, aumentando seu poder a quase nenhum custo;– Uma descrição formal pode ser usada para gerar mais de

um tipo de programa;– Exemplo: Flex/Bison; Lex/Yacc.

Page 7: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 7 Compiladores I

Por que estudar Compiladores?

• A construção de compiladores tem uma ampla aplicabilidade;– O uso de técnicas de construção de compiladores

são aplicadas em outros escopos– Exemplos:

• Conversão de formatos diferentes de arquivos;• Leituras de arquivos HTML ou PostScript.

• Compiladores são baseados em algoritmos gerais úteis– As estruturas de dados e algoritmos

implementados são didaticamente importantes– Exemplos:

• Árvores sintáticas;• Tabelas hash;• Tabelas pré-processadas ;• Coletor de lixo;• Programação dinâmica, etc.

• Enfim, estudar compiladores é solidificar o conhecimento de programação!

Page 8: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 8 Compiladores I

Propriedades de um bom compilador

• Gerar código correto;– De que adianta um compilador que erra uma vez a

cada um milhão;• Estar de acordo com a especificação da

linguagem;– Nada de super ou sub-conjuntos da linguagem;

• Ser escalável, ou seja, ser capaz de tratar códigos fonte de tamanhos arbitrários;– Atualmente isso é muito mais simples já que a

quantidade de memória disponível é cada vez maior;

• Velocidade de compilação não é mais importante;– Nada mais de cartões – compilar agora é rápido;

• Algoritmos desejavelmente lineares – O(n);– Não é interessante a existência de algoritmos não-

lineares no processo de compilação;– Problema: a otimização de código não é linear;

• Outras características importantes:– Portabilidade do compilador;– Portabilidade do código alvo;

Page 9: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 9 Compiladores I

Histórico de compiladores

• 1945 – 1960: Geração de Código– Linguagens sendo desenvolvidas lentamente;– O uso de compiladores era chamado de

“programação automática”;– Linguagens “de alto nível” não eram bem vistas;

• Se o compilador gerava código inferior àquele gerado manualmente com assemblers, para que uma linguagem de alto nível?

• 1960 – 1975: Parsing– Proliferação de novas linguagens;– Nasce a idéia que é melhor ter ferramentas para

gerar um compilador rapidamente que gerar código mais eficiente;

– Mudança no paradigma: maior enfoque na análise que na síntese;

– Aparecimento de técnicas formais notadamente voltadas para a geração de parsers;

• 1975 – dias atuais: Geração e Otimização de Código; Novos Paradigmas– Número de novas linguagens e de novas máquinas

caem;– Demanda por interfaces com o usuário mais

amigáveis (nascimento dos IDEs);– Novos paradigmas de programação, como

linguagens funcionais e lógicas e programação distribuída;

– A ênfase agora é “o que compilar” e não mais “como compilar”.

Page 10: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 10 Compiladores I

Análise Léxica

• O objetivo da análise léxica é ler o(s) arquivo(s) fonte de entrada, caractere a caractere, e transformá-lo(s) numa seqüência de símbolos léxicos chamados de tokens;

• Tokens são elementos indivisíveis da linguagem como palavras reservadas, constantes, cadeias de caracteres, identificadores, operadores e outros delimitadores

• Internamente, um token pode ser expresso por três informações:– Classe do Token: define seu tipo;

• Exemplos: operador, palavra reservada, identificador etc.

– Valor do Token: dependendo da classe do token, assume um valor que o representa;

• Exemplos: “i” para um identificador; “123” para uma constante numérica etc;

– Posição do Token: define o arquivo e a posição (linha e coluna) dentro daquele arquivo do respectivo token.

Page 11: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 11 Compiladores I

Implementação de um Analisador Léxico

• Como ler o arquivo texto de entrada?– Memória não é mais um problema;– A entrada por dois buffers (atual e anterior);– Leitura do arquivo de entrada colocando-o em

memória em uma única chamada ao sistema operacional;

• O problema da nova linha– No Windows/DOS, uma nova linha é marcada

pela seqüência de caracteres ASCII 13 e 10;– No Linux, uma nova linha é marcada pelo

caractere ASCII 10;– No OS/2, cada linha é um vetor de caracteres;

• O que é um token exatamente?– Simplificação: se você pode colocar espaços

na esquerda e direita sem alterar o significado, trata-se de um token;

• Comentários não são tokens. A análise léxica os remove da seqüência de tokens gerada como saída.

Page 12: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 12 Compiladores I

Interface de Programação (API) Léxica

• Funções públicas– void startLex(string fileName);

• Abre o arquivo fonte de entrada fileName e o copia por inteiro para a memória

• Caso o compilador manipule múltiplos arquivos, utiliza uma pilha para armazenar a posição em que estava manipulando o arquivo atual e abre o novo arquivo

– Token nextToken();• Avalia o arquivo fonte atual, caractere por

caractere, e retorna o próximo token• Implementação de autômatos

• Algumas funções privadas úteis– char nextChar();

• Retorna o próximo caractere do arquivo atual, contando as linhas e colunas;

– void skipLayoutAndComment();• Percorre o fonte ignorando comentários

até encontrar um caractere que não seja espaço, tabulação ou pulo de linha

Análise LéxicaArquivos fonte Tokens

Page 13: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 13 Compiladores I

Expressões Regulares (ER)

Padrões Básicos: Significado:x O caractere x. Qualquer caractere, exceto nova linha[xyz...] Quaisquer caracteres x, y, z, ...

Operadores de repetição:R? Um R ou nada (opcionalmente R)R* Zero ou mais ocorrências de RR+ Uma ou mais ocorrências de R

Operadores de composição:R1R2 Um R1 seguido de um R2R1|R2 Ou R1, ou R2

Agrupamento:(R) R por si só

Exemplos:inteiro := [0..9]+real := [0-9]*{.}[0-9]+identificador := [a-zA-Z][a-zA-Z0-9_]*

Page 14: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 14 Compiladores I

Autômatos expressando ER's

• Número inteiro – [0-9]+

• Número real – [0-9]*{.}[0-9]+

• Identificador – [a-zA-Z][a-zA-Z0-9_]*

• Exemplo mais complexo [a][b|c]*[d]+{e}

1 0-9

0-9

2

1 0-9

0-9

2 3 0-9

0-9

4

.

.

1 a-zA-Z

a-zA-Z0-9_

2

1 a e 42 d

bc

3

d

Page 15: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 15 Compiladores I

Análise Sintática

• Responsável pela construção da árvore sintática abstrata (AST) com base nos tokens de entrada;

• Há dois tipos de métodos de parsing (verificação sintática):– Top-down: a árvore sintática é construída da

raiz para as folhas– Bottom-up: a partir das folhas da árvore são

construídas hipóteses que montam recorrentemente seus pais, de forma que a raiz da árvore é o último nó a ser construído

• Uma linguagem de programação é formalmente definida por uma gramática, tipicamente livre de ambigüidade, de forma que uma única árvore sintática pode representar o fonte;

• Linguages de programação geralmente são expressas por meio de uma notação chamada BNF (Backus Naur Form) ou sua extensão E-BNF (Extended-BNF) que acrescenta o uso de expressões regulares

Análise SintáticaÁrvore SintáticaTokens

Page 16: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 16 Compiladores I

Árvore sintática – expressão b*b-4*a*c

Árvore sintática abstrata

Árvore Abstrata Anotada

Page 17: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 17 Compiladores I

Parser Recursivo Descendente

• Método top-down baseado no mecanismo de recursão das linguagens de programação;

• O processo inicia com a construção da raiz da árvore sintática, representando um não-terminal N;

• A decisão da alternativa correta a ser considerada de N é feita com base em um processo recursivo que tenta as alternativas de N;

• A alternativa escolhida é a primeira possível, de forma a evitar backtracking, o que simplifica o processo mas cria alguns problemas;

• Exemplo de gramática:entrada → expressao EOFexpressao → termo resto_expressaotermo → IDENT | parenteses_expparenteses_exp → '(' expressao ')'resto_expressao → operador expressao | εoperador → '+' | '-' | '*' | '/'

• Tokens dessa linguagem:IDENT := [a-zA-Z][a-zA-Z0-9_]*EOF, '(', ')', '+', '*', '-', '/'

Page 18: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 18 Compiladores I

Parser Recursivo Descendentebool entrada() {

return expressao() && tk(EOF);}bool expressao() {

return termo() && resto_expressao();}bool termo() {

return tk(IDENT) || parenteses_exp();}bool parenteses_exp() {

return tk('(') && expressao() && tk(')');

}bool resto_expressao() {

return (operador() && expressao() ) || true;

}bool operador() {

return tk('+') || tk('-') || tk('*') || tk('/');

}bool tk(Token tt) {

if(tokenAtual!=tt) return false;getNextToken(); return true;

}

Page 19: Projeto de Compiladores - DEINF/UFMAcsalles/comp/comp_parte1.pdf · • GRUNE, DICK et al. Projeto Moderno de Compiladores. Editora Campus. • AHO, Alfred; SETHI, Ravi; ULLMAN, ...

Slide 19 Compiladores I

Conjunto FIRST de uma gramática

• entrada { IDENT ’(’ }• expressao { IDENT ’(’ }• termo { IDENT ’(’ }• parenteses_exp { ’(’ }• resto_expressao { ’+’ ε }

Data definitions:1. Token sets called FIRST sets for all terminals, non-terminals and alternatives of non-terminals in G.2. A token set called FIRST for each alternative tail in G; an alternative tail is a sequence of zero or more grammar symbols α if A α is an alternative or alternative tail in G.Initializations:1. For all terminals T, set FIRST(T) to {T}.2. For all non-terminals N, set FIRST(N) to the empty set.3. For all non-empty alternatives and alternative tails α, set FIRST(α) to the empty set.4. Set the FIRST set of all empty alternatives and alternative tails to {ε}.Inference rules:1. For each rule N→α in G, FIRST(N) must contain all tokens in FIRST(α), including ε if FIRST(α) contains it.2. For each alternative or alternative tail α of the form Aβ, FIRST(α) must contain all tokens in FIRST(A), excluding ε, should FIRST(A) contain it.3. For each alternative or alternative tail α of the form Aβ and FIRST(A) contains ε, FIRST(α) must contain all tokens in FIRST(β), including ε if FIRST(β) contains it.