1 Revisão Compiladores – AP2 Prof. Alexandre Monteiro Recife.
-
Upload
isabel-martos -
Category
Documents
-
view
224 -
download
0
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: [email protected]
[email protected] 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