Vous êtes sur la page 1sur 41

ANALYSE LEXICALE

Phase de la compilation
 Modle Analyse et Synthse
 Les compilateurs actuels sont le plus souvent conus sur le
modle Analyse et Synthse qui consiste dissocier deux
parties distinctes:

 La partie Avant ou Frontale( front-end ) qui analyse le


programme source, conformment la dfinition du langage
compil, indpendamment du langage cible.

 La partie Arrire ou Finale ( back-end ) qui produit le code


gnr, conformment la dfinition du langage cible,
indpendamment du langage source.

 Les deux parties communiquent entre elles via une ou


plusieurs structures de donnes intermdiaire, le plus
souvent des tables et/ou des arbres.
vocabulaire
 Unit lexicale (token) : type gnrique dlments lexicaux
(correspond un ensemble de mots ayant une smantique proche)
(Ex. identificateur, oprateur relationnel, mot-cl )

 Lexme (mot) : occurrence dune unit lexicale


( Ex. i est un lexme dont lunit lexicale est identificateur)

 Modle (pattern) : sert spcifier une unit lexicale


( Ex. identificateur = lettre (lettre + chiffre)*)

 Attribut : information supplmentaire sur lunit lexicale, il influe sur


la traduction de lunit lexicale.
( Ex. Pour un nombre, il sagit de sa valeur; Plus pour +, )
Les principales units lexicales quon trouve dans
les langages de programmation courants sont :

 les caractres spciaux simples : + , = , etc


 Les caractres spciaux doubles: <= , ++, etc
 Les mots cls : if , while , etc
 les constantes littrales : 123 , -5 , etc
 Les identificateurs : i1 , n , etc
Unit lexme attribut Unit lexme attribut
lexicale lexicale
blanc - - < oprel inf

if if - <= oprel infeg

else else - == oprel egal

while while - != oprel diff

id i1 pointeur > oprel sup

etc. >= oprel supeg


Rle d'un analyseur lexical
lexmes
analyseur analyseur
code source lexical syntaxique

table des
symboles
 Fonctionnalits de l analyse lexicale
 cest la phase 1 du processus de compilation; ses
principales fonctions consistent :
 lire le texte source
 analyser ce texte conformment la dfinition lexicale du
langage compil
 dcouper le flot dentre en units lexicales:
 mots cls ou rservs
 constantes entires, relles,
 identificateurs
 sparateurs, oprateurs, etc.
 liminer certaines units inutiles pour la compilation:
 espaces et caractres spciaux,
 commentaires, etc.
 Flot d entre
 le texte source, caractre par caractre

 Flot de sortie
 des units lexicales ou lexmes ( tokens )

 Interactions
 lanalyseur lexical entretient des interactions avec les
composants suivants:
 le gestionnaire de la table des symboles, qui mmorise et identifie
les identificateurs
 lanalyseur syntaxique, qui reoit le flot des lexmes

Linterface avec lanalyseur syntaxique est une fonction ( int uniteSuivante(void) )


qui renvoit, chaque appel, lunit lexicale suivante dans le texte source.
Stratgie
 Lanalyseur lexicale reconnat le lexme le plus long
- Pour <= lanalyseur ne doit pas sarrter <
- x36estunevariable est reconnu comme identificateur

 Deux manires de traiter les mots cls :


- Soit de les incorporer dans les diagrammes de transition (automates), ce qui permet
davoir des automates trs volumineux

- Soit on les traite de la mme manire que les identificateurs; on les stocke dans une
table et on y fait une recherche pour savoir si le lexme reconnu est un mot rserv
ou un identificateur.

 Les sparateurs (espace, tabulation, retour chariot) sont considrs comme unit
lexicale vide (ne seront pas transmis)

 Les erreurs : lanalyseur peut essayer de resynchroniser pour dtecter dautres


erreurs ventuelles (aucun code ne sera gnr )
Outils de limplmentation
 Les outils thoriques

