1 análise sintática de descida recursiva prof. alexandre monteiro baseado em material cedido pelo...

66
1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

Upload: camille-inocencio

Post on 07-Apr-2016

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

1

Análise Sintática de Descida Recursiva

Prof. Alexandre MonteiroBaseado em material cedido pelo Prof. Euclides

Arcoverde

Recife

Page 2: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

Contatos Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/gtalk: [email protected]

[email protected] Site: http://www.alexandrecordel.com.br/fbv Celular: (81) 9801-1878

Page 3: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

3

Agenda Introdução Produção Única Múltiplas Produções

• Conjuntos FIRST Fatoração à Esquerda Recursão à Esquerda Recursão à Direita Produção Vazia

• Conjunto FOLLOW Produção de Substituição

Page 4: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

4

Análise de Descida Recursiva É uma análise sintática top-down ou

descendente

É um parser LL(1)• Left-to-right – a ordem de leitura dos tokens é

da esquerda para a direita

• Leftmost derivation – segue a ordem típica de uma derivação mais à esquerda

• Só olha 1 token por vez

Page 5: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

5

Análise de Descida Recursiva É útil para construir parsers manualmente, por

ser fácil de implementar Princípio Básico

• Se eu quero produzir um não-terminal e sei qual o terminal corrente eu devo saber que regra deve ser aplicada.

Porém, requer uma gramática muito bem ajustada

• Veremos os ajustes necessários Mostraremos como usar a técnica, assumindo

que o parser final será uma classe Java

Page 6: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

6

Exemplo de Reconhecedor Gramática:Terminais = {a,b,c}Não-terminais = {S, X}Produções = {

S a X bS b X aS cX b XX a

}Não-terminal inicial = S

a b cS a X

bb X a c

X a b X Error

Page 7: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

7

Classe Parser Atributos típicos

• A classe Lexer (será o atributo “lexer”)• O último token lido (será o atributo “token”)

Operação principal• Método “parse()”

Métodos auxiliares • Para aceitar os tokens, se estiverem corretos• Para reconhecimento (parsing) de não-

terminais

Page 8: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

8

Métodos para Tokens Serão dois métodos para aceitar tokens,

ambos serão chamados acceptToken()

Uma versão receberá o tipo do token que o analisador espera• Se o token não for do tipo esperado, reporta

um erro

A outra versão não receberá parâmetro• Usado quando o tipo dele já é conhecido e é

válido

Page 9: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

9

Métodos para Tokens Ambos os métodos acceptToken

atualizam o atributo token, lendo o próximo token• A primeira versão (tipo como parâmetro) só lê

se o tipo do token anterior estiver correto

Assim, só esses dois métodos atualizam o atributo token• Portanto, só eles podem chamar o lexer

Page 10: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

10

Métodos para Não-Terminais Cada não-terminal N terá um método específico que

chamaremos parseN()

O objetivo desse método é reconhecer uma sequência de símbolos que case com alguma das produções de N

É aqui que está a principal característica da análise de descida recursiva...

Page 11: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

11

Análise de Descida Recursiva Portanto, cada método parseN() deverá:

• Identificar a produção adequada N X1 X2 ...XK

• Em seguida, deverá chamar o método para reconhecer cada símbolo Xi

- Se for um não-terminal, chama parseXi()

- Se for um terminal, chama acceptToken()

Page 12: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

12

Produção Única Um não-terminal com apenas uma

produção é o caso mais simples de ser tratado

Ficará assim

frase ::= sujeito predicado “.”

void parseFrase() { parseSujeito(); parsePredicado(); acceptToken(PONTO); }

Page 13: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

13

Múltiplas Produções Porém, quando houver mais de uma

produção, é preciso usar um critério de escolha

Por exemplo:

Como escolher a produção certa (ou seja, a que representa o código fonte) durante a análise?

sujeito ::= “Eu” | “Um” substantivo | “O” substantivo

Page 14: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

14

Múltiplas Produções No exemplo anterior, basta olhar o token

atual void parseSujeito() { TokenType tp = this.token.getType(); if (tp == TokenType.EU) { acceptToken(); } else if (tp == TokenType.UM) { acceptToken(); parseSubstantivo(); } else if (tp == TokenType.O) { acceptToken(); parseSubstantivo(); } else { <.. reportar erro ..> } }

Page 15: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

15

Múltiplas Produções Como fazer no caso geral para escolher a produção?

Exemplo: reconhecer comando

