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

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

IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313.

Présentations similaires


Présentation au sujet: "IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313."— Transcription de la présentation:

1 IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313 Ensembles first et follow

2 IFT313© Froduald Kabanza2 Sujets Cest quoi un symbole nullable pour une grammaire? Cest quoi un ensemble first pour une grammaire ? Cest quoi un ensemble follow pour une grammaire ? Quels lest lalgorithme pour calculer ces symboles et ces ensembles ? Quel est le rôle de ces concepts dans lanalyse syntaxique descendante (prédictive) ? –Cest quoi une table danalyse LL ? –Comment la calculer.

3 IFT313© Froduald Kabanza3 Objectifs Savoir définir les concepts de symboles nullables, densemble first et densemble follow pour une grammaire. Pouvoir décrire et appliquer un algorithme pour calculer les symboles nullables, lensemble first et lensemble follow pour une grammaire. Savoir calculer une table danalyse LL pour une grammaire LL donnée.

4 IFT313© Froduald Kabanza4 Références [1] Sudkamp, T. A.. Languages and Machines. Third Edition Edition. Addison-Wesley, 2005. – Sections 19.1 à 19.5 [2] Appel, A. and Palsberg. J. Modern Compiler Implementation in Java. Second Edition. Cambridge, 2004. – Section 3.2 [4] Aho, A., Lam, M., Sethi R., Ullman J. Compilers: Principles, Techniques, and Tools, 2 nd Edition. Addison Wesley, 2007. – Section 4.4.2

