• Aucun résultat trouvé

CAP.4 LA TRADUZIONE

N/A
N/A
Protected

Academic year: 2022

Partager "CAP.4 LA TRADUZIONE"

Copied!
39
0
0

Texte intégral

(1)

CAP.4 LA TRADUZIONE

• 4.1 Le grammatiche con attributi

• 4.2 Le grammatiche S-attribuite

• 4.3 Le grammatiche L-attribuite

• 4.4 La traduzione discendente

• 4.5 La valutazione ascendente degli attributi ereditati

• 4.6 La valutazione ricorsiva

(2)

4.1 Le grammatiche con attributi Ogni variabile ha degli attributi.

Azioni che permettono il calcolo di questi attributi sono incluse nelle regole.

Esempio: Regola Azioni

A  E$ print(E.val)

E  E +T E.val := E1.val + T.val E  T E.val := T.val

T  T *F T.val := T1.val * F.val T  F T.val := F.val

F  (E ) F.val := E.val F  n F.val := n.vallex Grammatica con attributi per un calcolatore

(3)

Situazione generale:

Regola A   e azioni b := f(c1, c2 ,..., ck).

Attributi:

• ereditati: se b è un attributo di un simbolo che appare in  e se i ci sono attributi di simboli in  o di A ;

• sintetizzati: se b è un attributo di A, e se i ci sono attributi di simboli in  o attributi ereditati di A.

Nell’esempio, tutti gli attributi sono sintetizzati.

Albero decorato: albero sintattico al quale vengono aggiunti gli attributi e i loro valori.

Problema: ordine della valutazione degli attributi. Se tutti sono

sintetizzati, la valutazione si può fare dalle foglie verso il radice.

(4)

Esempio: 3 * 5 + 4$

T val = 4

F val = 4 T val = 3

F val = 3 n vallex= 3

E val = 15 T val = 15

n vallex= 4 F val = 5

n vallex= 5 A print(19)

E val = 19 $ +

* Freccie : grafo di dipendenze,

impone l’ordine della valutazione.

(5)

Attributi ereditati:

Esempio: Dichiarazione di variabili in C

Regola Azioni

D  TL L.he := T.type T  int T.type := integer T  real T.type := real L  L , id L1.he := L.he

addtype(id.ent, L.he) L  id addtype(id.ent, L.he) L’attributo L.he è ereditato; gli altri sono sintetizzati.

(6)

Esempio: real id1, id2, id3

real

T type = real he = real L addtype D

, id3 ent = 3 he = real L addtype

, id2 ent = 2 he = real L addtype

id1 ent = 1

La valutazione è possibile perchè il grafo delle dipendenze

è aciclico. Valutazione dedotta da un ordine topologico.

(7)

4.2 Le grammatiche S-attribuite

Si dice che una grammatica è S-attribuita quando tutti gli attributi sono sintetizzati.

L’analisi ascendente è particolarmente adatta alla valutazione degli attributi di una grammatica S-attribuita.

A ogni stato corrisponde un simbolo col quale si raggiunge questo stato. L’attributo sintetizzato di questo simbolo può essere messo nella pila accanto allo stato corrispondente.

Gli attributi necessari per il calcolo si trovano già nella pila, a distanza conosciuta dalla cima di essa.

Se c’è la regola A  XYZ con azione A.a := f(X.x, Y.y, Z.z), prima della riduzione, i valori X.x, Y.y, Z.z sono

val[top – 2], val[top – 1] et val[top]; Dopo riduzione, si mette A.a come nuovo val[ntop].

(8)

Esempio: espressioni aritmetiche e calcolatrice.

Regole Azioni

0 A  E$ print(val[top])

1 E  E +T val[ntop] := val[top – 2] + val[top]

2 E  T

3 T  T *F val[ntop] := val[top – 2] * val[top]

4 T  F

5 F  (E ) val[ntop] := val[top – 1]

6 F  n val[ntop] := n.vallex

L’indice top è quello della cima della pila prima della riduzione.

L’indice ntop è quello della cima della pila dopo la riduzione.

L’automa LR è quello che è già stato costruito. Il valore numerico è ritornato dall’analizzatore lessicale.

Per le regole 2 e 4, ntop = top e val[ntop] = val[top].

Non c’è dunque niente da fare.

(9)

Esempio: (3 + 2) * 4 $