langages rguliers :
* expression rgulire
* lexme ( token )
Automates finis
* dterministes
* non dterministes
* transducteurs
Outils de limplmentation
 Les outils logiciels

Les gnrateurs lexicaux


* lex, flex, javalex,
* grep, egrep, .
.
.
Les langages de programmation (mta langage)
Analyse lexicale programm en dur
Les diagrammes de transitions peuvent tre convertis en
code de manire systmatique.

lettre | _ | chiffre

autre * rendre ID
11 12 13
lettre
_

Identificateurs en C
.
autre *
0 1 2 rendre INF
<
=
3 rendre INFEG
>
autre * rendre SUP
4 5
=
= 6 rendre SUPEG

=
7 8 rendre EGAL
!

9 = 10 rendre DIFF

Oprateur de relation
. chiffre

chiffre
14 15 E|e
chiffre +|- chiffre autre *
16 17 18 19
chiffre
. . chiffre
E|e
20 21
chiffre chiffre

22 23 autre
chiffre
24 *
chiffre
. .
autre
25 26
chiffre

Nombres sans signe en C


RECONNAISSANCE DUNE UNITE LEXICALE
A chaque tat, on associe un bout de code.
Si ltat est final :
- si ltat comporte une toile, il faut rendre le dernier caractre lu
(utiliser la fonction unget, ce caractre peut tre le dbut
dun autre lexme.
- dterminer lunit lexicale (et ventuellement lattribut) qui se
trouve entre deux pointeurs dbut et fin.
- faire avancer le pointeur dbut jusqu la position de fin.
( on peut affecter ltat final le code de lunit lexicale
reconnue si ltat nest pas toil sinon le code
(code ngatif). Lunit lexicale rendue est abs(tat final)).

Sinon
- lire le prochain caractre et faire avancer le pointeur fin.
- si le caractre lu correspond une transition, effectuer la transition
- sinon appeler la fonction fail () pour dterminer le prochain tat initial.

La reconnaissance dune unit lexicale consiste initialiser les tats star


et state par ltat initial du premier automate.
Implmentation en C
Un programme C qui reconnat dans le dbut d'une chane de caractres un des
lexmes dfinis par les automates

/* Recherche de l'tat initial du prochain automate */


 int state = 0, start = 0 ;
 int lexical_value ;
 int fail() {
 fin = 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 ; }
 int nexttoken() {
 while (1) {
 switch(state) {
 case 0 : c = nextchar() ;
 if (c== || c== \t ||c== \n) {
 state = 0 ; debut ++ ; }
 else if (c == '<') state = 1 ;
 else if (c == '>') 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 ;
 case 12 : c = nextchar() ;
 if (isletter(c)||c=='_') state = 12 ;
 else if (isdigit(c)) state = 12 ;
 else state = 13 ;
 break ;
 case 13 : retract(1) ; ranger_id() ;
 return(code(ID)) ;
 /* ... cas 14-26 ... */
 }
 }
 }
OUTIL LOGICIEL : Lex (Flex)
 Gnalogie

 Lex a t cre par les laboratoires Bell sous Unix en 1975


 Il existe une version dnomme Flex, qui amliore les
fonctionnalits de Lex et qui peut tre utilise en mode
compatible Lex.
 Il existe des versions spcifiques de Lex ou Flex pour :
 Ada
 Eiffel, C++
 Java
.
spcification
(f)lex lex.yy.c compilateur C
(f)lex

caractres
a.out lexmes
(code source)
Entre de lex: Sorties
Lentre de lex est un ensemble de Lex construit un source C lex.yy.c, qui
rgles lexicales associant: implmente un analyseur lexical sur la
- des expressions rgulires base dun automate fini dterministe
tendues pour augmenter le rduit correspondant la spcification
confort de lutilisateur donne en entre.
- des actions smantiques La compilation du source lex.yy.c
programmes en C gnre une fonction de dcoupage:
yylex()

Interaction : - avec yacc, via la fonction yylex()


- avec la table des symboles, via la programmation en C.
Utilisation sous unix : $ lex anallex $ flex anallex
$ cc lex.yy.c ll $ gcc lex.yy.c -lfl
Spcification des units lexicales
 Les expressions rgulires constituent un outil de base pour dcrire
les units lexicales en utilisant les oprateurs: | , produit, * et les
parenthses pour les priorits entre oprateurs.
 On allge ces expressions en introduisant des dfinitions rgulires
qui permettent de donner des noms aux expressions. On crit:
d1 = r 1
d2 = r 2

dn = r n
o chaque di est un mot sur distinct de d1, d2, , di-1 et
chaque ri est expression rgulire sur {d1, d2, ,di-1}
Exemple.

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) (+ | - | ) chiffres |
num = (chiffres (frac | . | ) | frac) exp
Expressions rgulires tendues

 mta-oprateurs de confort
