1 Revisão Compiladores – AP2 Prof. Alexandre Monteiro Recife.

Post on 07-Apr-2016

224 views 0 download

Transcript of 1 Revisão Compiladores – AP2 Prof. Alexandre Monteiro Recife.

1

Revisão Compiladores – AP2

Prof. Alexandre Monteiro

Recife

Contatos Prof. Guilherme Alexandre Monteiro Reinaldo Apelido: Alexandre Cordel E-mail/gtalk: alexandrecordel@gmail.com

greinaldo@fbv.edu.br Site: http://www.alexandrecordel.com.br/fbv Celular: (81) 9801-1878

3

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

4

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

5

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); }

6

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

7

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 ..> } }

8

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(β)

9

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

10

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

11

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 | ε

12

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 | Ф

13

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

14

Exercícios

Resolver fatorações a esquerda: Direta:

X a c XX a d

Indireta:X a XX Y cX dY a b

15

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

16

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 !

17

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

18

Recursão à Esquerda O exemplo anterior reescrito

exp ::= NUM restoExpr

restoExpr ::= “+” NUM restoExpr | ε

19

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

20

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

21

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

22

Exercícios

Resolver recursividades a esquerda: Direta:

X X aX b

Indireta:X Y aX bY X cY d

23

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?

24

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)

25

Analisador Sintática LR Existem diversos tipos de analisadores

LR(k)

O nome LR(k) indica• Left-to-right – a ordem de leitura dos tokens é

da esquerda para a direita

• Rigthmost derivation – encontra uma derivação mais à direita (porém, de trás para a frente)

• K token são olhados à frente (lookahead)

26

Relembrando as Tabelas Tabela ACTION

• Diz qual ação será tomada, de acordo com o estado atual e o próximo token

Tabela GOTO (usada após um reduce)• Diz qual o próximo estado, de acordo com o estado atual e o símbolo não-terminal que foi reduzido

27

Funcionamento A medida que lê os terminais (tokens), o parser

poderá realizar certas ações, de acordo com o estado atual

• SHIFT• REDUCE• ACCEPT• ERROR

28

Exemplo (quadro)

0) S: stmt $

1) stmt: ID ':=' expr

2) expr: expr '+' ID

3) expr: expr '-' ID

4) expr: ID

29

Exemplo (autômato)

State 00)S: . stmt $ 1)stmt: . ID ':=' expr

State 10)S: stmt . $

State 21)stmt: ID . ':=' expr

State 31)stmt: ID ':=' . expr 2)expr: . expr '+' ID 3)expr: . expr '-' ID 4)expr: . ID

30

Exemplo (autômato)State 0 0) S: . stmt $ 1) stmt: . ID ':=' expr

GOTO 2 on stmtSHIFT 1 on ID

State 1 1) stmt: ID . ':=' expr

SHIFT 3 on ':='

State 2 0) S: stmt . $

SHIFT 4 on $

State 31) stmt: ID ':=' . expr 2) expr: . expr '+' ID 3) expr: . expr '-' ID

4) expr: . ID GOTO 6 on expr

SHIFT 5 on ID

State 40) S: stmt $.

State 5 4) expr: ID .

State 6 1) stmt: ID ':=' expr . 2) expr: expr . '+' ID 3) expr: expr . '-' ID SHIFT 7 on '+' SHIFT 8 on '-'

State 7 2) expr: expr '+' . ID SHIFT 9 on ID

State 8 3) expr: expr '-' . ID SHIFT 10 on ID State 9 2) expr: expr '+' ID .

State 10 3) expr: expr '-' ID .

31

Exemplo (Tabelas)

ID ':=' '+' '-' $ stmt expr0 s1 g2 1 s3 2 s4 3 s5 g64 acc acc acc acc acc 5 r4 r4 r4 r4 r4 6 r1 r1 s7 s8 r1 7 s9 8 s10 9 r2 r2 r2 r2 r2

10 r3 r3 r3 r3 r3

