La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Traduction dirigée par la syntaxe

Présentations similaires


Présentation au sujet: "Traduction dirigée par la syntaxe"— Transcription de la présentation:

1 Traduction 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

2 Objectifs 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

3 Exemple Grammaire attribuée pour une calculette règle action
L --> E '\n' 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 --> chiffre F.val := chiffre.val

4 Numérotation des non-terminaux
E --> 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

5 Arbres décorés En ajoutant à un arbre de dérivation les attributs et leurs valeurs, on obtient un arbre décoré L E .val=19 \n E .val=15 T + .val=4 T .val=15 F F .val=4 T .val=5 .val=3 * F .val=3 nombre .val=5 nombre .val=4 nombre .val=3

6 Grammaires 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 --> 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

7 Attributs synthétisés ou hérités
X --> 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

8 Exemple d'attributs synthétisés
Pour calculer les attributs synthétisés, on monte dans l'arbre L E .val=19 \n E .val=15 T + .val=4 T .val=15 F F .val=4 T .val=5 .val=3 * F .val=3 nombre .val=5 nombre .val=4 nombre .val=3

9 Exemple d'attributs hérités
Déclaration de variables en C D --> T L L.type := T.type T --> int T.type := integer T --> float T.type := real L --> L , id L1.type := L.type ; ajouterType(id.entree, L.type) L --> id ajouterType(id.entree, L.type) L'attribut L.type est hérité

10 Construction 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

11 Construction 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

12 Construction d'un arbre
E --> E + T E.ptr := makeNode('+', E1.ptr, T.ptr) E --> E - T E.ptr := makeNode('-', E1.ptr, T.ptr) E --> T E.ptr := T.ptr T --> ( E ) T.ptr := E.ptr T --> id T.ptr := makeLeaf(id, id.entree) T --> num T.ptr := makeLeaf(num, num.val) Les deux attributs E.ptr et T.ptr contiennent des pointeurs sur des arbres construits

13 Grammaires 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

14 Exemple Donnée Pile Valeurs Règle 3*5+4$  - *5+4$ N 3 F F --> N T
T --> F 5+4$ T * 3 - +4$ T * N 3 - 5 T * F 15 T --> T * F S --> E $ E --> E + T E --> T T --> T * F T --> F F --> ( E ) F --> N

15 Grammaires S-attribuées
Calculer les attributs pendant les réductions A --> 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

16 Exemple L --> E '\n' print(val[top-1])
E --> E + T val[ntop] := val[top - 2] + val[top] E --> T /* inutile de recopier */ T --> T * F val[ntop] := val[top - 2] * val[top] T --> F F --> ( E ) val[ntop] := val[top - 1] F --> 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)

17 Grammaires 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 ; }

18 Définition formelle Une grammaire est L-attribuée si
- tout attribut est synthétisé ou hérité ; - dans une règle A --> 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

19 Exemple : 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

20 Exemple : le langage EQN
S --> B B.cc := 10 ; S.ht := B.ht B --> B B B1.cc := B.cc ; B2.cc := B.cc ; B.ht := max(B1.ht, B2.ht) B --> B sub B B1.cc := B.cc ; B2.cc := diminue(B.cc) ; B.ht := position(B1.ht, B2.ht) B --> texte B.ht := texte.hn * B.cc diminue() applique un facteur d'échelle position() modifie la hauteur à cause de l'indice

21 Sché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 --> T R R --> addop T { print(addop.lexeme) } R |  T --> num { print(num.val) }

22 Un schéma de traduction mal formé
S --> A A { A1.val := 1 ; A2.val := 2 } A --> 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

23 Le langage EQN S --> { B.cc := 10 } B { S.ht := B.ht }
B --> { B1.cc := B.cc } B { B2.cc := B.cc } B { B.ht := max(B1.ht, B2.ht) } B sub { B2.cc := diminue(B.cc) } B { B.ht := position(B1.ht, B2.ht) } B --> 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

24 Sché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) ; }

25 Traduction descendante
Pour l'analyse descendante, on élimine la récursivité à gauche dans la grammaire Il faut aussi adapter les attributs Exemple 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 --> chiffre E.val := chiffre.val

