Compiladores

Parsing SLR(1)

Professor: Gabriel Soares Baptista

Aula de hoje

  • revisão rápida de LR(0)
  • exemplo LR(0) um pouco maior
  • conflito shift/reduce
  • ideia do SLR(1)
  • tabela SLR(1) passo a passo
  • comparação: LL(1), LR(0), SLR(1)

De LR(0) para SLR(1)

No LR(0):

  • estados são conjuntos de itens LR(0)
  • shift vem das transições por terminal
  • goto vem das transições por não terminal
  • item completo gera reduce

Problema do LR(0)

No LR(0), uma redução entra em todas as colunas.

Se o estado contém:

$$ A \to \alpha \cdot $$

então colocamos:

$$ r(A \to \alpha) $$

em todas as colunas de ACTION.

Ideia central do SLR(1)

Ideia central

SLR(1) usa os mesmos estados LR(0), mas coloca reduções apenas nas colunas de FOLLOW.

  • autômato: igual ao LR(0)
  • transições: iguais ao LR(0)
  • shift: igual ao LR(0)
  • goto: igual ao LR(0)
  • reduce: limitado por FOLLOW

Aquecimento LR(0)

Gramática:

$$ \begin{array}{rcl} (0) & S' & \to S \\ (1) & S & \to BB \\ (2) & B & \to aB \\ (3) & B & \to b \end{array} $$

  • cada B gera zero ou mais a seguidos de b
  • S gera dois blocos B B
  • exemplos: bb, abb, bab, aababb

Aquecimento: estado inicial

