Centro de Estudos, Desenvolvimento e Inovação em Software | Universidade de Brasília

Geração de código intermediário

FGA0003 - Compiladores 1 | Semana 8 | Aula prática

Prof. Sergio Antônio Andrade de Freitas
Curso de Engenharia de Software · 2025/2
símbolo CEDIS logo UnB
símbolo CEDISCEDIS
2/22

Resultado esperado da prática

Ao final da aula, cada equipe deverá ter executado, inspecionado e adaptado o protótipo de geração de TAC.

  • Compilar e executar o exemplo da semana 08.
  • Explicar a estrutura básica de um nó da AST.
  • Acompanhar a recursão da função gerarTAC().
  • Corrigir o tratamento didático da atribuição.
  • Planejar a integração com o parser do projeto da equipe.
símbolo CEDISCEDIS
3/22

Roteiro prático

  1. 01Acessar o repositório e localizar a semana 08
  2. 02Compilar e executar o protótipo
  3. 03Inspecionar ast.h, ast.c e main.c
  4. 04Acompanhar a geração recursiva de TAC
  5. 05Corrigir a atribuição e testar novamente
  6. 06Adaptar o caminho para o projeto da equipe
símbolo CEDISCEDIS
4/22

Acesso ao material

O código apresentado está no repositório público da disciplina.

  • Repositório: https://github.com/sergioaafreitas/COMP1
  • Diretório: semana 08/src
  • Abrir o projeto em terminal e editor de código.
  • Trabalhar em dupla ou equipe, mantendo registro das alterações.
símbolo CEDISCEDIS
5/22

Estrutura do projeto da prática

A prática está organizada em poucos arquivos para facilitar leitura, compilação e modificação incremental.

  • ast.h define a estrutura e os protótipos.
  • ast.c implementa criação de nós e gerarTAC().
  • main.c monta uma AST de exemplo.
  • Makefile automatiza a compilação.
Estrutura dos arquivos da prática semana 08
Antes de alterar, identifique a responsabilidade de cada arquivo.
símbolo CEDISCEDIS
6/22

Comandos iniciais

Preparação

git clone https://github.com/sergioaafreitas/COMP1.git cd "COMP1/semana 08/src"

  • Use git pull se o repositório já existir.
  • Confirme se está no diretório correto.

Execução

make clean make ./main

  • Observe se há erros de compilação.
  • Compare a saída com o esperado.
seção

Leitura orientada do código

A partir daqui, o objetivo é entender o que cada função faz antes de modificar o protótipo.

símbolo CEDISCEDIS
8/22

Estrutura de um nó da AST

Campos principais

  • operador: símbolo de operação.
  • valor: número inteiro.
  • nome: identificador textual.
  • tipo: tipo semântico associado.
  • esquerda e direita: filhos da árvore.

Interpretação

  • Folhas representam identificadores ou constantes.
  • Nós internos representam operações.
  • A estrutura preserva a precedência.
  • A travessia gera a forma linear TAC.
símbolo CEDISCEDIS
9/22

Funções construtoras

criarNoNum

Cria uma folha numérica com tipo inteiro.

criarNoId

Cria uma folha para identificadores, como x, a, b ou c.

criarNoOp

Cria um nó interno com operador e dois filhos.

imprimirAST

Percorre a árvore e imprime sua estrutura em formato infixo.

símbolo CEDISCEDIS
10/22
AST de x igual a a mais b vezes c com ordem de travessia
A numeração indica a ideia geral da travessia recursiva.

AST construída manualmente no main.c

O protótipo atual monta a árvore de x = a + b * c diretamente em C.

  • A multiplicação b * c é criada primeiro.
  • Depois, a soma a + (b * c).
  • Por fim, a atribuição x = expressão.
  • A ordem da árvore determina a ordem do TAC.
símbolo CEDISCEDIS
11/22

Como gerarTAC() funciona

1

1. Verificar folha

Se não há operador, retorna identificador ou constante.

2

2. Gerar esquerda

Percorre recursivamente o filho esquerdo.

3

3. Gerar direita

Percorre recursivamente o filho direito.

4

4. Emitir

Cria uma temporária e imprime a instrução TAC.

símbolo CEDISCEDIS
12/22

Da árvore para instruções lineares

A geração de TAC transforma uma expressão hierárquica em uma sequência explícita de instruções.

  • Cada operação composta produz uma temporária.
  • A sequência respeita a dependência entre resultados.
  • A saída pode ser comparada em testes automatizados.
  • A atribuição merece tratamento específico.
