• Aucun résultat trouvé

IFT313 Introduction aux langages formels

N/A
N/A
Protected

Academic year: 2022

Partager "IFT313 Introduction aux langages formels"

Copied!
30
0
0

Texte intégral

(1)

IFT313

Introduction aux langages formels

Froduald Kabanza

Département d’informatique Université de Sherbrooke

planiart.usherbrooke.ca/kabanza/cours/ift313

Ensembles first et follow

(2)

IFT313 © Froduald Kabanza

2

Sujets

• C’est quoi un symbole nullable pour une grammaire?

• C’est quoi un ensemble first pour une grammaire ?

• C’est quoi un ensemble follow pour une grammaire ?

• Quel l’algorithme pour calculer ces symboles et ces ensembles ?

• Quel est le rôle de ces concepts dans l’analyse syntaxique descendante (prédictive) ?

– C’est quoi une table d’analyse LL ?

– Comment la calculer.

(3)

IFT313 © Froduald Kabanza

8

Exemple

return true Pile

0.

3.

3.

3.

2.

3.

3.

2.

3.

3.

2.

3.

2.

3.

2.

3.

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

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’

FT’E’

nT’E’

nT’E’

nE’

n +TE’

n+TE’

n+FT’E’

n+nT’E’

n+nT’E’

n+n*FT’E’

n+n*FT’E’

n+n*nT’E’

n+n*nT’E’

n+n*nE’

n+n*n

S Þ déjà lu + pile

* n+n*n$ *

n+n*n$

n+n*n$

n+n*n$

+n*n$

+n*n$

+n*n$

n*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’ ε

E$

TE’$

FT’E’$

nT’E’$

T’E’$

E’$

+TE’$

TE’$

FT’É’$

nT’E’$

T’E’$

*FT’E’$

FT’E’$

nT’E’$

T’E’$

E’$

$

(4)

IFT313 © Froduald Kabanza

13

Définition de l’ensemble First

- Étant donné a une chaîne de terminaux et de non-terminaux, alors

First( a) est l’ensemble de terminaux commençant une chaîne dérivée de a.

- Exemple :

G = (V, A, R, E) : V = {E, E’, T, T’}

A = {(, ), +, *, n}

R = { E  TE’

E’  + TE’ | ε T  FT’ | ε T’  *FT’ | ε

F  ( E ) | n}

First(TE’) = {(, n, +}

First(+TE’) = { + } First(FT’) = { (, n}

First(*FT’) = { * } First((E)) = { ( } First(n) = { n}

(5)

IFT313 © Froduald Kabanza

14

Utiliser l’ensemble 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  a tel que le prochain token est dans First( a) .

- Exemple :

G = (V, A, R, E) : V = {E, E’, T, T’}

A = {(, ), +, *, n}

R = { E  TE’

E’  + TE’ | ε T  FT’ | ε T’  *FT’ | ε

F  ( E ) | 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  ( E )

- sinon, si le prochain token est n le driver LL prédit F  n

- sinon le driver sort avec une erreur.

(6)

IFT313 © Froduald Kabanza

15

Utiliser l’ensemble First dans le driver LL

- Si la grammaire ne contient pas deux productions X  a et X  b telles que First( a) et First(b) 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  a and X  b telles que First( a) et First(b) 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.

(7)

IFT313 © Froduald Kabanza

16

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}

(8)

IFT313 © Froduald Kabanza

17

Motivation pour l’ensemble Follow

- Nous venons de voir que la bonne production à prédire est une règle X  a telle le prochain token est dans First( a ) .

- 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

d’ensemble Follow.

(9)

IFT313 © Froduald Kabanza

18

Motivation pour les symboles nullables

- À première vue le calcul de l’ensemble First parait très simple.

 Si a= XY, on a l’impression que Y peut être ignoré et que First(a)= First(XY)

= First(X).

- En fait, cela est vrai uniquement si X ne peut pas dériver la chaîne vide.

- Autrement, First(a) 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) = { c}

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.

(10)

IFT313 © Froduald Kabanza

19

Définition de symboles nullables

- On vient de voir qu’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.

(11)

IFT313 © Froduald Kabanza

20

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(a) est l’ensemble de terminaux qui pourraient commencer une chaîne dérivée de a.

- Follow(X) est l’ensemble de terminaux qui pourraient suivre X immédiatement, dans une forme sententielle.

- En d’autres mots, l’ensemble de terminaux a tels que S => g Xab pour g et b 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 …

*

(12)

IFT313 © Froduald Kabanza

21

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  Y1 … Yk

If Y1 … Yk are all nullable or (if k = 0) nullable[X] = true;

for each i from 1 to k,

if Y1… Yi-1 are all nullable (or if i=1) First[X] = Union(First[X], First[Yi]);

if Yi+1… Yk are all nullable (or if i=k) Follow[Yi] = Union(Follow[Yi], Follow[X]);

for each j from i + 1 to k

if Yi+1… Yj-1 are all nullable (or if i+1=j) Follow[Yi] = Union(Follow[Yi], First[Yj]);

- 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 qu’on n’obtient pas une solution stable).

(13)

IFT313 © Froduald Kabanza

22

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 l’ensemble de terminaux qui peuvent commencer une chaîne dérivable de X

Follow(X) est l’ensemble de terminaux qui peuvent suivre X dans une dérivation.

(14)

IFT313 © Froduald Kabanza

23

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  Y1…Yk {

if Y1…Yk are all nullable or (if k = 0) nullable[X] = true;

for (i = 1; i <= k; i++) {

if Y1…Yi-1 are all nullable (or if i=1) First[X] = Union(First[X], First[Yi]);

if Yi+1…Yk are all nullable (or if i=k) Follow[Yi] = Union(Follow[Yi], Follow[X]);

for (j = i+1; j <= k; j++)

if Yi+1…Yj-1 are all nullable (or if i+1=j) Follow[Yi] = Union(Follow[Yi], First[Yj]);

} }

} while First, Follow or nullable is modified in the current iteration