$$ I_0 = \left\{ \begin{array}{l} S' \to \cdot S \\ S \to \cdot BB \\ B \to \cdot aB \\ B \to \cdot b \end{array} \right\} $$

Transições de I0:
Símbolo Destino
S I1
B I2
a I3
b I4

Aquecimento: estados

$$ I_1 = \left\{ \begin{array}{l} S' \to S \cdot \end{array} \right\} \qquad I_2 = \left\{ \begin{array}{l} S \to B \cdot B \\ B \to \cdot aB \\ B \to \cdot b \end{array} \right\} $$

$$ I_3 = \left\{ \begin{array}{l} B \to a \cdot B \\ B \to \cdot aB \\ B \to \cdot b \end{array} \right\} \qquad I_4 = \left\{ \begin{array}{l} B \to b \cdot \end{array} \right\} $$

Aquecimento: mais estados

$$ I_5 = \left\{ \begin{array}{l} S \to BB \cdot \end{array} \right\} \qquad I_6 = \left\{ \begin{array}{l} B \to aB \cdot \end{array} \right\} $$

Transições restantes:
Origem Símbolo Destino
I2 B I5
I2 a I3
I2 b I4
I3 B I6
I3 a I3
I3 b I4

Aquecimento: tabela LR(0)

Estado ACTION a ACTION b ACTION $ GOTO S GOTO B
0 s3 s4 1 2
1 acc
2 s3 s4 5
3 s3 s4 6
4 r3 r3 r3
5 r1 r1 r1
6 r2 r2 r2
Sem conflito: gramática LR(0).

Exercício rápido

Entrada:

abb$
  • simular usando a tabela LR(0)
  • identificar reduções por $B \to b$
  • identificar reduções por $B \to aB$
  • finalizar com $S \to BB$

Simulação: abb$

Pilha Entrada Ação
0 a b b $ s3
0 a 3 b b $ s4
0 a 3 b 4 b $ r3, reduz $B \to b$
0 a 3 B 6 b $ r2, reduz $B \to aB$
0 B 2 b $ s4
0 B 2 b 4 $ r3, reduz $B \to b$
0 B 2 B 5 $ r1, reduz $S \to BB$
0 S 1 $ acc

Agora um problema

Gramática:

$$ \begin{array}{rcl} (0) & S' & \to S \\ (1) & S & \to Aa \\ (2) & S & \to bA \\ (3) & A & \to b \end{array} $$

  • aceita ba
  • aceita bb
  • parece pequena
  • mas LR(0) entra em conflito

Estado inicial

$$ I_0 = \left\{ \begin{array}{l} S' \to \cdot S \\ S \to \cdot Aa \\ S \to \cdot bA \\ A \to \cdot b \end{array} \right\} $$

Transições de I0:
Símbolo Destino
S I1
A I2
b I3

Estado problemático

Ao ler b a partir de I0:

$$ I_3 = \left\{ \begin{array}{l} S \to b \cdot A \\ A \to b \cdot \\ A \to \cdot b \end{array} \right\} $$

Item Sugestão
$S \to b \cdot A$ e $A \to \cdot b$ próximo b: fazer shift
$A \to b \cdot$ reduzir $A \to b$

Conflito LR(0)

No LR(0), $A \to b \cdot$ reduz em todas as colunas.

Estado ACTION a ACTION b ACTION $
3 r3 s6 / r3 r3
Conflito shift/reduce na coluna b.

Intuição da decisão

Depois de ler o primeiro b:

  • entrada ba$: reduzir o primeiro b para A
  • entrada bb$: empilhar o segundo b
  • decisão depende do próximo símbolo
LR(0) não consulta o próximo símbolo para reduzir.

Regra SLR(1)

No LR(0):

$$ A \to \alpha \cdot \quad \Rightarrow \quad \text{reduz em todas as colunas} $$

No SLR(1):

$$ A \to \alpha \cdot \quad \Rightarrow \quad \text{reduz apenas em } FOLLOW(A) $$

FOLLOW do exemplo

Gramática:

$$ \begin{array}{rcl} S & \to Aa \\ S & \to bA \\ A & \to b \end{array} $$

$$ FOLLOW(S)=\{\$\} $$

De $S \to Aa$:

$$ a \in FOLLOW(A) $$

De $S \to bA$:

$$ FOLLOW(S) \subset FOLLOW(A) $$

FOLLOW final

$$ FOLLOW(A)=\{a,\$\} $$

Então, no estado I3:

$$ A \to b \cdot $$

reduz apenas nas colunas a e $.

Estado ACTION a ACTION b ACTION $
3 r3 s6 r3

Terminando o exemplo

Estados LR(0):

$$ I_0 = \left\{ \begin{array}{l} S' \to \cdot S \\ S \to \cdot Aa \\ S \to \cdot bA \\ A \to \cdot b \end{array} \right\} \qquad I_1 = \left\{ \begin{array}{l} S' \to S \cdot \end{array} \right\} $$

$$ I_2 = \left\{ \begin{array}{l} S \to A \cdot a \end{array} \right\} \qquad I_3 = \left\{ \begin{array}{l} S \to b \cdot A \\ A \to b \cdot \\ A \to \cdot b \end{array} \right\} $$

Terminando: mais estados

$$ I_4 = \left\{ \begin{array}{l} S \to Aa \cdot \end{array} \right\} \qquad I_5 = \left\{ \begin{array}{l} S \to bA \cdot \end{array} \right\} \qquad I_6 = \left\{ \begin{array}{l} A \to b \cdot \end{array} \right\} $$

Origem Símbolo Destino
I0 S I1
I0 A I2
I0 b I3
I2 a I4
I3 A I5
I3 b I6

Tabela SLR(1)

Estado ACTION a ACTION b ACTION $ GOTO S GOTO A
0 s3 1 2
1 acc
2 s4
3 r3 s6 r3 5
4 r1
5 r2
6 r3 r3

Simulação: ba$

Pilha Entrada Ação
0 b a $ s3
0 b 3 a $ r3, reduz $A \to b$
0 A 2 a $ s4
0 A 2 a 4 $ r1, reduz $S \to Aa$
0 S 1 $ acc

Simulação: bb$

Pilha Entrada Ação
0 b b $ s3
0 b 3 b $ s6
0 b 3 b 6 $ r3, reduz $A \to b$
0 b 3 A 5 $ r2, reduz $S \to bA$
0 S 1 $ acc

Algoritmo SLR(1)

  1. aumentar a gramática: $S' \to S$
  2. numerar produções
  3. construir estados LR(0)
  4. calcular FOLLOW
  5. inserir shift por transições terminais
  6. inserir goto por transições não terminais
  7. inserir reduce apenas em FOLLOW(A)
  8. inserir acc para $S' \to S \cdot$
  9. verificar conflitos

Exemplo SLR(1) completo

Gramática:

$$ \begin{array}{rcl} (0) & S' & \to S \\ (1) & S & \to (L) \\ (2) & S & \to a \\ (3) & L & \to L,S \\ (4) & L & \to S \end{array} $$

  • S: expressão
  • L: lista de expressões
  • exemplos: a, (a), (a,a), ((a),a)

Exemplo: estado inicial

$$ I_0 = \left\{ \begin{array}{l} S' \to \cdot S \\ S \to \cdot (L) \\ S \to \cdot a \end{array} \right\} $$

Símbolo Destino
S I1
( I2
a I3

Estados I1, I2, I3

$$ I_1 = \left\{ \begin{array}{l} S' \to S \cdot \end{array} \right\} $$

$$ I_2 = \left\{ \begin{array}{l} S \to ( \cdot L) \\ L \to \cdot L,S \\ L \to \cdot S \\ S \to \cdot (L) \\ S \to \cdot a \end{array} \right\} $$

$$ I_3 = \left\{ \begin{array}{l} S \to a \cdot \end{array} \right\} $$

Estados I4, I5

$$ I_4 = \left\{ \begin{array}{l} S \to (L \cdot ) \\ L \to L \cdot ,S \end{array} \right\} $$

$$ I_5 = \left\{ \begin{array}{l} L \to S \cdot \end{array} \right\} $$

  • I4: depois de reconhecer L dentro de parênteses
  • pode fechar com )
  • pode continuar lista com ,S

Estados I6, I7, I8

$$ I_6 = \left\{ \begin{array}{l} S \to (L) \cdot \end{array} \right\} $$

$$ I_7 = \left\{ \begin{array}{l} L \to L, \cdot S \\ S \to \cdot (L) \\ S \to \cdot a \end{array} \right\} $$

$$ I_8 = \left\{ \begin{array}{l} L \to L,S \cdot \end{array} \right\} $$

Transições completas

Origem Símbolo Destino
I0 S I1
I0 ( I2
I0 a I3
I2 L I4
I2 S I5
I2 ( I2
I2 a I3
I4 ) I6
I4 , I7
I7 S I8
I7 ( I2
I7 a I3

FOLLOW: começo

Começamos com:

$$ FOLLOW(S)=\{\$\} $$

Da produção $S \to (L)$:

$$ \texttt{)} \in FOLLOW(L) $$

Da produção $L \to L,S$:

$$ \texttt{,} \in FOLLOW(L) $$

FOLLOW: propagação

Em $L \to L,S$:

  • o S está no fim
  • então S herda FOLLOW(L)
Em $L \to S$:
  • o S está no fim
  • então S herda FOLLOW(L)

FOLLOW final

$$ FOLLOW(L)=\{\texttt{)},\texttt{,}\} $$

$$ FOLLOW(S)=\{\$,\texttt{)},\texttt{,}\} $$
  • depois de L: fecha parêntese ou vírgula
  • depois de S: fim, fecha parêntese ou vírgula

Tabela SLR(1)

Estado ACTION ( ACTION ) ACTION a ACTION , ACTION $ GOTO S GOTO L
0 s2 s3 1
1 acc
2 s2 s3 5 4
3 r2 r2 r2
4 s6 s7
5 r4 r4
6 r1 r1 r1
7 s2 s3 8
8 r3 r3

De onde vêm as reduções?

Estado Item completo Redução Colunas
I3 $S \to a \cdot$ r2 $FOLLOW(S)={$,\texttt{)},\texttt{,}}$
I5 $L \to S \cdot$ r4 $FOLLOW(L)=\{\texttt{)},\texttt{,}\}$
I6 $S \to (L) \cdot$ r1 $FOLLOW(S)={$,\texttt{)},\texttt{,}}$
I8 $L \to L,S \cdot$ r3 $FOLLOW(L)=\{\texttt{)},\texttt{,}\}$