Fluxo da transformação de AST para TAC
A versão ajustada evita temporária desnecessária na atribuição.
símbolo CEDISCEDIS
13/22

Saída atual e saída desejada

Protótipo atual

t0 = b * c t1 = a + t0 t2 = x = t1

  • A atribuição gera temporária extra.
  • Funciona como demonstração, mas não é o TAC ideal.

Ajuste esperado

t0 = b * c t1 = a + t0 x = t1

  • A expressão é gerada à direita.
  • O resultado é armazenado diretamente em x.
símbolo CEDISCEDIS
14/22

Correção guiada da atribuição

Na função gerarTAC(), trate o operador '=' antes da regra geral para operadores binários.

  • Gerar TAC da expressão à direita.
  • Obter o nome do identificador à esquerda.
  • Emitir destino = valor, sem criar nova temporária.
  • Retornar o destino ou NULL, conforme a estratégia adotada.
  • Recompilar e comparar a saída.
símbolo CEDISCEDIS
15/22

Limitação dos testes atuais

O que o script faz

Percorre arquivos em tests/ e chama ./main para cada um.

Limitação

O main.c atual não lê a entrada-padrão; ele monta uma AST fixa.

Consequência

Entradas diferentes ainda podem produzir a mesma saída.

Evolução

Integrar lexer, parser e AST para que cada entrada gere TAC próprio.

símbolo CEDISCEDIS
16/22

Extensão prática imediata

Nova expressão

y = (a + b) * (c - 2);

  • Criar nós para a + b.
  • Criar nós para c - 2.
  • Multiplicar os resultados.
  • Atribuir em y.

TAC esperado

t0 = a + b t1 = c - 2 t2 = t0 * t1 y = t2

  • Compare temporárias.
  • Verifique precedência.
  • Confirme a atribuição final.
símbolo CEDISCEDIS
17/22
Fluxo de integração entre Flex, Bison, AST e gerarTAC
A prática atual é um protótipo; o projeto deve automatizar a construção da AST.

Integração com Flex e Bison

No projeto da equipe, a AST não deve ser montada manualmente no main.c; ela deve ser construída pelo parser.

  • Flex reconhece tokens da linguagem.
  • Bison reduz regras e cria nós da AST.
  • A análise semântica valida e anota a árvore.
  • gerarTAC() percorre a AST final.
símbolo CEDISCEDIS
18/22

Roteiro de adaptação no projeto da equipe

Escolher escopo

Começar com expressões e atribuições simples.

Gerar AST

Fazer ações semânticas do Bison criarem nós reais.

Validar semântica

Checar tipos, escopos e identificadores antes do TAC.

Emitir TAC

Percorrer a AST e registrar instruções testáveis.

Automatizar testes

Comparar entradas pequenas com saídas intermediárias esperadas.

símbolo CEDISCEDIS
19/22

Padrão de identificação do código

Todo código produzido para a disciplina deve manter cabeçalho institucional.

  • FGA0003 - Compiladores 1
  • Curso de Engenharia de Software
  • Universidade de Brasília (UnB)
  • Semana 8 - prática de geração de código intermediário
  • Descrição breve da finalidade do arquivo
símbolo CEDISCEDIS
20/22
O primeiro objetivo da geração de TAC não é otimizar, mas tornar a execução do programa explicitamente representável e testável.
Síntese da aula prática
símbolo CEDISCEDIS
21/22

Referências e material de apoio

  1. Freitas, S. A. A. de. (2025). COMP1: Repositório da disciplina FGA0003 - Compiladores 1. GitHub. https://github.com/sergioaafreitas/COMP1
  2. Aho, A. V., Lam, M. S., Sethi, R., & Ullman, J. D. (2006). Compilers: Principles, Techniques, and Tools (2nd ed.). Pearson.
  3. Cooper, K. D., & Torczon, L. (2012). Engineering a Compiler (2nd ed.). Morgan Kaufmann.
  4. Wirth, N. (2005). Compiler Construction. ETH Zurich.
  5. GNU Project. (2025). GNU Bison Manual. Free Software Foundation.
símbolo CEDISCEDIS
22/22

Encerramento

Próximo passo: integrar a geração de TAC à AST real produzida pelo parser da equipe.

→ avançar · ← voltar · deslize (touch) · n notas · f tela cheia · p imprimir