Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Compiladores e suas características, Notas de estudo de Compiladores

Compiladores Análise sintática Análise Top-Down

Tipologia: Notas de estudo

2021

Compartilhado em 08/10/2021

alexandre-martins-jgt
alexandre-martins-jgt 🇧🇷

5 documentos

1 / 6

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
1
Compiladores
Análise sintática (2)
Análise Top-Down
Lembrando...
Gramáticas Livres de Contexto
Análise sintática = parsing.
Baseada em GLCs
Gramática: S A B
Ac | ε
B cbB | ca
String:
ccbca
S AB
cB
ccbB
ccbca
Top-Down
SAB
Ac
BcbB
Bca
Ac
Bca
BcbB
SAB
ccbca Acbca
AcbB
AB
S
Bottom-Up
Caraterísticas de Gramáticas
Gramática fatorada à esquerda
:
GLC que não possui produções do tipo A
αβ
1
| αβ
2
para alguma forma sentencial α.
Gramática recursiva à esquerda
:
GLC que permite a derivação
A
+
Aαpara algum A
N
O não terminal A deriva ele mesmo, de forma direta ou
indireta, como símbolo mais à esquerda de uma
subpalavra gerada
.
OBS: RECONHECEDOR TOP-DOWN não aceita gramáticas
recursivas à esquerda
Eliminação de recursividade à
esquerda
Exemplo
A Aa | b
Sem a palavra vazia
A b | bX
X a | aX
Com a palavra vazia
A bX
X aX |ε
Obs: pode ainda haver recursão indireta!
Exemplo
E -> E+T | T
T -> T*F | F
F -> (E)| Id
A regra E -> E+T | T se torna:
E -> TE’
E’ -> +TE’| ε
εε
ε
A regra T- > T*F | F se torna:
T -> FT’
T’-> *FT’ | ε
εε
ε
Fatoração de uma gramática
Elimina indecisão de qual produção aplicar
quando duas ou mais produções iniciam com a
mesma forma sentencial
A αβ
1
| αβ
2
Se torna:
A αX
X β
1
|β
2
pf3
pf4
pf5

Pré-visualização parcial do texto

Baixe Compiladores e suas características e outras Notas de estudo em PDF para Compiladores, somente na Docsity!

Compiladores

Análise sintática (2)

Análise Top-Down

Lembrando...

Gramáticas Livres de Contexto

  • Análise sintática = parsing.
  • Baseada em GLCs

Gramática: S → A B

A → c | ε

B → cbB | ca

String:

ccbca

S ⇒ AB

⇒ cB

⇒ ccbB

⇒ ccbca

Top-Down

S→AB

A→c

B→cbB

B→ca

A→c

B→ca

B→cbB

S→AB

ccbca ⇐ Acbca

⇐ AcbB

⇐ AB

⇐ S

Bottom-Up

Caraterísticas de Gramáticas

• Gramática fatorada à esquerda:

– GLC que não possui produções do tipo A →

αβ 1 | αβ 2 para alguma forma sentencial α.

• Gramática recursiva à esquerda:

– GLC que permite a derivação

A ⇒+^ Aα para algum A ∈ N

O não terminal A deriva ele mesmo, de forma direta ou

indireta, como símbolo mais à esquerda de uma

subpalavra gerada.

OBS: RECONHECEDOR TOP-DOWN não aceita gramáticas

recursivas à esquerda

Eliminação de recursividade à

esquerda

• Exemplo

A → Aa | b

Sem a palavra vazia

A → b | bX

X → a | aX

Com a palavra vazia

A → bX

X → aX |ε

Obs: pode ainda haver recursão indireta!

Exemplo

• E -> E+T | T

• T -> T*F | F

• F -> (E)| Id

A regra E -> E+T | T se torna:

E -> TE’

E’ -> +TE’| εεεε

A regra T- > T*F | F se torna:

T -> FT’

T’-> *FT’ | εεεε

Fatoração de uma gramática

• Elimina indecisão de qual produção aplicar

quando duas ou mais produções iniciam com a

mesma forma sentencial

A → αβ 1 | αβ 2

Se torna:

A → αX

X → β 1 |β 2

Exemplo de Fatoração a Esquerda

Cmd →→→→ if Expr then Cmd else Cmd

Cmd →→→→ if Expr then Cmd

Cmd →→→→ Outro

• Fatorando a esquerda:

Cmd →→→→ if Expr then Cmd ElseOpc

Cmd →→→→ Outro

ElseOpc →→→→ else Cmd | ε

Eliminação de produções vazias

• Objetivo:

– eliminar produções da forma A → ε.

• Algoritmo: seja G = (N,T,P,S) uma GLC

– Etapa 1:

  • construir Nε , o conjunto de não-terminais que

geram a palavra vazia:

Nε = {A | A → ε };

Repita

Nε = Nε ∪ {X | X → X 1 ...Xn ∈ P tq X1,...,Xn ∈

Nε}

Até que o cardinal de Nε não aumente.

Eliminação de produções vazias

  • Etapa 2:
    • construir o conjunto de produções sem produções

vazias:

gera G 1 = (N,T,P 1 ,S), onde P 1 é construído como

segue:

P 1 = {A → α | α ≠ ε};

Repita

Para toda A → α ∈ P 1 e X ∈ Nε tal que

α = α 1 Xα 2 e α 1 α 2 ≠ ε

Faça P 1 = P 1 ∪ {A → α 1 α 2 }

Até que o cardinal de P 1 não aumente

Eliminação de produções vazias

– Etapa 3:

