LRM Prof. Mantovani ← Aulas da disciplina
Aula 7 de 14

LL(1), FIRST/FOLLOW · Revisão

Os conjuntos FIRST e FOLLOW, que guiam o parser preditivo; a construção e o uso da tabela LL(1); e a revisão geral das aulas 1 a 6.

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

O que você vai aprender

1

Calcular FIRST e FOLLOW de uma gramática.

2

Explicar o que a tabela LL(1) garante ao compilador que a descida da aula 6, sozinha, não garante.

3

Montar e usar a tabela preditiva LL(1).

4

Diagnosticar conflitos e por que uma gramática não é LL(1).

5

Consolidar os conceitos para a Avaliação 1.

1 · Motivação

Como o parser decide sem errar?

No parser descendente, ao expandir um não-terminal com várias produções, qual escolher? Olhar o próximo token e adivinhar dá errado se a escolha for ruim. Precisamos de um critério seguro.

Os conjuntos FIRST e FOLLOW dão exatamente isso: ao ver o próximo token, o parser sabe qual produção aplicar — sem retroceder. É a base do parsing preditivo LL(1).

🔑
FIRST e FOLLOW transformam o parser de "tentativa e erro" em "decisão certeira com 1 token de antecipação".
2 · Comparação

O que a aula 6 deixou em aberto

A aula 6 terminou com um parser que funciona: uma função por não-terminal, a gramática sem recursão à esquerda e fatorada. Mas deixou uma pergunta sem resposta: como saber que a escolha com um token está sempre certa? A descida escolhe “a primeira alternativa cujo FIRST contém o token” — e, quando nenhuma contém, segue pela ε, sem olhar o que vem depois. Isso funciona na gramática da aula. Em outras, falha em silêncio. E, antes da aula 6, só com a gramática da aula 5, a única saída seria tentar: derivar, conferir os terminais com a entrada e voltar atrás a cada engano.

Aula 5: só a gramática (tentativa e erro)Aula 6: a primeira que casaAula 7: a tabela LL(1)
Como escolhetenta a 1ª alternativa, confere os terminais e volta atrás se não batema primeira alternativa cujo FIRST contém o token; senão, εa célula M[A, token], montada com FIRST e FOLLOW
Custopode explodir (exponencial)linearlinear
Resposta certa?simgarantida só se a gramática for LL(1) — e nada avisa quando não ésim, e a garantia vem antes: sem conflito na tabela, vale para toda entrada
Erro de sintaxedescoberto depois de esgotar as tentativasàs vezes só no fim, como “sobrou token”na célula vazia, no não-terminal onde ele está, com a lista do que cabia ali

É essa a vantagem para o compilador: a aula 6 dá um parser rápido; a aula 7 dá a certeza de que ele está certo — ou aponta a célula exata onde não está, antes de o primeiro programa ser compilado. A bancada abaixo põe as três aulas lado a lado: a mesma gramática, o mesmo programa e a mesma unidade de trabalho. Siga as três fases — antes do primeiro programa, este programa, todos os programas curtos — e repare em quando cada uma descobre o defeito: na gramática ③, o checklist da aula 6 aprova tudo e a descida recusa um programa válido; a tabela recusa a gramática antes de rodar e aponta a célula.

3 · Mapa

O que veremos nesta aula

FIRST→FOLLOW→Tabela LL(1)→Revisão
  • O conjunto FIRST e como calculá-lo.
  • O conjunto FOLLOW e seu papel com ε.
  • A construção da tabela preditiva e o que é uma gramática LL(1).
  • Consolidação das aulas 1 a 6.
4 · Definição

FIRST e FOLLOW

FIRST(α). Conjunto de terminais que podem iniciar uma cadeia derivada de α (inclui ε se α pode derivar a cadeia vazia).
FOLLOW(A). Conjunto de terminais que podem aparecer imediatamente após o não-terminal A em alguma derivação.
5 · Aprofundamento

Calculando FIRST

Regras para FIRST(X):

  • Se X é terminal, FIRST(X) = { X }.
  • Se X → ε é produção, adicione ε a FIRST(X).
  • Se X → Y1 Y2 ... Yk, adicione FIRST(Y1) (sem ε). Se Y1 pode derivar ε, inclua também FIRST(Y2), e assim por diante.
💡
FIRST responde: "que terminais posso ver primeiro se eu seguir por aqui?". É olhar o começo de tudo que aquele símbolo gera.
6 · Exemplo

FIRST e FOLLOW da gramática de expressões

Para E → T E', E' → + T E' | ε, T → F T', T' → * F T' | ε, F → ( E ) | id:

Não-terminalFIRSTFOLLOW
E( id) $
E'+ ε) $
T( id+ ) $
T'* ε+ ) $
F( id+ * ) $

O símbolo $ marca o fim da entrada.

