19.04.2013 Views

Análise Sintática botton-up - Departamento de Informática

Análise Sintática botton-up - Departamento de Informática

Análise Sintática botton-up - Departamento de Informática

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Análise</strong> <strong>Sintática</strong> <strong>botton</strong>-<strong>up</strong><br />

Magnos Martinello<br />

Universida<strong>de</strong> Fe<strong>de</strong>ral do Espírito Santo - UFES<br />

<strong>Departamento</strong> <strong>de</strong> <strong>Informática</strong> - DI<br />

Laboratório <strong>de</strong> Pesquisas em Re<strong>de</strong>s Multimidia - LPRM<br />

2009


<strong>Análise</strong> sintática Botton-<strong>up</strong><br />

Tenta construir a árvore gramatical começando pelas folhas e<br />

trabalhando em direção a raiz.<br />

Um bottom-<strong>up</strong> parser constroi uma <strong>de</strong>rivação da sentença <strong>de</strong><br />

entrada retornando ao simbolo inicial S<br />

S ⇒ γ 0 ⇒ γ 1 ⇒ γ 2 ⇒ … ⇒ γ n-1 ⇒ γ n ⇒ sentença<br />

Para <strong>de</strong>rivar γ i-1 a partir γ i, associa-se γ i = α β δ contra γ i,<br />

substitui-se β com sua parte correspon<strong>de</strong>nte lhs, N, para resultar γ<br />

1<br />

= α N δ . (assumindo N→β )<br />

Uma árvore sintática não precisa ser construída, mas po<strong>de</strong> ser<br />

simulada<br />

|parse tree no<strong>de</strong>s| = |words| + |reductions|


Encontrando reduções<br />

Consi<strong>de</strong>re a gramática a seguir<br />

1 Goal → a A B e<br />

2 A → A b c<br />

3 | b<br />

4 B → d<br />

String <strong>de</strong> entrada abbc<strong>de</strong><br />

Sentential Next Red’n<br />

Form Prod’n Pos’n<br />

abbc<strong>de</strong> 3 2<br />

a A bc<strong>de</strong> 2 4<br />

a A <strong>de</strong> 4 3<br />

a A B e 1 4<br />

Goal — —<br />

A idéia é percorrer a entrada encontrando a próxima redução


Encontrando Reduções<br />

Se G é não-ambígua, então toda a forma <strong>de</strong> sentença a<br />

direita tem uma única redução<br />

Se pu<strong>de</strong>rmos encontrar as reduções, então po<strong>de</strong>mos construir<br />

uma <strong>de</strong>rivação !<br />

Roteiro da Prova:<br />

1 G é não-ambígua ⇒ <strong>de</strong>rivação mais a direita é única<br />

2 ⇒ uma única produção N→ β aplicada para levar γ i-1 à γ i<br />

3 ⇒ uma única posição k na qual N→ β é aplicada<br />

4 ⇒ uma única redução


Botton-<strong>up</strong> parsers<br />

Handle é uma subca<strong>de</strong>ia que reconhece o lado direito <strong>de</strong> uma<br />

produção e cuja redução ao não-terminal representa um passo<br />

<strong>de</strong> uma <strong>de</strong>rivação mais a direita.<br />

O processo <strong>de</strong> <strong>de</strong>scrobrir um handle e reduzi-lo apropriadamente<br />

para o lado esquerdo é chamado <strong>de</strong> handle pruning (poda do<br />

handle)<br />

Forma a base para o método <strong>de</strong> parsing bottom-<strong>up</strong><br />

Para construir uma <strong>de</strong>rivação mais a direita<br />

S ⇒ γ 0 ⇒ γ 1 ⇒ γ 2 ⇒ … ⇒ γ n-1 ⇒ γ n ⇒ w<br />

Aplicar o seguinte algoritmo simples<br />

for i ← n to 1 by -1<br />

Encontrar o handle in γ i<br />

Substituir β i por N i para gerar γ i-1


Exemplo<br />

Prod’n. Sentential Form Handle<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

Goal<br />

Expr<br />

Term<br />

Factor<br />

→<br />