• incluir geração da palavra vazia, se

necessário.

• Se a palavra vazia pertence à linguagem,

então a gramática resultante é

• G 2 = (N,T,P 2 ,S), onde P 2 = P 1 ∪ {S → ε}

Plano da aula

  • Como reconhecer se uma sentença está de

acordo com uma gramática?

  • Pode-se implementar um reconhecedor de sentença
    • Recursivamente, com retrocesso
    • Com um mecanismo preditivo » Lookahead. » Primitivas First e Follow.
  • Para usar reconhecedores, deve-se transformar a GLC.
    • Eliminação de produções vazias
    • Eliminação de recursividade à esquerda: » recursão direta » recursão indireta
    • Fatoração de uma gramática

Análise Top-Down

• Como implementar um reconhecedor para uma

GLC?

• Constrói-se a árvore de derivação, lendo a

sentença de esquerda para a direita, e

substituindo sempre o não-terminal mais à

esquerda.

• Existe três tipos principais de parser top-down:

  • Recursivo com retrocesso
  • Recursivo preditivo
  • Tabular preditivo.

proc First(α: string of symbols)

Repeat {

Para todas as produções α → X 1 X 2 X 3 … Xn do if X 1 ∈T then // caso simples onde X 1 é um terminal First(α) := {X 1 } else { // X 1 é um não-terminal First(α) = First{X 1 } \ {ε}; for (i=1 ; i<=n ; i++) { if ε is in First(X 1 ) and in First(X 2 ) and in… First(Xi-1) First(α) := First(α) ∪ First(Xi) \ {ε} } } if (α =>* ε) then First(α) := First(α) ∪ {ε} end do } until no change in any First(α)

O que acontece se ε ∈ First(A)?

S → ACE

A → a | b | ε

C → c | d | ε

E → e

Consegue derivar?

  • ace
  • bde
  • ce
  • de
  • e

O que acontece se ε ∈ First(A)?

S → ACE

A → a | b | ε

C → c | d | ε

E → e

Consegue derivar?

  • ace
  • bde
  • ce
  • de
  • e

S () {

switch { case ‘a’: case ‘b’: A(); C(); E(); break; default: abort(“syntax_error”); }

O que acontece se ε ∈ First(A)?

S → ACE

A → a | b | ε

C → c | d | ε

E → e

Consegue derivar?

  • ace
  • bde
  • ce
  • de
  • e

S () {

switch { case ‘a’: case ‘b’: case ‘c’: case ‘d’: C(); E(); break; default: abort(“syntax_error”); }

O que acontece se ε ∈ First(A)?

S → ACE

A → a | b | ε

C → c | d | ε

E → e

Consegue derivar?

  • ace
  • bde
  • ce
  • de
  • e

S () {

switch { case ‘a’: case ‘b’: case ‘c’: case ‘d’: case ‘e’: E(); break; default: abort(“syntax_error”); }

O que acontece se ε ∈ First(A)?

S → ACE

A → a | b | ε

C → c | d | ε

E → e

Consegue derivar?

  • ace
  • bde
  • ce
  • de
  • e

A () {

switch { case ‘a’: MatchToken(‘a’); break; case ‘b’: MatchToken(‘b’); break; case ??: break; default: abort(“syntax_error”); }

Outro exemplo

• Escrever um reconhecedor recursivo

simples para as gramáticas equivalentes:

E -> E+T | T

T -> T*F | F

F -> (E)| Id

E -> TE’

E’ -> +TE’| ε

T -> FT’

T’-> *FT’ | ε

F -> (E)| Id

Para tratar o caso do ε:

o conjunto Follow

• Follow(B):

  • conjunto de terminais que podem aparecer à direita

de um não-terminal B em uma sentença válida.

  • $ passa a denotar um terminal “virtual” que marca o

fim da entrada (EOF, CTRL-D,…)

• Formalmente:

  • Se existe um t ∈ T e α, β ∈ V * tal que S ⇒* α B t β

então t ∈ Follow(B)

  • Se S ⇒* α B então $ ∈ Follow(B)

Exemplo First/Follow

S → A B

A → c | ε

B → cbB | ca

Exemplo First/Follow

S → A B

A → c | ε

B → cbB | ca

First(A) = {c, ε} Follow(A) = {c}

First(B) = {c} Follow(B) = {$}

First(S) = {c} Follow(S) = {$}

Algoritmo: proc Follow(B ∈ N)

Follow(S) := {$};

Repeat

foreach p ∈ P do {

// Varre as produções

case p == A → αB // a produção termina por B

Follow(B) := Follow(B) ∪ Follow(A);

case p == A → αBβ {// a produção NÃO termina por B

Follow(B) := Follow(B) ∪ First(β){ε};

if ε ∈ First(β) then

Follow(B) := Follow(B) ∪ Follow(A);

end

until no change in any Follow(N)

Observações First/Follow

  • Só terminais entram em First e Follow.
  • O algoritmo de cálculo de First(α):
    • É trivial quando α é um terminal t.
    • varre as produções X → tω quando α é um não-terminal X;
    • é chato quando o início de ume derivação de X deriva em ε.
    • Inclui ε apenas quando X pode derivar em ε.
  • O algoritmo de cálculo de Follow(X)
    • É reservado aos não-terminais X
    • Inclui o $ em alguns casos triviais (X == o start S)
    • Varre as produções onde X aparece à direita (A → ωX ω’)
    • É chato quando X aparece no fim (ou logo antes de algo que deriva em ε)
    • NUNCA inclui ε