• Nenhum resultado encontrado

Tradução dirigida por sintaxe

N/A
N/A
Protected

Academic year: 2021

Share "Tradução dirigida por sintaxe"

Copied!
38
0
0

Texto

(1)

Tradução dirigida por sintaxe

André Luis Meneses Silva

andreLuis.ms@gmail.com

Departamento de Estatística e Informática

Universidade Federal de Sergipe

(2)

Definições dirigidas por sintaxe

• Gramática + regras (ações) semânticas

– Cada símbolo possui um atributo

– Regras definem os valores dos atributos

– Cada produção tem sua(s) regra(s)

• Regras são avaliadas quando a produção é aplicada

• Gramática de atributos

– Defn. dirigida por sintaxe onde as regras não

têm efeitos colaterais (paradigma funcional)

(3)

terminal Integer NUM;

non terminal Integer expr; ...

expr ::= expr:a PLUS expr:b

{: RESULT = new Integer(a.intValue() + b.intValue()); :}

| expr:a TIMES expr:b

{: RESULT = new Integer(a.intValue() * b.intValue()); :}

| LPAREN expr:a RPAREN

{: RESULT = a :}

| NUM : i

{: RESULT = i :} ;

(4)

Atributos sintetizados e herdados

• Considere a árvore de derivação:

– O valor de um atributo sintetizado é definido

em função dos valores dos atributos dos filhos

• Exemplo anterior

– Atributos herdados dependem dos irmãos e/ou

o pai

• Cup só trabalha com atributos sintetizados

D T L { L.type = T.type }

L id , L1 { L1.type = L.type; id.type=L.type }

(5)

