Chap II Analyse Lexicale
Chap II Analyse Lexicale
Chap II Analyse Lexicale
: Analyse Lexicale
L'analyse lexicale consiste à segmenter un texte source en un ensemble de mots que l'on appelle
traditionnellement « tokens» (ou «lexème»), ce qui signifie un objet appartenant à une unité lexicale.
Il s'agit d'une part de déterminer la suite des caractères comprenant le token, et d'autre part
d'identifier le type de token (identificateur, nombre, opérateur, etc.), dans l’autre cas, c’est une erreur
lexicale !
Pour réaliser cette tache, il nous faut un Analyseur Lexical (ou Scanner) : c’est un programme
qui représente un Automate d’Etats Finis (AEF) correspondant à des Expressions Régulières (ER)
définissant les différents mots du langage à compiler (source). Donc, on peut déduire les taches
principales de cet analyseur :
1) Ignorer les commentaires et les caractères superflus (blancs, tabulations, fins des lignes, …).
2) Afficher les messages d’erreur (mots n’appartenant pas au langage).
3) Insérer les attributs correspondants aux différents « tokens »
Remarque :
L’analyseur lexical peut être réalisé directement au moyen d’un langage de haut niveau (C, Java, …), ou
bien, au moyen d’un outil d’aide comme le Lex ou Flex.
Outil d’aide
(Lex ou Flex)
Expressions
Régulières
Définition 1 : Une unité lexicale est une classe de chaines de caractères qui a une signification
collective.
Exemples : les chaînes ≥, ≤, >, < sont des opérateurs relationnels. L'unité lexicale est
OPREL (par exemple). Les chaînes toto, ind, tab, ajouter sont des identificateurs (de
variables, ou de fonctions). Les chaînes if, else, while sont des mots clefs. Les
symboles , ; () sont des séparateurs.
Définition 2 : Un modèle est une règle associée à une unité lexicale qui décrit l'ensemble des chaînes du
programme qui peuvent correspondre à cette unité lexicale.
Définition 3 : On appelle lexème toute suite de caractère du programme source qui concorde avec le
modèle d'une unité lexicale.
Exemples :
L'unité lexicale IDENT (identificateur) en C a pour modèle : toute suite non vide de
caractères composée de chiffres, lettres ou du symbole "_" et qui commencent par une
lettre. Des exemples de lexèmes pour cette unité lexicale sont : truc, i,a1, ajou_valeur
L'unité lexicale NOMBRE (entier signé) a pour modèle : toute suite non vide de chiffres
précédée éventuellement d'un seul caractère parmi {+ , -}.
Lexèmes possibles : -12, 83204, +0 ...
L'unité lexicale REEL a pour modèle : tout lexème correspondant à l'unité lexicale
NOMBRE suivi éventuellement d'un point et d'une suite (vide ou non) de chiffres, le tout
suivi éventuellement du caractère E ou e et d'un lexème correspondant à l'unité lexicale
NOMBRE. Cela peut également être un point suivi d'une suite de chiffres, et
éventuellement du caractère E ou e et d'un lexème correspondant à l'unité lexicale
NOMBRE. Exemples de lexèmes : 12.4, 0.5e3, 10., -4e-1, -.103e+2 ...
Pour décrire le modèle d'une unité lexicale, on utilisera des Expressions Régulières.
b) Expressions régulières
Les expressions régulières permettent de décrire les mots d’un langage régulier (de type 3). Pour
décrire cette notion, on doit se rappeler de quelques notions de la théorie des langages.
Définitions 1 :
On appelle alphabet un ensemble fini non vide de symboles (lettres).
On appelle mot toute séquence finie d'éléments de .
On note le mot vide.
On note l'ensemble infini contenant tous les mots possibles sur .
On note l'ensemble des mots non vides que l'on peut former sur , c'est à dire
On note |m| la longueur du mot m, c'est à dire le nombre de symboles de composant le mot.
On note l'ensemble des mots de de longueur n. on peut dire que
Exemples :
Soit l'alphabet , aaba, bbbacbb, c, , ca sont des mots de , de longueurs respectives :
4, 7, 1, 0 et 2.
Soit l'alphabet . , aba n'est pas un mot de . baab, caa, bc, aaaa sont des mots de
de longueurs 3, 2, 2 et 2.
Propriété
| u.v |=| u | + | v |
(u.v).w=u.(v.w) (associativité)
est l'élément neutre pour . :
Union :
Intersection :
Concaténation :
Itération :
Etoile :
Problème :
Étant donné un langage, comment décrire tous les mots acceptables ? Comment décrire un langage ?
Il existe plusieurs types de langage (classification –Voir cours Théorie de Langages), certains étant plus
facile à décrire que d'autres. On s'intéresse ici aux langages réguliers.
Définition 3 : Un langage régulier L sur un alphabet est défini récursivement de la manière suivante :
Définition 4 : Les expressions régulières (E.R.) sur un alphabet et les langages qu'elles décrivent
sont définis récursivement de la manière suivante :
Remarque : Il existe une priorité décroissante des opérations sur les E.R : *, concaténation, |
C'est à dire par exemple que ab*|c = ((a)((b)*))|(c)
Propriété : La concaténation est distributive par rapport à | : c'est à dire que r( s | t) = rs | rt et ( s|t )r=sr|
tr.
Exemples :
(a|b)* dénote l'ensemble de tous les mots formés de a et de b, ou le mot vide.
(a|b)*=(b|a)*
(a)|((b)*(c))=a|b*c est soit le mot a, soit les mots formés de 0 ou plusieurs b suivi d'un c. C'est à dire
Exemples :
Pour ce qui est des symboles <=, >=, <, >, <>, l'analyseur syntaxique a juste besoin de savoir que cela
correspond à l'unité lexicale OPREL (opérateur relationnel).
C'est seulement lors de la génération de code que l'on aura besoin de distinguer < de >= (par exemple).
Pour ce qui est des identificateurs, l'analyseur syntaxique a juste besoin de savoir que c'est l'unité
lexicale IDENT.
Mais le générateur de code, lui, aura besoin de l'adresse de la variable correspondant à cet
identificateur. L'analyseur sémantique aura aussi besoin du type de la variable pour vérifier que les
expressions sont sémantiquement correctes.
Université de Tébessa 2014 – 2015 6 M. : ZEBDI A
Compilation (3ème LMD –S5-) Chap2 : Analyse Lexicale
Remarque : Cette information supplémentaire, inutile pour l'analyseur syntaxique, mais utile pour les
autres phases du compilateur, est appelée Attribut.
Exemple : e0=0
, ,
(et sinon)
, , ,
Représentation graphique :
Convention : on dessinera un triangle pour l'état initial et un carré pour les états finaux
état a b
0 0,1 0
1 - 2
2 - 3
3 - -
e0=0 et
Définition 2 : Le langage reconnu par un automate est l'ensemble des chaînes qui permettent de
passer de l'état initial à un état terminal.
N.B : Un automate peut très facilement être simulé par un algorithme (et donc un programme simulant un
automate fini). C'est encore plus facile si l'automate est déterministe
Définition 2 : Un automate fini est dit déterministe lorsqu'il ne possède pas de -transition et lorsque
pour chaque état e et pour chaque symbole a, il y a au plus un arc étiqueté a qui quitte e
Remarque : L'automate donné en exemple précédent n'est pas déterministe, puisque de l'état 0, avec la
lettre a, on peut aller soit dans l'état 0 soit dans l'état 1.
NB : Les AFD sont plus faciles à simuler (pas de choix dans les transitions, donc jamais de retours en
arrière à faire).
Il existe des algorithmes permettant de « déterminiser » un automate non déterministe (c'est à
dire de construire un AFD qui reconnaît le même langage que l'AFN donné). L'AFD obtenu comporte en
général plus d'états que l'AFN, donc le programme le simulant occupe plus de mémoire.
Automate reconnaissant r+
Mettre des -transitions de chaque état terminal de A(r) vers son état initial
état a b
0 0,2 1
1 3 0,2
2 3,4 2
3 2 1
3
4 -
e0=0 et
"état" a b
en appliquant l’algorithme on obtient :
0 0,2 1
0,2 0,2,3,4 1,2
1 3 0,2
0,2,3,4 0,2,3,4 1,2,3
1,2 3,4 0,2
3 2 1 Puis, ça devient :
1,2,3 2,3,4 0,1,2
3,4 a b2
état 1,3
02 1 3,4 2 2
2,3,4 2,3,4 1,2,3
Université de Tébessa
0,1,2 0,2,3,4 0,1,2 2014 – 2015 10 M. : ZEBDI A
1,3 2,3 0,1,2
2,3 2,3,4 1,2
Compilation (3ème LMD –S5-) Chap2 : Analyse Lexicale
1 3 4
2 5 1
3 3 6
4 7 1
5 8 2
6 9 10
7 8 11
8 7 8
9 9 6
10 3 10
11 12 10
12 9 4
Exemple:
Soit l'AFN
état a b c
0 2 - 0 1
1 3 4 - -
2 - - 1,4 0
3 - 1 - -
4 - - 3 2
e0=0 et
-fermeture , ...
Déterminisation :
état a b c
0,1 2,3,0,1 4,2,0,1 0,1
0,1,2,3 0,1,2,3 0,1,2,4 0,1,4,2
0,1,2,4 0,1,2,3 0,1,2,4 0,1,3,4,2
0,1,2,3,4 0,1,2,3 0,1,2,4 0,1,2,3,4
état a b c
0 1 2 0
1 1 2 2
2 1 2 3
3 1 2 3
avec e0=0 et
But : obtenir un automate ayant le minimum d'états possible. En effet, certains états peuvent être
équivalents.
Principe : on définit des classes d'équivalence d'états par raffinements successifs. Chaque classe
d'équivalence obtenue forme un seul même état du nouvel automate.
1 - Faire deux classes : A contenant les états terminaux et B contenant les états non terminaux.
Sur l'exemple:
(1) et
Cet automate reconnaît le même langage que l'AFN que nous avions au début.
ou encore, en copiant le travail de l'automate (mais cela donne un code moins rapide, car il contient
beaucoup d'appels de fonctions).
void Etat1()
{
char c;
c= getchar();
swicth(c) {
case ':' : Etat2();
break;
case '<' : Etat5();
break;
case 'a' : Etat57();
break;
...
default : ERREUR();
}
}
void Etat36524()
...
Il n'est pas évident du tout dans tout ça de s'y retrouver si on veut modifier l'analyseur, le compléter, ...
Heureusement, il existe des outils pour écrire des programmes simulant des automates à partir de simples
définitions régulières. Par exemple : flex
Université de Tébessa 2014 – 2015 15 M. : ZEBDI A
Compilation (3ème LMD –S5-) Chap2 : Analyse Lexicale
Peu d'erreurs sont détectables au seul niveau lexical, car un analyseur lexical a une vision très
locale du programme source. Les erreurs se produisent lorsque l'analyseur est confronté à une suite de
caractères qui ne correspond à aucun des modèles d'unité lexicale qu'il a à sa disposition.
Par exemple, dans un programme C, si l'analyseur rencontre esle, s'agit t-il du mot clef else mal
orthographié ou d'un identificateur ? Dans ce cas précis, comme la chaîne correspond au modèle de
l'unité lexicale IDENT (identificateur), l'analyseur lexical ne détectera pas d'erreur, et transmettra à
l'analyseur syntaxique qu'il a reconnu un IDENT. S'il s'agit du mot clef mal orthographié, c'est l'analyseur
syntaxique qui détectera alors une erreur.
Autre exemple : s'il rencontre 1i, il ne sait pas s'il s'agit du chiffre 1 suivi de l'identificateur i ou d'une
erreur de frappe (et dans ce cas l'utilisateur pensait-il à i1, i, 1 ou à tout autre chose ?). L'analyseur lexical
peut juste signaler que la chaîne 1i ne correspond à aucune unité lexicale définie.
Lorsque l'analyseur est confronté à une suite de caractères qui ne correspond à aucun de ses modèles,
plusieurs stratégies sont possibles :
Cette dernière se fait en calculant le nombre minimum de transformations à apporter au mot qui
pose problème pour en obtenir un qui ne pose plus de problèmes. On utilise des techniques de calcul de
distance minimale entre des mots. Cette technique de récupération d'erreur est très peu utilisée en pratique
La stratégie la plus simple est le mode panique. En fait, en général, cette technique se contente de
refiler le problème à l'analyseur syntaxique. Mais c'est efficace puisque c'est lui, la plupart du temps, le
plus apte à le résoudre.