1 / 63

Introdução a Compiladores

Introdução a Compiladores. Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife. Contatos. Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/ gtalk : alexandrecordel@gmail.com greinaldo@fbv.edu.br

keegan-rice
Download Presentation

Introdução a Compiladores

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introdução a Compiladores Prof. AlexandreMonteiro Baseadoem material cedidopelo Prof. EuclidesArcoverde Recife

  2. Contatos • Prof. Guilherme Alexandre Monteiro Reinaldo • Apelido: Alexandre Cordel • E-mail/gtalk: alexandrecordel@gmail.com greinaldo@fbv.edu.br • Site: http://www.alexandrecordel.com.br/fbv • Celular: (81) 9801-1878

  3. Agenda • História • Linguagens de Alto Nível • Introdução a Compiladores

  4. Objetivo • O principal objetivo é responder à seguinte pergunta: • Como criar uma linguagem computacional? • Para responder a pergunta, estudaremos: • Como especificar uma linguagem • Como construir um compilador para ela

  5. História das Linguagens

  6. História • O surgimento dos compiladores está fortemente ligado à história das linguagens de programação, que, por sua vez, está ligada à história dos computadores modernos

  7. História dos Computadores • Computadores com “programas fixos” – todos até a década de 40 • Programa implícito no hardware • A maioria tinha propósito específico, como acontece com as calculadoras modernas • Apenas uma minoria podia ser reprogramada, o que era feito de maneira mecânica • Ligando e desligando fios

  8. História dos Computadores • Computadores de programas armazenados a partir da década de 40 com o SSEM – Manchester Small-Scale Experimental Machine • São os computadores modernos, de propósito geral • Diferentes programas podem ser criados e carregados na memória • Programas escritos usando um conjunto de instruções, representadas em código binário • Linguagem de máquina!

  9. Fonte: http://en.wikipedia.org/wiki/Manchester_Small-Scale_Experimental_Machine

  10. ENIAC • Pesava 30 toneladas, media 5,50 m de altura e 25 m de comprimento e ocupava 180 m² de área construída. • Foi construído sobre estruturas metálicas com 2,75 m de altura e contava com 70 mil resistores e 17.468 válvulas a vácuo ocupando a área de um ginásio desportivo, diodos de cristal de 7200, 1.500 relés, 70.000 resistores, 10.000 capacitores e cerca de 5 milhões de juntas soldadas à mão. • Segundo Tom Forester, quando acionado pela primeira vez, o ENIAC consumiu tanta energia que as luzes de Filadélfia piscaram. • Processador de 20 ciclos de clock de 0,1MHz na unidade. • Era incapaz de armazenar programa em memória (cartões perfurados) – Em 1970 DRAM de 1KB, mais tarde 256KB SDRAM.

  11. ENIAC

  12. Linguagem de Máquina • A linguagem de máquina do SSEM pode ser entendida (grosseiramente) como a primeira linguagem de programação • Essa linguagem define a associação entre uma instrução em binário e o efeito dela sobre o hardware • Linguagem entendida diretamente pelo processador • Cada arquitetura de computador define a sua própria linguagem

  13. 1011100 0001 0010 0011 adição reg. 1 reg. 2 reg. 3 História das Linguagens • Exemplo de instrução • Somar o valor dos registradores 1 e 2 e guardar o resultado no registrador 3 • Exemplo de código de máquina (fictício) • Podemos ver que escrever um programa em linguagem de máquina não é trivial...

  14. História das Linguagens • Programadores definiram uma notação simbólica para representar seus programas • Usada para anotar seus programas em papel antes de passar para linguagem de máquina • Essa notação definia símbolos para representar cada instrução, tais como: • ADD – operação de adição • LOAD – operação de leitura da memória • R1 – representa o registrador 1 • ...

  15. História das Linguagens • A nova notação simbólica recebeu o nome de linguagem assembly ou linguagem de montagem • Exemplo de instrução em assembly • ADD R1 R2 R3 • Representa a mesma operação dada antes em código de máquina

  16. História das Linguagens • Não demorou até alguém ter a idéia de criar um programa para traduzir... • De um texto digitado na linguagem assembly • Para um arquivo em linguagem de máquina • Este tipo de programa passou a ser conhecido pelo nome de assembler ou montador • Um compilador primitivo

  17. História das Linguagens • Programar em linguagem de montagem, porém, ainda tinha muitas das desvantagens da própria linguagem de máquina • O principal problema era a necessidade de pensar não só no algoritmo em si, mas no funcionamento do hardware

  18. História das Linguagens • Começaram a surgir outras linguagens mais elaboradas • Fortran (1957) • LISP (1959) • COBOL (1960) • BASIC (1964) • C (1972) • etc.

  19. História das Linguagens • Facilitaram a vida dos programadores ao tornar a notação mais intuitiva e mais distante dos detalhes de hardware • Por exemplo, o comando Fortran temp = 2 + 3 • Engloba várias operações de hardware: • Carregar os operadores em registradores • Operar a adição, guardando o resultado em algum registrador • Copiar o conteúdo do registrador de resultado para a memória

  20. História das Linguagens • As novas linguagens que surgiram foram chamadas de linguagens de alto nível • Em contraste, as linguagens assembly e de montagem passaram a ser chamadas de linguagens de baixo nível

  21. Linguagens de Alto Nível

  22. Linguagens de Alto Nível • O nome “alto nível” tem o sentido de “alto nível de abstração”, pois essas linguagens abstraem detalhes operacionais pouco relevantes • Assim, o programador pode (tenta) focar só no algoritmo • Veremos agora dois exemplos para comparar as linguagens de nível alto e baixo

  23. Exemplo em Baixo Nível • Programa Hello World em assembly x86 DOSSEG .MODEL SMALL .DATA Msgdb "Hello World.",13,10,"$" .CODE Start: mov AX, @DATA mov DS, AX lea DX, Msg mov AH, 9 int 21h mov ah, 4ch int 21h END Start

  24. Exemplo em Alto Nível • Programa Hello World em C #include <stdio.h> intmain() { printf(“Hello World”); return 0; }

  25. Linguagens de Baixo Nível • Características gerais • Dependentes de arquitetura • Oferecem instruções primitivas simples (operações sobre o hardware) • Programas extensos e pouco legíveis • Visam oferecer mais controle sobre o hardware

  26. Linguagens de Alto Nível • Características gerais • Especificadas independentemente de qualquer arquitetura • Oferecem comandos mais intuitivos • Dizem mais “o que” deve ser feito do que “como” deve ser feito • Mais fácil de programar e de ler códigos prontos • Restringem o uso do hardware para evitar bugs • Controle da alocação de memória em Java

  27. Introdução a Compiladores

  28. História dos Compiladores • A criação das linguagens de alto nível provocou o surgimento dos compiladores • Lêem um código de entrada e, como saída, geram um arquivo em código de máquina • O arquivo gerado pode ser executado para produzir os resultados desejados • Depois surgiriam também os interpretadores • Lêem um código de entrada e imediatamente executam o que está descrito no código

  29. compilação execução interpretação Compilação x Interpretação • Compilação • Interpretação código fonte código de máquina resultados código fonte resultados

  30. História dos Compiladores • Tanto compiladores como interpretadores são responsáveis por tornar "real” uma linguagem • Sem eles, a linguagem não tem utilidade • Nos anos 60 e 70 essa área amadureceu, causando um grande crescimento do número de linguagens de alto nível • Hoje a área está bem estabelecida...

  31. História dos Compiladores • Atualmente as técnicas são aplicadas não só em linguagens de programação, mas também em outros contextos da computação • Linguagens de consulta, como SQL • Linguagens de descrição de dados, como XML • Ferramentas auxiliares de desenvolvimento • Syntaxhighlighting, outline do código, etc.

  32. O que é um Compilador? • Um compilador é um programa que lê um programa escrito em uma linguagem (linguagem fonte) e a traduzem um programa equivalente em outra linguagem (linguagem alvo). Aho, Sethi, Ullman. Compilador Programa Fonte Programa Objeto

  33. O que é um Compilador? • Exemplo de linguagem fonte: C, Pascal, Java, etc. • Exemplo de linguagem destino: • Linguagem de máquina (assembler) de um processador • Linguagem de uma máquina virtual (Java) • Qualquer outra linguagem (C)

  34. O que é um Compilador? • Nesse processo de tradução, há duas tarefas básicas a serem executadas por um compilador: • análise, em que o texto de entrada (na linguagem fonte) é examinado, verificado e compreendido • síntese, ou geração de código, em que o texto de saída (na linguagem objeto) é gerado, de forma a corresponder ao texto de entrada

  35. O que é um Compilador? • A fase de análise normalmente se subdivide em análise léxica, análise sintática e análise semântica • É possível representar completamente a sintaxe de uma LP através de uma gramática sensível ao contexto • Mas como não existem algoritmos práticos para tratar essas gramáticas, a preferência recai em usar gramáticas livres de contexto • Deixa-se para a análise semântica a verificação de todos os aspectos da linguagens que não se consegue exprimir de forma simples usando gramáticas livres de contexto

  36. O que é um Compilador? • A implementação de reconhecedores de linguagens regulares (autômatos finitos) é mais simples e mais eficiente do que a implementação de reconhecedores de linguagens livres de contexto (autômatos de pilha) • Nesse caso, é possível usar expressões regulares para descrever a estrutura de componentes básicos das LP, tais como identificadores, palavras reservadas, literais numéricos, operadores e delimitadores, etc. • Essa parte da tarefa de análise (análise léxica) é implementada separadamente, pela simulação de autômatos finitos

  37. O que é um Compilador? • Um dos modelos possíveis para a construção de compiladores faz a separação total entre o front-end, encarregado da fase de análise, e o back-end, encarregado da geração de código, de forma que: • O front-end e back-end se comunicam apenas através de uma representação intermediária • O front-end depende exclusivamente da linguagem fonte • O back-end depende exclusivamente da linguagem objeto

  38. O que é um Compilador? • Essa idéia visa simplificar a implementação de várias linguagens de programação para várias máquinas: • Basta escrever um front-end para cada linguagem, e um back-end para cada máquina • Ou seja, para implementar m linguagens em n máquinas, precisamos fazer mfront-ends e nback-ends, em vez de mn compiladores completos

  39. O que é um Compilador? • Um compilador típico consiste de algumas fases onde cada uma passa sua saída para as fases seguintes • As principais fases são: • análise léxica (ou scanner) • análise sintática (ou parser) • análise semântica • otimização • gerador de código • otimização (novamente!)

  40. Fases da Compilação Programa Fonte Analisador Léxico Analisador Sintático e Semântico Manipulador de erros Tabela de Símbolos Gerador de Código Intermediário Otimizador de Código Gerador de código Programa Objeto

  41. Análise Léxica • Também chamada de scanner • Agrupa caracteres em símbolos (ou tokens) • Token: <nome-token, valor-atributo> • Entrada: fluxo de caracteres • Saída: fluxo de símbolos • Símbolos são: • Palavras reservadas, identificadores de variáveis e procedimentos, operadores, pontuação, etc. • Expressões regulares usadas para reconhecimento • Scanner é implementado como uma MEF (Método dos Elementos Finitos) • Lex/Flex (J) são ferramentas para gerar scanners

  42. Análise Léxica • Por exemplo, os caracteres na instrução de atribuição position= initial + rate * 60 • seriam agrupados nos seguintes tokens: • O identificador position • O símbolo de atribuição = • O identificador initial • O símbolo de adição + • O identificador rate • O símbolo de multiplicação * • O número 60 <id, 1> <=> <id, 2> <+> <id, 3> <*> <60>

  43. Análise Sintática • Também chamada de parser • Agrupa símbolos em unidades sintáticas • Ex.: os 3 símbolos A+B podem ser agrupados em uma estrutura chamada de expressão • Expressões depois podem ser agrupados para formar comandos ou outras unidades • Saída: representação de árvore sintátca do programa • Gramática livre de contexto é usada para definir a estrutura do programa reconhecida por um parser • Yacc/Bison (J) são ferramentas para gerar parsers

  44. Análise Sintática • Regras sintáticas (1) • Qualquer identificador é uma expressão • Qualquer número é uma expressão • Se expressão1 e expressão2 são expressões, então também são expressões • expressão1+ expressão2 • expressão1* expressão2 • ( expressão1)

  45. Análise Sintática • Regras sintáticas (2) • Se identificador1 é um identificador e expressão2 é uma expressão, então identificador1= expressão2é um comando (statement) • Se expressão1 é uma expressão e statement2 é um comando (statement), entãowhile( expressão1) { statement2 }if( expressão1) { statement2 } são comandos (statements)

  46. Análise Sintática position = initial + rate * 60 comando de atribuição identificador = expressão position expressão expressão + * expressão expressão identificador initial identificador número rate 60

  47. Análise Semântica • Verifica se estruturas sintáticas, embora corretas sintaticamente, têm significado admissível na linguagem • Por exemplo, não é possível representar em uma gramática livre de contexto uma regra como “todo identificador deve ser declarado antes de ser usado”, e a verificação de que essa regra foi aplicada cabe à análise semântica • Um importante componente é checagem de tipos • Considerando “A + B”, quais os possíveis problemas semânticos? • Saída: árvore sintática anotada

  48. Análise Semântica • Não existe um modelo matemático inteiramente adequado para descrever o que deve ser verificado na análise semântica, mas mecanismos como gramáticas de atributos tem sido usados • Durante o parser, informações sobre variáveis (e outros objetos) são armazenados em uma tabela de símbolos e são utilizadas na checagem

  49. Análise Semântica • Análise semântica insere uma conversão de inteiro para real = = position position + + initial * initial * rate rate 60 int2real 60

  50. Gerador de Código Intermediário • Usa as estruturas produzidas pelo analisador sintático e verificadas pelo analisador semântico para criar uma sequência de instruções simples (código intermediário) • Está entre a linguagem de alto nível e a linguagem de baixo nível

More Related