Analisi semantica e traduzione - Dipartimento di Ingegneria

Transcript

Analisi semantica e traduzione - Dipartimento di Ingegneria
Analisi semantica e
traduzione
Grammatiche ad attributi
Semantica
„ La semantica, come la sintassi, è costituita da un insieme
di regole che associano un significato ai costituenti
lessicali e sintattici del linguaggio.
„ Il significato dell’intera frase viene quindi ottenuto con un
processo compositivo, unendo il significato dei suoi
costituenti.
„ Le regole semantiche possono essere fornite seguendo
diversi modelli:
„
„
Semantica operazionale
Semantica denotazionale
„ Il particolare tipo di regole semantiche che costituiscono
l’argomento del corso sono note sotto il nome di
grammatica ad attributi, ed è senza dubbio il più diffuso
nel campo dei linguaggi di programmazione.
1
„ Un metodo di definizione del linguaggio si
dice semantico se soddisfa uno o più dei
seguenti criteri:
Il metodo è diverso da quello delle
grammatiche formali di Chomsky, ed in
particolare dalle sintassi libere.
„ Il metodo è basato sulla composizione di
funzioni aventi domini e codomini arbitrari, in
contrasto con i metodi sintattici che trattano
unicamente le stringhe per mezzo delle
operazioni della teoria dei linguaggi formali
(concatenamento, ripetizione, sostituzione di
stringhe).
„
Primo approccio
„ Sono classificati semantici i fondati su regole di riscrittura
più potenti di quelle libere.
„ Nella classificazione di Chomsky delle sintassi, le regole
del tipo 0 permettono di esprimere ogni linguaggio
computabile, in quanto è noto che tali sintassi definiscono
la classe degli insiemi ricorsivamente numerabili.
„
„
È concettualmente possibile descrivere il significato di qualsiasi
linguaggio artificiale mediante una sintassi le cui regole hanno una
forma più generale di quelle libere.
In pratica tale sistema sarebbe difficilissimo da progettare,
illeggibile e praticamente inutilizzabile.
„ Allo stato attuale delle conoscenze si può dire che il
rapporto costo-benefici del formalismo sintattico raggiunge
l’ottimo con le sintassi libere, ma peggiora rapidamente
quando si tenta di estenderlo verso modelli più complessi.
2
Secondo approccio
„ Nella semantica si sfruttano meccanismi definitori più generali di quelli
basati sulla manipolazione delle stringhe
„ La semantica raggiunge il suo potere espressivo grazie all’impiego
dell’aritmetica e al ricorso a strutture-dati più ricche delle stringhe: le
tabelle,liste, insiemi, relazioni, ecc. comunemente impiegati
dall’ingegneria del software.
„
Esempio: la tabella dei nomi delle variabili usate in un programma con le loro
proprietà.
„ Per costruire e consultare tali strutture, che costituiscono il dominio
semantico del linguaggio, si usano delle funzioni (dette semantiche),
scritte in un opportuno linguaggio algoritmico, che spesso viene scelto
tra i linguaggi programmativi più diffusi.
„ Le funzioni semantiche sono raggruppate in gruppi di
regole che riflettono strettamente la struttura della sintassi
„ Il potere espressivo ottenuto grazie al libero uso delle
strutture-dati e delle funzioni semantiche offusca il
carattere rigorosamente formale del modello semantico,
che va considerato un buon compromesso tra il rigore
formale della sintassi e la tecnica della programmazione.
Traduzione
„ Sarebbe difficile progettare in modo globale un algoritmo
di traduzione di un linguaggio complesso senza prima
analizzare la frase sorgente nei suoi costituenti definiti
dalla sintassi.
„ L’analisi sintattica riduce la complessità del problema
del calcolo della traduzione, decomponendolo in
sottoproblemi più semplici.
„ Per ogni costituente della frase sorgente il traduttore
esegue le azioni appropriate per preparare la
traduzione, azioni che consistono nel raccogliere certe
informazioni (ad es. le tabelle dei simboli), nel fare dei
controlli semantici, o nell’emettere certe parti della frase
pozzo.
„ In altre parole il lavoro del traduttore è modularizzato
secondo la struttura descritta dall’albero sintattico della
frase. Perciò questo tipo di traduttori è detto guidato
dalla sintassi.
3
Organizzazione del traduttore
„ Per il traduttore sia efficace, è necessario che
„ la sintassi sia strutturalmente adeguata, nel senso che
ogni sottoalbero deve permettere il calcolo di una parte
significativa della traduzione.
„ Le grammatiche ad attributi sono la tecnica per
eccellenza per sfruttare la struttura sintattica nel
calcolare la traduzione o il significato di una frase.
„ Le regole semantiche della grammatica sono definite
in corrispondenza delle produzioni sintattiche e gli
attributi semantici sono associati ai simboli
nonterminali e terminali della sintassi.
„ Sintassi e semantica hanno allora esattamente la
stessa modularità.
„ Vi sono altri approcci per formalizzare la semantica
che pure sfruttano la struttura sintattica.
„
metodo denotazionale: esprime il significato della frase
come composizione di funzioni matematiche.
Traduzioni puramente sintattiche
„ Un caso molto particolare di traduzione compositiva è
quello dei cosiddetti schemi sintattici di traduzione, un
formalismo puramente sintattico per definire una funzione
dal linguaggio sorgente al pozzo.
„ Anche se gli schemi sintattici non dispongono della
capacità algoritmica necessaria per i casi reali, essi sono
interessanti come modello semplice ed elegante della
traduzione.
„ Uno schema di traduzione è un sistema formale che
accoppia due sintassi libere, la sintassi-sorgente e la
sintassi-pozzo, ottenendo così una corrispondenza i
sottoalberi da esse generati, e quindi anche tra le frasi del
linguaggio-sorgente L e quelle del linguaggio pozzo L'.
4
Traduzione puramente sintattica
„ Siano Σ e Δ gli gli alfabeti sorgente e pozzo, e sia x ∈ L ⊆ Σ* una
una frase sorgente.
„ Allora la traduzione di x è una stringa y che viene detta immagine
nella traduzione.
„ L'insieme di tali coppie (x, y) costituisce una relazione
τ ⊆ (Σ* x Δ*)
„ Detta relazione di traduzione.
„ Il linguaggio pozzo L' è l'insieme delle stringhe y ⊆ Δ*) tali che per
qualche stringa x ∈ L sia (x, y) ∈ τ
„ Se poi ogni frase sorgente ammette una sola immagine, la
traduzione diventa una funzione (ad un solo valore)
τ : L → L’
„ Si può scrivere con notazione funzionale y= τ(x).
Definizione
„ Uno schema di traduzione puramente sintattico è
costituito dalla sintassi-sorgente G= (V,Σ, P, S) e dalla
sintassi pozzo G'= (V,Δ, P', S), aventi lo stesso alfabeto
nonterminale V, e da una corrispondenza biunivoca tra le
produzioni P e P', con le seguenti proprietà:
„
„
Siano (A→α) ∈P e (A→β) ∈ P’ le produzioni corrispondenti.
Allora I nonterminali presenti in α e β devono
„ essere gli stessi
„ comparire lo stesso numero di volte
„ comparire nello stesso ordine.
5
Esempio
„
„
„
„
„
„
Sorgente
A → aCD
C→D
C→b
D → DaCD
D→c
Pozzo
A → bCD
C → bDe
C → ca
D →DCD
D→f
„ A → aCD → aDD → aDaCDD → acaCDD →
acabDD → acabcD → acabcc
„ A → bCD → bbDeD →bbCDDeD → bbCfDeD
→bbcafDeD → bbcaffeD → bbcaffef
Esempio
„ La sintassi-sorgente espressioni aritmetiche, linguaggio pozzo
„
„
„
„
„
„
„
„
„
„
espressioni nella forma polacca postfissa, nella quale è noto che gli
operatori seguono i loro argomenti.
Un esempio di traduzione è:
v * v *(v+v) ⇔ v v mult v v add mult
dove gli alfabeti sorgente e pozzo sono
Σ = { v, ' (' , ' )' , +,*} e Δ = {v, add, mult}
Lo schema di traduzione è definito dalle seguenti coppie di
produzioni:
1. E → E + T
E → E T add
2. E → T
E→T
3. T → T * F
T → T F mult
4. T → F
T→F
5. F →( E )
F →E
6. F → v
F→v
6
Limiti
„ sono insiti nel fatto che, per costruire la stringa
pozzo, si possono soltanto applicare delle semplici
operazioni di spostamento dei terminali-sorgente e di
cancellazione o sostituzione di essi con i terminali
dell'alfabeto pozzo.
„ In tale modo ad esempio sarebbe impossibile definire
la traduzione che converte un numero dalla
rappresentazione in base due a quella in base dieci.
„ Per realizzare si possono utilizzare le grammatiche
ad attributi
Traduzione syntax direct
„ Ambito: traduzione di linguaggi guidata dalle grammatiche context- free
„ Traduzione: è una mappatura (mapping ) dell'input nell'output
„ Definizione syntax-directed: è un formalismo per specificare come si
traduce un costrutto di un ling. di progr. in termini di attributi associati ai
suoi componenti sintattici
„ Schema di traduzione è una notazione più procedurale
(implementativa) per specificare come si traduce un costrutto di un ling.
di progr.
7
Traduzione syntax direct
„ approccio classico (due passate):
1. si sintetizza l'albero sintattico (struttura dati) nella
fase di analisi sintattica
2. si utilizza l'albero sintattico per la sintesi dell'output
„ approccio semplificato (una passata):
1. si sintetizza l'output direttamente durante l'analisi
sintattica, senza costruire l'albero sintattico
`l'approccio semplificato ad una passata funziona
solo nei casi “semplici" di traduzione e, più in
generale, di elaborazione dell'input invece,
costruendo l'albero sintattico e visitandolo
successivamente si può implementare un insieme
molto più grande di funzioni di traduzione e di
elaborazione
Come opera una definizione syntaxdirected:
„ traduzione senza albero sintattico = analisi
sintattica dell'input e sintesi dell'output in una sola
passata
pertanto, la traduzione deve avvenire durante
l'analisi sintattica
„ occorre modificare l'analizzatore sintattico,
aggiungendo istruzioni che permettano la sintesi
dell'output in parallelo all'analisi dell'input
„
NOTA BENE: gli analizzatori sintattici LL e LR visti
in precedenza NON generano l'albero sintattico
8
„ si parla di traduzione guidata dalla sintassi nei casi in cui
„
„
„
„
è possibile definire il processo di sintesi dell'output
(traduzione) sulla base della struttura sintattica dell'input
in altre parole, in questi casi l'operazione di traduzione è
fortemente legata alla sintassi dell'input, pertanto la
traduzione puµo essere definita in modo ”parallelo" alla
definizione della sintassi dell'input
in moltissime applicazioni informatiche la funzione di
traduzione (o di elaborazione) è guidata dalla sintassi
nel seguito trattiamo solo funzioni di traduzione guidate
dalla sintassi
anche per traduzioni guidate dalla sintassi, si può avere
la necessità di costruire l'albero sintattico (due passate
distinte per analisi sintattica e sintesi dell'output) oppure
no (una sola passata per analisi sintattica e sintesi
dell'output)
„ per la traduzione guidata dalla sintassi viene
definita una estensione del formalismo delle
grammatiche non contestuali: le grammatiche
ad attributi
„ le grammatiche ad attributi estendono le
grammatiche non contestuali introducendo le
nozioni di:
attributi associati ai simboli (terminali e non
terminali) della grammatica
„ azioni semantiche e regole semantiche, che
affiancano le regole sintattiche della
grammatica
„
9
„ nelle grammatiche ad attributi:
„ ogni simbolo terminale o non terminale può avere uno
o più attributi
„ attributo = proprietà associata al simbolo, che può
essere letta o assegnata dalle azioni semantiche ( =
variabile di un linguaggio di programmazione)
„ ad ogni regola di produzione (regola sintattica) può
essere associata una regola semantica
„ regola semantica = sequenza di azioni semantiche
„ azione semantica = azione in grado di assegnare valori
agli attributi e di avere altri effetti ( = istruzione di un
linguaggio di programmazione)
„ gli attributi sono usati per rappresentare un
“significato" che viene associato ai simboli
sintattici
„ signicato = valore (numero, stringa, struttura
dati, ecc.) che assume l'attributo
„ le azioni semantiche sono il meccanismo che
effettua il calcolo di tali valori, e che quindi
calcola tale “significato"
„ possiamo effettuare la traduzione utilizzando
attributi e azioni semantiche, se assegnamo
come “significato" di un simbolo la traduzione
della parte di stringa di input che tale simbolo
rappresenta nell'albero sintattico
10
„ esempio:
„ in una grammatica per espressioni aritmetiche sui
numeri interi, possiamo associare un attributo di tipo
intero ad ogni simbolo non terminale della grammatica
„ possiamo poi definire delle azioni semantiche in modo
tale che il valoredi ogni attributo corrisponda al valore
della sottoespressione associata al corrispondente
simbolo non terminale
„ pertanto: valore dell'attributo associato alla radice
dell'albero sintattico = valore dell'intera espressione
aritmetica
Grammatiche ad attributi
„ Una grammatica ad attributi H è costituita dalle seguenti entità.
1. Una sintassi libera G = (V,Σ, P, S), dove V è il vocabolario
nonterminale, Σ, quello terminale, P è l’insieme delle produzioni e S è
l’assioma. Spesso conviene imporre che l’assioma non figuri in alcuna
parte destra di produzione.
2. Un insieme di simboli, gli attributi (semantici), associati ai simboli
nonterminali ed eventualmente ai terminali.
– L’attributo α associato al (non)terminale D si indica con α of D.
L’insieme degli attributi dei nonterminali è spartito in due insiemi
tra loro disgiunti detti attributi sintetizzati e attributi ereditati.
– Gli attributi dei terminali sono detti lessicali.
3. Per ogni attributo α è specificato un dominio, l’insieme dei valori che
esso può assumere.
4. Un insieme reg(H) di regole (semantiche). Ogni regola è associata ad
una produzione, ed in generale una produzione p ha più regole indicate
come reg(p).
11
Cosa sono gli attributi
„ Ogni attributo può rappresentare
qualunque cosa vogliamo: stringhe,
numeri, tipi, locazioni di memoria, etc.
„ Il valore di ogni attributo ad ogni nodo
è determinato da una regola semantica
associata alla produzione che si usa
nel nodo annotated (decorated) parse
tree: è un parse tree che mostra i valori
degli attributi (dei simboli) per ciascun
nodo
Definizioni guidate dalla sintassi
„ gli attributi si distinguono in:
attributi sintetizzati: sono gli attributi il cui valore dipende
solo dai valori degli attributi presenti nel sottoalbero del nodo
dell'albero sintattico a cui sono associati
„ attributi ereditati: sono gli attributi il cui valore dipende solo
dai valori degli attributi presenti nei nodi predecessori e nei
nodi fratelli del nodo dell'albero sintattico a cui sono
associati
„ gli attributi sintetizzati realizzano un flusso informativo
ascendente nell'albero sintattico (dalle foglie verso la radice)
„ gli attributi ereditati realizzano un flusso informativo discendente
(dalla radice verso le foglie) e laterale (da sinistra verso destra e
viceversa) nell'albero sintattico
„
12
Forma di una definizione
„ In un syntax-directed definition, ogni produzione A→α è
associata con un insieme di regole semantiche di forma
b=f(c1,c2,…,cn)
dove f è una funzione, e b è
b è un attributo sintetizzato di A e c1,c2,…,cn sono attributi dei
simboli della grammatiche presenti nella produzione A→α.
oppure
b è un attributo ereditato del simbolo sella grammatica in α
(nella parte destra della produzione), e c1,c2,…,cn sono
attributi dei simboli della grammatiche nella produzione A→α.
Regole semantiche
„ l'esecuzione di una regola semantica avviene in parallelo
„
„
„
„
all'applicazione della corrispondente regola sintattica
nell'analisi sintattica
pertanto, l'ordine di applicazione delle regole semantiche
è conseguenza dell'ordine di applicazione delle regole di
produzione nell'analisi sintattica
in particolare, dato un certo ordine di applicazione, le
istruzioni che nelle regole semantiche effettuano la
valutazione degli attributi potrebbero non essere
eseguibili in modo corretto
ad esempio, può accadere che in una azione semantica
si tenti di leggere il valore di un attributo non ancora
assegnato
questo problema, noto come problema della valutazione
degli attributi, µe un problema fondamentale per il
trattamento automatico delle grammatiche ad attributi
13
Regole semantiche
„ La valutazione può avere anche side-
effects (effetti collaterali) come la
stampa di valori o l’aggiornamento di
una veriabile globale
„ In una definizione guidata dalla sintassi
si assume che i simboli terminali
abbiano solo attributi sintetizzati
„ I valori per questi attributi sono in
genere forniti dall’analizzatore lessicale
„ Il simbolo iniziale, se non diversamente
specificato, non ha attributi ereditati
Esempio
„
„
„
„
„
ll calcolo del valore decimale di un numero frazionario in base due
(D. Knuth 1968)
L’esempio mostra il ruolo degli attributi ereditati, e la loro
sostituibilità con gli attributi sintetizzati.
Il linguaggio sintatticamente è definito dall’espressione regolare L=
{ 0,1}*. {0, 1}* da interpretare come un numero binario con il punto
che separa la parte intera da quella frazionaria.
„
Ad es. il significato di 1101.01 è il numero 13,25
Sintassi
1.
num → str . str
2.
str → str bit
3.
str → bit
4.
bit → 0
5.
bit → 1
num è l’assioma, str definisce la stringa binaria della parte intera e
frazionaria, che è composta di bit.
14
Grammatica ad attributi (1)
Grammatica ad attributi (1)
1.
num → str1 . str2
2.
str0 → str1 bit
3.
str → bit
4.
5.
bit → 0
bit → 1
f of str1 := 0
f of str2 := - l of str2
v of num= v of str1 +v of str2
f of str1 := f of str0 +1
f of bit := f of str
l of str0 := l of str1 + 1
v of str0 := v of str1 + v of bit
f of bit:= f of str
l of str := 1
v of str := v of bit
v of bit := 0
v of bit := 2 f of bit
15
Grammatica ad attributi (2)
num → str1 . str2
v of num= v of str1 +v of str2 * 2 -l of str2
2. str0 → str1 bit
1.
v of str0 := 2* v of str1 +v of bit
l of str0 := l of str1 + 1
3.
str → bit
v of str := v of bit
l of str := 1
4.
5.
bit → 0
bit → 1
v of bit := 0
v of bit := 1
Annotated Parse Tree
„ Albero sintattico annotato o Albero sintattico
decorato: albero sintattico contenente I
valori degli attributi.
„ Annotazione o decorazione dell’albero
sintattico: processo di calcolo degli attributi
16
Esempio
PRODUZIONE
REGOLE SEMANTICHE
L→En
print(E.val)
E → E1 + T
E.val := E1.val ⊕ T.val
E→T
E.val := T.val
T → T1 * F
T.val := T1.val ⊗ F.val
T→F
T.val := F.val
F→(E)
F.val := E.val
F → digit
F.val := digit.lexval
Esempio: spiegazioni
„ La grammatica genera le espressioni
aritmetiche tra cifre seguite dal carattere n di
newline
„ Ogni simbolo non terminale ha un attributo
sintetizzato val
„ Il simbolo terminale digit ha un attributo
sintetizzato il cui valore si assume essere
fornito dall’analizzatore lessicale
„ La regola associata al simbolo iniziale L è
una procedura che stampa un valore intero
(side-effect) mentre tutte le altre regole
servono per il calcolo del valore degli attributi
17
Annotated Parse Tree -- Example
L
Input: 5+3*4
E.val=17
E.val=5
+
return
T.val=12
T.val=5
T.val=3
*
F.val=5
F.val=3
digit.lexval=5
digit.lexval=3
F.val=4
digit.lexval=4
I simboli E, T, e F sono associati con gli attibuti sintetizzati
loc e code.
Il token id ha un attributo sintetizzato name (si assume che
l’analizzatore lessicale si occupi di tale valore)
Si assume che || e l’operatore di concatenazione di
stringhe.
Syntax-Directed Definition –
Esempio2
Production Semantic Rules
E → E1 + T
E→T
T → T1 * F
T→F
F→(E)
F → id
E.loc=newtemp(),
E.code = E1.code || T.code || add E1.loc,T.loc,E.loc
E.loc = T.loc, E.code=T.code
T.loc=newtemp(),
T.code = T1.code || F.code || mult T1.loc,F.loc,T.loc
T.loc = F.loc, T.code=F.code
F.loc = E.loc, F.code=E.code
F.loc = id.name, F.code=“”
18
Syntax-Directed Definition –
Inherited Attributes
Production
Semantic Rules
D→TL
T → int
T → real
L → L1 id
L → id
L.in = T.type
T.type = integer
T.type = real
L1.in = L.in, addtype(id.entry,L.in)
addtype(id.entry,L.in)
„ Il simbolo T è associato con un attributo sintetizzato
type.
„ IL simbolo L è associato con un attributo ereditato in.
Calcolo degli attributi
„ L’ordine di calcolo degli attributi dipende dal
grafo delle dipendenze creato sulla base
delle regole semantiche
19
Dipendenze funzionali e circolarità
„ L’attributo definito da una regola dipende dagli
argomenti della funzione semantica, dando luogo ad
una relazione di dipendenza funzionale tra l’attributo
definito ed ognuno dei suoi argomenti.
Data la produzione
E la regola
Si definisce dipendenza funzionale
Grafo delle dipendenze (Dependency
Graph)
„ Si definisce relazione di dipendenza funzionale della
produzione p l’unione relazioni dipp,α,k per tutte le regole
reg(p)
dipp,= ∪∀reg(p) dipp,α,k
„
„
una relazione binaria definita su un insieme può essere
visualizzata come un grafo
„ i nodi sono gli elementi dell’insieme
un arco n1 →n2 indica la relazione tra n1 ed n2.
„ Grafo dipp delle dipendenze funzionali della produzione
p e il grafo che ha come nodi gli attributi attr(p) e presenta
l’arco β of Dj → α of Dk se α of Dj è argomento di una
funzione semantica associata a p che calcola β of Dk .
20
Grafo delle dipendenze (Dependency
Graph)
„ E' un grafo orientato aciclico che illustra le interdipendenze tra gli
attributi dei nodi del parse-tree
„ Per costruire il grafo delle dipendenze per un parse- tree occorre
prima mettere tutte le regole semantiche nella forma
b := f( c1 ,c2 ,... ck )
anche quelle che consistono di una chiamata di procedura
(introducendo un attributo fittizio)
„ Il grafo ha un nodo per ogni attributo.
„
„
Se l'attributo b dipende dall'attributo c b = f ( c .........) ci sarà un
arco da c a b b ← c
Se un attributo b in un nodo dipende da un attributo c allora la
regola semantica per b deve essere valutata dopo la regola
semantica che definisce c
Esempio Grammatica 1
21
Circolarità delle definizioni
semantiche
„ Una frase di un linguaggio deve avere un ben
preciso significato, quindi è essenziale che la
grammatica determini, per ogni albero, una e una
sola soluzione per gli attributi, una volta fissati i
valori iniziali degli attributi lessicali.
„ Il grafo delle dipendenze funzionali dipp di una
produzione è aciclico se non contiene alcun
circuito (orientato).
„ l’albero semantico t è aciclico se il grafo delle
dipendenze funzionali dip(t) è privo di circuiti.
„ Una grammatica ad attributi è aciclica se per ogni
albero sintattico il corrispondente albero
semantico è aciclico.
Verifica di aciclicita
„ Il grafo di una produzione contiene un
numero ridotto di nodi e di archi, è semplice
controllare ad occhio che sia aciclico.
„ Se in qualcuno dei grafi dipp delle produzioni
vi fosse una circolarità certamente
esisterebbe in T(G) un albero t il cui grafo
dip(t) presenterebbe la stessa circolarità.
„ Non è vero il viceversa
22
Proprietà 1
„ Se per un albero t il grafo delle dipendenze
funzionali dip(t) è aciclico, il sistema delle
equazioni semantiche dell’albero ammette una
e una sola soluzione.
Proprietà 1: Dimostrazione.
„ Le incognite sono gli attributi dei nodi di t. Per ogni
incognita esiste una e una sola equazione che le
assegna un valore. Se dip(t) non ha cicli i nodi del grafo,
ossia le incognite, possono essere ordinati
topologicamente ottenendo un ordinamento totale:
a1 := f1
a2 := f2
.......
am := fm
„ dove fj è la regola che assegna il valore all’attributo aj .
La sequenza di istruzioni è tale che tutti gli argomenti di
una regola sono definiti da regole precedenti, quindi
sono di valore noto.
„ Poiché il programma non contiene istruzioni di salto,
ogni riga viene eseguita una sola volta, quindi ogni
incognita riceve un solo valore.
23
Algoritmo
1.Ordina topologicamente gli attributi
di t rispetto al grafo dip(t) e scrivi
nell’ordine le regole che li
calcolano.
2.Esegui nell’ordine le regole
semantiche.
Algoritmo
Inconventi dell’algoritmo sono
„ la necessità di calcolare l’ordinamento topologico
di t, operazione che richiede una complessità di
calcolo O(m) dove m è il numero dei nodi di dip(t),
„ Ogni nodo sintattico dell’albero viene attraversato
tante volte quanti sono i suoi attributi, e in
generale tali attraversamenti non sono contigui
nell’ordinamento topologico, con un conseguente
lavoro di spostamento sull’albero.
„ Come miglioramento si introdurranno più avanti certe
sottoclassi delle grammatiche in cui le dipendenze
funzionali consentono la valutazione degli attributi
con un numero più ridotto di attraversamenti dei nodi
sintattici.
24
Equivalenza forte e debole
„ Due grammatiche ad attributi H e H’ aventi la stessa
sintassi G sono equivalenti in senso forte se esse
definiscono la stessa traduzione, ossia Tf (H) = Tf(H')
„ Due grammatiche ad attributi H e H' aventi sintassi G
e G' sono equivalenti in senso debole seesse
definiscono la stessa traduzione, ossia Td(H) =
Td(H')
„ Due classi di grammatiche hanno lo stesso potere
espressivo (in senso forte o debole) se per ogni
grammatica di una classe esiste nell’altra classe una
grammatica equivalente (in senso forte o debole).
Proprietà
„ Proprietà 2
„ La classe delle grammatiche elementari ha lo
stesso potere espressivo della classe delle
grammatiche con attributi ereditati e
sintetizzati.
25
Metodi di valutazione degli
attributi semantici
„ Il problema della valutazione semantica consiste nel
calcolare i valori degli attributi in tutti i nodi di un albero
sintattico dato.
„ Tali valori sono la soluzione del sistema delle equazioni
determinate dalle regole semantiche, riportate su ogni nodo
dell’albero, soluzione che esiste ed è unica se la grammatica
è aciclica.
„ Caratteristiche del metodo di calcolo:
„
„
„
„
„
generalità del metodo: è la capacità di trattare grammatiche ad
attributi di tipo più generale;
efficienza di calcolo del valutatore: tempo di calcolo (o memoria);
possibilità di accorpare l’analisi sintattica e valutazione degli attributi;
incrementalità nel calcolo degli attributi di fronte a modifiche della
frase (o dell’albero) da analizzare: una modifica non richiede di rifare
da zero la valutazione;
complessità della costruzione del valutatore.
Ordine di valutazione
„ I numeri dell’esempio sulle dichiarazioni sono un
ordinamento topologico
„ Se scriviamo in ordine le regole semantiche
otteniamo il seguente programma:
a4 := real;
a5:= a4;
addtype(id3.entry, a5);
• La valutazione degli attributi
a7:= a5;
sintetizzati dei simboli terminali
addtype(id2.entry, a7);
non viene considerata
a9:= a7;
• Infatti questi valori sono già
addtype(id1.entry, a9);
disponibili dall’analisi lessicale
26
Ordinamento topologico
„ Si ordinano topologicamente (rispetto
alla relazione di dipendenza funzionale)
le comparse degli attributi nell' albero
„ Si applicano in tale ordine le funzioni
semantiche, si è così sicuri di rispettare
la condizione fondamentale che il
calcolo di un attributo sia preceduto
dalla valutazione di tutti i suoi
argomenti.
„ Tra i tanti ordinamenti topologici
possibili, sono da preferire quelli che
meglio rispondono alle esigenze
applicative
Schedulazione
„ La schedulazione e può avvenire in diversi momenti:
„ Statica: al momento della costruzione del valutatore. e
dipende da H ma non da t, in quanto la scelta del
prossimo attributo da calcolare è codificata nel
programma del valutatore. Un caso particolarmente
semplice è quello in cui l’ordine è lo stesso per ogni
produzione della sintassi (schedulazione fissa).
„ Dinamica: l’ordinamento topologico viene calcolato di
volta in volta per l’albero t.
„ esempio utilizzando un algoritmo parallelo seguente
che associa un processo ad ogni comparsa di un
attributo
27
Definizione degli attributi
„ Syntax-directed definitions sono utilizzate per specificare
traduzioni syntax-directed.
„ La creazione di un traduttore per un definizione syntaxdirected può essere difficile.
„ Per valutare le regole semantiche durante il parsing
(compilatori a singolo passo) si possono utilizzare due
sottoclassi di syntax-directed definitions:
S-Attributed Definitions: solo attributi sintetizzati
„ L-Attributed Definitions: attributi ereditati e attributi
sintetizzti dipendenti dalla parte sinistra.
„
L-Attributed Definitions
„ Una definzione syntax-directed è di tipo L (L-
attributed) se ogni attributo di Xj, con 1≤j≤n,
nella RHS di
„ A → X1X2...Xn dipende solo da:
1.
2.
Gli attributi dei simboli X1,...,Xj-1 della parte sinistra
di Xj nella produzione e
Gli attributi ereditati di A
„ Una grammatica del tipo L risulta
necessariamente aciclica. Infatti è immediato
vedere che il grafo delle dipendenze di ogni
produzione è aciclico.
28
Analizzatori a singolo passo
„ Nelle traduzioni più semplici si riesce a calcolare il significato di
una frase con un solo attraversamento dell’albero, ottenendo
così la massima efficienza possibile. Si presentano qui le
condizioni che assicurano la calcolabilità degli attributi mediante
una passata discendente da sinistra a destra o destrorsa (ordine
anche detto anticipato o preordine).
„ Il metodo qui esposto rientra come caso particolare in quelli ad
una scansione (one-sweep) più avanti descritti, che permettono
ordini di visita anche non rivolti da sinistra a destra.
„ Le grammatiche che permettono la valutazione con una visita
destrorsa in profondità sono ora caratterizzate mediante una
condizione nota come L (che sta per "left to right").
Una definizione che non è di tipo L
produzioni
A→LM
A→QR
regole semantiche
L.in=l(A.i), M.in=m(L.s), A.s=f(M.s)
R.in=r(A.in), Q.in=q(R.s), A.s=f(Q.s)
„ La grammatica non è di tipo L perchè la regola Q.in=q(R.s)
viola le restrizioni di tipo L
„ Q.in deve essere valutato prima che noi entriamo in Q
poichè esso è un attributo ereditato
„ Ma il valore di Q.in dipende da R.s che sarà disponibile alla
fine di R. Cosi, non sarà possibile valutare Q.in prima di
entrare in Q.
29
Grammatiche di tipo L
„ Data una grammatica della classe L è facile
esprimere l’algoritmo di calcolo sotto forma di
procedure a discesa ricorsiva. Sia p: D0→ D1
D2 ... Dr la produzione nel nodo n0 . Come
primo schema realizzativo, si definisce per ogni
produzione p, una procedura Discendente_p
con il compito di calcolare gli attributi sint(n0);
essa ha come parametri d’ingresso il
sottoalbero radicato in n0 e gli attributi ered(n0).
Grammatiche di tipo L
Void Discendente_p (in n0 : nodo, ered(n0) : out sint(n0) )
{
for k:=1 to r {
if (Dk è nonterminale) {
<calcola ered(nk) eseguendo le funzioni
semantiche corrispondenti>
-- sia qk la produzione del nodo nk ;
Discendente_ qk (nk, ered(nk); sint(nk)) -- chiamata
che ricorsivamente calcola sint(nk)
}}
calcola sint(n0) eseguendo le funzioni semantiche
corrispondenti>
}
30
Top-Down Evaluation (of S-Attributed Definitions)
Productions Semantic Rules
A→B
print(B.n0), print(B.n1)
B → 0 B1
B.n0=B1.n0+1, B.n1=B1.n1
B.n0=B1.n0, B.n1=B1.n1+1
B → 1 B1
B→ε
B.n0=0, B.n1=0
Dove B ha due attributi sintetizzati (n0 e n1).
Valutazione Top-Down (di attributi S)
„ In un parser ricorsivo discendente ogni non terminale
corrisponde ad una.
void A() { B();}
void B() {
if (currtoken=0) { nexttoken(); B(); }
else if (currtoken=1) { nexttoken; B(); }
else if (currtoken=$) {} // $ fine stringa
else error(“unexpected token”);
}
A→B
B→0B
B→1B
B→ε
31
Valutazione Top-Down (di attributi
S)
void A() {
int n0,n1;
B(out n0,out n1);
print(n0); print(n1);
}
void B(out int n0, out int n1) {
if (currtoken=0)
{int a,b; nexttoken(); B(out a, out b); n0=a+1; n1=b;}
else if (currtoken=1)
{ int a,b; nexttoken(); B(out a, ref b); n0=a; n1=b+1; }
else if (currtoken=$) {n0=0; n1=0; } // $ fine stringa
else error(“unexpected token”);
}
Analizzatori a singolo passo BottomUp Uso delle grammatiche S
„ Mettere il valore dell’attributo sintetizzato del simbolo della grammtica in
una pila in parallelo.
„
Quando un entry della pila del parser è un simbolo X
(terminale o non-terminale), il correspondente entry dello stack
parallelo conterra l’attribuyo sintetizzato del simbolo X.
„ Il valore dell’attributo viene valutato durante la riduzione.
„ A → XYZ
A.a=f(X.x,Y.y,Z.z) dove tutti gli attributi sono sintetizzati.
stack parallel-stack
top →
Z
Z.z
Y
Y.y
X
X.x
.
.
Î
top →
A
.
A.a
.
32
Bottom-Up Eval. of S-Attributed Definitions
Production
Semantic Rules
L → E return
E → E1 + T
E→T
T → T1 * F
T→F
F→(E)
F → digit
print(val[top-1])
val[ntop] = val[top-2] + val[top]
val[ntop] = val[top-2] * val[top]
val[ntop] = val[top-1]
„ Ad ogni spostamento di digit, il valore digit.lexval sarà inserito in
val-stack (stack parallelo).
„ Per gli altri spostamenti, inserire un simbolo qualsiasi in val-stack
poichè tutti gli altri terminali non hanno attributi (lo stack pointer di
val-stack deve essere incrementato).
Canonical LR(0) Collection for The Grammar
..
..
..
..
I0: L’→
L→
E→
E→
T→
T→
F→
F→
.
..
..
.
.. .
..
..
.
L I:
L
1 L’→L
Er
E I:
E+T
2 L →E r
E →E +T
T
T*F
T I:
F
3 E →T
(E)
T →T *F
d
F I:
4 T →F
(
d
I5: F →
E→
E→
T→
T→
F→
F→
I6: F →d
+
*
( E)
E+T
E
T
T*F
F
T
3
(E)
F
d
4
(
d
.
.. .
..
I7: L →Er
r
I8: E →E+ T
T → T*F
T→ F
F → (E)
F→ d
.. .
..
I9: T →T* F
F → (E)
F→ d
..
I11: E →E+T
T →T *F
T
F
4
(
*
9
5
d
6
.
F
I12: T →T*F
(
5
d
6
)
I10:F →(E )
E →E +T +
I13: F →(E)
.
8
5
6
33
Bottom-Up Evaluation -- Esempio
5+3*4r
stack
val-stack
0
input
action
semantic rule
5+3*4r
s6
d.lexval(5) into val-stack
F.val=d.lexval – do nothing
0d6
5
+3*4r
F→d
0F4
5
+3*4r
T→F
T.val=F.val – do nothing
0T3
5
+3*4r
E→T
E.val=T.val – do nothing
0E2
5
+3*4r
s8
push empty slot into val-stack
0E2+8
5-
3*4r
s6
d.lexval(3) into val-stack
F.val=d.lexval – do nothing
0E2+8d6
5-3
*4r
F→d
0E2+8F4
5-3
*4r
T→F
T.val=F.val – do nothing
0E2+8T11
5-3
*4r
s9
push empty slot into val-stack
0E2+8T11*9 5-3-
s6
d.lexval(4) into val-stack
0E2+8T11*9d6
5-3-4
r
F→d
F.val=d.lexval – do nothing
0E2+8T11*9F12
5-3-4
r
T→T*F
T.val=T1.val*F.val
0E2+8T11
5-12
r
E→E+T
E.val=E1.val*T.val
0E2
17
r
s7
push empty slot into val-stack
17-
$
L→Er
print(17), pop empty slot from val-
17
$
acc
0E2r7
4r
stack
0L1
Schema di traduzione
„ In una syntax-directed definition, noi non diciamo niente circa la l’ordine
di valutazione delle regole semantiche
„ Un translation scheme è una grammatica di tipo 2 nella quale:
Gli attributi sono associati con i simboli della
grammartica e
„ Le azioni semantiche sono incluse fra parentesi {} e
insirite nella parte destra delle produzioni.
„
„ Ex:
A → { ... } X { ... } Y { ... }
Semantic Actions
34
Schema di traduzione
„ Quando si progetta uno schema di traduzione, alcune
restrizioni dovrebbero essere osservate per
assicurare che il valore si un attributo sia disponibile
quando una azione samantica si riferisce a tale
attributo
„ Queste restrizioni (grammatiche L) assicurano che
una azione semantica non si riferisca ad un attributo
non ancora computato.
„ In uno schema di traduzione useremo il termine
semantic action piuttosto che semantic rule
utilizzato nella syntax-directed definitions.
Schema di traduzione per attributi S
„ Se la syntax-directed definition è di tipo S il corrispondente schema di
traduzione si ricava semplicemente.
„ Ogni regola semantica associata ad una syntax-directed definition con
attributi S sara inserita come azione semantica alla fine della parte destra
della prodeuzione associata
Production
Semantic Rule
E → E1 + T
E.val = E1.val + T.val
Î syntax directed definition
⇓
E → E1 + T { E.val = E1.val + T.val }
Î corresponding
translation scheme
35
Esempio di schema di traduzione
„ Un semplice schema di traduzione che converte espressioni
infisse nella corrispondente espressione postfissa
E→TR
R → + T { print(“+”) } R1
R→ε
T → id { print(id.name) }
Î ab+c+
a+b+c
Espressione infissa
Espressione postfissa
Schema Edi traduzione
R
T
id {print(“a”)
}
+
id
T
R
{print(“+”)}
{print(“b”)}
+
T
id
{print(“+”)}
{print(“c”)}
R
ε
„ L’attraversamento depth first dell’albero sintattico (eseguendo le azioni
semantiche in ordine) produrra la rappresentazione postfissa della
espressione infissa
36
Attributi ereditati in uno schema di traduzione
„
Se in uno schema di traduzione sono presenti sia attributi ereditati che
sintetizzati si devono seguire le seguenti regolo::
1.
2.
3.
„
Un attributo ereditato di un simbolo nel RHs di una
produzione deve essere computato in una azione semantica
prima del simbolo.
Una azione semantica non si deve riferire ad un attributo
sintetizzato di un simbolo della RHS di tale azione semantica
Un attributo sintetizzato per un non terminale nella LHS può
solo essere computato dopo che tutti gli attributi a cui si
riferisce sono stati computati (noi normalmente porremo tale
azione semantica alla fine della produzione)
Con una grammatica L (L-attributed syntax-directed definition) è posssible
sempre construire il corrispondente schema di traduzione che soddisfa queste
tre regole.
Un schema di traduzione con
attributi ereditati
D → T id { addtype(id.entry,T.type), L.in = T.type } L
T → int { T.type = integer }
T → real { T.type = real }
L → id { addtype(id.entry,L.in), L1.in = L.in } L1
L→ε
„ Questo e il translation scheme per una L-attributed
definitions.
37
Predictive Parsing (di attributi ereditati)
void D() {
int Ttype,Lin,identry;
T(&Ttype); nextoken(id,&identry);
addtype(identry,Ttype); Lin=Ttype;
call L(Lin);
a synthesized attribute (an output parameter)
}
Void T(int *Ttype) {
if (currtoken is int) {nextoken(int); *Ttype=TYPEINT; }
else if (currtoken is real) { consume(real); *Ttype=TYPEREAL; }
else { error(“unexpected type”); }
}
an inherited attribute (an input parameter)
Void L(int Lin) {
if (currtoken is id) { int L1in,identry; nextoken(id,&identry);
addtype(identry,Lin); L1in=Lin; call L(L1in); }
else if (currtoken is endmarker) { }
else { error(“unexpected token”); }
}
Eliminazione delle ricorsioni sinistre dallo
schema di traduzione
„ Schema di traduzione con una grammatica left.
E → E1 + T
{ val of E = E1.val + T .val }
E → E1 - T
{ E.val = E1.val –T .val }
E→T
{ E.val = T.val }
T → T1 * F
{ T.val = T1 .val* F.val }
T→F
{ T.val = F.val }
F→(E)
{ F.val = E.val }
F → digit
{ F.val = digit.lexval }
„ Quando eliminiamo la ricorsione sinistra dalla grammatica
dobbiamo eseguire delle modifiche nelle regole semantiche
38
Eliminazione ricorsione sinistra
E → T { A.in=T.val } A { E.val=A.syn }
A → + T { A1.in=A.in+T.val } A1 { A.syn =
A1.syn}
A → - T { A1.in=A.in-T.val } A1 { A.syn =
A1.syn}
A→ε
{ A.syn = A.in }
T → F { B.in=F.val } B { T.val=B.syn }
B → * F { B1.in=B.in*F.val } B1 { B.syn = B1.syn}
B→ε
{ B.syn = B.in }
F → ( E ) { F.val = E.val }
F → digit { F.val = digit.lexval }
Eliminazione ricorsione sinistra
A → A1 Y { A.a = g(A1.a,Y.y) }
sinistra
A → X { A.a=f(X.x) }
(a,y,x).
grammatica ricorsiva
con attributi sintetizzati
⇓ eliminazione ricorsione sinistra
attributo ereditato del nuovo non terminale
attributo sintetizzato del nuovo non terminale
A → X { R.in=f(X.x) } R { A.a=R.syn }
R → Y { R1.in=g(R.in,Y.y) } R1 { R.syn = R1.syn}
R → ε { R.syn = R.in }
39
Valutazione degli attributi
A
A
A
Y
A.a=g(f(X.x),Y.y)
X R.in=f(X. R R.syn=g(f(X.x),Y.y)
x)
X X.x=f(X.x)
Y R1.in=g(f(X.x),Y.y)R R.syn=g(f(X.x),Y.y
1
ε
R1.syn=g(f(X.x),Y
y)
Schema di traduzione – Generazione
di codice intermedio
E → T { A.in=T.loc } A { E.loc=A.loc }
A → + T { A1.in=newtemp(); emit(add,A.in,T.loc,A1.in) }
A1 { A.loc = A1.loc}
A → ε { A.loc = A.in }
T → F { B.in=F.loc } B { T.loc=B.loc }
B → * F { B1.in=newtemp(); emit(mult,B.in,F.loc,B1.in) }
B1 { B.loc = B1.loc}
B → ε { B.loc = B.in }
F → ( E ) { F.loc = E.loc }
F → id { F.loc = id.name }
40
Predictive Parsing – Intermediate
Code Generation
void E(char **Eloc) {
char *Ain, *Tloc, *Aloc;
T(&Tloc); Ain=Tloc;
A(Ain,&Aloc); *Eloc=Aloc;
}
Void A(char *Ain, char **Aloc) {
if (currtok is +) {
char *A1in, *Tloc, *A1loc;
nexttoken(+);
T(&Tloc); A1in=newtemp(); emit(“add”,Ain,Tloc,A1in);
A(A1in,&A1loc); *Aloc=A1loc;
}
else { *Aloc = Ain }
}
Predictive Parsing (cont.)
T(char **Tloc) {
char *Bin, *Floc, *Bloc;
F(&Floc); Bin=Floc;
B(Bin,&Bloc); *Tloc=Bloc;}
B(char *Bin, char **Bloc) {
if (currtok is *) {
char *B1in, *Floc, *B1loc;
nextoken(+); call F(&Floc); B1in=newtemp();
emit(“mult”,Bin,Floc,B1in);
B(B1in,&B1loc); Bloc=B1loc;}
else { *Bloc = Bin }}
F(char **Floc) {
if (currtok is “(“) { char *Eloc; nexttolken(“(“); call E(&Eloc); consume(“)”);
*Floc=Eloc }
else { char *idname; nexttoken(id,&idname); *Floc=idname }
}
41
Valutazione Bottom-Up di attributi
ereditati
„ Utilizzando uno schema di traduzione top-down si può
implementare qualsiasi L-attributed definition basata su
grammatiche LL(1).
„ Utilizzando uno schema di traduzione bottom-up translation
scheme, si può anche implementare qualsiasi L-attributed
definition basata su grammatiche LL(1) (qualsiasi
grammatica LL(1) è anche LR(1)).
„ Oltre alle L-attributed definitions basate su grammatiche
LL(1), noi possiamo impe,emtare alcune L-attributed
definitions basate su grammatiche LR(1) (non tutte)
utilzzando uno schema di traduzione bottom-up.
Removing Embedding Semantic Actions
„ Nello schema di valutazione bottom-up, le azioni semantiche sono
valutate durante la riduzione.
„ Durinte la valutazione bottom-up degli attributi S noi abbiamo uno stack
parallelo che contiene gli attributi sintetizzati.
„ Problema: dove memorizzare gli attributi ereditati?
„ Soluzione:
„
„
„
„
Convertie la nostra grammatica in una equivalente che
garantisca:
Tutte le azioni semantiche embedded sono rimosse
Tutti gli attributi ereditati sono copiati negli attributi sintetizzati.
Quindi valujtare tutte le azioni semantiche durante le riduzioni
e troveremo un posto per gli attributi ereditati
42
Rimozione di Azione Semantiche
Embedded
„
1.
2.
3.
4.
Per trasformare uno schema di traduzione in uno
equivalente
Rimuovere un azione semantica embedded Si, ponendo
un nuovo non terminale Mi al posto dell’azione
semantica.
Porre l’azione semantica Si alla fine della nuova
produzione Mi→ε per il non terminaleMi.
Questa azione semantica Si sara valutata quando la
nuova produzione sarà ridotta.
L’ordine di valutazione delle regole semantiche rimane
invariato da questa trasformazione
Esempio di rimozione delle azioni
semantiche embedded
A→ {S1} X1 {S2} X2 ... {Sn} Xn
⇓
A→ M1 X1 M2 X2 ... Mn Xn
M1→ε {S1}
M2→ε {S2}
.
.
Mn→ε {Sn}
43
Rimozione azioni semantiche embedded
E→TR
R → + T { print(“+”) } R1
R→ε
T → id { print(id.name) }
⇓
E→TR
R → + T M R1
R→ε
T → id { print(id.name) }
M → ε { print(“+”) }
Traduzione con attributi ereditati
„ Supponiamo che ogni non-terminale A abbia un attributo
ereditato A.i e ogni simbolo C abbia un attributo sintetizzato
nella nostra grammatica
„ Per ogni produzione A→ X1 X2 ... Xn, (1)
Introdurre dei nuovi non terminali M1,M2,...,Mn e
Sostituire (1) con A→ M1 X1 M2 X2 ... Mn Xn
„ Gli attributi sintetizzati di Xi non verranno modificati
„ Gli attributi ereditati di Xi saranno copiati in un attributo
sintetizzato di Mi nella nuova regola semantica aggiunta alla fine
della produzioneMi→ε.
A → {B.i=f1(...)} B {C.i=f2(...)} C {A.s= f3(...)}
„ Ora, glia attributi ereditati di Xi possono essere trovati in un
⇓
attributo sintetizzato di Mi (che è disponibile nello stack).
„
„
A → {M1.i=f1(...)} M1 {B.i=M1.s} B {M2.i=f2(...)} M2 {C.i=M2.s} C {A.s=
f3(...)}
M1→ε {M1.s=M1.i}
M2→ε {M2.s=M2.i}
44
Traduzione con attributi ereditati
S → {A.i=1} A {S.s=k(A.i,A.s)}
A → {B.i=f(A.i)} B {C.i=g(A.i,B.i,B.s)} C {A.s= h(A.i,B.i,B.s,C.i,C.s)}
B → b {B.s=m(B.i,b.s)}
C → c {C.s=n(C.i,c.s)}
S → {M1.i=1} M1 {A.i=M1.s} A {S.s=k(M1.s,A.s)}
A → {M2.i=f(A.i)} M2 {B.i=M2.s} B
{M3.i=g(A.i,M2.s,B.s)} M3 {C.i=M3.s} C {A.s= h(A.i, M2.s,B.s, M3.s,C.s)}
B → b {B.s=m(B.i,b.s)}
C → c {C.s=n(C.i,c.s)}
M1→ε {M1.s=M1.i}
M2→ε {M2.s=M2.i}
M3→ε {M3.s=M3.i}
Schema di traduzione reale
S → {M1.i=1} M1 {A.i=M1.s} A {S.s=k(M1.s,A.s)}
A → {M2.i=f(A.i)} M2 {B.i=M2.s} B {M3.i=g(A.i,M2.s,B.s)} M3
{C.i=M3.s} C {A.s= h(A.i, M2.s,B.s, M3.s,C.s)}
B → b {B.s=m(B.i,b.s)}
C → c {C.s=n(C.i,c.s)}
M1→ε {M1.s= M1.i}
M2→ε {M2.s=M2.i}
M3→ε {M3.s=M3.i}
45
Schema di traduzione reale
S → M1 A
M1→ ε
A → M2 B M3 C
M2→ ε
M3→ ε
B→b
C→c
{ s[ntop]=k(s[top-1],s[top]) }
{ s[ntop]=1 }
{ s[ntop]=h(s[top-4],s[top-3],s[top-2],s[top-1],s[top]) }
{ s[ntop]=f(s[top]) }
{ s[ntop]=g(s[top-2],s[top-1],s[top])}
{ s[ntop]=m(s[top-1],s[top]) }
{ s[ntop]=n(s[top-1],s[top]) }
Valutazione degli attributi
S
S.s=k(1,h(..))
A.i=1
A
A.s=h(1,f(1),m(..),g(..),n(..))
B.i=f(1)
B
C.i=g(1,f(1),m(..))
C
B.s=m(f(1),b.s)
b
C.s=n(g(..),c.s)
c
46
Evaluation of Attributes
stack
M1
M1 M2
M1 M2 b
M1 M2 B
M1 M2 B M3
M1 M2 B M3 c
M1 M2 B M3 C
n(g(..),c.s)
M1 A
S
input
bc$
bc$
bc$
c$
c$
c$
$
$
s-attribute stack
1
1
1
1
1
1
1
$
$
1 h(f(1),m(..),g(..),n(..))
k(1,h(..))
f(1)
f(1)
f(1)
f(1)
f(1)
f(1)
b.s
m(f(1),b.s)
m(f(1),b.s) g(1,f(1),m(f(1),b.s))
m(f(1),b.s) g(1,f(1),m(f(1),b.s)) c.s
m(f(1),b.s) g(1,f(1),m(f(1),b.s))
Problemi
„ Tutti gli L-attributed definitions basati su grammatiche LR non
possono essere valutati durante il parsing bottom-up.
S → { L.i=0 } L
essere
L → { L1.i=L.i+1 } L1 1
up
L → ε { print(L.i) }
Î questo schema di traduzione non può
implementato durante il parsing the bottom-
S → M1 L
Î ma dato che L → ε sara ridotto prima
L → M2 L1 1
dal’analizzatore
L → ε { print(s[top]) }
botton-up il traduttore non puo conoschere il
numero si.
M1 → ε { s[ntop]=0 }
1
M2 → ε { s[ntop]=s[top]+1 }
47
Problemi
„ La grammatica modificata non può essere LR.
L→Lb
L→a
Î
L→MLb
L→a
M→ε
NOT LR-grammar
.
L → . M L b, $
L → . a, $
M → .,a Î shift/reduce conflict
S’ → L, $
48