comando ::= atribuição | declaração atribuição ::= IDENTIFICADOR = <expressao> ;declaração ::= tipo IDENTIFICADOR ;tipo ::= “int” | “char” | “float”

Page 16: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

16

Conjunto FIRST FIRST(α)

• Aplicado a cadeias α quaisquer

É o conjunto de terminais que podem iniciar a cadeia α dada• Se a cadeia derivar vazio, também inclui ε

Como calcular?

Page 17: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

17

Conjunto FIRST Se α for a cadeia vazia (α = ε)

• FIRST(ε) = { ε }

Se for um terminal a qualquer• FIRST(a) = { a }

Se for um não-terminal N com as produções N → α | β• FIRST(N) = FIRST(α) FIRST(β)

Page 18: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

18

Conjunto FIRST Se for uma cadeia de símbolos α =

X1X2...Xk • Depende de X1

Se X1 não pode gerar vazio• FIRST (X1X2...Xk) = FIRST(X1)

Se X1 pode gerar vazio• FIRST (X1X2...Xk) = FIRST(X1)

FIRST(X2...Xk)• Calcula para X1 e continua o cálculo

recursivamente para o restante da cadeia

Page 19: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

19

Múltiplas Produções Calculando o FIRST para as duas produções de

comando ...• comando ::= atribuição | declaração

FIRST(atribuição) = FIRST(IDENTIFICADOR = <expressao> ;) = { IDENTIFICADOR }

FIRST(declaração) = FIRST(tipo IDENTIFICADOR ;) = FIRST(tipo) = { int , char, float }

Page 20: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

20

Múltiplas Produções A solução é comparar o token atual com o

FIRST de cada produção de comando... void parseComando() { TokenType token = this.token.getType(); if (token == IDENTIFICADOR) { parseAtribuicao(); } else if (token == INT || token == CHAR || token == FLOAT ) { parseDeclaracao(); } else { throw new CompilerException(...); } }

Page 21: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

21

Múltiplas Produções No caso geral, para fazer o parsing de um

não-terminal N, com produções N α | β

void parseN() { if (token estiver em FIRST(α)) { faz o parsing de α ...

} else if (token estiver em FIRST(β)) { faz o parsing de β ...

} else { reportar/tratar erro } }

Page 22: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

22

Análise de Descida Recursiva Uma limitação dessa técnica é que as

produções de um mesmo não-terminal têm que ter seus conjuntos FIRST disjuntos entre si

Ou seja, olhando apenas um terminal adiante tem que ser possível escolher a produção da gramática• Uma gramática com essa propriedade é

chamada uma gramática LL(1)• Assim como o parser é dito um parser LL(1)

Page 23: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

23

Fatoração à Esquerda Alguns casos em que as produções têm

seus conjuntos FIRST idênticos podem ser tratados

Um deles é quando as produções têm prefixos comuns

Exemplocmd ::= if exp then cmd else cmd | if exp then cmd | outro

Page 24: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

24

Fatoração à Esquerda A solução é parecida com a fatoração em

expressões matemáticas• Colocar a parte comum em evidência• A parte diferente pode se tornar outro não-

terminal

Exemplo anteriorcmd ::= if exp then cmd restoCmd | outrorestoCmd ::= else cmd | ε

Page 25: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

25

Fatoração à Esquerda Caso geral

• Seja N com produções com prefixo comum α

• Colocando α em comum e criando um novo não-terminal X

N → α X | Ф

X → β1 | β2

N → α β1 | α β2 | Ф

Page 26: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

26

Eliminação de Fatoração Direta:

X a b cX a d e

Sem fatoração:X a YY b cY d e

IndiretaX a bX Y cY a d

Elimina-se a indireção:X a bX a d cY a d

Sem fatoração:X a ZY a dZ bZ d c

Page 27: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

27

Exercícios

Resolver fatorações a esquerda: Direta:

X a c XX a d

Indireta:X a XX Y cX dY a b

Page 28: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

28

Recursão à Esquerda Outra limitação (menos grave) da técnica, é se

houver uma produção recursiva à esquerda

O que acontece se tentarmos criar o parser diretamente desta gramática?

exp ::= exp “+” NUM | NUM

Page 29: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

29

Recursão à Esquerda

Qual o problema com esse código?• Além dos conjuntos FIRST não serem disjuntos, ele apresenta recursão infinita!