26 Elimination de la récursivité à gauche
E --> T { E'.he := T.val } E' {E.val := E'.sy } E' --> + T { E'1.he := E'.he + T.val } E' {E'.sy := E'1.sy } E' --> - T { E'1.he := E'.he - T.val } E' {E'.sy := E'1.sy } E' -->  {E'.sy := E'.he } T --> ( E ) {T.val := E.val } T --> N {T.val := N.val } L'attribut E'.he sert à transmettre la valeur de l'expression située à gauche

27 Elimination de la récursivité à gauche
.val=9 - T .val=5 T .val=2 + E' .he=6 nombre .val=9 nombre .val=5 nombre .val=2

28 Traduction 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

29 Traduction 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

30 Traduction 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 --> 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)

31 Elimination 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 --> T R R --> + T { print('+') } R | - T { print('-') } R |  T --> num { print(num.val) } devient : R --> + T M R | - T N R |  M -->  {print('+') } N -->  {print('-') }

32 Sché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) ; }

33 Sché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

34 Trouver un attribut dans la pile
A --> 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 --> T L L.type := T.type T --> int T.type := integer T --> float T.type := real L --> L , id L1.type := L.type ; ajouterType(id.entree, L.type) L --> id ajouterType(id.entree, L.type)

35 Trouver un attribut dans la pile
donnée pile règle int p , q , r $ p , q , r $ int T T --> int , q , r $ T id T L L --> id , r $ T L , id L --> L , id r $ T L , $ D D --> T L L.type vient de T.type Le T en question est toujours juste au-dessous du L dans la pile

36 Trouver un attribut dans la pile
On peut donc accéder à une case de la pile au-dessous de la règle en cours D --> T L /* inutile de recopier ici */ T --> int val[ntop] := integer T --> float val[ntop] := real L --> L , id ajouterType(val[top], val[top-3]) /* dans la pile : T L , id */ L --> id ajouterType(val[top], val[top-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

37 Trouver 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...

38 Trouver un attribut dans la pile
S --> a A C C.he := A.sy S --> b A B C C.he := A.sy C --> c C.sy := f(C.he) Quand on réduit c vers C, A.sy peut se trouver en val[top-1]ou en val[top-2] Il faut modifier la grammaire S --> b A B M C M.he := A.sy ; C.he := M.sy M -->  M.sy := M.he Quand on réduit c vers C, A.sy est toujours en val[top-1]

39 Trouver un attribut dans la pile
S --> a A C C.he := g(A.sy) S --> b A B C C.he := A.sy C --> c C.sy := f(C.he) On modifie la grammaire S --> a A N C N.he := A.sy ; C.he := N.sy N -->  N.sy := g(N.he) S --> b A B M C M.he := A.sy ; C.he := M.sy M -->  M.sy := M.he Quand on réduit c vers C, C.he est toujours en val[top-1]

40 Exemple : le langage EQN
S --> L B B.cc := L.cc ; S.ht := B.ht L -->  L.cc := 10 B --> 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

41 Exemple : le langage EQN
S --> L B B.cc := L.cc ; S.ht := B.ht L -->  L.cc := 10 B --> B M B B1.cc := B.cc ; M.he := B.cc ; B2.cc := M.sy ; B.ht := max(B1.ht, B2.ht) M -->  M.sy := M.he B --> B sub N B B1.cc := B.cc ; N.he := B.cc ; B2.cc := N.sy ; B.ht := position(B1.ht, B2.ht) N -->  N.sy := diminue(N.he) B --> texte B.ht := texte.hn * B.cc

42 Exemple : le langage EQN
S --> L B val[ntop] := val[top] L -->  val[ntop] := 10 B --> B M B val[ntop] := max(val[top-2], val[top]) /* dans la pile : L B M B */ M -->  val[ntop] := val[top-1] /* dans la pile : L B */ B --> B sub N B val[ntop] := position(val[top-3], val[top]) N -->  val[ntop] := diminue(val[top-2]) /* dans la pile : L B sub */ B --> texte val[ntop] := val[top] * val[top-1]

43 Algorithme 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 --> X1 X2 ...Xn par A --> 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

44 Ré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"


Télécharger ppt "Traduction dirigée par la syntaxe"

Présentations similaires


Annonces Google