Esse quadro não sai de uma vez: sai de repetir as regras, produção por produção, até uma rodada inteira não acrescentar nada — o ponto fixo. Na bancada abaixo o cálculo roda exatamente assim, na ordem em que você faria no papel: dá para ver E esperando T, que espera F, e clicar em qualquer símbolo para saber quem o colocou ali.

7 · Interativo

Passo a passo: FOLLOW(T)

Passo 1
Em E → T E', após T vem E'. Adicionamos FIRST(E') sem ε a FOLLOW(T): logo + entra.
Passo 2
Como E' pode derivar ε, T também pode estar no fim de E. Então FOLLOW(T) recebe FOLLOW(E).
Passo 3
FOLLOW(E) = { ) , $ }. Adicionamos esses a FOLLOW(T).
Passo 4
Resultado: FOLLOW(T) = { + , ) , $ }.
8 · Definição

Gramática LL(1)

LL(1). Left-to-right scan, Leftmost derivation, 1 token de lookahead. Uma gramática é LL(1) se sua tabela preditiva não tiver conflitos (nenhuma célula com mais de uma produção).
9 · Aprofundamento

Montando a tabela preditiva

Para cada produção A → α, preenche-se a tabela (linha A, coluna terminal):

  • Coloque A → α em cada coluna t de FIRST(α).
  • Se ε ∈ FIRST(α), coloque A → α também em cada coluna t de FOLLOW(A).
💡
Em uso: o parser olha o topo da pilha (um não-terminal A) e o token atual (t); consulta a célula [A][t]; aplica a produção indicada. Sem ambiguidade, sem retrocesso.
10 · Analogia

O mapa de decisões

🔧 Analogia
A tabela LL(1) é como um GPS: em cada cruzamento (não-terminal) e com a placa que você vê adiante (o token de lookahead), ele diz exatamente qual rua pegar (qual produção). Se duas ruas aparecessem para a mesma situação, o GPS estaria confuso — e a gramática não seria LL(1).
11 · Comparação

FIRST × FOLLOW

FIRST(α)FOLLOW(A)
O que descreveO que pode começar αO que pode vir depois de A
Aplica-se aQualquer cadeia αNão-terminais A
Pode conter ε?SimNão (mas contém $)
Uso na tabelaColunas onde a produção entraColunas extras quando α deriva ε

Hora de montar a tabela com as suas mãos. Na bancada abaixo, uma produção por vez: marque as colunas em que ela entra e confira — a correção diz, coluna a coluna, se ela entrou pelo FIRST, pelo FOLLOW, ou por que não entra. Repare em E' → ε: é a produção que só entra pelo FOLLOW.

12 · Fluxo

Do cálculo à decisão

A construção do parser preditivo segue uma cadeia bem definida:

Gramática→FIRST→FOLLOW→Tabela LL(1)→Parser

O último elo é a decisão. Na bancada abaixo, o analisador preditivo usa a tabela: com um não-terminal no topo da pilha, ele consulta uma célula — M[topo, token] — e ela acende na tabela. Com um terminal no topo, ele nem olha a tabela: só confere se o token é o esperado.

13 · Aprofundamento

Quando NÃO é LL(1)

⚠️
Um conflito na tabela (duas produções na mesma célula) significa que a gramática não é LL(1). As causas típicas são: ambiguidade, recursão à esquerda não eliminada, ou falta de fatoração (FIRST de duas alternativas se sobrepõem).

Por isso as transformações da aula 6 (eliminar recursão à esquerda, fatorar) são pré-requisitos: sem elas, a tabela quase certamente terá conflitos.

Os conflitos têm dois tipos, e vale saber dar nome a eles:

ConflitoO que acontece na célula M[A, a]De onde costuma vir
FIRST/FIRSTduas alternativas de A podem começar com arecursão à esquerda, prefixo comum (às vezes escondido atrás de outros não-terminais), ambiguidade
FIRST/FOLLOWuma alternativa de A pode sumir (deriva ε), e a, que vem depois de A, também começa outra alternativaε mal colocado; o else pendente é o exemplo clássico

Na bancada abaixo, oito gramáticas: decida se cada uma é LL(1) e, se não for, que conflito ela tem. Depois da resposta, a tabela mostra a célula culpada e, quando existe, o remédio da aula 6 é aplicado na hora.

14 · Verifique

Verifique você mesmo: onde entra ε?

Para a produção E' → + T E' | ε, em quais colunas entra a produção E' → ε na tabela?

Como E' → ε tem FIRST = { ε }, a produção entra nas colunas de FOLLOW(E') = { ), $ }. O '+' fica reservado para a produção E' → + T E'.
15 · Caso prático

Geradores de parser LL

Ferramentas como ANTLL e bibliotecas de parser combinators usam a teoria LL. Geradores LL(1) clássicos constroem a tabela automaticamente a partir da gramática.

💡
Quando um gerador reclama de "conflito", é a tabela LL(1) acusando duas produções na mesma célula. A correção costuma ser exatamente fatorar ou eliminar recursão à esquerda — o que estudamos na aula 6.
16 · Erros comuns