void parseExp() { if (token.getType() == NUM) { parseExp(); acceptToken(MAIS); acceptToken(NUM); } else if (token.getType() == NUM) { acceptToken(); }

recursão infiinita !

Page 30: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

30

Recursão à Esquerda Neste caso, é preciso alterar a gramática

para remover a recursão à esquerda• É necessário haver outra produção sem a

recursão

Como reescrever o exemplo anterior para remover a recursão à esquerda? exp ::= exp “+” NUM

| NUM

Page 31: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

31

Recursão à Esquerda O exemplo anterior reescrito

exp ::= NUM restoExpr

restoExpr ::= “+” NUM restoExpr | ε

Page 32: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

32

Recursão à Esquerda Caso geral

• Seja a gramática

• Comentários- A recursão à esquerda serve apenas para produzir

repetições de α1 ou α2 (à direita das recursões)- A recursão só pára quando o N à esquerda for β1 ou

β2 (produções sem recursão à esquerda)

N → N α1 | N α2 | β1 | β2

Sejam α1, α2, β1 e β2 cadeias quaisquer

Page 33: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

33

Recursão à Esquerda Caso geral (solução)

• Criar um novo não-terminal X para criar zero ou mais repetições de α1 ou α2 com recursão à direita

• Fazer as produções sem recursão de N terminarem com X

N → β1 X | β2 X

X → α1 X | α2 X | ε

N → N α1 | N α2 | β1 | β2

Page 34: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

34

Eliminação da Recursividade Esquerda

Direta:X X aX b

Sem recursão:X’ εX’ a X’X b X’

Indireta:X Y aX bY X cY d

Remove-se a indireção:X X c aX d aX bY X cY d

Resolve-se como no caso anterior

Page 35: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

35

Exercícios

Resolver recursividades a esquerda: Direta:

X X aX b

Indireta:X Y aX bY X cY d

Page 36: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

36

Recursão à Direita para Listas As recursões servem para permitir repetições de

algum tipo de cadeia da gramática• Listas/Seqüências de comandos• Listas/Seqüências de declarações

A recursão à esquerda não pode ser usada, mas vamos ver agora uma maneira de usar a recursão à direita

Page 37: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

37

Recursão à Direita para Listas Exemplo

Problemas com “listaComandos”• Conjuntos FIRST das produções idênticos: { ID }

• Decidir quando parar de escolher a recursão

listaComandos ::= comando listaComandos | comando comando ::= ID "=" expressao

Page 38: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

38

Recursão à Direita para Listas Uma solução seria usar a fatoração à esquerda,

explicada antes

Mas tem outra solução mais simples

listaComandos ::= comando restoListaCmds restoListaCmds ::= listaComandos | comando ::= ID "=" expressao

Page 39: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

39

Recursão à Direita para Listas A recursão anterior pode ser reescrita

assim:

Foi feita uma fatoração à esquerda sem criação de um novo não-terminal

Isso foi possível com o operador regular *• Zero ou mais repetições

listaComandos ::= comando {comando}* comando ::= ID "=" expressao

Page 40: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

40

Recursão à Direita para Listas A parte do operador * pode ser resolvida

fazendo um loop• Enquanto o token atual for elemento do FIRST

de comando, faz o parsing de mais um comando void parseListaComandos() { parseComando(); while (token.getType() == ID) { parseComando(); } }

Page 41: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

41

Produção Vazia Um tipo de produção que ainda não foi

abordada é a produção vazia

Um exemplo apareceu quando falamos de fatoração à esquerda • restoCmdcmd ::= if exp then cmd restoCmd | outrorestoCmd ::= else cmd | ε

Page 42: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

42

Produção Vazia Uma solução simples é criar um else com

corpo vazio (não lançar erro), após verificar que o token não casa com as outras produções void parseRestoCmd() { if (token.getType() == ELSE) { ... } else { /* do nothing! */ } }

Page 43: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

43

Produção Vazia Um pequeno problema da abordagem

anterior é que erros sintáticos no código fonte só serão identificados depois• No método que for chamado após

parseRestoCmd

Uma abordagem mais robusta para tratar a produção vazia consiste em testar se o token é um dos tipos esperados depois do não-terminal

Page 44: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

44

Conjunto FOLLOW FOLLOW (N)

• Aplicado a não-terminais N quaisquer

É o conjunto de terminais que podem aparecer à direita do não-terminal N, em alguma cadeia derivada pela gramática

• Se o símbolo inicial deriva uma cadeia “... N x ...” então x faz parte de FOLLOW(A)

• O símbolo inicial tem $ no conjunto FOLLOW para indicar fim da entrada (EOF)

Como calcular?

Page 45: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

45

Conjunto FOLLOW Se N for o símbolo inicial

• Colocar $ (EOF) no conjunto FOLLOW(N)

Para toda produção X → α N β , em que beta não é vazio e não deriva vazio• Adicionar tudo de FIRST(β) no FOLLOW(N)

Para toda produção X → α N β , em que beta ou é vazio ou deriva vazio• Adicionar todo o FOLLOW(X) no FOLLOW(N)

Page 46: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

46

Produção Vazia Assim, a maneira mais correta de tratar a

produção vazia de um não-terminal N seria testar, no último caso, se o token está no conjunto FOLLOW(N)

Se não estiver, o caso else do parseN() já pode reportar um erro imediatamente

Alterando o caso geral de “múltiplas produções” mostrado antes...

Page 47: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

47

Produção Vazia Seja N um símbolo não-terminal N, com produções

N ::= α | β | ε

void parseN() { if (token estiver em FIRST(α)) { faz o parsing de α ... } else if (token estiver em FIRST(β)) { faz o parsing de β ... } else if (token estiver em FOLLOW(N)) /* faz nada, produção vazia */ } else { reportar/tratar erro... } }

