Analyse  Syntactique (Compilers, Principles, Techniques and Tools, Aho, Sethi et Ullman, 1986)

Slides:



Advertisements
Présentations similaires
Sintaks : Tentative de guide de mise en œuvre Michel Hassenforder.
Advertisements

LES NOMBRES PREMIERS ET COMPOSÉS
Chap. 4 Recherche en Table
Chapitre annexe. Récursivité
Fonctions & procédures
Les Prepositions.
GEF 435 Principes des systèmes d’exploitation
GEF 243B Programmation informatique appliquée Listes chaînées II §15.1 – 15.2.
24 septembre 2007Cours de compilation 4 - Intranet1 Cours de compilation Techniques danalyse descendantes.
Les éléments de mémorisation
La diapo suivante pour faire des algorithmes (colorier les ampoules …à varier pour éviter le « copiage ») et dénombrer (Entoure dans la bande numérique.
Chap 1 Grammaires et dérivations.
Introduction : Compilation et Traduction
IFT313 Introduction aux langages formels
Traitement Co-Séquentiel: Appariment et Fusion de Plusieurs Listes
Mr: Lamloum Med LES NOMBRES PREMIERS ET COMPOSÉS Mr: Lamloum Med.
IFT313 Introduction aux langages formels
Introduction : Compilation et Traduction
1 Cours numéro 3 Graphes et informatique Définitions Exemple de modélisation Utilisation de ce document strictement réservée aux étudiants de l IFSIC.
Récursivité.
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
Les structures de données arborescentes
II. Chaînage, SDD séquentielles
Analyse lexicale Généralités Expressions rationnelles Automates finis
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
1 SERVICE PUBLIC DE LEMPLOI REGION ILE DE France Tableau de bord Juillet- Août 2007.
IFT313 Introduction aux langages formels
1.2 COMPOSANTES DES VECTEURS
SELECT {* | Expression [Alias] [,...] } FROM Table [WHERE Condition] [ORDER BY { Expression | Alias } [ ASC | DESC ] [NULLS FIRST | NULLS LAST ] [,...]
Tableaux de distributions
Tableaux de distributions
F Copyright © Oracle Corporation, Tous droits réservés. Créer des programmes avec Procedure Builder.
LES NOMBRES PREMIERS ET COMPOSÉS
VOC 1 CE2 Je sais utiliser des mots de la vie quotidienne.
1.3 COORDONNÉES DES POINTS
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.
IFT313 Révision finale Département d’informatique
IFT313 Introduction aux langages formels
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke Analyseurs récursifs LL (1)
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke Automates à pile LR Notion de poignée.
Expressions régulières et hash tables
Représentation des systèmes dynamiques dans l’espace d’état
Représentation des systèmes dynamiques dans l’espace d’état
Courbes de Bézier.
Gestion de Fichiers Tri Interne Efficace et Tri Externe.
1 CSI3525: Concepts des Languages de Programmation Notes # 3: Description Syntaxique des Languages.
1.1 LES VECTEURS GÉOMÉTRIQUES
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.
Gestion de Fichiers GF-10: Traitement Co-Sequentiel: Appariment et Fusion de Plusieures Listes (Base sur les sections de Folk, Zoellick & Riccardi,
Résoudre une équation du 1er degré à une inconnue
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département dinformatique et de génie logiciel Édition Septembre 2009.
Programmation linéaire en nombres entiers : les méthodes de troncature
Structures de données IFT-2000 Abder Alikacem La récursivité Département d’informatique et de génie logiciel Édition Septembre 2009.
ASI 3 Méthodes numériques pour l’ingénieur
Mise en forme en Mathématiques
ECOLE DES HAUTES ETUDES COMMERCIALES MARKETING FONDAMENTAL
Expressions régulières et hash tables
Paradigmes des Langages de Programmation
LES PILES ET FILES.
Les Chiffres Prêts?
Partie II: Temps et évolution Energie et mouvements des particules
D.E ZEGOUR Ecole Supérieure d’Informatique. Problèmes de décision Concepts de base Expressions régulières Notation particulière pour exprimer certaines.
Le langage Racket (Lisp)
Abdelkader Heni FUNDP Syntaxe et sémantique Abdelkader Heni FUNDP
Chap 1 Grammaires et dérivations.
Chap 2. L'analyse descendante
Transcription de la présentation:

Analyse  Syntactique (Compilers, Principles, Techniques and Tools, Aho, Sethi et Ullman, 1986)

Compilateurs Un compilateur est un programme qui lit un programme écrit dans une langue (la langue source) et produit un programme écrit dans une autre langue (la langue cible). Un compilateur utilise plusieurs étapes. Chaque étape transforme le programme source en une autre représentation. Programme source Analyseur lexical  Analyseur Syntactique Analyseur Sémantique  Générateur de Code Intermédiaire  Optimiseur de Code  Générateur de Code  Programme objectif Pour cette partie de cours, nous allons nous concentrer sur l’Analyseur Syntactique

Analyse Syntactique L’analyse syntactique est le processus qui détermine si une chaine de jetons peut être produite par une grammaire. Il y a deux types principaux de méthodes d’ analyse syntactique – ascendant (de bas en haut) et descendent (de haut en bas). Pour l’analyse syntactique descendante, on commence à la racine et procède vers les noeuds terminaux. Pour analyse syntactique ascendante, on commence aux noeuds terminaux et procède vers la racine. Il est facile de construire des analyseurs descendant efficaces à la main. L’Analyse syntactique ascendante est plus flexible et on peut l’utiliser avec plus de classes de grammaires. Mais il est plus difficile de la développer. Par contre, il y a des outils disponible pour générer des parseurs directement, a partir de la grammaire.

Partie I Analyse Syntactique Descendante Idées fondamentales de l’Analyse Syntactique Descendante L’Analyse Syntactique Descendante prédictive Grammaires recursives a gauche Factorisation sur la gauche Construire un Analyseur Syntactique Grammaires LL(1)

Idées fondamentales de l’Analyse Syntactique Descendante Pour l’Analyse Syntactique Descendante, on essaye de trouver un dérivation a gauche pour la chaîne d'entrée. Exemple: S  cAd Trouvez un dérivation A  ab | a pour w  cad S S Backtrack S / | \  / | \  / | \ c A d c A d c A d / \ | a b a

Analyseur Syntactique Prédictif : Généralités Dans la majorité des cas, si on écrit la grammaire très soigneusement, on peut éliminer la recursion de gauche et faire une factorisation a gauche de la grammaire qui en résulte. Ceci nous permet d’obtenir une grammaire que l'on peut analyser syntactiquement avec un analyseur syntactique récursif descendent qui n'a pas besoin de backtracking. Cette classe de compilateur s’appelle un analyseur syntactique prédictif.

Grammaires Récursives a Gauche I Une grammaire est récursive a gauche si il y a un noeud non terminal A et il y a une dérivation A  Aα pour n’importe quelle chaîne α. Les Analyseurs Syntactiques descendants peuvent entrer dans une boucle infinie en presence de règles récursives a gauche. Donc, on doit les éliminer. On peut éliminer une règle récursive a gauche comme A  A α | β si on peut la remplacer par : A  β R ou R est un nouveau noeud non terminal R  α R | є et є est la chaîne vide. La nouvelle grammaire est récursive a droite.

Grammaires Récursives a Gauche II Si vous avez une récursion a gauche directe—c’est-à-dire, si la récursion se produit a l’interieure d’une seule règle—On peut l’ éliminer de la manière suivante: Groupez les règles A  Aα1 |… | Aαm | β1 | β2 |…| βn Assurez-vous qu’aucun des β’s commence par A Remplacez les A-règles originales par A  β1A’ | β2 A’ | … | βn A’ A’  α1 A’ | α2 A’ | … | αm A’ Ce procédé n'éliminera pas la récursion a gauche indirecte de la sorte A  BaA B  Ab [Il y a un autre procédé mais nous ne le discutons pas ici] La récursion a gauche directe ou indirecte est problématique pour tous les analyseurs descendents. Cependant, ce n'est pas un problème pour des algorithmes d'analyse ascendants.

Grammaires Récursives a Gauche III Voici un exemple d'une grammaire avec récursion a gauche directe: E  E + T | T T  T * F | F F  ( E ) | id Cette grammaire peut être réécrite comme la grammaire non récursive a gauche suivante: E  T E’ E’  + TE’ | є T  F T’ T’  * F T’ | є F  (E) | id

Factorisation a Gauche d'une Grammaire I La récursion a gauche n'est pas le seul trait qui empêche l'analyse descendante. Un autre est la question de savoir si l'analyseur peut toujours choisir le côté droit correct par seule analyse du jeton d'entrée suivant; c’est a dire, en utilisant seulement le premier jeton produit par le non terminal d’extrême gauche dans la dérivation courante. Pour s'assurer que c'est possible, nous avons besoin de factoriser a gauche la grammaire produite a l'étape précédente (qui n’est plus récursive a gauche).

Gauche-Factorisation d'une Grammaire II Voici le procédé utilisé pour factoriser une grammaire a gauche: Pour chacun des non terminaux A, trouvez le plus long préfixe α commun à deux ou à plus de ses alternatives. Remplacez toutes les A-productions: A  αβ1 | αβ2 … | αβn | γ (ou γ représente toutes les alternatives qui ne commencent pas avec α) par: A  α A’ | γ A’  β1 | β2 | … | βn

Gauche-Factorisation d'une Grammaire III Voici un exemple d'une grammaire qui a besoin d’etre factorisee a gauche: S  iEtS | iEtSeS | a E  b ( i = “if”; t = “then”; et e = “else”) Apres la factorisation a gauche cette grammaire devient : S  iEtSS’ | a S’  eS | є

Analyseur Syntactique Prédictif : Détails Le problème principal pendant l'analyse prédictive est celui de déterminer la production à appliquer pour un non terminal. Ceci est fait en employant une table d'analyse. Une table d'analyse est un tableau bidimensionnel M[A,a] où A est un non terminal, et a est un terminal ou le symbole $ qui signifie “fin de chaîne d’entrée”. Les autres entrées d’un Analyseur Syntactique Prédictif sont : La mémoire tampon d’entrée, qui contient la chaîne à analyser suivie de $. La pile qui contient une sequence de symboles de grammaire avec, au depart, simplement $S (la fin de la chaîne d’entrée et le symbole de départ).

Analyseur Syntactique Prédictif : Procédé Informel L’Analyseur Syntactique Prédictif utilise X, le symbole sur le dessus de la pile, et a, le symbole d’entrée suivant. Il utilise egalement M, la table d'analyse. Si X=a=$  arrêter et retourner: succès Si X=a≠$  Enlever X de la pile et avancer le pointeur d’entrée vers le prochain symbole Si X est un non terminal  consulter M[X,a] Si l’élément est un regle de production, remplacer X sur la pile avec le côté droit de la production Si l’élément est vide, arrêter et retourner: echec

Analyseur Syntactique Prédictif : Un Exemple Pile Entrèe Sortie $E id+id*id$ $E’T E  TE’ $E’T’F T  FT’ $E’T’id F  id $E’T’ +id*id$ $E’ T’  є $E’T+ E’  +TE’ id*id$ *id$ $E’T’F* T’  *FT’ id$ $ E’  є Analyseur Syntactique Prédictif : Un Exemple id + * ( ) $ E ETE’ E’ E’+TE’ E’є T T FT’ TFT’ T’ T’є T’*FT’ F Fid F(E) Table d'analyse Trace de l’Algorithme 

Construire la Table D'analyse I: First et Follow First(α) est l'ensemble des terminaux qui sont a la tete de la chaîne α. Follow(A) est l'ensemble des terminaux a qui peuvent être tout de suite à la droite de A. First et Follow sont employés dans la construction de la table d'analyse. Construire First: Si X est un terminal, alors First(X) est {X} Si X  є est une production, alors ajoutez є à First(X) Si X est un non terminal et X  Y1 Y2 … Yk est une production, alors placez a dans First(X) si, pour quelque i, a est dans First(Yi) et є est dans tous les First(Y1)… First(Yi-1)

Construire le Table D'analyse II: First et Follow Construire Follow: Mettre $ dans Follow(S), où S est le symbole de départ et $ est le symbole de fin de chaîne. Si il y a une production A  αBβ, alors tout le contenu de First(β) sauf є est mis dans Follow(B). Si il y a un production A  αB ou une production A  αBβ et First(β) contient є, alors tout le contenu de Follow(A) est dans Follow(B) Exemple: E  TE’ E’  +TE’ | є T  FT’ T’  *FT’ | є F  (E) | id First(E) = First(T) = First(F) = {(, id} First(E’) = {+, є} First(T’) = {*, є} Follow(E) = Follow(E’) = {),$} Follow(F)={+,*,),$} Follow(T) = Follow(T’) = {+,),$}

Construire la Table D'analyse III Algorithme pour construire une table d'analyse prédictive: Pour chaque A  α de la grammaire, fait étapes 2 et 3 Pout chaque terminal a dans First(α), ajouter A  α à M[A, a] Si є est dans First(α), ajouter A  α à M[A, b] pour chaque terminal b dans Follow(A). Si є est dans First(α), ajouter A  α à M[A,b] pour chaque terminal b dans Follow(A). Si є est dans First(α) et $ est dans Follow(A), ajouter A  α à M[A, $]. Chaque élément indéfini de M est une erreur.

LL(1) Grammaires Une grammaire avec un table d'analyse qui n'a aucune entrée contenant plus d’une définition s'appelle LL(1) Aucune grammaire ambiguë ou récursive a gauche ne peut être LL(1). Une grammaire G est LL(1) si et seulement si dans tous les cas ou A  α | β sont deux productions distinctes de G, les conditions suivantes sont verifiees: Il n’y a aucun terminal a pour lequel α ainsi que β dérivent des chaînes commençant par a α ou β peut dériver la chaîne vide, mais les deux ne peuvent pas le faire simultanement. Si β peut (directement ou indirectement) dériver є, alors α ne peut pas dériver de chaîne qui commence avec un terminal appartenant a Follow(A).

Partie II Analyseur Syntactique Ascendant Il y a différentes approches à l'analyse ascendante . Une approche s’appelle Shift-Reduce parsing. Cette approche peut, en outre, prendre des formes diverses. L’Une de ces méthode s’appelle Operator-precedence parsing. Cependent, elle n’est pas tres generale. Une autre methode: LR-Parsing l’est beaucoup plus. Dans ce cours, nous nous concentrerons sur le LR-Parsing. LR-Parsing prend, lui-meme, trois formes : Simple LR-Parsing (SLR) une version simple mais limitée; le LR canonique, la version la plus puissante, mais la plus chère ; et LALR qui est intermédiaire en coût et puissance. Nous allons nous concentrer, ici, sur le SLR.

LR-Parsing : Avantages Le LR Parsing peut identifier n'importe quelle langue pour laquelle une grammaire libre de contexte peut être écrite. Le LR parsing est la methode la plus générale de parsing. Cependant, elle est aussi efficace que toute autre approche Shift-Reduce. La classe de grammaires qui peuvent être analysées parle LR Parsing contient la classe de grammaires qui peut être analysé par un analyseur prédictif et est plus vaste. Le LR-Parsing peut détecter une erreur syntactique dès qu'il sera possible de le faire pendant un scan de gauche à droite de l'entrée.

LR-Parsing: Inconvénient/Solutions L'inconvénient principal du LR-Parsing est que, pour une grammaire typique de langage de programmation, sa construction à la main demande trop de travail. Heureusement, des outils spécialisés pour construire des parseur LR automatiquement ont été conçus. Avec de tels outils, un utilisateur peut écrire une grammaire libre de contexte et la passer dans un générateur de compilateur automatique afin de produire un parseur pour cette grammaire. Un exemple d'un tel outil est Yacc “Yet Another Compiler-Compiler"

Algorithmes de LR-Parsing : Détails I Un Parseur LR se compose d'une entrée, d’une sortie, d'une pile, d'un programme pilote et d'une table d'analyse a deux parties : action et goto. Le programme pilote est le même pour tous les parseurs LR. Seule la table d'analyse change d'un parseur a l’autre. Le programme emploie la pile pour stocker une chaîne de la forme s0X1s1X2…Xmsm, ou sm est le dessus de la pile. Les Sk‘s sont des symboles d’état et les Xi‘s sont des symboles de grammaire . Ensemble, les symboles d'état et de grammaire déterminent les décisions des parseurs LR.

Algorithmes de LR-Parsing : Détails II La table d'analyse se compose de deux parties : une fonction d'action du Parseur et une fonction goto. Le programme de Parsing LR détermine sm, l'état sur le dessus de la pile et ai, l'entrée courante. Il consulte alors l'action[sm, ai] ce qui peut prendre une des quatre valeurs suivantes: Shift Reduce Accept Error

Algorithmes de LR-Parsing : Détails III Si l’action[sm, ai] = Shift s, Décalez s, où s est un état et poussez ai et s sur le haut de la pile. Si l’action[sm, ai] = Reduce A  β, alors ai et sm sont remplaces par A, et, si s était l'état au-dessous de ai dans la pile , alors goto[s, A] est consulté et l'état qu'il stocke est poussé sur la pile. Si l’action[sm, ai] = Accept, alors l’analyse est accomplie. Si action[sm, ai] = Error, alors l'analyseur a découvert une erreur.

Algorithmes de LR-Parsing Exemple: La Grammaire E  E + T E  T T  T * F T  F F  (E) F  id

Algorithmes de LR-Parsing Exemple : La Table d’Analyse State Action Goto id + * ( ) $ E T F s5 s4 1 2 3 s6 Acc r2 s7 r4 4 8 5 r6 6 9 7 10 s11 r1 R1 r3 11 r5

Algorithmes de LR-Parsing Exemple : Trace du programme Pile Entrée Action id * id + id $ Shift (2) 0 id 5 * id + id $ Reduce by F  id (3) 0 F 3 Reduce by T  F (4) 0 T 2 (5) 0 T 2 * 7 id + id $ (6) 0 T 2 * 7 id 5 + id $ (7) 0 T 2 * 7 F 10 Reduce by T  T * F (8) 0 T 2 Reduce by E T (9) 0 E 1 (10) 0 E 1 + 6 id $ (11) 0 E 1 + 6 id 5 $ (12) 0 E 1 + 6 F 3 (13) 0 E 1 + 6 T 9 E  E + T (14) 0 E 1 Accept

Analyse SLR I Definition: Un article LR(0) d'une grammaire G est une production de G avec un point à une position particuliere du côté droit. Exemple: A  XYZ produit les quatre articles suivants: A  .XYZ A  X.YZ A  XY.Z A  XYZ. La production A  є produit un seul article , A  . Intuitivement, un article indique quel montant de la production nous avons vu à un point precis dans le processus d'analyse.

Analyse SLR II Pour créer une table d'analyse de SLR, nous définissons trois nouveaux éléments: Une grammaire augmentée pour G, la grammaire initiale. Si S est le symbole de départ de G, nous ajoutons la production S’  .S . Le but de cette nouvelle production est d'indiquer à l'analyseur quand il doit cesser l’analyze et accepter l'entrée. L'opération de fermeture (The closure operation) la fonction goto

Analyse SLR II : L'opération de fermeture Si I est un ensemble d'articles pour une grammaire G, alors closure(I) est l'ensemble d'articles construits a partir de I par les deux règles suivantes: Au commencement, chaque article de I est ajouté a closure(I) Si A  α . B β est dans closure(I) et B  γ est une production, alors ajouter l’article B  . γ à I, s'il n'est pas déjà present. Nous appliquerons cette règle jusqu'à ce qu’il n’y ait plus de nouveaux articles a ajouter a closure(I).

Analyse SLR : L'opération de fermeture– Example Grammaire Originale Grammaire augmentée 0. E’  E E  E + T 1. E  E + T E  T 2. E  T T  T * F 3. E  T * F T  F 4. T  F F  (E) 5. F  (E) F  id 6. F  id Si I = {[E’  E]} alors Closure(I)= { [E’  .E], [E  .E + T], [E  .T], [E  .T*F], [T  .F], [F  .(E)] [F  .id] }

Analyse SLR : L'opération Goto Goto(I,X), où I est un ensemble d'articles et X est un symbole de grammaire, est défini comme la fermeture de l'ensemble de tous les articles [A  αX.β] tels que[A  α.Xβ] est dans I. Exemple: Si I est l'ensemble de deux articles {E’  E.], [E  E.+T]}, alors goto(I, +) se compose de E  E + .T T  .T * F T  .F F  .(E) F  .id

Analyse SLR : Construction d’ensembles d'articles procedure articles(G’) C = {Closure({[S’  .S]})} Répétez Pour chaque ensemble de points I en C et chaque symbole X de grammaire tels que goto(I,X) n’est pas vide et pas en C, faites: ajoutez goto(I,X) à C Jusqu'à qu’aucun nouvel ensemble d'articles ne peut être ajouté à C

Exemple: La collection canonique LR(0) pour la grammaire G I0: E’  .E I4: F  (.E) I7: T  T * .F E  .E + T E  .E + T F  .(E) E  .T E  .T F  .id T  .T * F T  .T * F I8: F  (E.) T  .F T  .F E  E.+T F  .(E) F  .(E) I9: E  E + T. F  .id F  .id T  T.* F I1: E’  E. I5: F  id. I10: T  T*F. E  E.+T I6: E  E+.T I11: F  (E). I2: E  T. T  .T*F T  T. * F T  .F I3: T  F. F  .(E) F  .id

Construction d'une Table d'analyse de SLR Construire C={I0, I1, … In} la collection d'ensembles de d’ articles LR(0) pour G’ L'état i est construit a partir de Ii. Les actions d'analyse pour l'état i sont déterminées comme suit: Si [A  α.aβ] est dans Ii et goto(Ii,a) = Ij, alors action[i,a] devient “shift j”. Ici a doit être un terminal. Si [A  α.] est dans Ii, alors action[i, a] devient “réduce A  α” pour tout les a dans Follow(A); Ici A ne peut pas être S’. Si [S’  S.] est dans Ii, alors action[i,$] devient “accept” Si des actions contradictoires sont produites par les règles ci-dessus, nous disons que la grammaire n'est pas SLR(1). L'algorithme alors ne produit pas d’analyseur.

Construction d'une Table d'analyse de SLR (cont’d) 3. Les transitions goto pour l'état i sont construites pour tous les nonterminaux A en utilisant la règle: Si goto(Ii, A) = Ij, alors goto[i, A] = j. 4. Toutes les entrées non définies par les règles (2) et (3) deviennent des erreurs. 5. L'état initial de l'analyseur est celui qui a ete construit a partir de l'ensemble d'articles contenant [S’  S]. Voir l'exemple en classe