Title: Traduction dirig
1Traduction dirigée par la syntaxe
Grammaires attribuées Attributs
synthétisés Attributs hérités Arbres
syntaxiques Grammaires S-attribuées Grammaires
L-attribuées - schémas de traduction -
traduction descendante - traduction ascendante
2Objectifs
Faire la traduction pendant l'analyse
syntaxique Ajouter des actions portant sur les
attributs des symboles Obtenir un module qui fait
à la fois l'analyse syntaxique et la traduction
en une seule passe Analyse descendante Utiliser
des fonctions qui ont des paramètres et renvoient
des valeurs les attributs Analyse
ascendante La méthode est applicable avec Bison
3Exemple
Grammaire attribuée pour une calculette règle ac
tion L --gt E '\n' print(E.val) E --gt E
T E.val E1.val T.val E --gt T E.val
T.val T --gt T F T.val T1.val F.val T
--gt F T.val F.val F --gt ( E ) F.val
E.val F --gt chiffre F.val chiffre.val
4Numérotation des non-terminaux
E --gt E T E.val E1.val T.val Si la
règle comporte plusieurs fois un même
non-terminal Une occurrence avec un indice dans
l'action correspond à l'occurrence correspondante
dans le membre droit de la règle Une occurrence
sans indice correspond au membre gauche de la
règle
5Arbres décorés
En ajoutant à un arbre de dérivation les
attributs et leurs valeurs, on obtient un arbre
décoré
L
E
.val19
\n
E
.val15
T
.val4
T
.val15
F
.val4
F
.val5
T
.val3
F
.val3
nombre
nombre
.val4
.val5
nombre
.val3
6Grammaires attribuées
- Une grammaire attribuée est définie par
- - une grammaire
- - des attributs associés à chaque symbole
terminal ou non-terminal - - une action associée à chaque règle
- X --gt expr b f(c1, c2, ... ck)
- Une action peut avoir des entrées c1, c2, ... ck
et des sorties b - qui sont des attributs de X et des symboles
formant expr
7Attributs synthétisés ou hérités
X --gt expr b f(c1, c2, ... ck) L'attribut b
est un attribut synthétisé si dans toutes les
actions où il est calculé, c'est un attribut de
X C'est un attribut hérité si dans toutes les
actions où il est calculé, c'est un attribut d'un
des symboles formant expr
8Exemple d'attributs synthétisés
Pour calculer les attributs synthétisés, on monte
dans l'arbre
L
E
.val19
\n
E
.val15
T
.val4
T
.val15
F
.val4
F
.val5
T
.val3
F
.val3
nombre
nombre
.val4
.val5
nombre
.val3
9Exemple d'attributs hérités
Déclaration de variables en C D --gt T L L.type
T.type T --gt int T.type integer T --gt
float T.type real L --gt L , id L1.type
L.type ajouterType(id.entree, L.type) L
--gt id ajouterType(id.entree,
L.type) L'attribut L.type est hérité
10Construction d'un arbre
Une grammaire attribuée qui construit un arbre
représentant une expression arithmétique
.
.
-
.
.
.
id
id
.
num 4
entrée pour c
entrée pour a
11Construction d'un arbre
Fonctions utilisées makeNode(op, left, right)
crée un noeud dont l'étiquette est l'opérateur op
et avec deux champs pour les pointeurs left et
right makeLeaf(id, entree) crée un noeud dont
l'étiquette est id et avec un champ pour un
pointeur vers une entrée de la table des
symboles makeLeaf(num, val) crée un noeud dont
l'étiquette est num et avec un champ pour la
valeur de la constante
12Construction d'un arbre
E --gt E T E.ptr makeNode('', E1.ptr,
T.ptr) E --gt E - T E.ptr makeNode('-',
E1.ptr, T.ptr) E --gt T E.ptr T.ptr T --gt (
E ) T.ptr E.ptr T --gt id T.ptr
makeLeaf(id, id.entree) T --gt num T.ptr
makeLeaf(num, num.val) Les deux attributs E.ptr
et T.ptr contiennent des pointeurs sur des arbres
construits
13Grammaires S-attribuées
Grammaires dont tous les attributs sont
synthétisés Le calcul des attributs peut se faire
dans la pile de l'analyseur ascendant
état ... X Y Z
valeur ... X.x Y.y Z.z
14Exemple
Donnée Pile Valeurs Règle
354 ? -
54 N 3
54 F 3 F --gt N
54 T 3 T --gt F
54 T 3 -
4 T N 3 - 5
4 T F 3 - 5 F --gt N
4 T 15 T --gt T F
S --gt E E --gt E T E --gt T T --gt T
F T --gt F F --gt ( E ) F --gt N
15Grammaires S-attribuées
Calculer les attributs pendant les réductions A
--gt X Y Z A.a f(X.x, Y.y, Z.z) Réduction -
calculer A.a en fonction des valeurs contenues
dans la pile - dépiler X Y Z - empiler A -
sauvegarder A.a dans la pile
état ... X Y Z
valeur ... X.x Y.y Z.z
état ... A
valeur ... A.a
16Exemple
L --gt E '\n' print(valtop-1) E --gt E
T valntop valtop - 2 valtop E --gt
T / inutile de recopier / T --gt T F
valntop valtop - 2 valtop T --gt
F F --gt ( E ) valntop valtop - 1 F
--gt chiffre val pile des valeurs
d'attributs top taille actuelle de la pile ntop
taille de la pile après la réduction en cours
(se déduit de top et de la longueur de la règle)
17Grammaires L-attribuées
Grammaire dans laquelle le calcul des attributs
peut être fait lors d'un parcours en profondeur
de l'arbre de dérivation parcours(noeud n)
pour chaque fils m de n calculer les
attributs hérités de m parcours(m)
calculer les attributs synthétisés de n
18Définition formelle
- Une grammaire est L-attribuée si
- - tout attribut est synthétisé ou hérité
- - dans une règle A --gt X1 X2 ...Xn, si un
attribut Xi.b est calculé dans l'action associée,
il ne dépend que des attributs des variables X1
X2 ...Xi-1 ou des attributs hérités de A
19Exemple le langage EQN
EQN est un langage de composition de texte
permettant d'écrire des formules
mathématiques Chaque formule est contenue dans
une boîte virtuelle Une boîte peut être en indice
d'une autre Dans ce cas le corps de caractères
(taille) de la boîte indice est plus petit De
même pour une boîte en exposant La hauteur d'une
boîte (B.ht) dépend - de la hauteur normale des
caractères (texte.hn) - du corps de caractères
(B.cc) - des indices ou exposants à l'intérieur
20Exemple le langage EQN
S --gt B B.cc 10 S.ht B.ht B --gt B
B B1.cc B.cc B2.cc B.cc B.ht
max(B1.ht, B2.ht) B --gt B sub B B1.cc B.cc
B2.cc diminue(B.cc) B.ht
position(B1.ht, B2.ht) B --gt texte B.ht
texte.hn B.cc diminue() applique un facteur
d'échelle position() modifie la hauteur à cause
de l'indice
21Schémas de traduction
Comme une grammaire attribuée mais précise quand
on fait les actions pendant un parcours de
l'arbre en profondeur Elles sont insérées dans
les membres droits des règles Si une action
calcule un attribut d'un non-terminal du membre
droit, elle doit être placée avant lui Si une
action utilise un attribut d'un non-terminal du
membre droit, elle doit être placée après
lui Exemple traduction postfixe des
expressions additives E --gt T R R --gt addop T
print(addop.lexeme) R ? T --gt num
print(num.val)
22Un schéma de traduction mal formé
S --gt A A A1.val 1 A2.val 2 A --gt a
print(A.val) La deuxième condition n'est pas
satisfaite L'action qui calcule A1.val et A2.val
est placée après
23Le langage EQN
S --gt B.cc 10 B S.ht B.ht B
--gt B1.cc B.cc B B2.cc B.cc
B B.ht max(B1.ht, B2.ht) B --gt B1.cc
B.cc B sub B2.cc diminue(B.cc)
B B.ht position(B1.ht, B2.ht) B --gt
texte B.ht texte.hn B.cc Une grammaire
L-attribuée peut toujours être mise sous la forme
d'un schéma de traduction
24Schémas de traduction en Bison
Dans une spécification Bison, on peut insérer les
actions dans le membre droit des règles Le
traducteur engendré par Bison fera les actions au
moment correspondant E T R R addop T
printf(1) R T num print(1)
25Traduction descendante
Pour l'analyse descendante, on élimine la
récursivité à gauche dans la grammaire Il faut
aussi adapter les attributs Exemple E --gt E
T E.val E1.val T.val E --gt E - T E.val
E1.val - T.val E --gt T E.val T.val T --gt (
E ) T.val E.val T --gt chiffre E.val
chiffre.val
26Elimination de la récursivité à gauche
E --gt T E'.he T.val E' E.val E'.sy
E' --gt T E'1.he E'.he T.val E'
E'.sy E'1.sy E' --gt - T E'1.he E'.he
- T.val E' E'.sy E'1.sy E' --gt ? E'.sy
E'.he T --gt ( E ) T.val E.val T --gt
N T.val N.val L'attribut E'.he sert à
transmettre la valeur de l'expression située à
gauche
27Elimination de la récursivité à gauche
E
E'
.he9
E'
.he4
T
.val9
T
.val5
-
T
.val2
E'
.he6
nombre
.val9
nombre
.val5
nombre
.val2
?
28Traduction descendante
Donnée un schéma de traduction non récursif à
gauche Résultat le code d'un traducteur
descendant Pour chaque non-terminal A,
construire une fonction dont les paramètres sont
les attributs hérités de A et qui renvoie comme
valeur les attributs synthétisés de A (on suppose
qu'il n'y en a qu'un) Le code pour A décide
quelle règle appliquer en fonction du symbole
courant dans la donnée Pour chaque attribut d'une
variable du membre droit, déclarer une variable
locale
29Traduction descendante
Le code associé à une règle parcourt le membre
droit et fait les actions suivantes - pour un
symbole terminal X avec un attribut x,
sauvegarder la valeur de x dans une variable
locale et lire X - pour un non-terminal B, faire
c B(b1, b2, ... bk) où c est l'attribut
synthétisé de B et b1, b2, ... bk sont les
attributs hérités de B - pour une action, faire
l'action
30Traduction ascendante
Le problème est de calculer les attributs
hérités On effectue les actions seulement au
moment où on réduit Dans une règle A --gt X1 X2
...Xn, au moment où on passe Xi, on a dans la
pile X1 X2 ...Xi-1 mais pas A Si un attribut
hérité de Xi dépend d'un attribut de A, quand et
comment le calculer ? on ira le chercher dans la
pile et non dans la règle La méthode présentée
est applicable à certaines grammaires
L-attribuées dont la grammaire sous-jacente est
LR(1)
31Elimination des actions insérées
On remplace le schéma de traduction par une
grammaire L-attribuée en remplaçant certaines
actions par de nouveaux non-terminaux appelés
marqueurs Exemple E --gt T R R --gt T
print('') R - T print('-') R ? T --gt
num print(num.val) devient E --gt T R R
--gt T M R - T N R ? T --gt num
print(num.val) M --gt ? print('') N --gt ?
print('-')
32Schémas de traduction en Bison
Pour traiter un schéma de traduction Bison fait
de même R addop T printf(1) R
devient R addop T M R M
printf(1)
33Schémas de traduction en Bison
La numérotation des symboles dans le membre droit
des règles tient compte des actions Chaque action
compte comme un symbole R addop T
printf(1) R L'attribut de R est
dans 4
34Trouver un attribut dans la pile
A --gt X1 X2 ...Xn Quand on analyse Xi, les
attributs hérités de A sont parfois calculables à
partir d'autres attributs qui sont déjà dans la
pile Exemple D --gt T L L.type T.type T --gt
int T.type integer T --gt float T.type
real L --gt L , id L1.type L.type
ajouterType(id.entree, L.type) L --gt id
ajouterType(id.entree, L.type)
35Trouver un attribut dans la pile
donnée pile règle
int p , q , r ?
p , q , r int
p , q , r T T --gt int
, q , r T id
, q , r T L L --gt id
, r T L , id
, r T L L --gt L , id
r T L ,
T L , id
T L L --gt L , id
D D --gt T L
L.type vient de T.type Le T en question est
toujours juste au-dessous du L dans la pile
36Trouver un attribut dans la pile
On peut donc accéder à une case de la pile
au-dessous de la règle en cours D --gt T L /
inutile de recopier ici / T --gt int valntop
integer T --gt float valntop real L --gt
L , id ajouterType(valtop, valtop-3) /
dans la pile T L , id / L --gt id
ajouterType(valtop, valtop-1) / dans
la pile T id / L'action de la première règle
est effectuée à la fin trop tard pour recopier
l'attribut
37Trouver un attribut dans la pile
Cette méthode est applicable avec Bison D T
L T int INTEGER T
float REAL L L , id
ajouterType(3, 0) / dans la pile T L ,
id / id ajouterType(1, 0) /
dans la pile T id / Pour descendre dans
la pile 0, -1, -2...
38Trouver un attribut dans la pile
S --gt a A C C.he A.sy S --gt b A B C C.he
A.sy C --gt c C.sy f(C.he) Quand on réduit c
vers C, A.sy peut se trouver en valtop-1ou en
valtop-2 Il faut modifier la grammaire S --gt a
A C C.he A.sy S --gt b A B M C M.he A.sy
C.he M.sy M --gt ? M.sy M.he C --gt
c C.sy f(C.he) Quand on réduit c vers C, A.sy
est toujours en valtop-1
39Trouver un attribut dans la pile
S --gt a A C C.he g(A.sy) S --gt b A B C C.he
A.sy C --gt c C.sy f(C.he) On modifie la
grammaire S --gt a A N C N.he A.sy C.he
N.sy N --gt ? N.sy g(N.he) S --gt b A B M
C M.he A.sy C.he M.sy M --gt ? M.sy
M.he C --gt c C.sy f(C.he) Quand on réduit c
vers C, C.he est toujours en valtop-1
40Exemple le langage EQN
S --gt L B B.cc L.cc S.ht B.ht L --gt
? L.cc 10 B --gt B M B B1.cc B.cc M.he
B.cc B2.cc M.sy B.ht
max(B1.ht, B2.ht) .cc corps de caractères 10
points, 12 points... .ht hauteur distance
entre la ligne de pied et le haut de
la boîte .hn hauteur normale d'un caractère
hauteur du caractère lorsqu'il est composé en
corps 1
41Exemple le langage EQN
S --gt L B B.cc L.cc S.ht B.ht L --gt
? L.cc 10 B --gt B M B B1.cc B.cc M.he
B.cc B2.cc M.sy B.ht
max(B1.ht, B2.ht) M --gt ? M.sy M.he B --gt B
sub N B B1.cc B.cc N.he B.cc B2.cc
N.sy B.ht position(B1.ht, B2.ht) N
--gt ? N.sy diminue(N.he) B --gt texte B.ht
texte.hn B.cc
42Exemple le langage EQN
S --gt L B valntop valtop L --gt
? valntop 10 B --gt B M B valntop
max(valtop-2, valtop) / dans la pile L
B M B / M --gt ? valntop valtop-1 /
dans la pile L B / B --gt B sub N B valntop
position(valtop-3, valtop) N --gt
? valntop diminue(valtop-2) / dans
la pile L B sub / B --gt texte valntop
valtop valtop-1 / dans la pile L B /
43Algorithme général
Donnée une grammaire L-attribuée Résultat un
traducteur ascendant On suppose que chaque
non-terminal A a un attribut hérité A.he et que
chaque symbole X a un attribut synthétisé
X.sy Remplacer chaque règle A --gt X1 X2 ...Xn
par A --gt M1 X1 M2 X2 ... Mn Xn Associer les
Xi.he aux Mi Quand on réduit ? vers Mi, la
position de A.he, X1.he X2.he ... dans la pile se
déduit de la nouvelle grammaire
44Résumé
Les schémas de traduction permettent d'incorporer
la traduction à l'analyse syntaxique pour obtenir
un traducteur en une passe Les attributs
synthétisés sont faciles à calculer - analyse
descendante valeurs des fonctions associées aux
non-terminaux de la grammaire - analyse
ascendante dans la pile Les attributs hérités
sont calculés - en analyse descendante comme
paramètres des fonctions - en analyse ascendante
en remontant dans la pile, et s'il le faut en
introduisant des non-terminaux "marqueurs"