Prévia do material em texto
UNIVERSIDADE DE BELAS COMPILADORES CURSO: ENGENHARIA INFORMÁTICA ANO: 4º SEMESTRE: II PROF: NSIMBA BIRTON Conceitos de compiladores Um compilador é um programa que transforma um outro programa escrito em uma linguagem de programação de alto nível qualquer em instruções que o computador é capaz de entender e executar, isto é, em código de máquina. 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 programação para uma linguagem que possa ser entendida e executada por um computador. Métodos de implementação 1.Compilação: Tradução do programa fonte paraLinguagem máquina: Tradução lenta, execução rápida 2.Interpretação: Traduz e executa Consome muito tempo: de 10 a 100 vezes mais lento que um programa compilado. Métodos de implementação 3.Sistemas híbridos: Tradução do programa fonte para Linguagem intermediária (bytecodes) para facilitar a interpretação - Máquina virtual - (implementações iniciais de Java usavam esse conceito). 4. Sistemas híbridos Just – in – time: Tradução do programa fonte Linguagem intermediária (bytecodes) compila os bytecodes em código de máquina nativa quando eles são chamados (tempo de execução) execução) para executar executar na máquina máquina nativa. Código é mantido mantido para chamadas subsequentes. Ex: Java Divisão de compilador O compilador divide-se em duas fases: análise e síntese: A fase da análise está directamente associada à verificação de se o programa foi escrito correctamente, isto é, de acordo com as regras da linguagem. A análise está subdividida em 3 etapas: • Léxica: em que se verifica se os nomes das entidades estão correctos. • Sintática: analisa-se se os comandos estão correctos. Chama a verificação da frase. Aqui, não basta escrever as palavras correctamente, importando também a ordem em que elas aparecem. • Semântica: nesse ponto, verifica-se o contexto. No caso das linguagens de programação, o compilador deverá analisar se os valores envolvidos nos comandos estão compatíveis. A fase de análise, portanto, trata da corretude do programa quanto à sua gramática. Análise léxica (AL) Erros léxicos: O AL tem uma visão muito localizada no programa-fonte. Exemplo: fi (a > b) then O AL não consegue dizer que fi é a palavra reservada if mal escrita desde que fi é um identificador válido O AL devolve o código de identificador e deixa para as próximas fases identificar os erros. Reais: há um limite para o número de casas decimais Strings: o token ‘aaaaaaaaaaaaaaaaa … não fecha antes do tamanho máximo. É exemplo de má formação de string; Há um limite para o tamanho da string; Se ferir o limite há erro; Outros erros léxicos Tamanho de identificadores ➢ Geralmente, a linguagens aceitam até um tamanho de diferenciação e descartam descartam o resto sem indicar indicar erro. Fim de arquivo inesperado ➢ ocorre quando se abre comentário e não se fecha, por exemplo. Análise sintática(AS) A AS é o processo de determinar se uma cadeia de átomos (tokens), isto é, o programa já analisado pelo AL, pode ser gerado por uma gramática seu objetivo é a construção da árvore sintática ou apenas a decisão se a cadeia fornecida é ou não uma sentença da gramática que define a linguagem. Erros sintáticos: a AS se preocupará com a estrutura (formação) do programa Erros sintáticos: a AS se preocupará com a estrutura (formação) do programa Exemplo: fi (a > b) then O AL não consegue dizer que fi é a palavra reservada if mal escrita desde que fi é um identificador válido É na AS que este erro é detectado Erros sintáticos: a AS se preocupará com a estrutura (formação) do programa. Exemplos: esquecer de abrir e/ou fechar parênteses ou aspas usar uma palavra reservada como variável uso de = ao invés de := (pascal) writelm ao invés de writeln (pascal) Fro ao invés de For Análise semântica (ASem) A ASem é o processo de Calcular o “significado” do programa Erros semânticos tipos inválidos - o programa dá um resultado, mas não é correcto! o computador não advinha o que eu quero logo: o programa que escrevi não resolve o problema pretendido os erros semânticos são os mais difíceis de corrigir. Funções da Asem Checa os tipos de cada expressão Relaciona declarações de variáveis com seus usos É caracterizado pela manipulação de tabelas de símbolo Mapeiam identificadores a seus tipos e localizações Declarações geram inclusões nas tabelas de símbolos Exercício Analise o código fonte (pascal) abaixo e identifique/classifique os erros em: léxicos, sintáticos e semânticos: int I2, A@; I2=0; while I2>=0; do I:=I+1; I2= ´ a ´ 2A=I2$5; A fase de síntese visa gerar o código alvo a partir dos resultados obtidos pelas fases intermediárias, que são: • Gerenciamento da tabela de símbolos: as diversas etapas do compilador alimentam e consultam essa tabela para coletar informações (nomes, tipos, atributos). • Geração do código intermediário: a conversão para o código alvo é feita em etapas, e esta é uma conversão intermediária, em que as instruções serão representadas em não mais que três endereços. • Otimização do código: realiza transformações no código com o objetivo de melhorar o tempo de execução, o consumo de memória ou o tamanho do código. • Geração do código: essa é a fase final, que gera o código alvo. Nesta seção estudamos a evolução das linguagens de programação, os princípios comuns a todas as linguagens, os principais paradigmas de programação e como esse conhecimento é fundamental para compreendermos as estruturas das linguagens. Isso dará base para, na próxima seção, compreendermos e especificarmos a gramática das linguagens e aprofundarmos os conhecimentos sobre os tipos de tradutores das linguagens, como os compiladores estão estruturados e, sobretudo, entendermos a organização das fases do processo de compilação. Estrutura geral de um compilador Construção de compiladores A construção de compiladores engloba várias áreas desde teoria de linguagens de programação até engenharia de software, passando por arquitectura de máquina, sistemas operativos e algoritmos. Algumas técnicas básicas de construção de compiladores podem ser usadas na construção de ferramentas variadas para o processamento de linguagens, como por exemplo: • compiladores para linguagens de programação: um compilador traduz um programa escrito numa linguagem fonte em um programa escrito em uma linguagem objecto; • formatadores de texto: um formatador de texto manipula um conjunto de caracteres composto pelo documento a ser formatado e por comandos de formatação (parágrafos, figuras, fórmulas matemáticas, negrito, itálico, etc). São exemplos de textos formatados os documentos escritos em editores convencionais, os documentos escritos em HTML (HyperText Markup Language), os documentos escritos em Latex, etc.; • interpretadores de queries (consultas a base de dados): um interpretador de queries traduz uma query composta por operadores lógicos ou relacionais em comandos para percorrer um base de dados. Processadores de linguagens Um processador é um programa que permite ao computador “entender” os comandos de alto nível escritos pelos usuários. Existem dois tipos principais de processadores de linguagem: os interpretadores e os tradutores. Um interpretador (figura 3.4) é um programa que aceita como entrada um programa escrito em uma linguagem chamada linguagem fonte e executa directamente as instruções dadas nesta linguagem. Um tradutor (figura 3.5) é um programa que aceita como entrada um programa escrito em uma linguagem fonte e produz como saída um programa escrito em uma linguagem objecto. Muitas vezes a linguagem objecto é a própria linguagem de máquina do computador. Nesse caso, o programa objecto pode ser directamente executadopela máquina. Tradutores são divididos em dois tipos: montadores e compiladores, os quais traduzem linguagens de baixo nível e linguagens de alto nível, respectivamente. Existem também o pré-processador que traduz uma linguagem de alto nível em outra linguagem de alto nível e o cross-compiler que gera código para outra máquina diferente da utilizada para compilação. A figura abaixo (FIGURA 3.6) esquematiza os três tipos de tradutores. Diferença entre interpretador e compilador? Compiladores e interpretadores recebem código legível por seres humanos e convertemno para código de máquina, legível pelo computador. Em uma linguagem compilada, a máquina de destino traduz o programa diretamente. Em uma linguagem interpretada, o código fonte não é traduzido diretamente pela máquina de destino. Diferente do compilador o interpretador recebe como entrada uma especificação executável e produz como saída, a execução dessa especificação. Linguagens como PHP, Scheme, Python são interpretadas. Um interpretador pode ser entendido como um processo que, ao invés de visar um conjunto de instruções de um processador, visa produzir o efeito de sua execução. Eles normalmente interpretam uma representação intermediária do programa fonte. No esquema abaixo podemos ter uma ideia macro das diferenças de funcionamento de um compilador e um interpretador.