Stat 0 0 4 0 4 5 0 4 3 0 4 2 0 4 8 0 4 8 6 0 4 8 6 5 0 4 8 6 3 0 4 8 6 9 0 4 8 0 4 8 11 0 3

0 2

Parte non tradotta

(3 + 2) * 4 $ 3 + 2) * 4 $ + 2) * 4 $ + 2) * 4 $ + 2) * 4 $ + 2) * 4 $ 2) * 4 $ ) * 4 $ ) * 4 $ ) * 4 $ ) * 4 $

* 4 $

* 4 $

* 4 $ Valore

*

**

**3

**3

**3

**3

**3*

**3*2

**3*2

**3*2

**5

**5*

*5

*5

Stato 0 2 7 0 2 7 5 0 2 7 10 0 2

0 1

Parte non tradotta 4 $

$

$

$

$ Valore

*5*

*5*4

*5*4

*20

*20

print(20)

Il * segnala che non esiste un attributo corrispondente.

La struttura de dati adeguata è

una pila di record(stato, attributo)

(10)

4.3 Le grammatiche L-attribuite

Gli attributi ereditati dipendono solo dagli attributi ereditati della variabile alla sinistra della regola, e dagli attributi (sintetizzati o ereditati) delle variabili che appaiono prima. Gli attributi

sintetizzati possono dipendere da tutti gli altri attributi.

Così, il calcolo degli attributi si può fare mediante un percorso

in profondità dell’albero di derivazione, con precedenza a sinistra.

h A s

h B s h C s h D s

(Certe freccie non sono indicate)

(11)

Schemi di traduzione:

Le azioni vengono inserite nelle regole:

1. Un attributo ereditato di una variabile in parte destra di regola è calcolato con un’azione inserita prima di questa variabile;

2. Un’azione non può referirsi a un simbolo che appare alla destra di questa azione;

3. Un attributo sintetizzato della variabile alla sinistra della regola è calcolato dopo che tuttli gli argomenti dei quali dipende sono stati calcolati (è il caso se l’azione è inserita alla fine della regola) Le grammatiche L-attribuite possono essere convertite in schemi di traduzione.

(12)

Esempio 1: dichiarazione di variabili D  T{L.he := T.type}L T  int{T.type := integer}

T  real{T.type := real}

L  {L1.he := L.he}L , id{addtype(id.ent, L.he)}

L  id{addtype(id.ent, L.he)}

(13)

Esempio 2: il linguaggio di tipografia TeX

E’ un linguaggio di descrizione di formule matematiche.

L’oggetto di base è la scatola B. I suoi attributi sono la taglia di base dei caratteri che contiene, B.ps, attributo ereditato dall’ambiente e sua altezza B.ht, attributo sintetizzato.

Utilizzeremo le funzioni shrink che diminuisce la taglia

proporzionalmente a una scala (per gli indici) e disp che calcola l’altezza di una scatola con un indice (come E1 nel esempio).

Per esempio, E _ 1 .val specifica, in un ambiente di 12 punti, la composizione seguente:

E 1 .val

(14)

Si possono costruire la grammatica L-attribuita e lo schema di traduzione corrispondente:

Regola Azioni S  B B.ps := 10

S.ht := B.ht B  BB B1.ps := B.ps

B2.ps := B.ps

B.ht := max(B1.ht, B2.ht) B  B _B B1.ps := B.ps

B2.ps := shrink(B.ps) B.ht := disp(B1.ht, B2.ht) T  text B.ht := text.h * B.ps

Schema di traduzione S  {B.ps := 10}

B {S.ht := B.ht}

B  {B1.ps := B.ps}

B {B2.ps := B.ps}

B {B.ht := max(B1.ht, B2.ht)}

B  {B1.ps := B.ps } B

_ {B2.ps := shrink(B.ps)}

B {B.ht := disp(B1.ht, B2.ht)}

T  texte{B.ht := text.h * B.ps}

(15)

Implementazione della traduzione discendente per le grammatiche S-attribuite.

Problema: Eliminazione della ricorsività a sinistra.

Grammatica risultata L-attribuita, sotto la forma di uno schema di traduzione, con una nuova variabile.

Principio:

A  AY {A.a := g(A1.a, Y.y)}

A  X {A.a := f(X.x)}

Grammatica modificata:

A  X {R.he := f(X.x)}

