Analyse descendante LL(k)
Transcription
Analyse descendante LL(k)
Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyse descendante LL(k) Mirabelle Nebut Bureau 203 - M3 extension mirabelle.nebut at lifl.fr 2012-2013 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 2/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Objectif du cours Comprendre le fonctionnement des générateurs de parser descendants : I LL(1), ex antLR V1 I LL(k), ex javaCC I LL(*), ex antLR V3 3/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyse descendante L’automate à pile sous-jacent : I effectue uniquement des lectures et des expansions ; I construit un arbre en ordre préfixe (idem aut. items) ; I I construit une dérivation gauche (idem aut. items). part de l’axiome (idem aut. items) ; 4/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Différence avec l’automate des items Deux différences fondamentales : I analyse déterministe dite prédictive ; I plus d’items ni de réductions explicites. 5/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyse déterministe À chaque expansion l’analyseur sait choisir une production. Il ne revient jamais sur ce choix : I en cas de succès le mot appartient au langage ; I en cas d’échec on est sûr que mot n’appartient pas au langage. 6/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyse prédictive L’analyseur ”prédit” quelle production utiliser. . . . . . en analysant les k prochains symboles sous la tête de lecture. Conséquences : I ne fonctionne qu’avec certaines grammaires, dites LL(k) ; I tête de lecture toujours définie : marqueur de fin de mot #. NB : dans ce cours techniques pour k=1, on regarde uniquement la tête de lecture. 7/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Se passer des items Rappel : item de la forme [X → α • β] : I X est en cours de reconnaissance ; I α a déjà été reconnu ; I il reste à reconnaı̂tre β, le futur de l’item Un analyseur LL : I ne mémorise pas qu’il est en train de reconnaı̂tre X ; I ne mémorise pas qu’il a reconnu α ; I considère uniquement β. 8/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Se passer des items : conséquences Plus besoin d’axiome supplémentaire. Dans la pile : I plus d’items mais des mots étendus : mots de (VN ∪ VT )∗ ; I l’alphabet est VN ∪ VT ; I le symbole de pile initiale est l’axiome. S pile initiale A b B une pile pile vide (acceptation) 9/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Exemple à suivre dans le cours Soit la grammaire G = {VT , VN , S, P} avec : I VT = {a, b, d, e} ; I VN = {S, A, B, D} ; I P contient les productions : S → AB | Da A → aAb | B → bB | D → dD | e 10/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Exemple - les piles pour abb# S → AB | Da A → aAb | B → bB | D → dD | e abb# ? a A A A b b b S B B B B abb# abb# abb# bb# bb# (1) (2) (3) (4) (5) B b# (6) b B b# (7) B # (8) # (9) Comparer avec l’automates des items ! Dérivation gauche, arbre en ordre préfixe. 11/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Généralisation I La configuration initiale est (m#, S) ; I La configuration finale est (#, ) : acceptation par pile vide. On traite systématiquement le sommet de pile. 12/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Transition de lecture Si le sommet de pile est un terminal a ∈ VT : I on contrôle que a est bien sous la tête de lecture (sinon échec) ; I on le consomme ; I on le dépile. Lecture de a : (am, z1 . . . zn a) ` (m, z1 . . . zn ) 13/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Transition d’expansion Si le sommet de pile est un non terminal X ∈ VN . . . . . . et que la tête de lecture est y ∈ VT ∪ {#}. . . si Table[X , y ] contient X → X1 . . . Xn : I on dépile X ; I on empile à sa place X1 . . . Xn , avec X1 au sommet. (m, z1 . . . zn X ) ` (m, z1 . . . zn Xn . . . X1 ) sinon erreur. 14/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Transition d’expansion : remarque Expansion par X → X1 . . . Xn : (m, z1 . . . zn X ) ` (m, z1 . . . zn Xn . . . X1 ) I X1 sera traité en premier. I on assure ainsi la construction d’une dérivation gauche ; 15/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Construction de l’arbre syntaxique : ordre préfixe Transition d’expansion par X → X1 . . . Xn : I X est le prochain l’ordre préfixe) ; I on lui rajoute les fils X1 . . . Xn de la gauche vers la droite ; I le prochain nœud à traiter devient X1 . nœud à traiter dans l’arbre (pour Transition de a-lecture : I a est le prochain préfixe) ; I on vérifie que a concorde bien avec la tête de lecture ; I et on passe au nœud suivant. nœud à traiter dans l’arbre (pour l’ordre 16/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Mise en œuvre Les outils n’implantent pas un automate à pile. Ils utilisent une implémentation récursive. Dans tous les cas, le choix de l’expansion est indiqué par une table d’analyse. 17/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Table d’analyse - exemple a b d e # S S → AB S → AB S → Da S → Da S → AB A A → aAb A→ erreur erreur A→ B erreur B → bB erreur erreur B→ D erreur erreur D → dD D→e erreur 18/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Table d’analyse LL(1) Contient toute l’intelligence de l’analyseur syntaxique. Definition La table d’analyse Table est un tableau à deux dimensions tel que : I chaque colonne est indicée par un non-terminal ∈ VN ; I chaque ligne est indicée par un terminal ∈ VT ou # ; I chaque case contient une production ∈ P ou erreur. On verra plus tard comment remplir cette table. 19/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Interprétation de Table[a, X ] I si le terminal a ∈ VT est sous la tête de lecture ; I et si le non-terminal en cours de traitement est X ∈ VN ; alors on consulte Table[a, X ]. Si Table[X , a] contient I X → γ alors on choisit une expansion par cette production ; I erreur alors erreur de syntaxe : X et a ne s’accordent pas. 20/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 21/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyseur descendant récursif Principe : I analyseur LL codé par un ensemble de fonctions ; I ces fonctions s’appellent les unes les autres ; I n’utilise pas de pile explicite : pile implicite des appels. Codage des fonctions : I une fonction X() par non-terminal X ∈ VN de la grammaire ; I X() reconnaı̂t un mot engendré par X ; I la fonction X() code les productions Table[X , y ] de la table d’analyse, pour tout y ∈ VT ∪ #. 22/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Exemple Écrire un analyseur syntaxique récursif LL(1) Parser pour G : S → AB | Da A → aAb | B → bB | D → dD | e À voir : I écriture de S(), A(), B(), D() ; I collaboration avec un analyseur lexical. 23/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Collaboration avec un analyseur lexical On reprend les conventions utilisées en TP : I un an. lexical anLex de type Scanner (supposé donné) ; I symboles de type Symbole ; I codage entier du type des symboles dans TypeSymboles (noté TS dans les transparents) ; I méthode int getType() de Symbole pour obtenir ce type ; méthode Symbole next token() de Scanner : I I I I avance la tête de lecture teteLect ; retourne le symbole lu, de type Symbole. on remplace le marqueur # par TS.EOF. 24/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Construction de l’analyseur syntaxique ... public class Parser { // analyseur lexical private Scanner anLex; // symbole courant reçu de l’analyseur lexical private Symbole teteLect; public Parser (Scanner anLex) { this.anLex = anLex; } 25/119 ... Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Lancement de l’analyseur syntaxique Dans la classe Parser : public void analyser() throws ScannerException, ParserExcep // positionnement tete de lecture this.teteLect = (Symbole) this.anLex.next_token(); this.S(); // je veux reconna^ ıtre l’axiome // et uniquement l’axiome if (this.teteLect.getType() != TS.EOF) throw new ParserException(); } 26/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code de S() La tête de lecture est déjà positionnée sur le symbole de prédiction. a b d e # S S → AB S → AB S → Da S → Da S → AB private void S() throws ... { if (this.teteLect.getType() == TS.a) ... // S -> AB else if (this.teteLect.getType() == TS.b) ... // S -> AB else if (this.teteLect.getType() == TS.d) ... // S -> Da else if (this.teteLect.getType() == TS.e) ... // S -> Da else if (this.teteLect.getType() == TS.EOF) ... // S -> AB else throw new ParserException(); 27/119 } Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code de S() On factorise. a b d e # S S → AB S → AB S → Da S → Da S → AB private void S() throws ... { if (this.teteLect.getType() == TS.a || this.teteLect.getType() == TS.b || this.teteLect.getType() == TS.EOF) ... // S -> AB else if (this.teteLect.getType() == TS.d || this.teteLect.getType() == TS.e) ... // S -> Da else throw new ParserException(); } 28/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code des productions de S() Code pour S → AB : I je veux reconnaı̂tre A puis B ; I ⇒ A() ; B() ; Code pour S → Da : I je veux reconnaı̂tre D. . . I . . . puis vérifier que a est bien sous la tête de lecture ; I et consommer a. 29/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Terminaux : vérification et consommation Méthode consommer dédiée à la gestion des terminaux : private void consommer(int type) throws ScannerException, ParserException { if (this.teteLect.getType() == type) this.teteLect = (Symbole) this.anLex.next_token(); else throw new ParserException(); } Code pour S → Da : D(); this.consommer(TS.a);. 30/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code final de S() a b d e # S S → AB S → AB S → Da S → Da S → AB private void S() throws ... { if (this.teteLect.getType() == TS.a || this.teteLect.getType() == TS.b || this.teteLect.getType() == TS.EOF) { A(); B(); // S -> AB } else if (this.teteLect.getType() == TS.d || this.teteLect.getType() == TS.e) { D(); this.consommer(TS.a); // S -> Da } else throw new ParserException(); } Quand S() termine, pour un mot accepté, la tête de lecture est sur TS.EOF. 31/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code de A() La tête de lecture est déjà positionnée sur le symbole de prédiction. a b d e # A A → aAb A→ erreur erreur A→ private void A() throws ... { if (this.teteLect.getType() == TS.a) ... // A -> aAb else if (this.teteLect.getType() == TS.b || this.teteLect.getType() == TS.EOF) ... // A -> else // erreur throw new ParserException(); } 32/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code des productions de A() Code pour A → aAb : this.consommer(TS.a); A(); this.consommer(TS.b); Code pour A → : I le mot vide est immédiatement reconnu ; I sans toucher à la tête de lecture ; I on ne fait rien. 33/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code final de A() a b d e # A A → aAb A→ erreur erreur A→ private void A() throws ... { if (this.teteLect.getType() == TS.a) { // A -> aAb this.consommer(TS.a); A(); this.consommer(TS.b); } else if (this.teteLect.getType() == TS.b || this.teteLect.getType() == TS.EOF) // rien, A -> } else // erreur throw new ParserException(); } Quand A() termine, pour un mot accepté, la tête de lecture est positionnée pour reconnaı̂tre un B ou lire un b. 34/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code final de B() a b d e # B erreur B → bB erreur erreur B→ private void B() throws ... { if (this.teteLect.getType() == TS.b) { // B -> bB this.consommer(TS.b); B(); } else if (this.teteLect.getType() == TS.EOF) // rien, B -> } else // erreur throw new ParserException(); } 35/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Code final de D() a b d e # D erreur erreur D → dD D→e erreur private void D() throws ... { if (this.teteLect.getType() == TS.d) { // D -> dD this.consommer(TS.d); D(); } else if (this.teteLect.getType() == TS.e) // D -> e this.consommer(TS.e); else // erreur throw new ParserException(); } 36/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Exemple d’exécution Reconnaı̂tre abb# ? 37/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 38/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 39/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Outils pour l’analyse prédictive, intuition - 1 Comment choisir entre S → AB et S → Da ? Supposons que je sache que : I AB ne permet de dériver que des mots préfixés par a ou par b ; I AB ⇒∗ au et AB ⇒∗ bu, pour u ∈ VT ∗ ; I Da ne permet de dériver que des mots préfixés par d ou par e ; I Da ⇒∗ du et Da ⇒∗ eu, pour u ∈ VT ∗ . 40/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Outils pour l’analyse prédictive, intuition - 1 Maintenant je sais (partiellement) choisir entre S → AB et S → Da : I si tête lecture ∈ {a, b} : choisir S → AB ; I si tête lecture ∈ {d, e} : choisir S → Da. a b d e # S S → AB S → AB S → Da S → Da ? 41/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Ensemble Premier - définition On dit que Premier (AB) = {a, b} et Premier (Da) = {d, e}. Pour α ∈ (VT ∪ VN )+ , Premier (α) contient l’ensemble des terminaux de VT susceptibles de commencer un mot de VT + dérivé de α. Si α = , cet ensemble est vide. Definition Soit une grammaire algébrique. On définit : Premier : (VT ∪ VN )∗ → P(VT ) α 7→ {a ∈ VT | α ⇒∗ au, u ∈ VT ∗ } 42/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Les Premier sur les arbres syntaxiques S S A B A B A a S A B B b b S α ∈ (VT ∪ VN )∗ S D D D d a e Mirabelle Nebut a ∈ Premier (α) Analyse descendante LL(k) 43/119 Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier - 0 Soit α ∈ (VN ∪ VT )∗ : cas α = :? α = a, a ∈ VT : ? α = aβ, a ∈ VT , β ∈ (VN ∪ VT )∗ : ? α = X , X ∈ VN : ? α = X β, X ∈ VN , β ∈ (VN ∪ VT )∗ : ? fcas 44/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier - 1 Soit α ∈ (VN ∪ VT )∗ : cas α=:∅ α = a, a ∈ VT : {a} α = aβ, a ∈ VT , β ∈ (VN ∪ VT )∗ : {a} α = X , X ∈ VN : ? α = X β, X ∈ VN , β ∈ (VN ∪ VT )∗ : ? fcas 45/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul de Premier (X ), X ∈ VN Si l’ensemble des productions de membre gauche S est : S → AB | Da alors on a : Premier (S) = Premier (AB) ∪ Premier (Da) Cas général : Si la grammaire contient les productions de membre gauche X : X → γ1 | . . . | γn alorsPremier (X ) = S {Premier (γi ) | X → γi ∈ P} Mirabelle Nebut Analyse descendante LL(k) 46/119 Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier - 2 Soit α ∈ (VN ∪ VT )∗ : cas α=:∅ α = a, a ∈ VT : {a} α = aβ, a ∈ VT , β ∈ (VN ∪ VT )∗ : {a} S α = X , X ∈ VN : {Premier (γi ) | X → γi ∈ P} α = X β, X ∈ VN , β ∈ (VN ∪ VT )∗ : ? fcas 47/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier , α = X β, X ∈ VN Deux cas selon que X peut s’effacer ou non : X ⇒∗ ? Si X ⇒∗ on dit que X est -productif : X ∈ -Prod 48/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier , α = X β, X 6∈ -Prod - exemple S Par exemple D 6∈ -productif : D D → dD | e alors Premier (Da) = Premier (D) S D D d a e a Donc, si X 6∈ -Prod, Premier (X β) = Premier (X ) 49/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier , α = X β, X ∈ -Prod - exemple Par exemple A ∈ -productif : S A → | aAb A Premier (AB) = Premier (A) ∪ Premier (B) Premier (ABS) = Premier (A) ∪ Premier (BS) S B A B A a B b b Donc, si X ⇒∗ alors Premier (X β) = Premier (X ) ∪ Premier (β) 50/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Premier Soit α ∈ (VN ∪ VT )∗ : cas α=:∅ α = a, a ∈ VT : {a} α = aβ, a ∈ VT , β ∈ (VN ∪ VT )∗ : {a} S α = X , X ∈ VN : {Premier (γi ) | X → γi ∈ P} α = X β, X ∈ VN \ -Prod, β ∈ (VN ∪ VT )∗ : Premier (X ) α = X β, X ∈ VN ∩ -Prod, β ∈ (VN ∪ VT )∗ : Premier (X ) ∪ Premier (β) fcas 51/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul effectif des ensembles Premier On procède en deux étapes : 1. on pose un système d’équations pour Premier ; 2. on calcule par itération de point fixe les plus petits ensembles qui satisfont ces équations. Pour le moment on suppose donné -Prod, l’ensemble des -productifs. 52/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple S → AB | Da A → aAb | B → bB | D → dD | e -Prod = {A, B, S} Premier (S) = ? Premier (A) = ? Premier (B) = ? Premier (D) = ? α=:∅ α = a, a ∈ VT : {a} α = aβ, a ∈ VT , β ∈ (VN ∪ VT )∗ : {a} α = X , X ∈ VN : S {Premier (γi ) | X → γi ∈ P} α = X β, X ∈ VN \ -Prod, β ∈ (VN ∪ VT )∗ : Premier (X ) α = X β, X ∈ VN ∩-Prod, β ∈ (VN ∪VT )∗ : Premier (X ) ∪ Premier (β) 53/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple Premier (S) = Premier (A) ∪ Premier (B) ∪ Premier (D) Premier (A) = {a} Premier (B) = {b} Premier (D) = {d, e} D’où Premier (S) = {a, b, d, e} Premier (A) = {a} Premier (B) = {b} Premier (D) = {d, e} Premier (AB) = {a, b} Premier (Da) = {d, e} Premier (aAb) = {a} Premier (bB) = {b} Premier (dD) = {d} Premier (e) = {e} Premier () = ∅ 54/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple : remplissage de la table A → aAb et Premier (aAb) = {a} A → et Premier () = ∅ a b d e # S S → AB S → AB S → Da S → Da S → AB A A → aAb A→ erreur erreur A→ B erreur B → bB erreur erreur B→ D erreur erreur D → dD D→e erreur 55/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple : remplissage de la table S → AB et Premier (AB) = {a, b} S → Da et Premier (Da) = {d, e} a b d e # S S → AB S → AB S → Da S → Da S → AB A A → aAb A→ erreur erreur A→ B erreur B → bB erreur erreur B→ D erreur erreur D → dD D→e erreur 56/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Remarque : résolution du système Premier (S) = Premier (A) ∪ Premier (B) ∪ Premier (D) Premier (A) = {a} Premier (B) = {b} Premier (D) = {d, e} Se résoud sans itération de point fixe : système d’équations non récursif. Ce n’est pas toujours le cas. 57/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Résolution du système : autre exemple Premier (S) = Premier (S1 ) ∪ {a} Premier (S1 ) = Premier (S) ∪ {b} Premier (S2 ) = {c} S → S1 S2 | a S1 → S | b S2 → c iter 0 1 2 3 Premier (S) ∅ {a} {a, b} {a, b} Premier (S1 ) ∅ {b} {b, a} {b, a} Premier (S2 ) ∅ {c} {c} {c} stabilisation 58/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 59/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Définition des -prod Definition Un non terminal X ∈ VN est dit -productif si X ⇒∗ . L’ensemble des -productif est -Prod. X est -productif si la grammaire contient la production : I X → ; I ou X → Y1 Y2 . . . Yn telle que l’ensemble des non-terminaux {Y1 , Y2 , . . . , Yn } ⊆ VN ne contient que des non-terminaux -productifs. Algorithme de calcul similaire à celui qui calcule les productifs. 60/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple S → AB | Da A → aAb | B → bB | D → dD | e -Prod ? 61/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 62/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Outils pour l’analyse prédictive, intuition - 2 Pour choisir entre S → AB et S → Da : I si tête lecture ∈ {a, b} : choisir S → AB ; I si tête lecture ∈ {d, e} : choisir S → Da. Et si la tête de lecture est # ? # 6∈ Premier (AB) ∪ Premier (Da). Comment choisir entre A → aAb et A → ? Premier () = ∅ ⇒ les ensembles Premier ne suffisent pas. 63/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Ensembles Suivant, intuition Quand appliquer A → ? Quand la tête de lect. correspond à un terminal qui peut suivre A. S A A a A B b b ∈ Suivant(A) Suivant(A) ⊇ Premier (B) 64/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Ensembles Suivant, intuition On a donc b ∈ Suivant(A) a b d e # A A → aAb A→ ? ? ? 65/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Ensembles Suivant, intuition Pour α ∈ (VT ∪ VN )+ , Suivant(α) contient l’ensemble des terminaux de VT susceptibles de suivre α dans un mot de VT + dérivé de l’axiome S. Si α = , cet ensemble est vide. Par convention, Suivant(S) ⊇ {#}. 66/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Ensembles Suivant, définitions équivalentes Definition Soit une grammaire algébrique d’axiome S. On définit : Suivant : (VT ∪ VN )∗ → P(VT ) α 7→ {a ∈ VT | S ⇒∗ βαaγ, pour β, γ ∈ (VN ∪ VT )∗ } Definition Suivant : (VT ∪ VN )∗ → P(VT ) α 7→ {a ∈ Premier (γ) | S ⇒∗ βαγ, pour β, γ ∈ (VN ∪ VT )∗ } 67/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 1 Pour calculer Suivant(X ), on regarde les productions dans lesquelles X apparaı̂t en partie droite (différent du calcul des Premier ). Pour Suivant(A) : S → AB A → aAb S A A a A B b 68/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 2 Soit PX ⊆ P l’ensemble des productions p dans lesquelles X apparaı̂t en partie droite : S Suivant(X ) = p∈PX Suivant p (X ) Ex : PA = {S → AB, A → aAb} Suivant(A) = Suivant(A)S→AB ∪ Suivant(A)A→aAb 69/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant, cas de l’axiome Pour l’axiome, on ajoute le marqueur de fin de mot : S Suivant(S) = {#} ∪ p∈PS Suivant p (S) Ex : pour X → aXb | PX = {X → aX b} Suivant(X ) = {#} ∪ Suivant(X )X →aX b 70/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 3 - exemple Suivant(A)S→AB ? (exemple précédent) Cas déjà vu : S A B Suivant(A) ⊇ Premier (B) 71/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 3 - exemple Suivant(A)S→AB ? (exemple précédent) mais B est -Prod ! S A B Suivant(A) ⊇ Suivant(S) 72/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 3 - exemple Puisque B est -Prod : Suivant(A)S→AB = Premier (B) ∪ Suivant(S) 73/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 4 Quand une production est de la forme . . .→ X α : I pour calculer Suivant(X ) ; I Il faut pouvoir dire si α ∈ (VN ∪ VT )∗ est -productif ou pas. Definition α ∈ (VN ∪ VT )∗ est -productif si α ⇒∗ . On définit la fonction : Eps : (VN ∪ VT )∗ → {vrai, faux} α 7→ α est -productif On verra après comment calculer Eps. 74/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 5 Pour calculer Suivant p (X ) avec : p = Y → αX β et Eps(β) = faux, α, β ∈ (VN ∪ VT )∗ Y X β Suivant p (X ) = Premier (β) Ex : pour Y → Xb, Suivant(X )Y →Xb = {b}. 75/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 6 Pour calculer Suivant p (X ) avec : p = Y → αX Y α X Suivant p (X ) = Suivant(Y ) 76/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant - 7 Pour calculer Suivant p (X ) avec : p = Y → αX β et Eps(β) = vrai, α, β ∈ (VN ∪ VT )∗ Y X β Suivant p (X ) = Premier (β) ∪ Suivant(Y ) Ex : pour S → AB, Suivant(A)S→AB = Premier (B) ∪ Suivant(S). 77/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Remarque - 1 Si X apparaı̂t plusieurs fois en partie droite d’une production, il faut prendre en compte toutes ses occurrences dans le calcul de Suivant(X ). Ex : Y → X aX aX c Suivant Y →X aX aX c (X ) = {a, c} 78/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Remarque - 2 Pourquoi pas Suivant(X )Y →X β = Premier (β) ∪ Suivant(β) ? Parce que Suivant(Y ) ⊆ Suivant(β). Ex : S → Y |Z Y → X1 X2 X1 → a X2 → | b Z → X2 c Suivant(S) = {#} Suivant(Y ) = Suivant(S) = {#} Suivant(Z ) = Suivant(S) = {#} Suivant(X2 ) = {c} ∪ Suivant(Y ) = {c, #} Suivant(X1 ) = Premier (X2 ) ∪ Suivant(Y ) 79/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des Suivant, récapitulons ! # ∈ Suivant(axiome) Soit PX ⊆ P l’ensemble des productions p dans lesquelles X apparaı̂t en partie droite : S Suivant(X ) = p∈PX Suivant p (X ) avec : Suivant p (X ) = cas p = Y → αX : Suivant(Y ) p = Y → αX β et Eps(β) = faux : Premier (β) p = Y → αX β et Eps(β) = vrai : Premier (β) ∪ Suivant(Y ) fincas 80/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul effectif des ensembles Suivant On procède en deux étapes : I on pose un système d’équations pour Suivant ; I on calcule par itération de point fixe les plus petits ensembles qui satisfont ces équations. I avec initialement Suivant(S) = {#}, et pour les autres non-terminaux Suivant(X ) = ∅. 81/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple S → AB | Da A → aAb | B → bB | D → dD | e Eps(B) = vrai Suivant ? # ∈ Suivant(axiome) S Suivant(X ) = p∈PX Suivant p (X ) avec : cas p= p= p= Suivant p (X ) = Y → αX : Suivant(Y ) Y → αX β et Eps(β) = faux : Premier (β) Y → αX β et Eps(β) = vrai : Premier (β) ∪Suivant(Y ) fincas 82/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple de remplissage de table A → et Suivant(A) = {b, #} a b d e # S S → AB S → AB S → Da S → Da S → AB A A → aAb A→ erreur erreur A→ B erreur B → bB erreur erreur B→ D erreur erreur D → dD D→e erreur 83/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple de remplissage de table S → AB et Suivant(S) = {#} a b d e # S S → AB S → AB S → Da S → Da S → AB A A → aAb A→ erreur erreur A→ B erreur B → bB erreur erreur B→ D erreur erreur D → dD D→e erreur 84/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Calcul des -productifs On connaı̂t déjà -Prod, ens. des non-terminaux -productifs. Pour calculer Eps(α) : Eps(α) = cas α = : vrai α = X1 . . . Xn , n ≥ 1 avec {X1 , . . . , Xn } ⊆ VN et {X1 , . . . , Xn } ⊆ -Prod : vrai autre : faux // α contient un terminal fincas 85/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple Sachant que -Prod = {A, B, S} : Eps(Da) ? Eps(AB) ? Eps() ? Eps(B) ? 86/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 87/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Table d’analyse : au préalable On calcule : I les -productifs ; I les ensembles Premier ; I les ensembles Suivant. 88/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Remplissage de la table Entrée : une gram. alg. G , ses ensembles Premier et Suivant Sortie : la table d’analyse Table pour toute production X → γ ∈ P faire pour tout a ∈ Premier (γ) faire ajouter X → γ à Table[X , a] fait si Eps(γ) = vrai alors pour tout b ∈ Suivant(X ) faire Table[X , b] = X → γ fait finsi fait Ajouter erreur dans les entrées de Table restées vides 89/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple S → AB : I Premier (AB) = {a, b} ; I Eps(AB) = vrai ; I Suivant(S) = {#}. S → Da : I Premier (Da) = {d, e} ; I Eps(Da) = faux. a b d e # S S → AB S → AB S → Da S → Da S → AB Rien à compléter par erreur. 90/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Exemple A → aAb : I Premier (aAb) = {a} ; I Eps(aAb) = faux. A→: I Premier () = ∅ ; I Eps() = vrai ; I Suivant(A) = {b, #}. a b d e # A A → aAb A→ erreur erreur A→ On complète par erreur. 91/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 92/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyseur LL(1) Un analyseur LL(1) est déterministe et piloté par le sommet de pile : I si terminal a : lecture de a (ou erreur) ; I si non terminal X avec a sous la tête de lecture : expansion selon Table[X , a]. Et si Table[X , a] contient plus d’une production ? Non-déterminisme : I la grammaire n’est pas LL(1) ; I on ne peut pas appliquer une analyse LL(1). 93/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Caractérisation d’une grammaire LL(1) Caractérisation par table d’analyse : une grammaire est LL(1) si chaque case contient exactement une production ou erreur. Caractérisation par contre-exemple : une grammaire n’est pas LL(1) s’il existe 2 productions X → α et X → β telles que : 1. soit Premier (α) ∩ Premier (β) 6= ∅ ; Ex : S → aS | A, A → a 2. soit Eps(α) = vrai et Premier (β) ∩ Suivant(X ) 6= ∅ ; Ex : S → aS | Ab, A → | b 3. soit Eps(α) = vrai et Eps(β) = vrai (la grammaire est ambiguë) Ex : S → A | B, A → , B → 94/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) LL(1) et ambiguı̈té Une grammaire LL(1) n’est pas ambiguë. Une grammaire ambiguë n’est pas LL(1). 95/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Cas classiques non LL(1) Dans les cas suivants, la grammaire n’est pas LL(1) : I I ambiguı̈té ; récursivité gauche : A → Aa | ; I I intuitivement récursivité infinie de A(). non factorisation gauche : S → aA | aB Solutions : : I factorisation à gauche (parfois) ; I suppression de la récursivité gauche (parfois) ; I utiliser un générateur de parser plus puissant ! 96/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 97/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 98/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Factorisation à gauche : exemple - 1 Les listes d’identificateur de Init : listeIdent → IDENT | IDENT SEPVAR listeIdent On factorise IDENT et on obtient : listeIdent → IDENT suiteListeIdent suiteListeIdent → | SEPVAR listeIdent 99/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Factorisation à gauche : exemple - 2 X → ab | abbX | abbbX Factorisation de ab : on prend le plus grand préfixe commun. X → abY Y → | bX | bbX Puis à nouveau factorisation de b. 100/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Factorisation à gauche - algorithme On remplace les règles de la forme : X → αβ1 | . . . | αβn | γ1 | . . . | γm où α ∈ (VT ∪ VN )+ et βi , γj ∈ (VT ∪ VN )∗ ; I le préfixe commun α est choisi le plus grand possible ; I α n’est pas préfixe de γj . par les règles : I X → αX 0 | γ1 | . . . | γm X 0 → β1 | . . . | βn où X 0 est un nouveau non-terminal. On réitère ce processus tant que nécessaire. Mirabelle Nebut Analyse descendante LL(k) 101/119 Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 102/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Suppression de la récursivité à gauche Récursivité gauche : I immédiate : production A→Aα, α ∈ (VT ∪ VN )+ ; I générale : il existe une dérivation A⇒∗ Aα, α ∈ (VT ∪ VN )+ . Il est possible de supprimer les deux cas. On ne verra que la récursivité immédiate. 103/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Suppression de la récursivité gauche immédiate On remplace les règles de la forme X → X α1 | . . . | X αn | β1 | . . . | βm où I αi ∈ (VT ∪ VN )+ et βj ∈ (VT ∪ VN )∗ ; I les βj ne commencent pas par X . par les règles : X → β1 X 0 | . . . | βm X 0 X 0 → α1 X 0 | . . . | αn X 0 | où X 0 est un nouveau non-terminal. Mirabelle Nebut Analyse descendante LL(k) 104/119 Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Suppression de la récursivité gauche : exemple Grammaire non ambiguë des expressions arithmétiques : E → E + T |T T → T ∗ F |F F → i | (E ) X → X α1 | . . . | X αn | β1 | . . . | βm Après suppression gauche : de la rec E → TE 0 E 0 → +TE 0 | T → FT 0 T 0 → ∗FT 0 | F → i | (E ) X → β1 X 0 | . . . | βm X 0 X 0 → α1 X 0 | . . . | αn X 0 | 105/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Parfois ça ne suffit pas La grammaire ({a, b}, {S, A}, S, P) avec P = {S → aSb | A, A → aA | } I n’est pas ambiguë ; I n’est pas récursive gauche ; I est factorisée à gauche ; mais elle n’est pas LL(1). 106/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Factorisation à gauche Suppression de la récursivité à gauche Au delà des grammaires LL(1) - 1 La grammaire ({a, b}, {A, B}, A, P) avec P = {A → abB | , B → Aaa | b} n’est pas LL(1). En effet Eps(A) = vrai et a ∈ Premier (A) ∩ Suivant(A). 107/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Principes Analyseur récursif Construction de la table d’analyse Ensembles Premier Ensemble des -prod Ensembles Suivant Remplissage de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Factorisation à gauche Suppression de la récursivité à gauche Analyseurs LL(k), LL(*) 108/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Grammaires LL(k), exemple La grammaire : declaration → DECLINT listeIdent FININSTR listeIdent → IDENT | IDENT SEPVAR listeIdent n’est pas LL(1). Elle est LL(2), et acceptée par un analyseur LL(k). En regardant 2 symboles sous la tête de lecture : I si IDENT FININSTR : choisir listeIdent → IDENT I si IDENT SEPVAR : choisir listeIdent → IDENT SEPVAR listeIdent 109/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Grammaire LL(k), autre exemple P = {A → abB | , B → Aaa | b} Cette grammaire est LL(2) : Premier 2 (A) = {ab} Premier 2 (B) = {ab, aa, b} Suivant 2 (A) = {aa, #} 110/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Table d’analyse LL(2) A → abB | B → Aaa | b A B aa A→ B → Aaa ab A → abB B → Aaa b erreur B→b # A→ erreur 111/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyseurs LL(k), principe Effectuent une prédiction basée sur k symboles. k borné. Ex : javaCC 112/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Insuffisance de l’approche LL(k), [antLR] method → type ID [ args ] ; | type ID [ args ] { body } args → unarg | unarg , args unarg → INT ID ... Cette grammaire n’est pas LL(k), mais est acceptée par antLR. 113/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Analyseurs LL(*) Ne fixent pas une taille de look-ahead a priori. Représentent par un AFD le langage de look-ahead, pourvu qu’il soit régulier. 114/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Vers les formes eBNF Même un analyseur LL(*) refuse la récursivité gauche. Fâcheux pour les grammaires à opérateurs ! Solution : grammaires dites en forme eBNF. E → T ( + T) * T → F ( * T) * F → ( E ) | id E →E +T | T T →F *T | F F → ( E ) | id 115/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Grammaires sous forme eBNF Grammaires algébriques avec facilités d’écriture. En partie droite de production : opérateurs à la expression régulière Refusé par Cup et tout générateur de parseur n’acceptant pas les eBNF Accepté par la majorité des analyeurs LL(k). Semble plus simple, attention à l’attribution. Ne pas utiliser en DS sauf si explicitement demandé. 116/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Grammaires non LL(*) [antLR] s : label ID ’=’ expr | label ’return’ expr ; label : ID ’:’ label | ; n’est pas LL(*) : [fatal] rule s has non-LL(*) decision due to recursive rule invocations from alts 1,2. [...] Version LL(*) : label : ( ID ’:’)* Mirabelle Nebut 117/119 Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Génération de code à la eBNF E → T ( + T) * E() { T(); tant que tetelect est ’+’ { consommer(+); T(); } } Clôture de Kleene ⇒ itération dans le code 118/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) Génération de code à la eBNF listeA → a* listeA() { tant que tetelect est ’a’ { consommer(a); } } plus efficace que le code récursif généré par : listeA → a listeA | 119/119 Mirabelle Nebut Analyse descendante LL(k) Principes Analyseur récursif Construction de la table d’analyse Caractérisation d’une grammaire LL(1) Quand une grammaire n’est pas LL(1) Analyseurs LL(k), LL(*) AntLR Outil très riche. Décrit dans le même formalisme eBNF les entités lexicales et la syntaxe. Lit toute l’entrée avant de lancer l’analyse lexicale. 120/119 Mirabelle Nebut Analyse descendante LL(k)