Title: Analyse lexicale
1Analyse lexicale
Généralités Expressions rationnelles Automates
finis Analyseurs lexicaux
2Rôle d'un analyseur lexical
lexèmes
analyseur lexical
analyseur syntaxique
code source
...
table des symboles
Séparer l'analyse lexicale de l'analyse
syntaxique Réduire la complexité du compilateur
et la complexité de conception de ces deux
modules Augmenter la flexibilité du compilateur
portabilité, maintenabilité Augmenter
l'efficacité du compilateur
3Méthodes de construction
- Utiliser un générateur d'analyseurs lexicaux
(Flex) - Ecrire l'analyseur lexical dans un langage évolué
4Lecture du code source (1/2)
On utilise un tampon de lecture cyclique en deux
moitiés Anticiper lire quelques caractères
d'avance pour décider la valeur du lexème en cours
... a 4 i 1 ...
fin
debut
Une anticipation de quelques caractères suffit Un
langage où il n'y avait pas de limite à la taille
de l'anticipation PL/1 DECLARE ( ARG1, ARG2,
... , ARGn ) Il faut attendre la fin de
l'expression pour savoir si DECLARE est un
mot-clé ou un nom de tableau
5Lecture du code source (2/2)
... a 4 i 1 ...
fin
debut
si fin atteint la fin de la première moitié alors
charger la deuxième moitié fin fin 1
sinon si fin atteint la fin de la deuxième
moitié alors charger la première moitié fin
0 sinon fin fin 1
6Mots et langages formels
Un mot sur un alphabet A est une suite finie de
symboles pris dans A A peut être l'ensemble des
caractères, dans ce cas les lexèmes sont des mots
alphabet mots
code ASCII 0, 1 caractères
analyse lexicale caractères lexèmes
analyse syntaxique lexèmes programmes
Le mot vide est noté e, sa longueur est 0 Un
langage formel est un ensemble de mots
7Expressions rationnelles
On forme des expressions à partir des symboles
(éléments de l'alphabet) et de e en utilisant -
l'union notée (ou ) - la concaténation (pas
de symbole) - l'itération notée On utilise
souvent des opérations supplémentaires
(abréviations) pour l'itération au moins une
fois ? pour l'option . pour tout
l'alphabet ... pour une union de
symboles Priorités entre opérateurs itération,
concaténation, union
8Expressions rationnelles
Identificateurs en C lettre A B ... Z
a b ... z chiffre 0 1 ... 9 id
(lettre _) (lettre _ chiffre) Nombres
sans signe en C chiffre 0 1 ...
9 chiffres chiffre chiffre frac .
chiffres exp (E e) ( - e) chiffres e
num (chiffres (frac . e) frac) exp
Les mêmes avec les abréviations chiffre 0 1
... 9 chiffres chiffre frac .
chiffres exp ((E e) ( -) ? chiffres)?
num (chiffres (frac .)? frac) exp
9Lexèmes
Définition des espaces blancs delim \b \t
\n ws delim On dit habituellement lexème
pour "catégorie de lexèmes"
expression lexème attribut
ws - -
if if -
else else -
id id pointeur
num num valeur
etc.
expression lexème attribut
lt relop lt
lt relop le
relop eq
! relop ne
gt relop gt
gt relop ge
10Automates finis
Les analyseurs lexicaux utilisent des graphes
appelés automates finis - les sommets sont
appelés états - les transitions sont orientées et
étiquetées - certains états sont finaux et
comportent une action
lettre _ chiffre
autre
11
12
13
return(gettoken(), install)
lettre
_
Identificateurs en C
11Automates finis
autre
0
1
2
return(relop, lt)
lt
3
return(relop, le)
gt
autre
5
4
return(relop, gt)
6
return(relop, ge)
8
7
return(relop, eq)
!
10
9
return(relop, ne)
Opérateurs de comparaison
12Automates finis
chiffre
chiffre
14
15
E e
chiffre
-
chiffre
autre
19
16
17
18
chiffre
.
.
chiffre
E e
21
20
chiffre
chiffre
22
23
autre
chiffre
24
chiffre
.
.
autre
26
25
chiffre
Nombres sans signe en C
13Implémentation en C
Un programme C qui reconnaît dans le début d'une
chaîne de caractères un des lexèmes définis par
les automates / Recherche de l'état initial du
prochain automate / int state 0, start 0
int lexical_value int fail() forward
token_debut switch(start) case 0 start
11 break case 11 start 14 break
case 14 start 22 break case 22
recover() break default / erreur /
return start
14token nexttoken() while (1) switch(state)
case 0 c nextchar() if
(cblankctabcnewline) state 0
debut else if (c 'lt') state 1
else if (c 'gt') state 4 else if (c
'') state 7 else if (c '!') state
9 else state fail() break / ...
cas 1 - 10 ... / case 11 c nextchar()
if (isletter(c)c'_') state 12
else state fail() break
15 case 12 c nextchar() if
(isletter(c)c'_') state 12 else if
(isdigit(c)) state 12 else state 13
break case 13 retract(1)
install_id() return(gettoken()) / ...
cas 14-26 ... /
16Automates déterministes
Un automate fini est déterministe si - il
possède au plus un état initial - de chaque état
part au plus une flèche étiquetée par un symbole
donné Exemple d'automate non déterministe
a
a b
2
1
a
Exemple d'automate déterministe
a
b
a
2
1
b
17Automates déterministes
Un automate déterministe représentant un ensemble
de mots peut être utilisé commodément pour
reconnaître l'un des mots dans une chaîne de
caractères il suffit de partir de l'état
initial, de suivre les flèches et de voir si
l'état dans lequel on arrive est final. Tout
automate fini est équivalent à un automate fini
déterministe il existe un automate fini
déterministe qui reconnaît le même langage.
18Déterminisation
Algorithme on part d'un automate fini A (Q,
I, F, ?). On construit l'automate déterministe D
ayant 1. comme états les parties de Q 2. comme
état initial I 3. comme états finaux les parties
de Q contenant au moins un élément de F 4. comme
transitions les (U, a, V) si V est l'ensemble des
états atteignables depuis U par une transition
étiquetée a Complexité si A a n états, D a au
plus 2n états.
19Exemple
a b
a
b
1
2
3
Un automate non déterministe
b
a
a
b
1
1 2
1 3
a
b
Le résultat de l'algorithme
20Généralisation
On peut admettre des transitions d'étiquette ?
(transitions spontanées). Pour être déterministe,
un automate ne doit pas contenir de transitions
spontanées. Pour déterminiser, on adapte
l'algorithme précédent - à l'étape 2 on prend
l'ensemble des états atteignables depuis I par un
chemin de transitions spontanées - à l'étape 3,
V est l'ensemble des états atteignables depuis U
par un chemin étiqueté a
21La construction récursive
On peut construire un automate fini équivalent à
une expression rationnelle il reconnaît le même
langage. L'automate construit est tel que - il
a un seul état initial i - il a un seul état
final f ? i - aucune transition n'entre dans i -
aucune transition ne sort de f. Pour ? et a, on
prend
? ?
a
22??
union
??
??
??
concaténation
??
??
??
itération
??
??
??
23Utilisation de Flex
spécification Flex
lex.yy.c
flex
compilateur C
caractères (code source)
a.out
lexèmes
...
4 étapes - créer sous éditeur une spécification
Flex (expressions rationnelles) - traiter cette
spécification par la commande flex - compiler le
programme source C obtenu - exécuter le programme
exécutable obtenu
24Spécifications Flex
Un programme Flex est fait de trois parties
déclarations règles de traduction fon
ctions auxiliaires en C Les règles de traduction
sont de la forme p1 action1 p2 action2
... pn actionn où chaque pi est une
expression rationnelle et chaque action une suite
d'instructions en C.
25Exemple
/ Partie en langage C définitions de
constantes, déclarations de variables globales,
commentaires... / delim \t\n letter a-zA-Z
delim / pas d'action / if
return IF then return THEN else
return ELSE letter(letter0-9) yyval
install_id() return ID
(0-9(\.0-9)?\.0-9)((Ee)(\-)?0-9)
? yyval install_num() return NUMBER
26Exemple
"lt" yyval LT return RELOP "lt"
yyval LE return RELOP install_id()
/ fonction installant dans la table des
symboles le lexème vers lequel pointe yytext et
dont la longueur est yylength. Renvoie un
pointeur sur l'entrée dans la table
/ install_num() / fonction calculant la
valeur du lexème /
27Spécifications Flex
Les commentaires / ... / ne peuvent être
insérés que dans une portion en C - dans la
partie déclaration, seulement entre et -
dans la partie règles, seulement dans les actions
- dans la partie fonctions auxiliaires,
n'importe où. Dans les règles pi actioni
les expressions rationnelles pi ne peuvent pas
contenir d'espaces blancs (ou alors
dé-spécialisés). Dans la partie règles, si une
règle commence par un espace blanc, elle est
interprétée comme du langage C et est insérée
dans lex.yy.c au début de la fonction qui renvoie
le prochain lexème (utilisable pour déclarer des
variables locales).
28Segmentation du code sourcepar l'analyseur
lexical (1/3)
L'analyseur lexical produit par Flex - commence à
chercher les lexèmes au début du code source -
après chaque lexème reconnu, recommence à
chercher les lexèmes juste après Exemple si
piraté est reconnu, raté n'est pas reconnu Si
aucun lexème n'est reconnu à partir d'un point du
code source l'analyseur affiche le premier
caractère sur la sortie standard et recommence à
chercher à partir du caractère suivant
29Segmentation du code sourcepar l'analyseur
lexical (2/3)
Si plusieurs lexèmes sont reconnus à partir d'un
point du code source (conflit) 1. Deux lexèmes
de longueurs différentes C'est le plus long qui
gagne Exemple a-zA-Z_ a-zA-Z_0-9
30Segmentation du code sourcepar l'analyseur
lexical (3/3)
2. Deux lexèmes de même longueur Ils commencent
au même point et terminent au même point s'il y
a conflit, c'est qu'ils sont issus de deux règles
différentes. C'est la règle qui apparaît la
première dans la spécification Flex qui
gagne Exemple conflit entre a-zA-Z_
a-zA-Z_0-9 et while Mettre l'exception avant
la règle En dehors de ce cas, l'ordre des règles
ne joue pas