[ ] pour les numrations associes -
+ pour la rptition une fois ou plus
? pour 0 ou 1 fois
. comme caractre joker sauf \n
^ pour le complmentaire dans un [ ]
.
Structure dun fichier lex
Un fichier source pour lex doit avoir un nom qui se termine par .l .
Il est fait de quatre parties :
%{
dclaration (en C) de variables, constante,
%}
dclaration de dfinitions rgulires
%%
rgles de traduction
%%
fonctions C supplmentaires
 La premire partie dclaration de variable, et %{ et %} peuvent tre omis. On
trouve souvent ici une directive #include qui produit linclusion du fichier .h
contenant les codes des units lexicales.

 La dernire partie fonctions C supplmentaires est optionnelle et le symbole %%


qui la prcde peut alors tre omis. On y trouve la fonction main() par exemple.

 Les dfinitions rgulires sont de la forme :


identificateur expressionRgulire
(identificateur doit tre crit au dbut de la ligne et des espaces le spare de
expressionRgulire)

 Exemples de dfinitions
Minuscule [a-z]
Majuscule [A-Z]
NonLettre [^a-zA-Z]
Lettre ({Minuscule}|{Majuscule})
Chiffre [0-9]
Mot {Lettre}+
Motdauplus7L {Lettre}{1, 7}
Entier [0-9]+
EntierSign (("-"|"+")?{Entier})
 Les rgles de traductions sont de la forme :
expressionRgulire { action }
expressionRgulire doit tre au dbut de ligne et action est du code C
qui sera recopi tel quel dans la fonction yylex.

Exemple.
lettre [A-Za-z]
chiffre [0-9]
alphanum ({lettre}|{chiffre})
%%
{lettre}{alphanum}* {return IDENTIF}
{chiffre}+(.{chiffre}+)? {return NOMBRE}
if {return SI}
then {return ALORS}
else {return SINON}

Remarque: dans cet exemple, toute action est de la forme return token.
Quand une chane du texte source est reconnue, la fonction yylex se termine.
Il faudra appeler de nouveau cette fct pour que lanalyse du texte reprenne.
Variables et fonctions prdfinies
 Char yytext[] : tableau de caractres qui contient la chane reconnue
 Int yyleng : longueur de la chane reconnue
 Int yylex() : fonction qui lance lanalyseur (et appelle yywrap() ).
 Int yywrap() : fonction toujours appele en fin de flot dentre. Elle
ne fait rien par dfaut, mais lutilisateur peut la redfinir dans la
section des fonctions supplmentaires. yywrap() retourne 0 si
lanalyse doit se poursuivre (sur un autre fichier dentre) et 1 sinon.
 Int main() : la fonction main() par dfaut contient juste un appel
yylex(). Lutilisateur peut la redfinir.
 Int yylineno : numro de la ligne courante.
Exemples de fichiers .l

Exemple1 : Un filtre qui compte le nombre de caractres,