Page 48: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

48

Produção de Substituição Uma produção de substituição de não-

terminal

Este tipo de produção cria apenas uma chamada de método a mais

comando ::= cmdDecisão cmdDecisão ::= if expressao... | switch expressao ...

void parseComando() { parseCmdDecisao(); }

Page 49: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

49

Produção de Substituição Para melhorar a eficiência do parser, é melhor trocá-

la pelas produções do não-terminal referenciado

O exemplo anterior ficaria simplesmente

comando ::= if expressao... | switch expressao ...

Page 50: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

50

Exemplo Linguagem XPR-0*

• Descrição- É uma linguagem simples para reconhecer e calcular

expressões matemáticas de adição e multiplicação com operandos de apenas um dígito. Os programas desta versão são formados por um único comando, onde um comando pode ser qualquer expressão terminada com ponto-e-vírgula. A semântica (significado) deste comando é a avaliação da expressão seguida de sua impressão na saída padrão

• Definir- Sintaxe abstrata- Sintaxe concreta- Implementacao

* Continuação do código disponibilizado para o lexer “manual”

Page 51: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

51

Exemplo Sintaxe Abstrata

<program> ::= <command>

<command> ::= <expr> ";"

<expr> ::= <expr> "+" <expr> | <expr> "*" <expr> | NUMERO | "(" <expr> ")"

Page 52: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

52

Exemplo Sintaxe Concreta

<program> ::= <command> <command> ::= <expr> ";" <expr> ::= <term> <restExpr> <restExpr> ::= "+" <term> <restExpr> | ε <term> ::= <factor> <restTerm> <restTerm> ::= "*" <factor> <restTerm> | ε <factor> ::= NUMERO | "(" <expr> ")"

Page 53: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

53

Exemplo Implementar duas versões

• Classe ParserTemp- Implementação “vazia” da análise sintática- Apenas indica se a expressão está ou não correta

• Classe Parser- Construído a partir do ParserTemp- Calcula o resultado da expressão- Funciona como um interpretador

Page 54: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

Euclides Arcoverdehttp://sites.google.com/site/euneto/

Algoritmos FIRST e FOLLOWTabela LL(1)

Page 55: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

55

Algoritmo 1: Cálculo de FIRST Calcular FIRST(A) para todos os não

terminais de uma gramática G1. Inicialmente para todos os não terminais A

da gramática, todos os conjuntos FIRST(A) estão vazios

2. Para cada regra A B1 ... Bma tal que para todo i = 1, ..., m, Bi ε, acrescente a a FIRST(A)

3. Para cada regra A B1 ... BmB tal que, para todo i = 1, ..., m, Bi ε, acrescente FIRST(B) a FIRST(A)

4. Repita o passo 3 enquanto houver alteração no valor de algum dos conjuntos FIRST

Page 56: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

56

FIRST() = {} FIRST(t) = {t} FIRST(XY) = FIRST(X) FIRST(Y),

se X gera FIRST(XY) = FIRST(X), se X não gera FIRST(X|Y) = FIRST(X) FIRST(Y) FIRST(X*) = FIRST(X)

Resumo FIRST

Page 57: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

57

Algoritmo 1: Exemplo Considere a seguinte gramática:

1. E -> E + T2. E -> T3. T -> T * F4. T -> F5. F -> ( E )6. F -> a

