Notes - MIECT
Compiladores
Notes - MIECT
Compiladores
  • Compiladores
  • Compiladores, Linguagens e Gramáticas
    • Enquadramento
    • Compiladores
      • Interpretadores
      • Estrutura de um Compilador
    • Implementação de um Compilador
    • Linguagens: Definição como Conjunto
      • Conceito básicos e terminologia
      • Operações sobre palavras
      • Operações sobre linguagens
    • Introdução às gramáticas
      • Hierarquia de Chomsky
      • Autómatos
  • Introdução, Estrutura, Aplicação
    • Exemplos
      • Expr
      • Exemplo figuras
      • Exemplo visitor
      • Exemplo listener
    • Construção de gramáticas
      • Especificação de gramáticas
    • Estrutura léxica
    • Regras léxicas
      • Padrões léxicos típicos
      • Operador léxico “não ganancioso”
    • Estrutura sintática
      • Secção de Tokens
      • Acções no preâmbulo da gramática
    • Regras sintácticas
      • Padrões sintácticos típicos
      • Precedência
      • Associatividade
      • Herança de gramáticas
    • Outras funcionalidades
      • Tabelas CSV
      • Gramáticas ambíguas
      • Predicados semânticos
      • Separar analisador léxico do analisador sintáctico
      • “Ilhas” lexicais
      • Enviar tokens para canais diferentes
      • Reescrever a entrada
      • Desacoplar código da gramática - ParseTreeProperty
  • Análise Semântica
    • Estrutura de um Compilador
    • Sistema de Tipos
    • Gramáticas de Atributos
    • Tabela de símbolos
    • Instruções restringidas por contexto
    • ANTLR4: gestão de erros
  • Síntese
    • Síntese: Geração de código
    • String Template
    • Síntese: geração de código intermédio
  • Análise Lexical
    • Análise Lexical: Estrutura de um Compilador
    • Linguagens regulares
    • Gramáticas regulares
    • Expressões regulares
    • Conversão entre ER e GR
    • Reconhecimento de tokens
    • Autómatos finitos
    • Autómato finito não determinista
    • Autómato finito determinista
      • Projecto de autómato finito determinista
    • Conversão de AFND em AFD
    • Conversão de uma expressão regular num AFND
    • Autómato finito generalizado (AFG)
  • Gramática de Atributos
    • Conteúdo semântico
    • Gramática de atributos
    • Avaliação Dirigida pela Sintaxe
  • Análise Sintática Descendente
    • Análise Sintática
    • Análise Sintática Descendente
    • Analisador (parser) Recursivo-Descendente Preditivo
    • Questões a resolver
    • Fatorização à Esquerda
    • Eliminação de Recursividade á Esquerda
    • Conjuntos predict, first e follow
      • Conjunto first
      • Conjunto follow
    • Reconhecedor Descendente Preditivo
  • Análise Sintática Ascendente
    • Análise Sintática Ascendente
    • Construção de um reconhecedor ascendente
    • Tabela de decisão de um reconhecedor ascendente
    • Reconhecedor Ascendente
    • Tabela de Decisão de um Reconhecedor Ascendente
Powered by GitBook
On this page
  • Exemplo
  • Geração de código máquina
  • Geração de código
  1. Síntese

Síntese: Geração de código

PreviousANTLR4: gestão de errosNextString Template

Last updated 2 years ago

Podemos definir o objectivo de um compilador como sendo traduzir o código fonte de uma linguagem para outra linguagem.

A geração do código para a linguagem destino pode ser feita por diferentes fases (podendo incluir fases de optimização), mas nós iremos abordar apenas uma única fase.

A estratégia geral consiste em identificar padrões de geração de código, e após a análise semântica percorrer novamente a árvore sintáctica (mas já com a garantia muito importante de inexistência de erros sintácticos e semânticos) gerando o código destino nos pontos apropriados.

Exemplo

Código fonte:

  • 1+2*3:4

Uma possível compilação para Java:

Geração de código máquina

Tradicionalmente, o ensino de processadores de linguagens tende a dar primazia à geração de código baixo nível (linguagem máquina, ou assembly).

A larga maioria da bibliografia mantém esse enfoque.

No entanto, do ponto de vista prático serão poucos os programadores que, fazendo uso de ferra- mentas para gerar processadores de linguagens, necessitam ou ambicionam este tipo de geração de código.

Nesta disciplina vamos, alternativamente, discutir a geração de código numa perspectiva mais abrangente, incluindo a geração de código em linguagens de alto nível.

No que diz respeito à geração de código em linguagens de baixo nível, é necessário um conheci- mento robusto em arquitectura de computadores e lidar com os seguintes aspectos:

  • Representação e formato da informação (formato para números inteiros, reais, estruturas, array, etc.);

  • Gestão e endereçamento de memória;

  • Implementação de funções (passagem de argumentos e resultado, suporte para recursividade com pilha de chamadas e frame pointers);

  • Alocação de registos do processador.

(Consultar a bibliografia recomendada para estudar este tipo de geração de código.)

Geração de código

Seja qual for o nível da linguagem destino, uma possível estratégia para resolver este problema consiste em identificar sem ambiguidade padrões de geração de código associados a cada elemento gramatical da linguagem.

Para esse fim, é necessário definir o contexto de geração de código para cada elemento (por exemplo, geração de instruções na linguagem destino, ou atribuir a valor a uma variável), e depois garantir que o mesmo é compatível com todas as utilizações do elemento.

Como a larguíssima maioria das linguagens destino são textuais, esses padrões de geração de código consistem em padrões de geração de texto.

Assim sendo, em Java, poderíamos delegar esse problema no tipo de dados String, StringBuilder, ou mesmo na escrita directa de texto em em ficheiro (ou no standard output).

No entanto, também aí o ambiente ANTLR4 fornece uma ajuda mais estruturada, sistemática e modular para lidar com esse problema.