5 IFT313© Froduald Kabanza5 Driver LL Algorithm LLDriver variables : stack (pile), x (symbole au sommet de la pile), a (symbole dentrée courant), in (entrée) initialement la pile contient $S (le symbole départ S) et lentrée contient w$ (chaîne de tokens w). while (true) { if (x = = $) && (a= = $) return true ; // on accepte la chaîne dentrée comme étant correcte if (x = = a) && (a != $) // match transition { pop a from the stack; // dépiler le symbole de la pile a = in.read(); // lire le token (symbole) courant et avancer la tête de lecture continue;} if x is a nonterminal // predictive transition { find a production x y 1 … y k ; // trouver une production dont la partie gauche est x // les essayer tous jusquà en trouver menant à lacceptation (backtracking) exit with error if no such production exists; pop x from the stack; push y k on the stack; …; push y 1 on the stack; continue; } exit with error;}

6 IFT313© Froduald Kabanza6 Deux observations importantes Lexécution du driver LL, sur une chaîne dentrée donne la dérivation la plus à gauche de lentrée dans la mesure où si on concatène le préfixe de la chaîne déjà scannée avec le contenu de la pile, on obtient une forme sententielle gauche de la grammaire. Ceci veut dire à tout instant durant lexécution du driver LL, la chaîne restant à scanner doit être dérivable de la chaîne de symbole sur la pile pour que la chaîne de départ soit acceptée. En dautres mots: Soit le contenu de la pile à une étape quelconque, v le reste de la chaîne à lire et w la chaîne dentrée originale (donc w = uv avec u la chaîne déjà lue; forcément dans A*). Alors, on doit avoir v pour que la chaîne dentrée soit acceptée, cest-à-dire, pour que S w (avec S le symbole de départ de la grammaire). * *

7 IFT313© Froduald Kabanza7 Exemple G = (V, A, R, E) : V = {E, E, T, T, F} A = {(, ), +, *, n} R = { E TE E + TE | ε T FT *FT | ε F n } G = (V, A, R, E) : V = {E} A = {(, ), +, *, n} R = { E n E ( E) E E + E E E * E} Soit la grammaire suivanteElle génère le même langage que la grammaire suivante : Mais la première est non-ambigüe et possède dautres caractéristiques intéressantes que nous verrons plus tard.

8 IFT313© Froduald Kabanza8 Exemple return true Pile 0. 3. 2. 3. 2. 3. 2. 3. 2. 3. 2. 3. 1. Étape Règle Algorithm LLDriver 0. stack = ($S); a = in.read(); x=stack.top(); while (true) { 1. if (x = = $) && (a= = $) return true ; 2. if (x = = a) && (a != $) { pop a from stack; a = in.read(); continue;} 3. if x is a nonterminal { find x y; pop x from stack; push y on stack; continue; } 4. exit with error;} Entrée 1. E TE 2. E + TE | 3. ε 4. T FT 5. T *FT | 6. ε 7. F ( E ) | n Entrée : n+n*n E TE FTE nTE nEnE n +TE n+FTE n+nTE n+n*FTE n+n*nTE n+n*nE n+n*n S déjà lu + pile * * $E $ET $ETF $ETn $ET $E $E T+ $E T $ETF $ETn $ET $ETF* $ETF $ETn $ET $E $ n+n*n$ +n*n$ n*n$ *n$ n$ $ $ $ E TE T FT F n T ε E +TE T FT F n T *FT F n T ε E ε

9 IFT313© Froduald Kabanza9 Driver LL Le seul problème significatif avec lalgorithme LLDRiver précédent est létape de prédiction de la règle ( find x y). À cette étape on pourrait avoir plus dune règle de production applicable. Dans ce cas, nous avons du non-déterminisme. On pourrait toujours implémenter lalgorithme, soit avec une technique de backtracking (mémoriser les différentes règles pour y revenir en cas déchec) ou par récursivité. Dans chaque, on aurait besoin dune pile additionnelle pour mémoriser les étapes avec plus dune règle ou pour la récursivité. Ce ne serait donc pas efficace. Nous allons voir une approche bien plus efficace (quoique légèrement moins générale) basée sur les notions de nullable symbols, First set and Follow set.

10 IFT313© Froduald Kabanza10 Motivation pour lensemble First Considérons encore lexemple précédent pour dériver la chaîne n+n*n. Lorsque le contenu de la pile était $ETF et lentrée n+n*n$, on avait deux règles de production applicables : F et F n. Comment le driver peut-il déterminer que la règle appropriée à cette étape est F n plutôt que F ? La réponse est : en observant que le reste de la chaîne dentrée commence par le token n. En prédisant F n, on obtient un contenu de pile dont le sommet est n, ce qui « matche » le prochain token à lire.

11 IFT313© Froduald Kabanza11 Motivation pour lensemble First Plus généralement, à chaque étape de prédiction, le driver va choisir une règle qui lui assure que le reste de la chaîne dentrée est dérivable du contenu actuel de la pile. Ceci découle de notre observation antérieure que le reste de lentrée doit toujours être dérivable du contenu actuel de la pile pour que lentrée originale soit acceptée, cest-à-dire pour que lentrée originale dérive du symbole de départ. En dautre mots, si pour une production donnée le nouveau contenu de la pile ne permettrait pas de dériver le reste de la chaîne, la production ne doit pas être appliquée même si sa partie gauche est au sommet de la pile. En particulier, ceci est le cas si le terminal qui commence la partie droite de la production nest pas le prochain symbole dans lentrée.

12 IFT313© Froduald Kabanza12 Motivation pour lensemble First Dans lexemple précédent, nous avions deux productions dont la partie gauche est au sommet de la pile: F (E) et F n. Le reste de lentrée était : n+n*n. La chaîne dérivée de F commence par ( alors que celle dérivée de F n commence par n. Donc la bonne production était: F n.

13 IFT313© Froduald Kabanza13 Définition de lensemble First Étant donné une chaîne de terminaux et de non-terminaux, alors First( est lensemble de terminaux commençant une chaîne dérivée de Exemple : G = (V, A, R, E) : V = {E, E, T, T} A = {(, ), +, *, n} R = { E TE E + TE | ε T FT | ε *FT | ε F n} First(TE) = {(, n, +} First(+TE) = { + } First(FT) = { (, n} First(*FT) = { * } First((E)) = { ( } First(n) = { n}

14 IFT313© Froduald Kabanza14 Utiliser lensemble First dans le driver LL Si le sommet de la pile contient un terminal X, le driver LL doit prédire la règle X tel que le prochain token est dans First( Exemple : G = (V, A, R, E) : V = {E, E, T, T} A = {(, ), +, *, n} R = { E TE E + TE | ε T FT | ε *FT | ε F n} First((E)) = {( } First(n) = {n} Si le sommet de la pile est F : - si le prochain token est (, le driver LL prédit F - sinon, si le prochain token est n le driver LL prédit F n - sinon le driver sort avec une erreur.

15 IFT313© Froduald Kabanza15 Utiliser lensemble First dans le driver LL Si la grammaire ne contient pas deux productions X et X telles que First( et First( ont une intersection, alors le driver LL exécute de manière déterministe : Il y a zéro ou une production à prédire à chaque étape. Par contre si la grammaire contient deux productions X and X telles que First( et First( ont une intersection, le driver LL ne peut pas prédire la production à appliquer en lisant juste un token : le driver LL exécuterait de manière non-déterministe. On va justement éviter des grammaires qui donneraient lieu à un tel non- déterminisme.

16 IFT313© Froduald Kabanza16 Exemple First(n) = {n} First((E)) = {(} First(E+E) = {n,(} First(E*E) = {n,(} Si le sommet de la pile est E : - Si le prochain token est n, le driver ne peut pas prédire laquelle des productions 1, 3 ou 4 est appropriée. - Si le prochain token est (, le driver ne peut pas prédire non plus laquelle des productions 2, 3 ou 4 est appropriée. G = (V, A, R, E) : V = {E} A = {(, ), +, *, n} R = { 1. E n 2. E (E) 3. E E+E 4. E E*E}

17 IFT313© Froduald Kabanza17 Motivation pour lensemble Follow Nous venons de voir que la bonne production à prédire est une règle X telle le prochain token est dans First(. Toute fois, cette ligne directrice doit être généralisée pour tenir compte des productions commençant par la chaîne vide. Pour ce faire, nous allons introduire les notions de symbolles nullables et densemble Follow.

18 IFT313© Froduald Kabanza18 Motivation pour les symboles nullables À première vue le calcul de lensemble First parait très simple. Si XY, on a limpression que Y peut être ignoré et que First( First(XY) = First(X). En fait, cela est vrai uniquement si X ne peut pas dériver la chaîne vide. Autrement, First( doit aussi inclure First(Y). Exemple : G = (V, A, R, S) : V = {X, Y, S} A = {a, b, c} R = { 1. S a | 2. S X Y S 3. X b | 4. X Y 5. Y ε | 6. Y c} First(S) = { a, b, c } First(X) = { b, c } First(Y) = { c } First(a) = { a } First(b) = { b } First(c) = { bc} Puisque X peut dériver Y (production 4), une chaîne dérivée de XYS peut tout aussi bien être dérivée de YYS. Vu que Y peut dériver la chaîne vide (production 5), la chaîne peut tout aussi bien être dérivée de YS, ou de S.

19 IFT313© Froduald Kabanza19 Définition de symboles nullables Par conséquent, en calculant First(S) ou First(XYS) on doit tenir compte des non- terminaux qui pourraient dériver la chaîne vide et de ceux qui pourraient les suivre dans une dérivation. Les non-terminaux qui peuvent dériver la chaîne vides sont appelés des symboles nullables. Ainsi, X et Y sont nullables dans la grammaire ci après. Exemple : G = (V, A, R, S) : V = {X, Y, S} A = {a, b, c} R = { 1. S a | 2. S X Y S 3. X b | 4. X Y 5. Y ε | 6. Y c} First(S) = { a, b, c } First(X) = { b, c } First(Y) = { c } First(a) = { a } First(b) = { b } First(c) = { b } Puisque X peut dériver Y (production 4), une chaîne dérivée de XYS peut tout aussi bien être dérivée de YYS. Vu que Y peut dériver la chaîne vide (production 5), la chaîne peut tout aussi bien être dérivée de YS, ou de S.

20 IFT313© Froduald Kabanza20 Définitions formelles nullable(X) est vrai si et seulement si X peut dériver la chaîne vide en zéro ou plusieurs étapes. First( est lensemble de terminaux qui pourraient commencer une chaîne dérivée de Follow(X) est lensemble de terminaux qui pourraient suivre X immédiatement, dans une forme sententielle. En dautres mots, lensemble de terminaux a tels que S => Xa pour et quelconques. En plus, si X peut être le dernier symbole dans une forme sententielle, on ajoute $ à Follow(X). Ceci arriverait aussi si une dérivation contient XY tel que Y peut dériver la chaîne vide. Récursivement, ceci arriverait aussi si une dérivation contient XYZ tel que Y et Z peuvent chacun dériver la chaîne vide. Ainsi de suite … *

21 IFT313© Froduald Kabanza21 Définitions formelles Une définition plus formelle de nullable, First and Follow est que ce sont les plus petits ensembles pour lesquels les propriétés suivantes sont valides : If S is the start symbol, then Follow[S] contains $; For each terminal symbol a, First(a) = { a }; For each production X Y 1 … Y k If Y 1 … Y k are all nullable or (if k = 0) nullable[X] = true; for each i from 1 to k, if Y 1 … Y i-1 are all nullable (or if i=1) First[X] = Union(First[X], First[Y i ]); if Y i+1 … Y k are all nullable (or if i=k) Follow[Y i ] = Union(Follow[Y i ], Follow[X]); for each j from i + 1 to k if Y i+1 … Y j-1 are all nullable (or if i+1=j) Follow[Y i ] = Union(Follow[Y i ], First[Y j ]); Pour obtenir les ensembles nullable, First et Follow, on calcule le point fixe (ou la fermeture) de ces équations (c-à-d., on refait des itérations tant quon nobtient pas une solution stable).

22 IFT313© Froduald Kabanza22 Algorithme pour calculer nullable, First et Follow Algorithme nullableFirstFollow Entrée : une grammaire. Sortie : Trois vecteur (nullable, First et Follow) tel que pour chaque symbole de grammaire X (terminal ou non): nullable(X) est true si X est nullable First(X) est lensemble de terminaux qui peuvent commencer une chaîne dérivable de X Follow(X) est lensemble de terminaux qui peuvent suivre X dans une dérivation.

23 IFT313© Froduald Kabanza23 Algorithme pour calculer nullable, First et Follow Algorithme nullableFirstFollow initialize all entries of First and Follow to the empty set and those of nullable to false; set Follow[S] = {$}, where S is the start symbol and $ the end marker; for each terminal symbol a, First(a) = {a}; do { for each production X Y 1 …Y k { if Y 1 …Y k are all nullable or (if k = 0) nullable[X] = true; for (i = 1; i <= k; i++) { if Y 1 …Y i-1 are all nullable (or if i=1) First[X] = Union(First[X], First[Y i ]); if Y i+1 …Y k are all nullable (or if i=k) Follow[Y i ] = Union(Follow[Y i ], Follow[X]); for (j = i+1; j <= k; j++) if Y i+1 …Y j-1 are all nullable (or if i+1=j) Follow[Y i ] = Union(Follow[Y i ], First[Y j ]); } } while First, Follow or nullable is modified in the current iteration

24 IFT313© Froduald Kabanza24 Exemple 1 G = (V, A, R, S) : V = {X, Y, S} A = {a, b, c} R = { 1. S a 2. S X Y S 3. X b 4. X Y 5. Y ε 6. Y c} Iter 0. SXY nullable First Follow false {} {$}{} Iter 1. nullable First Follow false truefalse {a}{b}{c} {$}{a, c}{a} Iter 2. nullable First Follow true false {a, b, c}{b, c}{c} {$}{a, b, c}

25 IFT313© Froduald Kabanza25 Exemple 2 EET nullable First Follow true false {(,n}{+}{*} {), $}{+, ), $} G = (V, A, R, E) : V = {E, E, T, T, F, (, )} A = {(, ), +, *, n} R = { E TE E + TE | ε T FT *FT | ε F n } TF truefalse {(,n} {), $}{+, ), $}{+,*,), $}

26 IFT313© Froduald Kabanza26 Généralisation aux chaînes de symboles Il est utile de généraliser nullable et First à de chaînes de symboles dune grammaire : Étant donne une chaîne nullable( ) si et seulement si chaque symbole de est nullable. Étant donne un symbole X et une chaîne First(X )=First[X] if not nullable[X] First(X )=Union(First[X], First( if nullable[X]

27 IFT313© Froduald Kabanza27 Comment prédire une production ? Nous utilisons les ensembles First et Follow pour prédire une production en fonction du non-terminal au dessus de la pile et du prochain token (terminal) à lentrée. Lidée de base est que si le sommet de la pile est A, et le prochain token est a, alors on prédit la production A telle que a est dans First( ). Ainsi le driver LL va appliquer A en remplaçant A par au sommet de la pile. La seule complication est lorsque peut dériver la chaîne vide. Dans ce cas, nous allons prédire A si a est dans Follow( ) ou si le prochain token est $ (EOF) et $ est dans Follow(A).

28 IFT313© Froduald Kabanza28 Exemple G = (V, A, R, E) : V = {E, E, T, T, F, (, )} A = {(, ), +, *, n} R = { E TE E + TE | ε T FT *FT | ε F n } EET nullable First Follow true false {(,n}{+}{*} {), $}{+, ), $} TF truefalse {(,n} {), $}{+, ), $}{+,*,), $}

29 IFT313© Froduald Kabanza29 Exemple return true Pile 0. 3. 2. 3. 2. 3. 2. 3. 2. 3. 2. 3. 1. Étape Règle Algorithm LLDriver 0. stack = ($S); a = in.read(); x=stack.top(); while (true) { 1. if (x = = $) && (a= = $) return true ; 2. if (x = = a) && (a != $) { pop a from stack; a = in.read(); continue;} 3. if x is a nonterminal { find x y; pop x from stack; push y on stack; continue; } 4. exit with error;} Entrée 1. E TE 2. E + TE | 3. ε 4. T FT 5. T *FT | 6. ε 7. F ( E ) | n Entrée : n+n*n $E $ET $ETF $ETn $ET $E $E T+ $E T $ETF $ETn $ET $ETF* $ETF $ETn $ET $E $ n+n*n$ +n*n$ n*n$ *n$ n$ $ $ $ E TE T FT F n T ε E +TE T FT F n T *FT F n T ε E ε EET nullable First Follow truefalse {(,n}{+}{*} {), $} {+, ), $} TF truefalse {(,n} {), $} {+, ), $} {+,*), $}

30 IFT313© Froduald Kabanza30 Résumé Une fois de plus voici les règles pour prédire une production: Lidée de base est que si le sommet de la pile est A, et le prochain token est a, alors on prédit la production A telle que a est dans First( ). Ainsi le driver LL va appliquer A en remplaçant A par au sommet de la pile. La seule complication est lorsque peut dériver la chaîne vide. Dans ce cas, nous allons prédire A si a est dans Follow( ) ou si le prochain token est $ (EOF) et $ est dans Follow(A). Avec ces règles, on peut générer une table danalyse M, telle que M[A,a] contient la règle de production à appliquer lorsque A est au sommet de la pile et a est le prochain token. Nous verrons comment à la prochaine leçon.


Télécharger ppt "IFT313 Introduction aux langages formels Froduald Kabanza Département dinformatique Université de Sherbrooke planiart.usherbrooke.ca/kabanza/cours/ift313."

Présentations similaires


Annonces Google