LRM Prof. Mantovani ← Aulas da disciplina
Semana 13 · Aula 13 de 14

Projeto integrador — mini-compilador

Juntando as fases: do código-fonte aos tokens, à árvore e ao código de três endereços, em um projeto único que exercita o front-end ponta a ponta.

📚 Compiladores🧪 2 simulador(es)📝 mini-quiz ao final
Objetivos da aula

O que você vai aprender

1

Integrar análise léxica, sintática e geração de RI em um pipeline.

2

Testar o compilador ponta a ponta com casos de aceitação.

3

Planejar a arquitetura e a divisão de tarefas do projeto.

4

Diagnosticar erros em cada fase do pipeline integrado.

1 · Motivação

Hora de juntar as peças

Estudamos cada fase isoladamente: scanner, parser, semântica, geração de RI. Agora as conectamos em um mini-compilador real, onde a saída de uma fase é a entrada da próxima — do texto-fonte ao código de três endereços.

Esta aula é a síntese prática do curso: ver o pipeline inteiro funcionando consolida tudo o que veio antes e prepara a entrega do projeto da disciplina.

💡
Um mini-compilador de expressões é pequeno, mas contém em miniatura toda a arquitetura de um compilador profissional.
2 · Mapa

O pipeline completo

Para a entrada x = a + b * 2, o caminho é:

Scanner
tokens
Parser
árvore
Semântica
tipos
Gerador
TAC

Os dois simuladores da aula mostram as pontas: primeiro a tokenização (léxico), depois a árvore + código intermediário (síntese).

3 · Conceito

O contrato entre fases

Pipeline de compilação. Sequência de fases em que cada uma consome a saída da anterior por um contrato bem definido: o scanner produz tokens, o parser produz a árvore, a semântica a anota, o gerador produz a RI.

O segredo da integração é que cada fase só precisa conhecer o formato da entrada que recebe e da saída que produz — não os detalhes internos das vizinhas.

4 · Explicação

A saída de cada fase

Detalhando o que flui entre as fases:

  • Scanner → Parser: uma sequência linear de tokens (categoria + lexema).
  • Parser → Semântica: a árvore sintática que estrutura os tokens.
  • Semântica → Gerador: a árvore anotada com tipos + a tabela de símbolos.
  • Gerador → (saída): a sequência de código de três endereços.
💡
Como cada interface é clara, dá para implementar e testar as fases em paralelo — base da divisão de tarefas em equipe.
5 · Exemplo

Rastreando x = a + b * 2

Veja a transformação da entrada ao longo do pipeline:

FaseResultado para x = a + b * 2
Scannerid(x) = id(a) + id(b) * num(2)
ParserAtrib( x , Soma( a , Prod( b , 2 ) ) )
Semânticatipos checados; x, a, b na tabela de símbolos
Geradort1 = b * 2; t2 = a + t1; x = t2
6 · Interativo

Siga o dado pelo pipeline

Passo 1
Scanner: lê os caracteres e emite os tokens id(x), =, id(a), +, id(b), *, num(2).
Passo 2
Parser: organiza os tokens na árvore, com * mais fundo que + (precedência).
Passo 3
Semântica: verifica que a, b, x existem e têm tipos compatíveis; anota a árvore.
Passo 4
Gerador: percorre a árvore em pós-ordem e emite t1 = b * 2; t2 = a + t1.
Passo 5
Gerador: emite a atribuição final x = t2. Pipeline concluído.
7 · Conceito

Casos de teste de aceitação

Caso de teste de aceitação. Par (entrada, saída esperada) que define o comportamento correto do compilador para um cenário específico. Serve de critério objetivo de "pronto".

Antes de implementar, defina os casos: que entradas o mini-compilador deve aceitar, que TAC deve produzir, e que entradas inválidas deve rejeitar com erro.

8 · Explicação

Testando ponta a ponta

Testes de aceitação verificam o pipeline inteiro, não fases isoladas. Um bom conjunto cobre:

  • Casos válidos: expressões simples e aninhadas, com precedência variada.
  • Casos de borda: um único número, parênteses redundantes, expressões longas.
  • Casos inválidos: parêntese não fechado (erro sintático), variável não declarada (erro semântico), símbolo estranho (erro léxico).
9 · Analogia

A linha de produção

🏭 Analogia
O mini-compilador é uma linha de produção: a matéria-prima (texto) entra numa ponta e o produto (TAC) sai na outra. Cada estação (fase) faz sua parte e passa adiante. Os casos de teste de aceitação são o controle de qualidade no fim da linha: você não inspeciona cada parafuso, mas verifica que o produto final está correto para um conjunto representativo de pedidos.
10 · Comparação

Mini-compilador × compilador real

Mini-compilador (projeto)Compilador real
Linguagem-fonteExpressões + atribuiçãoLinguagem completa
FasesLéxica, sintática, semântica, RI+ otimização e geração de código
SaídaCódigo de três endereçosBinário executável
ArquiteturaA mesma, em miniaturaA mesma, em escala

A diferença é de escopo, não de princípio: a arquitetura é idêntica.

11 · Fluxo

Do planejamento à entrega

Definir escopo
minilinguagem
Dividir tarefas
por fase
Implementar
+ testar
Integrar
+ demonstrar