R {A.a := R.s}

R  Y {R1.he := g(R.he, Y.y)}

R {R.s := R .s}

4.4 La traduzione discendente

(16)

Esempio:

E  E +T {E.val := E1.val + T.val}

E  E –T {E.val := E1.val – T.val}

E  T {E.val := T.val}

T  (E) {T.val:= E.val}

T  n {T.val := n.val}

Dopo modifiche:

E  T {R.he := T.val}

R {E.val := R.s}

R  +T {R1.he := R.he + T.val}

R {R.s := R1.s}

R  –T {R1.he := R.he – T.val}

R {R.s := R1.s}

R  {R.s := R.he}

T  (E) {T.val:= E.val}

(17)

Valutazione di 9 – 5 + 2 :

E val=6

T val=9 he=9 R s=6

T val=5 he=4 R s=6

T val=2 he=6 R s=6 +

n val=9

n val=5

n val=2

(18)

Metodo generale.

Dato: Uno schema di traduzione non ricorsivo a sinistra,

associato a una grammatica L-attribuita. Si suppone che ogni variabile ha un solo attributo sintetizzato.

Risultato: Codice per un traduttore.

Metodo:

1. A ogni variabile A vienne associata una funzione che ritorna

il valore dell’attributo sintetizzato di A. I suoi parametri sono gli attributi ereditati di A. Per ogni attributo di ogni variabile che appare in parte destra di una produzione di A, si dichiara una variabile locale.

2. Il codice di A fa la scelta della regola dipendente dal simbolo di previsione (grammatica LL(1)).

(19)

3. La parte del codice associata a una regola di riscrittura di A contiene:

(a) Per un terminale (unità lessicale) X con attributo sintetizzato X.x, salvare il suo valore nella variabile locale dichiarata per questo attributo. Verificare poì la validità di questo terminale leggendo il testo all’ingresso.

(b) Per una variabile B, assegnare c := B(b1, b2 ,..., bk) dove b1, b2 ,..., bk sono le variabili locali create per gli attributi

ereditati di B e c è quella creata per l’attributo sintetizzato di B.

(c) Per un’azione, copiare suo codice dove appare nello schema, sostituendo ogni referenza a un attributo con la variabile

locale associata. L’ultima azione (che ritorna il valore

dell’attributo sintetizzato di A) indica il valore ritornato dalla funzione A.

(20)

Esemple : grammatica precedente, aumentatta con A  E$

function E() ;

var tval, rhe, rs : integer ;

begin tval := T() ; rhe := tval ; rs := R(rhe) ; E := rs end ;

function R(x : integer) ;

var tval, r1he, r1s : integer ; begin

if prevision = ‘+’ then {regola R > +TR}

begin match(‘+’) ; tval := T(); r1he := x + tval ; r1s := R(r1he) ; R := r1s end

else if prevision = ‘–’ then {regola R > –TR}

begin match(‘–’) ; tval := T(); r1he := x – tval ; r1s := R(r1he) ; R := r1s end

else R := x {regola R > epsilon}

end;

(21)

functionT() ;

var eval, nval: integer ; begin

