Chap 2. L'analyse descendante

Slides:



Advertisements
Présentations similaires
Explorer un espace d’états
Advertisements

Chapitre annexe. Récursivité
3. Variantes de l’algorithme
Sensibilisation à l’Algorithmique et structure de données
GEF 435 Principes des systèmes d’exploitation
24 septembre 2007Cours de compilation 4 - Intranet1 Cours de compilation Techniques danalyse descendantes.
Système formel Nous avons introduit : signes de variables (x, y, z, …), de constantes (0, 1), d’opérations (+, ), de relations (=, ) Axiomes : ce sont.
Chap 1 Grammaires et dérivations.
INTRODUCTION.
Introduction : Compilation et Traduction
Expressions rationnelles
La fonction Style Permet de créer des types de texte, par exemple
IFT313 Introduction aux langages formels
Utilisation des tableaux
IFT313 Introduction aux langages formels
Les bases de l’Algorithmique
IFT313 Introduction aux langages formels
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Structures de données linéaires
Introduction : Compilation et Traduction
Analyse  Syntactique (Compilers, Principles, Techniques and Tools, Aho, Sethi et Ullman, 1986)
Démarche de résolution de problèmes
IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.
Algorithmes Branch & Bound
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.
IFT313 Introduction aux langages formels
Programmation linéaire
Programmation logique Démonstrateur automatique
Bases de données lexicales
Algorithmique et Programmation
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 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke Révision de mi-session.
IFT313 Révision finale Département d’informatique
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.
Chapitre 3 Machines de Turing.
IFT Complexité et NP-complétude
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.
Traduction dirigée par la syntaxe
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
Mise en oeuvre des MMCs L'utilisation des MMCs en reconnaissance des formes s'effectue en trois étapes : définition de la topologie de la chaîne de Markov,
Partie II Sémantique.
Programmation dynamique
Le GRAFCET GRAphe Fonctionnel de Commande par Etapes et Transitions
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.
Programmation procédurale Transformations
Paradigmes des Langages de Programmation
INTRODUCTION.
Programmation linéaire en nombres entiers
Arbres binaires et tables de hachage
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.
GF-11: Tri Interne Efficace et Tri Externe
Exploration systématique de graphes
ISBN Chapitre 10 L'implémentation des sous- programmes.
Structures de données avancées : LH (Hachage linéaire) D. E ZEGOUR Institut National d ’Informatique.
Abdelkader Heni FUNDP Syntaxe et sémantique Abdelkader Heni FUNDP
Chap 1 Grammaires et dérivations.
La pile de crêpes.
Les bascules et registres
Algorithmes Branch & Bound Module IAD/RP/RO Master d ’informatique Paris 6 Philippe Chrétienne.
Cycle, Cocycle, Arbre et Arborescence
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é.
Transcription de la présentation:

Chap 2. L'analyse descendante Nous introduisons les idées de base sous-tendant l'analyse descendante efficace et montrons comment construire un analyseur syntaxique efficace, sans rebroussement, appelé analyseur prédictif. Nous définissons la classe des grammaires LL(1) à partir desquelles on peut construire automatiquement des analyseurs prédictifs. L'analyse descendante peut être considérée comme une tentative pour déterminer une dérivation gauche associée à une chaîne d'entrée.

L’analyse récursive La forme générale d'analyse descendante appelée descente récursive peut impliquer des retours arrière, c.à.d. nécessiter des passages répétés sur le texte source. Cependant, les analyseurs avec rebroussement ne sont pas très fréquents. Une des raisons est que le rebroussement est rarement nécessaire pour analyser les constructions des langages de programmation. Pour des situations comme analyse des langues naturelles, le rebroussement n'est pas très efficace et on lui préfère d'autres méthodes.

Exemple Grammaire : ScAd Aab|a la chaîne d'entrée w = cad. S S c A d c A d a b a

Suppression de la récursivité à gauche. Une grammaire est récursive à gauche si elle contient un non-terminal A tel qu'il existe une dérivation A  A, où  est une chaîne quelconque. Les méthodes d'analyse descendante ne peuvent pas fonctionner avec les grammaires récursives à gauche ; on a donc besoin d'une transformation grammaticale qui élimine cette récursivité à gauche. On peut éliminer une production récursive à gauche en la réécrivant.

expr  expr + terme | terme Considérons le non-terminal A dans les deux productions :   A  A |   où  et  sont des suites de terminaux et de non-terminaux qui ne commencent pas par A. Par exemple, dans : expr  expr + terme | terme  A = expr,  = + terme et  = terme. Le non-terminal A est récursif à gauche car la production A  A contient A comme symbole le plus à gauche de sa partie droite. Une application répétée de cette production fabrique une suite de  à droite de A : A   A   A   A      . . …… 

Quand A is finalement remplacé par , nous avons  suivi par une sequence de 0 ou plus . On peut obtenir le même effet, en réécrivant la production définissant A de la manière suivante : AR RR |  Ici R est un nouveau non-terminal. A  R  R ……………………  R  R 

Exemple Grammaire d’expressions arithmétiques: E E + T | T T T * F | F F (E) | id. Suppression de la récursivité à gauche. E TE' E' + TE' |  T FT' T' * FT' | 