Comece pelo contrato entre fases: com as interfaces definidas, cada integrante pode trabalhar em paralelo e a integração no fim é tranquila.

12 · Aprofundamento

Onde a semântica entra no projeto

Mesmo num mini-compilador de expressões, a semântica tem papel: ela verifica se cada identificador usado foi declarado e se os tipos das operações são compatíveis, consultando a tabela de símbolos (aula 9).

💡
Se o projeto incluir atribuição (x = ...), a semântica também registra x na tabela e checa o tipo do lado direito contra o de x. É a fase 8/9 em ação dentro do pipeline.
13 · Interativo

Verifique seu entendimento

No pipeline integrado, a saída do scanner alimenta qual fase?

O scanner produz tokens; o parser os organiza na árvore. Tokens → árvore → significado → código.
14 · Caso prático

Planejando a divisão de tarefas

Um grupo de quatro pode dividir o mini-compilador assim:

// responsabilidades por integrante Léxico : scanner() -> produz tokens Sintaxe : parser() -> produz a árvore Geração : gerarTAC() -> produz o código QA : testes() -> casos de aceitação

Com as assinaturas das funções acordadas, cada um implementa e testa sua parte isoladamente, montando no fim o pipeline completo.

15 · Erros comuns

Armadilhas do projeto integrador

⚠️
Interfaces mal definidas. Sem combinar o formato dos tokens e da árvore, as fases não se encaixam na integração.

Deixar testes para o fim. Sem casos de aceitação cedo, bugs se acumulam e a depuração explode.

Ignorar entradas inválidas. Um bom compilador rejeita erros com clareza, não só aceita o caso feliz.

Precedência incorreta. A árvore errada propaga TAC errado até o fim do pipeline.
16 · Dicas

Para um projeto bem-sucedido

Defina primeiro as interfaces entre fases; só depois implemente.

Escreva casos de aceitação antes do código: eles guiam a implementação.

Aproveite os simuladores da aula como referência de saída esperada.

Integre cedo e com frequência: junte as fases assim que cada uma tiver um esqueleto funcionando, em vez de só no fim.
17 · Interativo

Pense antes de revelar

Se o TAC gerado para "a + b * c" sair errado, em qual(is) fase(s) pode estar o defeito?
Pode estar em mais de uma fase. Se os tokens estiverem corretos mas a árvore agrupar a + b antes de b * c, o defeito está no parser (precedência mal codificada na gramática). Se a árvore estiver certa mas o TAC sair fora de ordem, o defeito está no gerador (percurso ou emissão das instruções). Raramente está no scanner, a menos que ele classifique mal um token. Testar fase a fase — inspecionar tokens, depois a árvore, depois o TAC — isola o defeito rapidamente. É por isso que interfaces claras entre fases facilitam a depuração.
18 · Flashcards

Revise os termos

Pipelinevirar
Sequência de fases em que a saída de uma é a entrada da próxima.
Caso de aceitaçãovirar
Par (entrada, saída esperada) que define o comportamento correto do compilador.
Interface entre fasesvirar
Contrato do formato de dados trocados (tokens, árvore, RI) entre fases vizinhas.
Front-end completovirar
Léxico + sintático + semântico + geração de RI, integrados ponta a ponta.
19 · Conexões

Como esta aula reúne o curso

  • Aula 3/4 (léxico): o scanner que tokeniza a entrada.
  • Aula 5/6/7 (sintaxe): o parser que constrói a árvore.
  • Aula 8/9 (semântica): a verificação de tipos e a tabela de símbolos.
  • Aula 10 (RI): a geração do código de três endereços — o coração do projeto.
20 · Síntese

O essencial da aula

🔑
O projeto integrador conecta scanner, parser, semântica e geração de RI em um pipeline onde a saída de cada fase é a entrada da próxima. Defina interfaces claras entre as fases para dividir o trabalho e depurar com facilidade, e use casos de aceitação (entrada → saída esperada) para guiar a implementação e validar o todo.
Mão na massa · colaborativo

Atividade em grupo · Sprint do mini-compilador

Em grupos, planejem e iniciem o projeto integrador.

⏱️ 40 min👥 grupos de 3–4🧩 projeto

Roteiro

  1. Definam o escopo da minilinguagem (ex.: expressões aritméticas com atribuição).
  2. Dividam tarefas: scanner, parser, gerador de TAC.
  3. Definam os casos de teste de aceitação (entradas e saídas esperadas).
  4. Montem um cronograma de implementação até a aula 14.
Líder de léxicoscanner e tokens
Líder de sintaxeparser e árvore
Líder de geraçãoTAC
QAcasos de teste
📤 Entrega: Documento de escopo + divisão de tarefas + 5 casos de teste de aceitação.
Teste seu conhecimento

Mini-quiz · Aula 13

20 questões sobre esta aula. Escolha e veja a explicação na hora.

0/20

📌 Resumo — leve isto para a prova

  • O pipeline integra scanner, parser, semântica e geração de RI; a saída de cada fase alimenta a próxima.
  • Interfaces claras entre fases permitem dividir o trabalho e depurar com facilidade.
  • Casos de teste de aceitação (entrada → saída) guiam a implementação e validam o todo.
  • O projeto exercita o front-end completo e produz código de três endereços.
  • O mini-compilador tem a mesma arquitetura de um compilador real, em escala menor.