Passo 0: FIRST(E) = FIRST(T) = FIRST(F) = Passo 1:

• (Regra 5) FIRST(F) = { ( }• (Regra 6) FIRST(F) = { a }

Passo 2:• (Regra 4) FIRST(T) = FIRST(F) = { (, a }• (Regra 2) FIRST(E) = FIRST(T) = FIRST(F) = { (, a }

Page 58: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

58

Algoritmo 1: Exercício Considere a seguinte gramática:

1. P -> A B C D2. A -> ε3. A -> a A4. B -> ε5. B -> B b6. C -> c7. C -> A B8. D -> d

Page 59: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

59

Algoritmo 2: Cálculo de FOLLOW Calcular FOLLOW(A) para todos os não

terminais de uma gramática G1. Inicialmente para todos os não terminais A

da gramática, todos os conjuntos FOLLOW(A) estão vazios, exceto FOLLOW(S) = { $ }

2. Se há uma regra A Ba e = B1, ..., Bm ε, acrescente “a” a FOLLOW(B)

3. Se há uma regra A BC e = B1, ..., Bm ε, acrescente FIRST(C) a FOLLOW(B)

4. Se há uma regra A B e = B1, ..., Bm ε, acrescente FOLLOW(A) a FOLLOW(B)

5. Repita o passo 4 enquanto houver alteração no valor de algum dos conjuntos

Page 60: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

60

Algoritmo 2: Exemplo

Considere a seguinte gramática:1. E -> E + T2. E -> T3. T -> T * F4. T -> F5. F -> ( E )6. F -> a

FIRST(E) = FIRST(T) =FIRST(F) = { (, a }

Passo 0:• FOLLOW(E) = { $ }• FOLLOW(T) = FOLLOW(F) =

Passo 1:• (Regra 1) FOLLOW(E) = { $, + }• (Regra 3) FOLLOW(T) = { * }• (Regra 5) FOLLOW(E) = { $,

+, ) }• FOLLOW(F) =

Passo 2:• (Regra 2) FOLLOW(T) =

FOLLOW(E) = { $, +, ), * }• (Regra 4) FOLLOW(T) =

FOLLOW(F) = { $, +, ), * }

Resultado final• FOLLOW(E) = { $, +, ) }• FOLLOW(T) = FOLLOW(F) = { $,

+, ), * }

Page 61: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

61

Algoritmo 2: Exercício Considere a seguinte gramática:

1. E -> T E’2. T -> F T’3. F -> ( E )4. F -> a5. E’ -> + T E’6. E’ -> ε7. T’ -> * F T’8. T’ -> ε

FIRST(T) = FIRST(F) = { (, a }FIRST(E’) = { + }FIRST(T’) = { * }

Page 62: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

62

Construção da Tabela LL(1) Para cada produção A ->

• Para cada terminal em FIRST(A), inclua A -> em M[A, ]

• Se ε pertence a FOLLOW(), inclua A -> em M[A, b] para cada terminal b em FOLLOW()

• Se ε pertence a FIRST() e $ pertence a FOLLOW(A), acrescente também A -> em M[A, $]

Page 63: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

63

Construção da Tabela LL(1) Para toda regra: X -> A B C:

• Se A for um terminal:- Adicione “ABC” na posição (A,X) da tabela

• Se A for um não-terminal:- Adicione “ABC” na linha X somente nas colunas definidas pelos

FIRST(A) Para toda regra: X ->

• Adicione “” na linha X e nas colunas vazias (error)

Page 64: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

64

Exemplo de Tabela LL(1)

Produções:X -> a XX -> b

a bX a X b

Produções:S -> a X bS -> b X aS -> cX -> b XX -> a

a b c

S a X b b X a c

X a b X error

Page 65: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

65

Exercícios

Produções 1E -> E + TE -> TT -> T * FT -> FF -> ( E )F -> a

Produções 2X > abX > YbX > bY > caY > dZZ > ab

Produções 3E -> T E’T -> F T’F -> ( E )F -> aE’ -> + T E’E’ -> εT’ -> * F T’T’ -> ε

Page 66: 1 Análise Sintática de Descida Recursiva Prof. Alexandre Monteiro Baseado em material cedido pelo Prof. Euclides Arcoverde Recife

66

Bibliografia AHO, A., LAM, M. S., SETHI, R., ULLMAN, J. D.,

Compiladores: princípios, técnicas e ferramentas. Ed. Addison Wesley. 2a Edição, 2008 (Capítulo 4)