Peu importe combien il y en a des A-productions, nous pouvons toujours éliminier la récursivité à gauche. A A 1 | A2 | …| Am | 1 | 2 | …| n ou aucun i ne commence avec A. Nous remplaçons les A-productions de la façon suivante. A 1A' | 2A' | … |nA' A'1A' | 2A' | … |mA' |  Le non-terminal A génère exactement les mêmes chaînes.

Analyse prédictif non-récursif Il est possible de construire un analyseur prédictif non récursif en tenant à jour une pile explicite, plutôt que la pile implicite résultant des appels récursifs. Le problème clé de l'analyse prédictive est la détermination de la production à appliquer pour développer un non-terminal. L'analyseur non récursif recherche la production à appliquer dans une table d'analyse.

Entrée a + b $ Analyseur prédictif X Y Table d’analyse M Z Pile Sortie   Entrée a + b $  Analyseur prédictif Pile X   Sortie Y  Table d’analyse M Z

Un analyseur syntaxique prédictif dirigé par table possède un tampon d’entrée, une pile, une table d’analyse et un flot de sortie. Le tampon d’entrée contient la chaîne à analyser, suivie de $, symbole utilisé comme marqueur de fin. La pile contient une séquence de symboles grammaticaux, avec $ marquant le fond de la pile. Initialement, la pile contient l’axiome de la grammaire au-dessus du $. La table d’analyse est un tableau à deux dimensions M[A,a] ou A est un non-terminal et a est un terminal ou un $.

L’analyse syntaxique est contrôlée par un programme qui a le comportement suivant. Ce programme considère X, le symbole en sommet de pile et a, le symbole d’entrée courant. Ces deux symboles déterminent l’action de l’analyseur. Il y a 3 possibilités : SI X = a = $, l’analyseur s’arrête et annonce la réussite finale de l’analyse. SI X = a <> $, l’analyseur enlève X de la pile et avance son pointeur d’entrée sur le symbole suivant. SI X est un non-terminal, le programme consulte l’entrée M[X,a] de la table d’analyse M. Cette entrée sera soit une X-production de la grammaire soit une erreur. Si, par exemple, M[X,a] = {X  UVW}, l’analyseur remplace X en sommet de pile par WVU (avec U au sommet). L’analyseur se contente, pour tout résultat, d’imprimer la production utilisée : n’importe quelle autre action pourrait être exécutée à la place. Si M[X,a]=erreur, l’analyseur appelle une procédure de récupération sur erreur. Le comportement de l’analyseur peut se décrire en termes de ses configurations, qui décrivent le contenu de sa pile et le texte d’entrée restant.

Algorithme de l’analyse prédictive non récursive. Donnée : Une chaîne w et une table d’analyse M pour une grammaire G. Résultat : Si w est dans L(G), une dérivation gauche pour w ; sinon, une indication d’erreur. Méthode : Initialement, l’analyseur est dans une configuration dans laquelle il a $S dans sa pile avec S, l’axiome de G au sommet et w$ dans son tampon d’entrée.

Programme d'analyse syntaxique prédictive Positionner le pointeur source ps sur le premier symbole de w$. Répéter Soit X le symbole en sommet de pile et a le symbole repéré par ps ; Si X est un terminal ou $ alors Si X=a alors Enlever X de la pile et avancer ps Sinon Erreur() Sinon /* X est un non-terminal */ Si M[X,a]=XY1Y2…Yk alors début Enlever X de la pile ; Mettre Yk, Yk-1,…, Y1 sur la pile, avec Y1 au sommet ; Emettre en sortie la production XY1Y2…Yk Fin Jusqu'à X=$ /* la pile est vide */

Exemple Considérons la grammaire : E  E + T | T T  T * F | F F  (E) | id Eliminons la récursivité à gauche : E  T E' E'  + T E' |  T  F T' T'  * F T' | 

Non-terminal Symbole d'entrée id + * ( ) $ E E  TE' E’ E’ ε T   E’ E’ +TE' E’ ε T T  FT' T’ T’ ε T ‘ *FT' F F  id F  (E)

Sur la chaîne source id + id Sur la chaîne source id + id * id l'analyseur prédictif effectue la séquence d'entrée suivante : 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$ F id $ T'   E'  

PREMIER et SUIVANT La construction d’un analyseur Synt. Préd. est facilitée par 2 fonctions associées à une grammaire G. Ces fonctions PREMIER et SUIVANT, nous permettent, quand c’est possible, de remplir les entrées de la table d’analyse prédictive pour G. Si α est une chaîne de symboles grammaticaux, PREMIER(α) désigne l’ensemble des terminaux qui commencent les chaînes qui se dérivent de α. Si αε, alors ε est aussi dans PREMIER(α). Pour chaque non-terminal A, SUIVANT(A) définit l’ensemble des terminaux a qui peuvent apparaître immédiatement à droite de A dans une protophrase, c.a.d. l’ensemble des terminaux a tels qu’il existe une dérivation de la forme S αAaβ où α et β sont de chaînes de symboles grammaticaux. Si A peut être le symbole le plus à droite d’une proto-phrase, alors $ est dans SUIVANT(A).

