A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Teoria e Implementação de Linguagens Computacionais Revisão 1º EE André Ricardo Schäffer Lopes – Rodrigo Diego Melo Amorim–

Apresentações semelhantes


Apresentação em tema: "Teoria e Implementação de Linguagens Computacionais Revisão 1º EE André Ricardo Schäffer Lopes – Rodrigo Diego Melo Amorim–"— Transcrição da apresentação:

1 Teoria e Implementação de Linguagens Computacionais Revisão 1º EE André Ricardo Schäffer Lopes – Rodrigo Diego Melo Amorim–

2 Níveis de Linguagem Linguagem de máquina Linguagem de alto nível Linguagem de montagem Assembly language

3 Processadores de Linguagens Manipulam programas expressos em alguma linguagem de programação: Compiladores Interpretadores

4 Tradutores e Compiladores Tradutor Linguagem fonte -> Linguagem destino Chinês para inglês Java para C Compilador Ling. de alto nível -> Ling. de baixo nível

5 Interpretadores Programa fonte -> executa imediatamente Lê, analisa e executa as instruções, uma de cada vez

6 Compiladores x Interpretadores Compiladores Tempo de espera pela compilação Execução dos programas com máxima performance, em linguagem de máquina Interpretadores Resultados imediatos Execução (de linguagem de alto nível) até 100 vezes mais lenta que a versão compilada

7 Uso de interpretadores Programador trabalha em modo interativo Quer ver o resultado de uma instrução antes de entrar na próxima Execução de instruções apenas um vez, ou raramente Programas descartáveis Em que a velocidade de execução não é tão importante

8 Diagramas Tombstone Programas Máquinas P L M

9 Diagramas Tombstone Execução Programa P rodando na máquina M P M Msort PPC sort PPC x86 X

10 Diagramas Tombstone Compiladores S L T 

11 Diagramas Tombstone Tradução Um programa fonte P expresso na linguagem S -> um programa objeto expresso na linguagem T, usando um tradutor de S para T executando na máquina M?

12 Diagramas Tombstone Tradução P S P T S M T  M

13 Diagramas Tombstone Interpretador S L

14 Diagramas Tombstone Interpretação Um programa P expresso em uma linguagem S, usando um interpretador de S executando na máquina M?

15 Diagramas Tombstone S M P S M

16 Compilação em estágios sort Java sort C Java x86 C  C  sort x86

17 Cross-Compiler Roda em uma máquina hospedeira, mas gera código para outra máquina Máquina destino débil em memória, compilador ou outras ferramentas

18 Exemplo Cross-Compiler sort Java sort PPC Java x86 PPC  x86 sort PPC

19 Interpretive Compiler Características de interpretadores e compiladores Simples e rápido de traduzir para ela, e simples e rápida de interpretar Exemplo: Java, no JDK

20 Java no JDK Java M JVM  M Java M JVM  M M P M P Java P JVM

21 Máquina Real x Abstrata Projeto de uma nova máquina “Ultima” P Ultima M M P 

22 Bootstrapping Compilação de uma linguagem utilizando um compilador dessa mesma linguagem Utilizado para melhorar a eficiência de um compilador Precisa de um compilador escrito em outra linguagem que depois será descartado

23 Bootstrapping - melhorando a eficiência Ada Mslow Mfast  Ada Mslow  Ada Mfast  M

24 Bootstrapping - melhorando a eficiência Ada Mslow Mfast  M P Ada P Mfast M P

25 Bootstrapping - melhorando a eficiência Ada Mslow Mfast  M Ada Mfast  Ada Mfast 

26 Especificação de Linguagens Sintaxe A forma do programa Organização das frases Palavras reservadas Semântica estática (Restrições contextuais) Regras de escopo e regras de tipo Semântica Significado do programa

27 O processo de Compilação begin if x = 5 then Código Fonte Compilador Programa output + params

28 Fases de Compilação abstração implementação Código fonte Tokens e Lexemas Árvore sintática abstrata Código máquina AST decorada Análise Léxica Análise Sintática Análise Semântica Geração de Código

