Vous êtes sur la page 1sur 11

SAOUDI Lalia

Analyse lexicale

2007/2008

II. Analyse lexicale

1. Introduction :

L'analyse lexicale constitue la première phase de compilation ; elle consiste à segmenter un texte source en un ensemble de mots quon appelle traditionnellement «tokens» (leur terme exact est «lexème», ce qui signifie unité lexicale, que l’analyseur syntaxique va utiliser ; cette interaction est implantée en faisant de l’analyseur lexical un sous programme de l’analyseur syntaxique, à la réception d’une commande « prochaine unité lexicale » émanant de l’analyseur syntaxique, l’analyseur lexical lit les caractères d’entrées jusqu’à ce qu’il puisse identifier la prochaine unité lexicale.

Unité lexicale

Pgm source--analyseur lexical----------------------analyseur syntaxique

lexical----------------------  analyseur syntaxique <---------------------- Obtenir prochaine unité

<----------------------

 analyseur syntaxique <---------------------- Obtenir prochaine unité lexicale Table des symboles Il peut

Obtenir prochaine unité lexicale

Table des symboles

Il peut également réaliser certaines taches secondaires, une de ces tâches est l’élimination dans le programme source des commentaires et des espaces qui apparaissent sous formes de caractères blanc tabulation ou fin de ligne.

Une autre tâche consiste à relier les messages d’erreur issus du compilateur au programme source par exemple un analyseur lexical peut associer un message d’erreur au numéro de ligne.

2 . Unité lexicale

Définition : Une unité lexicale est une suite de caractères qui a une signification collective

Exemple :

Les chaines <,>,= sont des opérateurs relationnels, l’unité lexicale est OPREL par exemple

est une règle associe à unité lexicale qui décrit l’ensemble des

chaines du programme qui peuvent correspondre à cette unité lexicale

Définition : on appelle lexème toute suite de caractère du pgm source qui concorde avec le modèle d’une unité lexicale.

Définition Un modèle

Exemple

L’unité lexicale IDENT (identificateur) en C a pour modèle toute suite non vide de caractère composé de chiffre, lettre, ou des symboles et qui commence par une lettre

Exemple de lexème pour cette unité lexicale sont a ; b ; montant, tot1….

Pour décrire un modèle d’une unité lexicale on utilisera les expressions régulières.

SAOUDI Lalia

Analyse lexicale

2007/2008

3 .Rappels:

Dans cette partie, nous introduisons quelques notions de base de la théorie des langages Les expressions régulières est une notation importante pour spécifier des modèles. Chaque modèle reconnait un ensemble de chaines.

Rappels de notation

On appellera alphabet un ensemble fini dont les éléments seront appelés lettres.

Exemple : 0,1 sont les lettres de l’alphabet binaire

Un mot sur un alphabet A est une suite finie d’éléments de A.

Un mot de longueur n composé des lettres a 1 , a 2 ……., an sera noté a 1 a 2 …a n , le mot vide est noté ε

La concaténation de deux mots w1 et w2 est notée w1w2

L’ensemble des mots sur A est noté A*

Un langage sur un alphabet A est un ensemble de mots de A*

Opérations sur les langages

L U M= {s/sϵL ou sϵM}

LM={st/sϵL et tϵM}

L*=U i=0 L i L + =U i=1 L i

4. Expression régulière

Une expression régulière est une formule close permettant de désigner un ensemble de chaines de caractères construites à partir d’un alphabet ∑ (éventuellement augmentée de la chaine vide). On appelle cet ensemble de chaîne de caractère un langage. Une expression régulière est une notation pour décrire un langage régulier.

Soit un alphabet (un ensemble de lettres), une expression régulière est donc

1. Les éléments de , ε et Ø sont des expressions régulières.

2 .Si α et β sont des expressions régulières, alors (α | β), (αβ) et α* sont des expressions