Enganos com FIRST/FOLLOW

⚠️
Cuidado. Não inclua ε em FOLLOW (FOLLOW só tem terminais e $). Não esqueça de propagar FOLLOW quando o símbolo pode estar no fim de uma produção (via ε). E lembre: FIRST aplica-se a cadeias (α), enquanto FOLLOW aplica-se só a não-terminais.
17 · Boas práticas

Calculando com segurança

✅
Dica. Calcule todos os FIRST antes de começar os FOLLOW — o cálculo de FOLLOW depende de FIRST. Repita o processo até nada mudar (ponto fixo): os conjuntos crescem por iterações sucessivas até estabilizar.
18 · Revelar

Reflita: LL(1) é o limite?

Toda linguagem livre de contexto tem uma gramática LL(1)?
Não. Existem linguagens livres de contexto para as quais nenhuma gramática LL(1) existe — elas exigem mais lookahead ou um método ascendente (LR). LL(1) é uma subclasse conveniente, porque permite parsers preditivos simples e eficientes, mas não cobre todas as GLC. Quando LL(1) não dá conta, recorre-se a LL(k), LR(1), LALR e similares.
19 · Flashcards

Termos-chave da aula

FIRST(α)virar
Terminais que podem iniciar uma cadeia derivada de α (com ε se α deriva vazio).
FOLLOW(A)virar
Terminais que podem aparecer logo após A em alguma derivação (inclui $).
LL(1)virar
Left-to-right, Leftmost, 1 lookahead. Tabela sem conflitos.
Conflitovirar
Célula da tabela com duas produções: a gramática não é LL(1).
20 · Conexões

O quadro geral das aulas 1 a 6

Esta semana fecha o primeiro bloco. Veja como tudo se conecta:

  • Aulas 1-2: o panorama e as linguagens formais (Chomsky).
  • Aulas 3-4: léxico — tokens, ER, autômatos (tipo 3).
  • Aulas 5-6: sintaxe — GLC, ambiguidade, parsing descendente (tipo 2).
  • Aula 7: FIRST/FOLLOW e LL(1) coroam o parsing preditivo. A Prova 1 cobre tudo isso.
21 · Síntese

Resumo visual

🔑
FIRST = terminais iniciais; FOLLOW = terminais seguintes. LL(1) = top-down, derivação à esquerda, 1 lookahead. A tabela preditiva sem conflitos significa gramática LL(1). Conflitos vêm de ambiguidade, recursão à esquerda ou falta de fatoração.
22 · Simulador

Calcule FIRST/FOLLOW automaticamente

Todas as bancadas desta aula aceitam a sua gramática: escreva na caixa de texto e tudo se recalcula. Para os conjuntos e a tabela prontos, use a mesa LL(1); para ver o cálculo acontecer, o ponto fixo rodada a rodada.

Tente: o que acontece com os conjuntos se você adicionar uma produção com ε? E se introduzir recursão à esquerda? Observe como os conjuntos mudam — e em que célula da tabela o conflito aparece.

Mão na massa · colaborativo

Atividade em grupo · Mutirão de revisão (Prova 1)

Em grupos, montem um mapa de revisão das aulas 1–6.

⏱️ 30 min👥 grupos de 4🧩 estudo colaborativo

Roteiro

  1. Cada integrante fica responsável por um tema: léxico, ER/autômatos, GLC, parsing descendente.
  2. Montem um mapa mental conectando os temas (uma página).
  3. Criem 2 questões originais por tema e troquem com outro grupo.
  4. Resolvam as questões recebidas e discutam.
Léxicotokens, ER, autômatos
SintaxeGLC, árvores, ambiguidade
Parsingdescendente, FIRST/FOLLOW
Curadormonta o mapa final
📤 Entrega: Mapa mental de revisão + 8 questões autorais com gabarito.
Teste seu conhecimento

Mini-quiz · Aula 7

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

0/20

📌 Resumo — leve isto para a prova

  • A aula 6 dá um parser rápido; a aula 7 dá a garantia: sem conflito na tabela, a escolha com um token é certa para toda entrada — e o conflito aparece antes de o primeiro programa ser compilado.
  • FIRST = terminais iniciais (pode conter ε); FOLLOW = terminais seguintes (contém $, nunca ε).
  • LL(1) = leitura da esquerda para a direita, derivação mais à esquerda, 1 lookahead.
  • A tabela preditiva sem conflitos significa gramática LL(1).
  • Conflitos vêm de ambiguidade, recursão à esquerda ou falta de fatoração.
  • Nem toda linguagem livre de contexto admite gramática LL(1).
  • FIRST e FOLLOW se calculam por ponto fixo: repita as regras, produção por produção, até uma rodada inteira não acrescentar nada — e o FOLLOW só depois do FIRST.
  • Conflito FIRST/FIRST: duas alternativas começam com o mesmo token. Conflito FIRST/FOLLOW: uma alternativa some, e o token que vem depois dela também começa outra.