29 Análise Léxica (Scanning) Código fonte -> sequência de tokens Símbolos como identificadores, literais, operadores, palavras-chave, pontuação etc. if (n == 0) { return 1; } else {... } RPARLCUR RCUR if LPAR return else "n" id "0" intLit assign "1" intLit comm

30 Análise Sintática Agrupa caracteres ou Tokens em uma estrutura hierárquica com algum significado Determina se uma dada cadeia de entrada pertence ou não à linguagem definida por uma gramática int y = 0,k = 0; int x = y+++k; A seguinte construção é válida?

31 Gramáticas – descrevendo Linguagens Gramáticas Livres de Contexto são utilizadas para descrever linguagens de programação Produções Símbolos terminais Símbolos não-terminais Símbolo inicial

32 Exemplo S → S ; S S → id := E S → print (L) E → id E → num E → E + E E → (S, E) L → E L → L, E Terminais: id print, + ; := ( ) num Não terminas: S E L Símbolo inicial: S → é utilizado na notação de produções A cadeia seguinte pertence à gramática? a := 7; b := c + (d := 5 + 6, d)

33 Derivações S S ; S S ; id := E id := E ; id := E id := num ; id := E id := num ; id := E + E id := num ; id := E + (S, E) id := num ; id := id + (S, E) id := num ; id := id + (id := E, E) id := num ; id := id + (id := E + E, E) id := num ; id := id + (id := E + E, id) id := num ; id := id + (id := num + E, id) id := num ; id := id + (id := num + num, id)