Simulação: (a,a)$

Pilha Entrada Ação
0 ( a , a ) $ s2
0 ( 2 a , a ) $ s3
0 ( 2 a 3 , a ) $ r2, reduz $S \to a$
0 ( 2 S 5 , a ) $ r4, reduz $L \to S$
0 ( 2 L 4 , a ) $ s7
0 ( 2 L 4 , 7 a ) $ s3
0 ( 2 L 4 , 7 a 3 ) $ r2, reduz $S \to a$

Simulação: continuação

Pilha Entrada Ação
0 ( 2 L 4 , 7 S 8 ) $ r3, reduz $L \to L,S$
0 ( 2 L 4 ) $ s6
0 ( 2 L 4 ) 6 $ r1, reduz $S \to (L)$
0 S 1 $ acc

Comparação

Técnica Direção Derivação Decisão Informação
LL(1) esquerda para direita mais à esquerda expandir produção FIRST, FOLLOW
LR(0) esquerda para direita mais à direita ao contrário empilhar ou reduzir estado LR(0)
SLR(1) esquerda para direita mais à direita ao contrário empilhar ou reduzir estado LR(0), FOLLOW

Quando é LL(1)?

Para cada não terminal:

  • alternativas não podem começar com o mesmo terminal
  • conjuntos FIRST das alternativas não podem se sobrepor
  • se houver $\epsilon$, usar FOLLOW para decidir
  • não pode ter recursão à esquerda

Quando é LR(0)?

Uma gramática é LR(0) se a tabela LR(0) não tem conflitos.

Conflitos:
  • shift/reduce
  • reduce/reduce
Ponto fraco: redução entra em todas as colunas.

Quando é SLR(1)?

Uma gramática é SLR(1) se a tabela com estados LR(0) e reduções por FOLLOW não tem conflitos.

  • resolve alguns conflitos LR(0)
  • usa um símbolo de lookahead indiretamente
  • FOLLOW é uma aproximação global
  • ainda pode rejeitar gramáticas LR(1)

Relação entre classes

Dentro da família LR:

$$ LR(0) \subset SLR(1) \subset LR(1) $$

  • todo LR(0) é SLR(1)
  • nem todo SLR(1) é LR(0)
  • LR(1) é mais preciso que SLR(1)

Por que precisamos disso?

  • LL(1): decide cedo demais para muitas gramáticas
  • LR(0): reduz cedo demais em muitos estados
  • SLR(1): reduz apenas onde o contexto permite
  • CLR/LR(1): leva o lookahead para dentro dos itens

Exercícios finais

  • montar LR(0) para $S \to aS \mid b$
  • refazer o conflito $S \to Aa \mid bA$, $A \to b$
  • montar SLR(1) para $S \to (L) \mid a$, $L \to L,S \mid S$
  • simular (a,(a,a))$

Próxima aula

CLR / LR(1) canônico

  • itens com lookahead explícito
  • decisões mais precisas que SLR(1)
  • menos conflitos falsos
  • base conceitual para LR(1) e LALR