Pour calculer PREMIER(X), pour tout symbole de la grammaire X, appliquer les règles suivantes jusqu’à ce qu’aucun terminal ni ε ne puisse être ajouté aux ensembles PREMIER. 1. Si X est un terminal, PREMIER(X) est {X} 2. Si X ε est une production, ajouter ε à PREMIER(X). 3. Si X est un non-terminal et XY1Y2…Yk une production, mettre a dans PREMIER(X) s’il existe i tel que a est dans PREMIER(Yi) et ε est dans tous les PREMIER(Y1), …, PREMIER(Yi-1), c.a.d. Y1…Yi-1 ε. Si ε est dans PREMIER(Yj) pour tous les j=1,…,k, ajouter ε à PREMIER(X), mais si Y1 ε, on ajoute PREMIER(Y2), etc.

On peut calculer PREMIER pour une chaîne X1X2…Xn de la façon suivante On peut calculer PREMIER pour une chaîne X1X2…Xn de la façon suivante. Ajouter à PREMIER(X1X2…Xn) tous les symboles de PREMIER(X1). Si ε est dans PREMIER(X1), ajouter également les symboles de PREMIER(X2) différents de ε. Si ε est dans PREMIER(X1) et également dans PREMIER(X2) ajouter également les symboles de PREMIER(X3) différents de ε, etc. Finalement, si quel que soit i, PREMIER(Xi) contient ε, ajouter ε à PREMIER(X1X2…Xn).

Pour calculer SUIVANT(A) pour tous les non-terminaux A, appliquer les règles suivantes jusqu’à ce qu’aucun terminal ne puisse être ajouté aux ensembles SUIVANT. 1.Mettre $ dans SUIVANT(S), où S est l’axiome et $ est le marqueur de fin. 2. S’il y a une production AαBβ, le contenu de PREMIER(β) excepté ε, est ajouté à SUIVANT(B). 3. S’il existe une production AαB ou une production AαBβ telle que PREMIER(β) contient ε (c.a.d. β ε), les éléments de SUIVANT(A) sont ajoutés à SUIVANT(B).

Exemple ETE' E'+TE' |  TFT' T'*FT' |  F(E) | id Alors FIRST(E) = FIRST(T) = FIRST(F) = {(, id} FIRST(E') = {+, } FIRST(T') = {*, } FOLLOW(E) = FOLLOW(E') = {), $} FOLLOW(T) = FOLLOW(T’) ={$, ), +} FOLLOW(F) = {+,*, ), $}

Construction d’une table d’un analyseur prédictif Algorithme. Donnée. Grammaire G Sortie. Table d’analyse M Méthode : 1. Pour chaque production A α de la grammaire, procéder aux étapes 2 et 3. 2. Pour chaque terminal a dans PREMIER(α), ajouter A α à M[A,a]. 3. Si ε est dans PREMIER(α), ajouter A α à M[A,b] pour chaque terminal b dans SUIVANT(A). Si ε est dans PREMIER(α) et $ est dans SUIVANT(A), ajouter A α à M[A,$]. 3. Faire de chaque entrée non définie de M une erreur.

Exemple Appliquons l'algorithme donné à la grammaire des expressions arithmétique : 1. Puisque PREMIER(TE') = PREMIER(T) = {(, id}, la production E  TE' implique que les entrées M[E,(] et M[E,id] prennent toutes les deux la valeur E  TE'. 2. La production E'  +TE' implique que l'entrée M[E',+] prend la valeur E'  +TE'. 3. La production E'  implique que les entrées M[E',)] et M[E',$] prennent tous les deux la valeur E'   car SUIVANT(E') = {),$}

Grammaires LL(1) L’algo décrit peut être appliqué à une grammaire G pour produire la table d’analyse M. Cependant, pour certaines grammaires, M peut avoir des entrées qui sont définies de façon multiple. Par exemple, si G est récursive à gauche ou ambiguë, M aura alors au moins une de ses entrées définie de façon multiple.

Exemple Considérons la grammaire : S  iEtSS' | a S'  eS |  E  b   PREMIER(S) = {i, a} PREMIER(S') = {e, } PREMIER(E) = {b} SUIVANT(S) = SUIVANT(S') ={$,e} SUIVANT(E) = {t}

Non-terminal Symbole d'entrée a b e i t $ S S a S' S'   S'  eS E   S iEtSS' S' S'   S'  eS E E  b

L'entrée M[S',e] contient à la fois S'   et S'  eS, car SUIVANT(S') = {e,$}. La grammaire est ambiguë et cette ambiguïté se manifeste par un choix sur la production à utiliser quand on voit un e (sinon). Nous pouvons résoudre cette ambiguïté en choisissant S'  eS. Ce choix correspond à l'association du sinon avec le alors précédent le plus proche.

Une grammaire dont la table d’analyse n’a aucune entrée définie de façon multiple est appelée LL(1). Parcours de l’entrée de la gauche vers la droite. (Left to right scanning) Leftmost derivation. Dérivation gauche (Leftmost derivation) Un seul symbole d’entrée de pré-vision