Traduction dirigée par la syntaxe

Slides:



Advertisements
Présentations similaires
Les Structures.
Advertisements

Chapitre annexe. Récursivité
L-System et modélisation de plantes…
CINEMATIQUE.
Portée des variables VBA & Excel
DTD Sylvain Salvati
Langages objet Définitions Traduction des méthodes en C++
C.
Chap 1 Grammaires et dérivations.
Paramètres et pointeurs
Introduction : Compilation et Traduction
La fonction Style Permet de créer des types de texte, par exemple
8. Les tableaux P. Costamagna – ISEN N1.
Algorithme et programmation
Les sous-programmes Chapitre n° 5: Objectifs : Activité:
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Introduction : Compilation et Traduction
Récursivité.
Points importants de la semaine Les boucles. Les types arithmétiques. Les opérateurs.
Cours d’Algorithmique
OCaml – Les arbres L3 MI.
Les structures de données arborescentes
II. Chaînage, SDD séquentielles
Algèbre de Boole et les Boucles
Analyse lexicale Généralités Expressions rationnelles Automates finis
CSI3525: Concepts des Langages de Programmation Notes # 12: Implementation des Sous-Programmes ( Lire Chapitre 9 )
Création d’un programme :
RESUMES Module II1 SOMMAIRE CYCLE 1 : Saisir – Afficher – Données
Programmation fonctionnelle Le langage LISP
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
Génération de code intermédiaire
LA STRUCTURE D'ARBRE-B Institut National des Sciences Appliquées – Rouen Département Architecture des Systèmes d’Information.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Structures de données IFT-2000
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke Grammaires attribuées.
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
Applications des langages hors-contextes Les analyseurs syntactiques ascendants GNU Yacc et Bison.
Chapitre 3 Syntaxe et sémantique.
Analyse lexicale et syntaxique
Partie II Sémantique.
Programmation logique Le Langage PROLOG
Algorithmique et structures de données en C
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département dinformatique et de génie logiciel Édition Septembre 2009.
Procédures et fonctions
Plan cours La notion de pointeur et d’adresse mémoire.
Structures de données IFT-2000 Abder Alikacem La récursivité Département d’informatique et de génie logiciel Édition Septembre 2009.
Paradigmes des Langages de Programmation
LES PILES ET FILES.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
La fonction RECHERCHEV
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
Arbres binaires et tables de hachage
Tutorat en bio-informatique
Chaînage et LSC : motivation et principe Manipuler la LSC : exemples Variantes : LDC, liste circulaire, … Etude de cas : réalisation d’un buffer clavier.
Tutorat en bio-informatique Le 14 novembre Au programme… Les objets –Propriétés (attributs) –Constructeurs –Méthodes.
Le langage Racket (Lisp)
ISBN Chapitre 10 L'implémentation des sous- programmes.
IUT SRC Année 2004/2005Antonio Capobianco 1 HTML>Formater du texte>Les titres Définir les titres HTML distingue 6 niveaux de titre : Titre N°1 Titre N°2.
1 Deuxième journée La programmation procédurale. 2 Unité de programmation : la procédure ou fonction Très semblable au math Un programme est un ensemble.
Cours LCS N°4 Présenté par Mr: LALLALI
Abdelkader Heni FUNDP Syntaxe et sémantique Abdelkader Heni FUNDP
Les bases de l’algorithmique
Introduction à la compilation
Chap 1 Grammaires et dérivations.
Chap 2. L'analyse descendante
8PRO107 Éléments de programmation Les tableaux. Étude de cas 1 Description du problème : Lire une liste d’entiers et l’afficher d’abord dans le même ordre.
Chaînage et LSC : motivation et principe Manipuler la LSC : exemples Variantes : LDC, liste circulaire, … Etude de cas : réalisation d’un buffer clavier.
Philippe Gandy - 15 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
1 Initiation aux bases de données et à la programmation événementielle VBA sous ACCESS Cours N° 4 Support de cours rédigé par Bernard COFFIN Université.
Informatique 2A Langage C 5ème séance. Déroulement de la séance 5 1 ère partie Étude des chaînes de caractères 2 ème partie Les structures 3.
Transcription de la présentation:

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

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

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

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

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

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

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

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

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é

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

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

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

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

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

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

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)

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

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

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

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

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) }

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

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

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) ; }

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

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

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 

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

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

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)

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('-') }

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) ; }

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

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)

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

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

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

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]

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]

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

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

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]

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

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"