→<br />

|<br />

|<br />

→<br />

|<br />

|<br />

→<br />

Expr<br />

Expr + Term<br />

Expr – Term<br />

Term<br />

Term *<br />

Factor<br />

Term / Factor<br />

Factor<br />

number<br />

—<br />

1<br />

3<br />

5<br />

9<br />

7<br />

8<br />

4<br />

Goal<br />

Expr<br />

Expr - Term<br />

Expr -Term * Factor<br />

Expr - Term * <br />

Expr - Factor * <br />

Expr - *<br />

<br />

Term - *<br />

—<br />

1,1<br />

3,3<br />

5,5<br />

9,5<br />

7,3<br />

8,3<br />

4,1<br />

9 | id<br />

<br />

7 Factor - *<br />

<br />

7,1<br />

9 - * 9,1<br />

Gramática Derivação mais a direita <strong>de</strong> x - 2 * y


Técnica <strong>de</strong> implementação<br />

Parser shift-reduce<br />

push INVALID<br />

token ← next_token( )<br />

repeat until (top of stack = Goal and token = EOF)<br />

if the top of the stack is a handle N→β<br />

then /* reduce β to N */<br />

pop |β | symbols off the stack<br />

push N onto the stack<br />

else if (token ≠ EOF)<br />

then /* shift */<br />

push token<br />

token ← next_token( )<br />

Como mostrar os erros?<br />

• Falha para encontrar<br />

um handle<br />

• Atingiu EOF & precisa<br />

executar o shift (else<br />

final)<br />

Gerar um erro


Avançar e reduzir<br />

Stack Input Handle Action<br />

$ id – num * id none shift<br />

$ id – num * id 9,1 red. 9<br />

$ Factor – num * id 7,1 red. 7<br />

$ Term – num * id 4,1 red. 4<br />

$ Expr – num * id none shift<br />

$ Expr – num * id none shift<br />

$ Expr – num * id 8,3 red. 8<br />

$ Expr – Factor * id 7,3 red. 7<br />

$ Expr – Term * id none shift<br />

$ Expr – Term * id none shift<br />

$ Expr – Term * id 9,5 red. 9<br />

$ Expr – Term *<br />

5,5 red. 5<br />

Factor<br />

$ Expr – Term 3,3 red. 3<br />

$ Expr 1,1 red. 1<br />

$ Goal none accept<br />

5 shifts +<br />

9 reduces<br />

+ 1 accept


Stack Input Action<br />

$ id – num * id shift<br />

$ id – num * id red. 9<br />

$ Factor – num * id red. 7<br />

$ Term – num * id red. 4<br />

$ Expr – num * id shift<br />

$ Expr – num * id shift<br />

$ Expr – num * id red. 8<br />

$ Expr – Factor * id red. 7<br />

$ Expr – Term * id shift<br />

$ Expr – Term * id shift<br />

$ Expr – Term * id red. 9<br />

$ Expr – Term *<br />

red. 5<br />

Factor<br />

$ Expr – Term red. 3<br />

$ Expr red. 1<br />

$ Goal accept<br />

Exemplo<br />

Term<br />

Fact.<br />

Goal<br />

Expr<br />

Expr -<br />

Term<br />

Fact.<br />

<br />

Term<br />

*<br />

Fact.<br />


Avançar e Reduzir<br />

Shift reduce parsers são mais simples <strong>de</strong> ser construídos e<br />

facilmente entendidos<br />

Um shift-reduce parser tem apenas quatro ações<br />

• Shift — próxima palavra é avançada e empilhada<br />

• Reduce — lado direito do handle está no topo da pilha<br />

Localiza o lado esquerda do handle <strong>de</strong>ntro da pilha<br />

Desempilha o handle & empilha apropriadamente lhs<br />

• Accept — parar o parsing & reportar sucesso<br />

• Error — chamar um relato <strong>de</strong> erro /rotina <strong>de</strong> rec<strong>up</strong>eração<br />

Shift executa apenas empilhar e uma chamada para o léxico<br />

Reduce toma |rhs| <strong>de</strong>sempilha & 1 empilha

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!