N N1 D { N.v = N1.v*10 + D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

Exemplo: números simples

N N D N D N D N N D

(6)

N N1 D { N.v = N1.v*10 + D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 } S N { N.h = 0; } N D N1 { N.s = N1.s ; N1.h = N.h*10 + D.s } N D { N.s = N.h*10 + D.s; } D 0 { D.s = 0 }

Exemplo: números simples

N N D N D N D N N D

Qual é mais adequada para definir o valor semântico de N

somente com atributos sintetizados?

(7)

Árvore de derivação

D

N

N

D

N

0

D

1

9

• 901  árvore

de derivação

(8)

Árvore de derivação

D

N

N

D

N

0

D

1

• 901  árvore

de derivação

N N1 D { N.v = N1.v*10+D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

(9)

Árvore de derivação

D

N

N

D

N

0

D

1

9

D.v = 9

• 901  árvore

de derivação

N N1 D { N.v = N1.v*10+D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

(10)

Árvore de derivação

D

N

N

D

N

0

D

1

D.v = 9 N.v = 9

• 901  árvore

de derivação

N N1 D { N.v = N1.v*10+D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

(11)

Árvore de derivação

D

N

N

D

N

0

D

1

9

D.v = 9 N.v = 9 N.v = 90 D.v = 0

• 901  árvore

de derivação

N N1 D { N.v = N1.v*10+D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

(12)

Árvore de derivação

• 901  árvore

de derivação

N N1 D { N.v = N1.v*10+D.v } N D { N.v = D.v } D 0 { D.v = 0 } D 1 { D.v = 1 } ... D 9 { D.v = 9 }

D

N

N

D

N

0

D

1

D.v = 9 N.v = 9 N.v = 90 D.v = 0 N.v = 901 D.v = 1

(13)

Implementando Atributos Sintetizados – LR

• Empilha-se o valor do atributo junto com o símbolo/estado • Quando há redução, a respectiva regra semântica é avaliada ( , 2 + 4 * 8 $) ├ (<NUM,2>, + 4 * 8 $)(<expr,2>, + 4 * 8 $) ├ ( <expr,2><PLUS>, 4 * 8 $) ├ (<expr,2><PLUS><NUM,4>, * 8 $) ├ (<expr,2><PLUS><expr,4>, * 8 $) ├ (<expr,2><PLUS><expr,4><TIMES>, 8 $) ├ (<expr,2><PLUS><expr,4><TIMES><NUM,8>, $) ├ (<expr,2><PLUS><expr,4><TIMES><expr,8>, $) ├ (<expr,2><PLUS><expr,32>, $)

(14)

4+9 ; <ENTER>

13

5*(4+2); <ENTER>

30

Ações com efeitos colaterais

• Gramáticas de atributos são declarativas

• As vezes é interessante escrever ações com efeitos colaterais

– Maior cuidado pois a execução das ações depende da ordem em que as produções são reduzidas

(15)

terminal SEMI, PLUS, TIMES, LPAREN, RPAREN;

terminal Integer NUMBER; // com atributo

non terminal Integer expr; // com atributo

non terminal expr_, calc;

precedence left PLUS;

precedence left TIMES;

(16)

calc ::= expr_ SEMI calc

| expr_ SEMI {: System.out.println("BYE"); :} ;

expr_ ::= expr:e {: System.out.println(e.toString()); :} ;

expr ::= expr:a PLUS expr:b

{: RESULT = new Integer(a.intValue() + b.intValue()); :}

| expr:a TIMES expr:b

{: RESULT = new Integer(a.intValue() * b.intValue()); :}

| LPAREN expr:a RPAREN

(17)

Ações imperativas exigem cuidado

calc ::= expr:e SEMI calc

{: System.out.println(e.toString()); :}

| expr:e SEMI

{: System.out.println(e.toString()); System.out.println("BYE"); :} ; expr ::= ...

(18)

Ações imperativas exigem cuidado

calc ::= expr:e SEMI calc

{: System.out.println(e.toString()); :}

| expr:e SEMI

{: System.out.println(e.toString()); System.out.println("BYE"); :} ; expr ::= ...

Como se comportam os parsers das seguinte gramáticas?

calc ::= calc expr:e SEMI

{: System.out.println(e.toString()); :}

| expr:e SEMI

(19)

s ::= calc {: System.out.println("BYE"); :} ;

calc ::= calc expr:e SEMI

{: System.out.println(e.toString()); :}

| expr:e SEMI

{: System.out.println(e.toString()); :} ;

(20)

Ações embutidas

calc ::= calc expr:e {: System.out.println(e.toString()); :}

SEMI

| expr:e SEMI {: System.out.println(e.toString()); :} ; expr ::= ...

Quando são executadas as ações embutidas?

– São tratadas como não terminais (um novo para c/ação) – Uma produção vazia é adicionada para c/ação

– Conflitos podem ser introduzidos

calc ::= calc expr:e $N_1 SEMI | ...

(21)

Implementação totalmente imperativa

import java.util.*;

action code {:

List pilha = new Vector();

void push(int a) { pilha.add(pilha.size(), new Integer(a)); } int pop() { Integer i = (Integer) pilha.remove(pilha.size()-1);

return i.intValue(); } :}

terminal PLUS, TIMES, SEMI, LPAREN, RPAREN;

terminal Integer NUM;

non terminal expr, expr_, calc;

precedence left PLUS;

(22)

calc ::= expr_ SEMI calc

| expr_ SEMI {: System.out.println("BYE"); :}

;

expr_ ::= expr {: System.out.println(pop()); :} ;

expr ::= expr PLUS expr

{: int a = pop(); int b = pop(); push(a+b); :}

| expr TIMES expr

{: int a = pop(); int b = pop(); push(a*b); :}

(23)

Exemplo estendido:

Todo um interpretador em Ações semânticas

Prog → Stm

Stm → Stm ; Stm

| id := Exp

| print ( ExpList )

Exp → Exp BinOp Exp

| Stm , Exp

| ( Exp )

| id

| num

ExpList → Exp , ExpList

| Exp

BinOp → + | *

Sintaxe de

Straight-line

(24)

terminal Integer NUM;

terminal String ID;

terminal PLUS, TIMES, SEMI, COMMA, LPAREN, RPAREN, ASSIGN, PRINT ;

non terminal exp, stm, exps, prog;

precedence right SEMI;

precedence left PLUS;

precedence left TIMES;

(25)

action code {:

List pilha = new Vector(); void push(int a) {

pilha.add(pilha.size(), new Integer(a)); } int pop() {

Integer i = (Integer) pilha.remove(pilha.size()-1); return i.intValue(); }

Map mem = new HashMap(); void store(int v, String id) {

mem.put(id, new Integer(v)); } int get(String id) {

Integer v = (Integer) mem.get(id); return v.intValue(); }

(26)

prog ::= stm ;

stm ::= stm SEMI stm

| ID:id ASSIGN exp {: store(id,pop()); :}

| PRINT LPAREN exps RPAREN

{: System.out.println(); :}

;

exps ::= exp {: System.out.println(pop()); :}

| exps COMMA exp

{: System.out.println(pop()); :}

;

exp ::= exp PLUS exp

{: int a = pop(); int b = pop(); push(a+b); :}

| exp TIMES exp

{: int a = pop(); int b = pop(); push(a*b); :}

| LPAREN exp RPAREN | stm COMMA exp

(27)

Misturando estilos

// declarações de símbolos e precedências como antes, salvo:

non terminal Integer exp ;

action code {: ... // só definições de get e store:} prog ::= stm ;

stm ::= stm SEMI stm

| ID:id ASSIGN exp:e {: store(id,e.intValue()); :}

| PRINT LPAREN exps RPAREN

{: System.out.println(); :}

;

exps ::= exp:e {: System.out.println(e.intValue()); :}

| exps COMMA exp:e

{: System.out.println(e.intValue()); :}

;

(28)

exp ::= exp:e1 PLUS exp:e2

{: RESULT = new Integer(e1.intValue()+ e2.intValue(); :}

| exp TIMES exp

{: RESULT = new Integer(e1.intValue()* e2.intValue(); :}

| LPAREN exp:e RPAREN {: RESULT = e; :}

| stm COMMA exp:e {: RESULT = e; :}

| NUM : i {: RESULT = i; :}

(29)

Ações Semânticas em LL

• Ações semânticas são misturadas com o

fluxo de controle das ações do parser

• Ordem de avaliação é fácil predizer

• Atributos sintetizados

– Valor de retorno da função

• Atributos herdados

(30)

Atributos sintetizados em LL

E → num + E

1

{ E.v = num.v + E

1

.v }

| num

{ E.v = num.v }

int E() {

if (tok1.code == NUM && tok2.code == PLUS ) {

int i = tok1.value();

reconhece(NUM ); reconhece (PLUS); int j = E( ); return(i+j); }

else if (tok1.code == NUM && tok2.code == EOF) {

int i = tok1.value; reconhece(NUM); return i; }

else erro();

LL(2)

Atributos sintetizados são passados de filhos para pai através do retorno da função

(31)

Atributos herdados em LL

E → num E’

E’ → + num E

1

| - num E’

|

Se aumentarmos a operação “-”, o parser começa a complicar Podemos fatorar à esq. para termos LL(1)

No entanto a gramáticade atributos precisa de atributos herdados

O computo do + e – associa a esq. ou a dir.?

{ E’.h = num.v ;

E.v = E’.v}

{ E

1

’.h = E’.h + num.v;

E’.v = E

1

’.v }

{ ... // similar }

{ E’.v = E’.h }

(32)

Atributos herdados em LL

Atributos herdados são passados

• de pai para filho através de argumentos da função

• de irmão (à esquerda) para irmão na avaliação da produção

int E() {switch(tok.code) {

case NUM: int v = tok.value(); reconhece(NUM); return E’(v); default: erro(); } }

int E’(int h) {switch(tok.code) { // h atributo herdado

case PLUS: reconhece(PLUS); int v = reconhece(NUM);

return E’(h+v); case MINUS: ... // similar

(33)

Interprete de Expressões LL

E → T E’

E’ → + T E’ |

T → F T’

T’ → * F T’ |

F → num | ( E )

Gramática de expressões por camadas e fatorada

Primeiro(E) = { id, num, ( } Primeiro(E’) = { ,+, $ } ...

Seguinte(E) = { ), $ } Seguinte(E’) = { ), $ } ....

Exercício tipo prova:

• Calcular a tabela de parser LL(1)

• Dar uma gramática de atributos para um interpretador desta gramática

• Implementar na mão

(34)

Ações com efeitos colaterâis

public class InterpretadorSL {

Map mem = ...;

void SimpleStm() {switch(tok.code) {

case PRINT: reconhece(PRINT); reconhece(LPAREN); ExpList(); reconhece (RPAREN)

case ID: String id = (String) tok.value();

reconhece (ID); reconhece(ASSIGN);

int v = Exp( ); mem.store(id,v); break;

default: erro();

(35)

void compoundStm { ... }

void ExpList( ) {switch(tok.code) {

case ....: int v = Exp( );

System.out.print(v+" "); reconhece(COMMA); ExpList();

break;

case RPAREN: System.out.println(); break;

default: erro(); }

(36)

Ações semânticas no JavaCC

void SimpleStm( ) : { Token t;

int v; }

{ “print” “(” ExpList() “)”

| t=<ID> <ASSIGN> v = Exp( ); { mem.store(t.image(),v); }

} ... void ExpList( ) : { int v; } { v = Exp( ) { System.out.print(v+" "); }

(37)

Exercício opcional

• Completar o interpretador de straight-line

na mão ou usando JavaCC

(38)

Exercício opcional

• Utilizando uma gramática de atributos escrita em JavaCC, dar uma implementação em estilo funcional do

interpretador de straight-line

– Definir o tipo memória com funções

• int get(String), Memoria store(int,String) – Atributos herdados são necessários?

– Atributo sintetizado de Stm

• Memória e Lista de valores (impressos), ou • Memória (aqui a impressão será imperativa) – Atributo de Exp

• ?

Referências

Documentos relacionados

Como o próprio povo que o gerou, este Livro identificou-se de tal modo com lugares e épocas que se tornou um patrimônio da humanidade.. Quebrou barreiras étnicas

O projeto EstudA da Faculdade de Ciências e Tecnologia do Campus de Ananindeua é composto pelos módulos Mineração e Meio Ambiente e Produção Industrial e Recursos Hídricos, cada

Como hipótese inicial da nossa pesquisa, acreditamos que o investimento no acesso à educação superior através de políticas como o ProUni, permitirá que uma

Frutos maduros de março a maio, consumidos in natura, ou utilizados na elaboração de geléias; são carnosos, saborosos e aromáticos, com potenciais similares aos da Goiabeira Serrana

5 Esta informação encontra-se compilada nas tabelas constantes do separador “monitorização dos planos de ação por eixo”, numa perspetiva macro, vertendo o relatório de

Para o conversor boost PFC operando em MCC obter tensão e corrente de entrada proporcionais, é necessário controlar a forma de onda da corrente de entrada, introduzindo

Esse trabalho é um esboço das primeiras discussões da pesquisa 1 em andamento no Programa de Pós-Graduação em Educação Matemática (PPEduMat) da Universidade Federal

b) A Comissão Especial Eleitoral, de posse de todos os Boletins de Urna, fará a contagem final dos votos e, em seguida, afixará, no local onde ocorreu a apuração final, o