Goto TableAction Table

32

Exemplo: a:= b + c - dStack Remaining Input Action

0/S a:= b + c - d s10/S 1/a := b + c - d s3

0/S 1/a 3/:= b + c - d s50/S 1/a 3/:= 5/b + c - d r4

0/S 1/a 3/:= + c - d g6 on expr0/S 1/a 3/:= 6/expr + c - d s7

0/S 1/a 3/:= 6/expr 7/+ c - d s90/S 1/a 3/:= 6/expr 7/+ 9/c - d r2

0/S 1/a 3/:= - d g6 on expr0/S 1/a 3/:= 6/expr - d s8

0/S 1/a 3/:= 6/expr 8/- d s100/S 1/a 3/:= 6/expr 8/- 10/d $ r3

0/S 1/a 3/:= $ g6 on expr0/S 1/a 3/:= 6/expr $ r1

0/S $ g2 on stmt0/S 2/stmt $ s4

0/S 2/stmt 4/$ accept

Análise Semântica O que é?

Para que serve?

Qual a finalidade de uma tabela de símbolos (TS) no projeto de um compilador?

33

34

Tradução em Parsers de Descida Recursiva ...basta posicionar a ação semântica

dentro do bloco que trata a produção desejada

void parseLoopComand() { if (token.getType() == WHILE) { acceptToken(); System.out.println(“While!"); ... } else if (token.getType() == DO) { acceptToken(); parseComand(); System.out.println(“Do-While!"); ... } }

35

Código de Três Endereços

É uma linguagem de baixo nível (simples), porém independente de máquina

Programas representados como uma simples lista de instruções

As instruções usam, no máximo, três operandos (endereços)

36

Tipos de Endereços Um endereço pode ser:

• Um nome – representando uma variável, função, etc.

• Uma constante – valor literal de um número, uma string, um caractere, etc.

• Um temporário – variável auxiliar criada pelo compilador (t1, t2, etc.)

• Um rótulo – localização de uma instrução

37

Tipos de Instruções Instruções de atribuição da forma

Onde op é um operador binário aritmético, binário ou lógico• Exemplo:

x = y op z

aux = t1 + temp

38

Tipos de Instruções Instruções de atribuição da forma

Onde op é um operador unário, como: negação lógica, menos, conversão de tipo• Exemplos:

x = op y

t1 = (int) temp; t1 = - temp;

39

Tipos de Instruções Instruções de cópia

Usadas, em alguns casos, para facilitar a geração do código intermediário

Numa fase posterior, de otimização, essa instrução pode ser removida

x = y

40

Tipos de Instruções Desvio incondicional

Desvia para o rótulo L : faz com que a próxima instrução a ser executada seja a que tem o rótulo L• Exemplo:

goto L

label2: aux = t + 1; ... goto label2

41

Tipos de Instruções Desvios condicionais

Desviam para o rótulo L dependendo do valor booleano de x

if x goto LifFalse x goto L

42

Tipos de Instruções

Desvios condicionais com operadores relacionais (<, >, ==, !=, ...)

Desvia para L se o resultado da operação relacional for verdadeiro• Exemplo:

if x op_cond y goto L

label2: aux = t + 1; if aux < temp goto label2

43

Traduzindo Expressões Uma expressão com várias operações...

...é decomposta em expressões menores, com uma operação cada

myVar = aux + temp * 3

t1 = 3 t2 = temp * t1 t3 = aux + t2 myVar = t3

44

If-Else Exemplo:

int x = 0; if (x < 10) { x = 20; } else { x = 10; } int y = x;

x = 0 t1 = x < 10 ifFalse t1 goto F1 x = 20 goto R1 F1: x = 10 R1: y = x

45

While Exemplo:

x = 0; while (x < 10) { x = x + 1; } y = x;

x = 0 I1: t1 = x < 10 ifFalse t1 goto R1 t2 = x + 1 x = t2 goto I1 R1: y = x