de mots et de lignes dun fichier.
%{
int Nb_Car, Nb_Word, Nb_Line;
%}
chiffre [0-9]
lettre [a-z]|[A-Z]
alphanum {chiffre}|{lettre}
blanc " "
%%
({alphanum})+ {ECHO; Nb_Car += yyleng; Nb_Word++;}
({blanc})+ {ECHO; Nb_Car += yyleng;}
\n {ECHO; Nb_Line++;}
%%
#include <studio.h>
int main()
{
Nb_Car=Nb_Word=Nb_Line=0;
yylex() ; /* pas de return */
printf("\nNb_Car=%d\nNb_Word=%d\nNb_Line=%d\n\n",
Nb_Car,Nb_Word,Nb_Line);
return(1);
}

Remarque : - l entre /sortie de lex est standard.


- les caractres qui ne font partie daucune chane reconnue sont
recopis sur la sortie standard
- les chanes reconnues ne sont pas recopies sur la sortie standard
- ECHO est quivalent : printf("%s , yytext)
Exemple 2.
%{
int ncar, nmot, nline;
%}
%%
\n {nline++; ncar++; }
[^ \t\n]+ {nmot++; ncar += yyleng; }
. {ncar++; }
%%
int main( int argc, char *argv[])
{
yyin = fopen (arg[1], r);
yylex();
fclose (yyin)
}
Exemple: (Ex.6 de la srie 2)
1. Expression rgulire .
tendue acceptant les
phrases correctes selon les
critres suivants:
- Le 1er mot commence par
une majuscule (en dbut de
ligne)
^[A-Z][A-Za-z]*(\ [A-Za-z]+)*\.$
- La phrase se termine par un
point (en fin de ligne)
- La phrase est constitue par
un ou plusieurs mots
spars par un espace.
2. Fichier lex danalyse lexicale.
Les lexmes reconnus sont :
- les nombres
- les identificateurs
- les oprateurs relationnels
- les mots clefs : si, sinon, alors
Fichier unitsLexicales .h :
#define INF 256
#define INFEG 257
#define EGAL 258
#define DIFF 259
#define SUP 260
#define SUPEG 261
#define SI 262
#define ALORS 263
#define SINON 264
#define NOMBRE 265
#define IDENTIF 266

extern int valNombre;


extern char valIdentif[]
Fichier anallex .l (source pour lex)
%{
#include "unitsLexicales .h
%}
chiffre [0-9]
lettre [A-Za-z]
%%
[" "\t\n] { ECHO; /* pas daction */ }
{chiffre}+ {ECHO; valNombre = atoi (yytext); return NOMBRE; }
si { ECHO; return SI; }
alors {ECHO; return ALORS; }
Sinon {ECHO; return SINON; }
{lettre}({lettre}|{chiffre})* {ECHO; strcpy(valIdentif, yytext); return IDENTIF; }
== {ECHO; return EGAL; }
!= {ECHO; return DIFF; }
< {ECHO; return INF; }
<= {ECHO; return INFEG; }
> {ECHO; return SUP; }
>= {ECHO; return SUPEG; }
.
%%
Int valNombre;
Char valIdentif[256];
Int yywrap(void) { return 1; }
Fichier principal .c (purement dmonstratif)
#include <stdio .h>
#include "unitsLexicales .h
Int main(void) {
Int unite;
Do {
unite = yylex();
printf(" (unit: %d", unite);
if ( unite == NOMBRE) printf(" val : %d", valNombre);
else if ( unite == IDENTIF)
printf(" %s", valIdentif);
printf(")\n");
} while (unite != 0);
Return 0;
}
Fichier essai .txt (comme entre pour excuter lanalyseur)
Si x == 123 alors
y = 0;
Cration dun excutable et test sur le texte
(lex sous Linux est flex; $ est le prompt du systme)
$ flex anallex.l
$ gcc lex.yy.c principal.c o monprog
$ monprog < essai.txt

(la fonction yywrap est appele lorsque lanalyseur rencontre la fin du


fichier analyser. Elle indique que le flot dentre est dfinitivement
puis ou bien ouvrir un autre flot dentre.)