régulières. (α | β)représente l’union, (αβ) la concaténation et α * la répétition (C’est donc

l’union des concaténations de α avec lui même zéro fois (c’est `a dire la chaîne vide) ou plus. ε est l’élément neutre par rapport à la concaténation et Ø est l’ensemble vide de caractère, neutre par rapport à l’union. On peut éviter les parenthèses dans des expressions régulières si l’on adopte les conventions suivantes :

1-

* a la plus haute priorité et est associatif à gauche

2-

La concaténation a la deuxième plus haute priorité

3-

/ a la plus faible priorité

Exemple :

SAOUDI Lalia

Analyse lexicale

2007/2008

1-Selon ces conventions, (a)/ ((b)* (c)) <-->à a/b*c

Les deux expressions dénotent l’ensemble des chaines qui ont soit un seul a ou un nombre quelconque ; ou nul ; de b suivi par un c

2 - Soit C={a,b}

1. l’expression réguliere a |b dénote l’ensemble {a,b}

2. L’expression régulière (a |b) (a |b) dénote {aa,ab,ba,bb} l’ensemble de toutes les chaines de

a et b de longueur 2

3. L’expression régulière a* dénote l’ensemble de toutes les chaines formées d’un nombre

quelconque de a, c. à. d {ε,a,aa,aaa, …………… }

4. l’expression régulière a|a*b dénote l’ensemble contenant la chaine a et toutes les chaines

constituées d’un nombre quelconque de a (éventuellement nul) suivi de b.

Notations abrégées :

1. Au moins une instance : r + =rr*

2. Zéro ou une instance : r ? c une abréviation de r| ε

3. ε r°= ε

4. Classes de caractères : la notation [abc] où a,b,c sont des symboles d’alphabets dénote l’expression régulière a/b/c

Une classe de caractères comme [a-z] dénote l’expression réguliere a/b/c… /z

On peut décrire un identificateur comme

Identificateur = lettre (lettre | chiffre|sep)*

Tel que lettre=[a-zA-Z]

Chiffre=[0-9 ]

Sep=_

5.Reconnaissance des unités lexicales

Un reconnaisseur pour un langage est un pgm qui prend en entrée une chaine x et répond oui si x est un mot du langage et non autrement. On compile une expression réguliere en un reconnaisseur en construisant un diagramme de transition généralisé appelé automate fini.

Pour illustrer cette section nous allons nous donner comme exemple le problème de la reconnaissance des unités lexicales INFEG, DIFF, INF, EGAL, SUPEG, SUP, IDENTIF, respectivement définies par les expressions régulières <=, <>, <, =, >=, > et lettre(lettre/chiffre)*. Par exemple, figure suivante montre les diagrammes traduisant la reconnaissance des unités lexicales INFEG, DIFF, INF, EGAL, SUPEG, SUP et IDENTIF.

SAOUDI Lalia

Analyse lexicale

2007/2008

SAOUDI Lalia Analyse lexicale 2007/2008 Les automates fini peut être déterministes ou non ; sont capables

Les automates fini peut être déterministes ou non ; sont capables de reconnaitre exactement ce que les expressions régulières peuvent dénoter, cependant il ya un conflit temps / espace ; alors les AFD peuvent conduire à des reconnaiseurs plus rapide que les AFND ; un AFD peut être beaucoup volumineux qu’un AFND.

Les automates finis non déterministe

Un automate fini non déterministe (AFND) est un quintuplet A=(Q , ,δ,q0, F), où

-Q est in ensemble fini d’états

- est un alphabet

- δ : Q x u { ε } Q est la fonction de transition

-q0 est l’état initial

- F est l’ensemble des états terminaux ou finaux

Un automate non-déterministe est un automate qui présente la particularité suivante :

Plusieurs arcs reconnaissant le même caractère peuvent « sortir » du même état. Il peut y avoir des transitions, notées ε, qui ne correspondent à une aucune reconnaissance de caractères.

Le langage reconnu par un automate (Q , ,δ,q0, F) est l’ensemble des mots w tels qu il existe q F tel que q0---w q

SAOUDI Lalia

Analyse lexicale

2007/2008

Présentation de l’automate :

Un automate est souvent représenté par un graphe orienté dont les sommets sont les états et les arêtes étiquetées correspondent aux transitions, on distingue les états d’acceptations que l’on entourera d’un cercle et l’état initial.

que l’on entourera d’un cercle et l’état initial. Exemple : construire l’AFN qui reconnait le langage

Exemple : construire l’AFN qui reconnait le langage ( a/b) * abb.

Le langage défini par un AFN est l’ensemble des chaines d’entrée qu’il accepte.

Un AFN accepte une chaine d’entrée x si et seulement s’il existe un certain chemin dans le graphe de transition entre l’état initial et l’état final

Automate fini déterministe.

L’automate est dit déterministe lorsque

1. la fonction δ associe à chaque couple (état, lettre) un état unique

2. aucun état n’a de ε transition

6. EXPRESSIONS REGULIERES ET AUTOMATES

Pour être capable de construire un automate qui reconnaisse un langage régulier quelconque, il suffit d’avoir un mécanisme qui reconnait chaque lettre, puis un mécanisme qui reconnait la Concaténation, l’union et la fermeture de langages reconnus. Construction d’un AFN à partir d’une expression réguliere :

Donnée : une expression réguliere r sur un alphabet ∑

Résultats : Un AFN qui connait L(r)

Page

10

SAOUDI Lalia

Analyse lexicale

2007/2008

Méthode : On décompose d’abord r en ses sous expressions. Puis, en utilisant les règles 1 et 2, on construit des automates pour chacune des symboles de base c.à.d. soit ε soit les symboles de l’alphabet

Ensuite en se guidant sur la structure syntaxique de l’expression régulière r, on combine récursivement les AFN de chaque sous expression de r, en utilisant la règle 3 jusqu’à obtenir l’AFN pour l’expression complète

Si les expressions régulières r 1 et r 2 sont reconnues respectivement par les automates A1 et A2, avec q0 comme état initial et q comme un état final alors

0-si r= Ø alors l’automate a deux états distincts q0 et q sans transition entre eux (q n’est donc pas atteignable)

1-si r=ε alors l’automate a un seul état q0=q et pas de transitions.

2-Si R=a alors on met une seule transition entre q0 et q.

3- Si r=(r1|r2) Un automate connaissant r1|r2 est construit de la manière suivante à partir des automates A1 et A2 : son état d’entrée est un nouvel état qui possède deux ε transitions vers les états d’entrée de A1 et A2. Il possède un état accepteur, qui est un nouvel état recevant des εtransitions de tous les états accepteurs de A1 et A2. -Si r=r1r2 lautomate est construit comme la juxtaposition de A1 et A2. Il a pour entrée l’´etat d’entrée de A1, pour états accepteurs les états accepteurs de A2, -Si r=r1 * on crée un nouvel état t initial et final, on peut aller de i à f directement en suivant un arc étiqueté ε ou bien on peut aller de i à f traversant A1 une ou plusieurs fois

Exemple d’automate non-déterministe :

Nous allons illustrer ce processus sur un exemple simple, il est élémentaire à généraliser. Considérons le langage désigné par l’expression régulière : a(b/ c)* . Le parenthésage indique l’ordre dans lequel on doit décomposer l’expression ; il faut reconnaitre dans l’ordre : les langages b et c puis (b/ c) puis (b/c)* puis a puis a(b/c)*.

Page

11

SAOUDI Lalia

Analyse lexicale

2007/2008

SAOUDI Lalia Analyse lexicale 2007/2008 Exemple : Utilisez l’algorithme pour construire l’AFN pour l’ER r=

Exemple : Utilisez l’algorithme pour construire l’AFN pour l’ER r= ( a/b) * abb

7. Déterminisation :

On veut maintenant obtenir un automate déterministe ( D , ∑ , δd , d0 , Df) à partir d’un Automate Non Déterministe ( N , ∑ , δn , n0 , Nf) , la clef est de dériver D et δd. ∑ reste le même.

Page

12

SAOUDI Lalia

Analyse lexicale

2007/2008

L’algorithme utilisé est appelé la construction des sous ensembles ( subset construction) . L’idée est que les états du nouvel automate sont des ensembles d’états de l’ancien automate. un nouvel état qi = { n1 ,n2…nk} contient l’ensemble des anciens états pouvant être atteints en lisant un caractère particulier depuis un état qj. L’algorithme utilisé est le suivant :

- Q0 ε- fermeture (n0)

- initialiser Q avec q0

- WorkList q0

Tant que ( WorkList ≠ Ø) Choisir qi dans WorkList Pour chaque caractère c ϵ ∑ qε- fermeture ( Δ(qi ,c))

δd (qi ,c)q

si q Q alors ajouter q à worklist ajouter q à Q

l’ ε- fermeture

atteint par des ε- transitions à partir des états de l’ensemble. l’opérateur Δ ( qi , c) calcule l’ensemble des états atteignables en lisant c depuis les états ni i

de qi : si qi= { n i 1 , n i 2 ………

Algorithme de calcul de ε- fermeture ( q)

d’un ensemble d’états ajoute à cet ensemble d’état tous les états pouvant être

n

i k } alors

Δ ( qi , c ) =

U

δ n ( n i j

, c )

- Empiler tous les états de q dans une pile

- Initialiser ε- fermeture (q) à q

- Tant que pile n’est pas vide faire Début Dépiler ni , le sommet de la pile Pour chaque état e avec un arc de ni à e étiqueté ε faire Si e n’est pas dans ε- fermeture (q) faire Début Ajouter e à ε- fermeture (q) Empiler e dans la pile Fin Fin Appliquons cet algorithme sur l’automate non-d´eterministe :

cet algorithme sur l’automate non -d´eterministe :   A B C S0  q0 s1 ,s8,s6,s9,s2,s4
 

A

B

C

S0q0

s1 ,s8,s6,s9,s2,s4

-

-

s1 ,s8,s6,s9,s2,s4q1

-

s3,s7,s9,s6,s2,s4

s5,s7,s9,s6,s2,s4

s3,s7,s9,s6,s2,s4q2

-

s3,s7,s9,s6,s2,s4

s5,s7,s9,s6,s2,s4

s5,s7,s9,s6,s2,s4q3

-

s3,s7,s9,s6,s2,s4

s5,s7,s9,s6,s2,s4

Page

13

SAOUDI Lalia

Analyse lexicale

2007/2008

SAOUDI Lalia Analyse lexicale 2007/2008 Nous obtenons l’automate suivant : Exemple 2 : rendre l’automate

Nous obtenons l’automate suivant :

Exemple 2 : rendre l’automate AFN de l ER ( a /b ) * abb déterministe

b C b b a b b A B D E a
b
C
b
b
a
b
b
A
B
D
E
a

a

a 8. Minimisation Le grand nombre d’états de l’automate résultant de la déterminisation est un problème pour l’implémentation. La minimisation permet de regrouper les états équivalents, c’est `a dire qui ont le même comportement sur les mêmes entrées. L’algorithme de minimisation construit une partition de l’ensemble D des états de l’automate déterministe, chaque état étant dans le même sous ensemble a le même comportement sur les mêmes entrées. L’algorithme est le suivant :

Initialement, la partition consiste en deux groupes : les états finaux et les états non-finaux. L’étape principale consiste à prendre un groupe d’états par exemple A= {e1,e2…ek} et un symbole a, et à étudier les transitions des états de A sur a, si ces transitions conduisent à des états qui tombent dans au moins deux groupes différents de la partition courante, alors on doit diviser A de manière que les transitions depuis chaque sous ensemble de A soient toutes confinées à un seul groupe de la partition courante. Nous répétons ce processus de division de groupes de la partition courante jusqu’à ce que plus aucun groupe n’ait besoin d’être divisé. Soit un AFD dont l’ensemble d’états est E et l’alphabet d’entrées est ∑, nous supposons que chaque état a une transition sur chaque symbole d’entrée, si ce n’était pas le cas, nous pourrions introduire un nouvel état « état mort » d avec des transitions depuis d vers d sur tous les symboles, ainsi qu’une transition depuis l’état e vers d sur le symbole a s’il n y avait pas déjà de transition de e sur a. Algorithme : minimisation du nombre d’états d’un AFD

1. Construire une partition initiale II de l’ensemble des états avec deux groupes : les états finaux F et les états non finaux E-F

2. Appliquer la procédure partitionner à II pour construire une nouvelle partition II n.

3. Si II n = II , soit II f = II et continuer à l’étape 4. Sinon répéter l’étape 2 avec II = II n

4. choisir un état dans chaque groupe de la partition II f en tant que représentant de ce groupe. Les représentants seront les états de l’AFD réduit.

5. Si l’AFD réduit a un état mort d, alors supprimer d de l’ AFD, supprimer aussi tout état non accessible depuis l’état de départ.

Procédure Partitionner :

Page

14

SAOUDI Lalia

Analyse lexicale

2007/2008

Pour chaque groupe G de II faire Début

- Partitionner G en sous groupes de manière que deux états e et t de G soient dans le même sous groupe si et seulement si , pour tout symbole a, les états e et t ont des transitions sur a vers des états du même groupe de II.

- Remplacer G dans II n par tous les sous groupes ainsi formés

Fin Exemple : Revenons à l’AFD de l’expression régulière : ( a /b) * abb , construire son AFD minimisé

1-II={ E , ABCD}

2-

*sur le symbole b D a une transition vers E II1={ E, D, ABC}

3- sur le symbole b B a ne transition vers D II2={E, D, AC,B}

a

b

A

B

C

B

B

D

C

B

C

D

B

B,E

4-Dans la passe suivante on ne peux découper aucun des groupes, donc IIf= {E,B,D, AC}

5-Si l’on a choisi A comme représentant du groupe AC , on obtient

l'automate réduit , l’état A est l’état de départ et E est le seul état

d’acceptation ( final)

9. Implémentation d’un automate Il s’agit maintenant de produire une implémentation de l’automate généré lors de la production précédente. Il y a essentiellement deux types d’implémentation, les analyseurs basés sur des tables et les analyseurs codés directement.

9.1 Analyseur lexical à base de table

L’analyseur utilise un programme squelette commun à tous les analyseurs lexicaux et une table dans laquelle est stockée la fonction de transition. Pour notre exemple cela donne :

char prochain caractère states0 tant que (char EOF) state δ(state; char) char prochain caractère si (state ϵ F )

alors accepter

sinon rejeter

caractère si ( state ϵ F ) alors accepter sinon rejeter 9.2 Analyseur lexical codé directement

9.2 Analyseur lexical codé directement

Le type d’analyseur précédent passe beaucoup de temps à tester et manipuler la variable

d’état, on peut éviter cela en codant directement l’´etat dans l’´etat du programme :

s0 : char prochain caractère si (char =’ a’) alors goto s1 sinon goto se s1 : char prochain caractère si (char =’ b|char =c) alors goto s1 sinon si (char =EOF) alors accepter sinon goto se

Page

15

SAOUDI Lalia

Analyse lexicale

2007/2008

se : rejeter Ce type d’implémentation devient rapidement difficile à gérer manuellement, mais il peut être généré automatiquement et sera en général plus rapide que l’analyseur à base de table.

10. Implémentation efficace des analyseurs lexicaux :

Une procédure à suivre pour implémenter un analyseur lexical pour un langage donné pourrait se résumer comme suit :

0-

Spécifier chaque type d’entité lexicale à l’aide d’une expression régulière

1-

Convertir chaque expression régulière obtenue en 1 en un automate finis

2-

Construire l’automate union de tous les automates de l’étape 2

3-

Rendre l’automate de l’étape 3 déterministe

4-

Réduire au minimum, le nombre des états de l’automate de l’étape 4.

5-

Implémenter l’automate obtenu à l’étape 5

11. Outils d’analyse lexicale :

Des nombreux outils ont été bâtis pour construire des analyseurs lexicaux tels que : lex , flex , ocamllex qui prennent en entrée un fichier source contenant les expressions régulières et les actions associées et après la compilation produisent un fichier de langage cible associé ( c pour lex et flex et ocaml pour ocamllex), qui doit être compilé par le compilateur de code cible.

Page

16