34 Parse tree S S S E Eid:= ; E id + E ) (, ES E := id E E+ num Construída conectando cada derivação à sua origem. Obs. Na prática não é implementada pelos compiladores.

35 Gramática Ambígua A partir dela uma sentença pode dar origem a mais de uma árvore de parsing diferente Indeterminismo Eliminação de ambigüidade Refatoração da gramática

36 Exemplo x := ; S E id:= E +E E +E num S E id:= E +E E +E num

37 Refatoração S → S ; S S → id := E S → print (L) E → id E → num E → E + E E → (S, E) L → E L → L, E S → S ; S S → id := E S → print (L) E → id E → num E → E + T E → T E → (S, E) L → E L → L, E

38 Parsers Avaliam uma entrada quanto à sintaxe Podem ser Top-down Recursive-descent / LL(k) Bottom-up LR(k)

39 Recursive descent parser Algoritmo baseado em previsões Funções mutuamente recursivas Simples implementação Uma função para cada não-terminal Uma cláusula para cada produção Verifica o primeiro símbolo terminal para decidir qual função usar

40 Exemplo A ::= aBcC B ::= CB | cC C ::= da parseA() { accept(‘a’); parseB(); accept(‘c’); parseC(); } parseB() { case (d): parseC(); parseB(); case (c): accept(‘c’); parseC(); } parseC() { accept(‘d’); accept(‘a’); }

41 Recursive descent parser Na prática, constrói uma tabela de produções indexadas por não-terminais e terminais A ::= aBcC B ::= CB | CA C ::= da acd AA::= aBcC BB::= CB B::= CA CC::= da

42 Recursive descent parser Vantagens Fácil de implementar Fácil de entender Desvantagens Performance deficiente Gramática reconhecida possui restrições Sem recursão à esquerda Deve estar fatorada

43 Recursive descent parser A ::= aBcC B ::= CB | CA C ::= da A ::= aBcC B ::= CX X ::= B | A C ::= da acd AA::= aBcC BB::= CX CC::= da XX::=AX::=B Gramática LL(k)

44 Parsers LL(k) Gramáticas SEM entradas duplicadas na tabela são conhecidas como LL(k) LL(1) -> Left-to-right, leftmost-derivation, 1-symbol lookahead Left-to-right – direção na qual os símbolos serão examinados Leftmost-derivation – ordem pela qual os símbolos não- terminais serão expandidos 1-symbol lookahead – não mais que um símbolo será avaliado por vez Também existem LL(2), LL(3),... Toda LL(1) é LL(2), toda LL(2) é LL(3),... LL(k)

45 Recursão à esquerda Gramáticas LL(1) são vulneráveis a entradas duplicadas. Por exemplo, o fragmento a seguir: E → E + T E → T O fato de E aparecer no início do lado direito da produção é a causa do problema. Isso é conhecido como Recursão à Esquerda. Para corrigir, precisamos refatorar a gramática com Recursão à Direita: E → T E´ E´ → +T E´ E´ →

46 Parsers LR(k) Supera as fraquezas de LL(k) LR(1) -> Left-to-right, rightmost-derivation, 1- symbol lookahead Uso de uma pilha para armazenar símbolos de forma temporária Possui duas operações, shift e reduce shift - move o primeiro símbolo para o topo da pilha reduce - escolhe uma regra da gramática do tipo X → A B C. pop C B A da pilha e push X.

47 Parsing LR - de Gramáticas Ambíguas Gramáticas ambíguas ocasionam conflitos em parsers LR Shift-reduce conflict O parser não consegue decidir se empilha o próximo símbolo da entrada, ou se reduz para uma regra já disponível Reduce-reduce conflict O parser pode realizar uma redução para duas regras distintas

48 Parsing LR - de Gramáticas Ambíguas Dangling-else if a then if b then s1 else s2 if a then { if b then s1 else s2 } if a then { if b then s1 } else s2 ?

49 Parsing LR - de Gramáticas Ambíguas Solução: Transformar a gramática Introdução dos conceitos de matched e unmatched S ::= 'if' E 'then' S 'else' S S ::= 'if' E 'then' S S ::=... S ::= M | U M ::= 'if' E 'then' M 'else' M |... U ::= 'if' E 'then' S | 'if' E 'then' M 'else' U

50 Análise Semântica (Contextual) Verifica se o programa está de acordo com as restrições contextuais da linguagem fonte Em uma linguagem com tipos estáticos e ligação estática: Verifica regras de escopo Verifica regras de tipos Duas fases: Identificação Verificação

51 Identificação Faz a ligação entre uso de nomes e sua definição Tabela de identificação (tabela de símbolos), com nome e atributos de cada identificador Cada definição tem o seu escopo – parte do programa sobre a qual ela tem efeito Delimitado por um bloco

52 Estrutura de blocos de um programa Monolítica: O único bloco é o programa inteiro Declarações estão em um escopo global Regras de escopo: Nenhum identificador pode ser declarado mais de uma vez Nenhum identificador pode ser usado sem ter sido definido

53 Estrutura de blocos de um programa Plana O programa pode ser particionado em vários blocos disjuntos Dois níveis de escopo: Escopo local: ocorrências de identificadores declarados localmente são restritos a um bloco em particular Outras declarações têm escopo global

54 Estrutura de blocos de um programa Aninhada Blocos podem ser aninhados um dentro do outro Vários níveis de escopo: Declarações no nível mais externo têm escopo global (nível 1) Declarações dentro de um bloco interno são locais ao bloco Cada bloco está dentro de outro bloco, com um nível a mais

55 Passos Travessia do programa fonte Um compilador de um passo atravessa o programa uma única vez Um compilador de múltiplos passos faz várias travessias O projeto de um compilador é diretamente relacionado ao número de passos

56 Compilação em múltiplos passos Módulo principal (driver) Chama cada um dos passos Driver do Compilador Analisador SintáticoAnalisador ContextualGerador de Código

57 Compilação em passo único Analisador sintático Realiza/chama as atividades à medida que lê e reconhece o programa Analisador Sintático Analisador ContextualGerador de Código Driver do Compilador

58 Pontos relevantes no Projeto de um Compilador Velocidade – possível vantagem para um passo Espaço – possível vantagem para um passo (dados x programa) Modularidade – vantagem de múltiplos passos Flexibilidade – vantagem de múltiplos passos Transformações/otimizações de programas – vantagem de múltiplos passos


Carregar ppt "Teoria e Implementação de Linguagens Computacionais Revisão 1º EE André Ricardo Schäffer Lopes – Rodrigo Diego Melo Amorim–"

Apresentações semelhantes


Anúncios Google