(15)

IFT313 © Froduald Kabanza

24

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.

S X Y

nullable First

Follow

false false false

{} {} {}

{$} {} {}

Iter 1.

nullable First Follow

false true false

{a} {b} {c}

{$} {a, c} {a}

Iter 2.

nullable First Follow

true true false

{a, b, c} {b, c} {c}

{$} {a, b, c} {a,b, c}

(16)

IFT313 © Froduald Kabanza

25

Exemple 2

E E’ T

nullable First Follow

true false false

{(,n} {+} {*}

{), $} {+, ), $}

G = (V, A, R, E) :

V = {E, E’, T, T’, F, (, )}

A = {(, ), +, *, n}

R = {

E  TE’

E’  + TE’ | ε

T  FT’

T’  *FT’ | ε

F  ( E ) | n }

T’ F

true false

{(,n} {(,n}

{), $} {+, ), $}{+,*,), $}

(17)

IFT313 © Froduald Kabanza

26

Généralisation aux chaînes de symboles

- Il est utile de généraliser nullable et First à de chaînes de symboles d’une grammaire :

• Étant donne une chaîne a, nullable( a ) si et seulement si chaque symbole de a est nullable.

• Étant donne un symbole X et une chaîne g : First(X g )=First[X] if not nullable[X]

First(X g )=Union(First[X], First( g)) if nullable[X]

(18)

IFT313 © Froduald Kabanza

27

Comment prédire une production ?

- Nous utilisons les ensembles First et Follow pour prédire une production en fonc- tion du non-terminal au dessus de la pile et du prochain token (terminal) à l’entrée.

- L’idé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  a telle que a est dans First(a).

 Ainsi le driver LL va appliquer A  a , en remplaçant A par a au sommet de la pile.

- La seule complication est lorsque a peut dériver la chaîne vide.

 Dans ce cas, nous allons prédire A  a si a est dans Follow(A) (ceci inclus le cas où le prochain token est $ (EOF) et $ est dans Follow(A)).

(19)

IFT313 © Froduald Kabanza

28

Exemple

G = (V, A, R, E) :

V = {E, E’, T, T’, F, (, )}

A = {(, ), +, *, n}

R = {

E  TE’

E’  + TE’ | ε

T  FT’

T’  *FT’ | ε

F  ( E ) | n }

E E’ T

nullable First Follow

true false false

{(,n} {+} {*}

{), $} {+, ), $}

T’ F

true false

{(,n} {(,n}

{), $} {+, ), $}{+,*,), $}

(20)

IFT313 © Froduald Kabanza

29

Exemple

return true Pile

0.

3.

3.

3.

2.

3.

3.

2.

3.

3.

2.

3.

2.

3.

2.

3.

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

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

n+n*n$

n+n*n$

n+n*n$

n+n*n$

+n*n$

+n*n$

+n*n$

n*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’ ε

E E’ T

nullable First

Follow

true false false

{(,n} {+} {*}

{), $} {+, ), $}

T’ F

true false

{(,n} {(,n}

{), $} {+, ), $}{+,*), $}

E$

TE’$

FT’E’$

nT’E’$

T’E’$

E’$

+TE’$

TE’$

FT’É’$

nT’E’$

T’E’$

*FT’E’$

FT’E’$

nT’E’$

T’E’$

E’$

$

(21)

IFT313 © Froduald Kabanza

30

Résumé

- Une fois de plus, voici les règles pour prédire une production:

- L’idé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  a telle que a est dans First(a).

 Ainsi le driver LL va appliquer A  a , en remplaçant A par a au sommet de la pile.

- La seule complication est lorsque a peut dériver la chaîne vide.

 Dans ce cas, nous allons prédire A  a si a est dans Follow(A) (ceci inclut le cas où le prochain token est $ (EOF) et $ est dans Follow(A)).

- Avec ces règles, on peut générer une table d’analyse 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.

Références

Documents relatifs

- Ceci nous donne deux chois pour coder un analyseur lexical (scanner) à partir d’une expression régulière :.. Convertir l’AFN en AFD et utiliser un pilote (driver)

- Étant donné un ensemble S d’états de l’AFN, ε-closure(S) est l’ensemble des états atteignables dans l’automate, à partir d’un état dans S, et sans consommer un

• Deux états dans d’un AFD M sont équivalents (indistinguable) si et seulement si pour chaque mot u, lorsque une exécution de M sur l’entrée u commence dans l’un ou

- Pour analyser la syntaxe d’une grammaire hors-contexte, nous ajoutons une pile à un automate fini pour obtenir un modèle de programmes plus puissant connu sous le nom de

 Pour ce faire la partie gauche de la production (un non-terminal) est enlevée de la pile et remplacée par la partie droite de la production. (q, ε, A)  (q, a) pour chaque

 Parce que les deux règles ont la même fonction d’analyse (c-à-d., la fonction correspondant au non terminal dans la partie gauche de chaque production).. Si elle partagent le

– Si le symbole est un non terminal, l’attribut pourrait être une donnée calculée en utilisant les actions sémantiques. – Une grammaire avec des attributs est appelée

• Pour aller au-delà, il faut utiliser d’autres outils ou des méthodes adhoc pour évaluer les attributs (avec l’aide