if prevision = ‘(‘ then {regola T > (E)}

begin match(‘(‘) ; eval := E() ; match(‘)’) ; T := eval end

else if prevision = number then {regola T > n}

begin nval := number_val ; match(number) ; T := nval end

else writeln(‘syntactic error’) end ;

procedure A ;

var eval : integer ;

begin eval := E() ; match(‘$’) ; println(eval) end ;

(22)

4.5 La valutazione ascendente degli attributi ereditati Problema: le azioni possono essere effettuate solamente

in fine di regola, quando si riduce. Il metodo presentato qui permette di trattare tutte le grammatiche L-attribuite

associate a una grammatica LL(1), e un certo numero di altre grammatiche LR(1) (però non tutte!) con un analisi ascendente.

Eliminazione delle azioni interne

Vanno inserite variabili speciali, i marchi, che si riscrivano solo come parola vuota. Il loro uso è solo di prendere in conto le azioni interne.

(23)

Esempio:

Schema di traduzione che stampa la forma postfissa di un'espressione con somme e differenze.

E  TR

R  +T{print('+')}R | – T{print(' – ')}R | T  n {print(n.val)}

Diventa:

E  TR

R  +TMR | – TNR | M {print('+')}

N {print(' – ')}

T  n {print(n.val)}

(24)

Attributi ereditati presenti sulla pila di analisi

Caso frequente: attributo ereditato = copia di un attributo

sintetizzato già presente sulla pila. Si può dunque utilizzare quest'attributo invece dell'attributo ereditato.

Esempio: dichiarazione di tipo di variabili.

D  T {L.he := T.type}

T  Lint {T.type := integer}

T  real {T.type := real}

L  {L1.he := L.he}

L , id {addtype(id.ent, L.he)}

L  id {addtype(id.ent, L.he)}

Qui, L.he è sempre una copia di T.type, che si trova immediatamente prima nella pila.

(25)

Per simplicità, i numeri degli stati sono sostituiti da variabili.

stato testo regola

- int p,q,r

int p,q,r

T p,q,r T  int

T p ,q,r

T L ,q,r L  id

T L , q,r

T L , q ,r

T L ,r L  L,id

T L , r

T L , r

T L L  L,id

(26)

Programma associato:

Regola Istruzioni

D  TL

T  int val[ntop] := integer T  real val[ntop] := real

L  L , id addtype(val[top], val[top – 3] ) L  id addtype(val[top], val[top – 1] )

Questo è reso possibile perchè si sà dove si trova nella pila l'attributo ereditato necessario.

Esempio:

Regola Azioni S  aAC C.h := A.s S  bABC C.h := A.s C  c C.s := g(C.h)

C.h est une copia di A.s.

Ma non si sà se il valore necessario

nell'ultima regola si trova a val[top – 1]

oppure a val[top – 2].

(27)

Regola Azioni S  aAC C.h := A.s

S  bABMC M.h := A.s ; C.h := M.s C  c C.s := g(C.h)

M  M.s := M.h

In questo modo, il valore di C.h è sempre il valore dell'attributo sintetizzato della variabile immediatamente alla sinistra di C. Si trova dunque sempre a top – 1 quando se ne bisogna in

C.s := g(C.h).

Regola Istruzioni

S  aAC

S  bABMC

C  c val[ntop] := g(val[top – 1])

(28)

si possono utilizzare marchi quando le regole non sono soltanto regole di copia.

Esempio:

S  aAC C.h := f(A.s) diventa:

S  aAMC M.h := A.s ; C.h := M.s M  M.s := f(M.h)

Esempio: Ritorniamo a TeX, con marchi incorporati.

(29)

Originale Con marchi

Regola Azioni S  LB B.ps := L.s

S.ht := B.ht L   L.s := 10 B  BMB B1.ps := B.ps

M.h := B.ps B2.ps := M.s

B.ht := max(B1.ht, B2.ht) B  B_NB B1.ps := B.ps

N.h := B.ps B2.ps := N.s

B.ht := disp(B1.ht, B2.ht) B  text B.ht := text.h * B.ps M   M.s := M.h

N   N.s := shrink(N.h) Regola Azioni

S  B B.ps := 10 S.ht := B.ht B  BB B1.ps := B.ps

B2.ps := B.ps

B.ht := max(B1.ht, B2.ht) B  B _B B1.ps := B.ps

B2.ps := shrink(B.ps) B.ht := disp(B1.ht, B2.ht) T  text B.ht := text.h * B.ps

(30)

Regola Istruzioni

S  LB val[ntop] := val[top]

L   val[ntop] := 10

B  BMB val[ntop] := max(val[top – 2] , val[top]) B  B sub NB val[ntop] := disp(val[top – 3] , val[top]) B  texte val[ntop] := val[top] * val[top – 1]

M   val[ntop] := val[top]

N   val[ntop] := shrink(val[top – 1])

Programma:

Algoritmo generale:

Dato: Grammatica L-attribuita, LL(1);

(può fallire se solo LR(1))

Risultato: Programma per un traduttore ascendente.

Regole della forma: A  X1X2 ... Xn; supponiamo un solo attributo eredi- tato per ogni variabile, A.h e un solo attributo sintetizzato per simbolo, X.s.

(31)

Regola Azioni

A  X1X2 ... Xk ... Xn ; ..., Xk.h := fk(A.h,..., Xi.h, Xi.s,..., Xk -1.h, Xk -1.s), ... ,

A.s := g(A.h,..., Xi.h, Xi.s,...)

Si sostituisce con: A  M1X1M2X2 ... Mn Xn ; L'attributo Xk.h è sostituito da un attributo sintetizzato Mk.s.

Regole Azioni

A  M1X1M2X2 ... MkXk ... MnXn ;

..., Mk.h := fk(A.h,..., Mi.s, Xi.s,..., Mk -1.s, Xk -1.s), Xk.h := Mk.s,...

A.s := g(A.h,..., Mi.s, Xi.s,...) Mk ; Mk.s := Mk.h

Si può dimostrare che l'attributo ereditato A.h si trova sulla pila sempre

(32)

Infatti, Xk.h serve solo per calcolare Xk.s ed è una copia dell'attributo che precede immediatamente.

Quando  è ridotto in Mk, si trova A.h a val[top – 2k + 2], poi M1.s a val[top – 2k + 3], X1.s a val[top – 2k + 4] ecc.

Rimarchi: Se Xk non ha attributi ereditati (caso frequente), è inutile introdurre Mk.

Si può spesso fare a meno di M1, soprattutto se l'attributo X1.h è una copia di A.h.

In questi casi, i valori precedenti delle posizioni degli attributi non sono

Regole Istruzioni

A  M1X1M2X2 ... MkXk ... MnXn ;

val[ntop] := g(val[top – 2n + 1],..., val[top – 2n – 1 + 2k], val[top – 2n + 2k], ..., val[top – 1], val[top])

Mk ; val[ntop] := fk(val[top – 2k + 2],..., val[top – 2k + 1 + 2i], val[top – 2k + 2 + 2i], ..., val[top – 1], val[top])

(33)

4.6 La valutazione ricorsiva

Certe volte, la valutazione non si può fare in un solo passo.

In questo caso, l'albero di analisi vienne costruito esplicitamente e la valutazione degli attributi si può fare se il grafo di

dipendenza degli attributi è aciclico.

Gli attributi possone essere valutati in modo ricorsivo se possono essere valutati nello stesso ordine in tutte le produzioni di ogni variabile.

Nell'esempio seguente, ci sono due attributi sintetizzati s e t e uno ereditato h. Il contesto è quello del sovraccarico dei tipi di un identificatore in ADA. Il primo, s, rappresenta l'insieme dei tipi possibili, h è l'informazione contestuale e t è il tipo finale

dedotto dai primi due.

(34)

Regola Azione

S  E E.h := g(E.s) S.s := E.t

E  EE E.s := fs(E1.s, E2.s) E1.h := fh1(E.h) E2.h := fh2(E.h) E.t := ft(E1.t, E2.t) E  id E.s := id.s

E.t := l(E.h)

Grafi di dipendenze

S

E

h s t

s

E

E E

h s t h s t

h s t

E

h s t

id s

Gli attributi di E possono sempre essere valutati nell'ordine s, h, t.

Quindi, la funzione per calcolare E.t deve avere un parametro per E.h.

Da dove risulta il codice seguente, nel quale n disegna un nodo

(35)

function Es(n) ;

begin case la regola al nodo n equals

E  EE : s1 := Es(Figlio(n,1)) ; s2 := Es(Figlio(n,2)) ; return fs(s1,s2) ; E  id : return id.s ;

other : Errore end case

end function ; function Et(n, h) ;

begin case la regola al nodo n equals

E  EE : h1 := fh1(h) ; t1 := Et(Figlio(n,1), h1) ;

h2 := fh2(h) ; t1 := Et(Figlio(n,2), h2) ; return ft(t1,t2) ; E  id : return l(h) ;

other : Errore end case

end function ; function Ss(n) ;

Références

Documents relatifs

Domaine : Lecture PS Prénom : Compétence : associer des mots identiques Date :.. Retrouve le nom de

L’immagine dell’economia mondiale, quindi, non può più rimanere quella di un faccia a faccia asimmetrico tra paesi imperialisti e paesi dipendenti, ma è quella dell’integrazione di

[r]

Quels sont les deux triangles dans lesquels le théorème de Thalès sera appliqué?. Repasser en bleu le petit triangle et en vert le

Calculer les impédances d’entrée et de sortie de l’étage et le gain de l’étage si : – il n’y a aucun découplage

Une guêpe a piqué ma mère à la tête pendant

La nuit dans la forêt, j’entends la chouette. Je cherche ma mère derrière

Cette semaine, un élève est parti à la neige.. Il a bu son verre