Correction TD de Traduction no1

Transcription

Correction TD de Traduction no1
Correction TD de Traduction no1
Licence d’informatique
—2006-2007—
Introduction à l’analyse lexicale
Le but de ce TD est d’écrire des expressions régulières caractérisant certains
lexèmes, puis d’écrire le programme flex correspondant.
x Exercice 1. Expressions régulières
Écrire des expressions régulières pour reconnaı̂tre :
1. les identificateurs du C (commencent par une lettre ou un , puis une suite de
chiffres, lettres ou ) ;
2. les chaı̂nes de caractères du Pascal (’ ... ’ avec ’’ pour faire une apostrophe) ;
3. les chaı̂nes de caractères du C ;
4. les commentaires du C (/* ... */ et // ...) ;
5. les entiers (décimal, hexadécimal 0x... et octal 0...) ;
6. les flottants avec exposant.
✁
1. (LETTRE+_) (LETTRE+_+CHIFFRE)∗
2. ’ (’’+NON-APOSTROPHE)∗ ’
3. " ((\ CARACTERE)+NON-GUILLEMET)∗ "
4. – /* (NON-ETOILE + *+ NI-SLASH-NI-ETOILE∗ *∗ */
Dire que l’expression régulière n’est pas la bonne solution et qu’il faut utiliser à la
place les start-conditions.
– // (NON-RETOUR-CHARIOT)∗
5. – décimal : 0 + ([1-9] [0-9]∗ )
– hexadécimal : 0x [0-9A-Fa-f] [0-9A-Fa-f]∗
– octal : 0 [0-7] [0-7]∗
6. – 23. 23.455 : [0-9] [0-9]∗ . [0-9]∗
– .4546 : . [0-9] [0-9]∗
– 2.545e-6 : [0-9] . [0-9]∗ e (ε+-++) [0-9] [0-9]∗
✁
1
x Exercice 2. Analyse d’un programme flex
Que fait le programme flex suivant ?
%%
"/*" printf("<SE>");
"*/" printf("<ASE>");
"\\n" printf("<ASN>");
"("|"["|"{" printf("<PO>");
")"|"]"|"}" printf("<PF>");
"?"+ printf("<?;%d>",yyleng);
. ;
%%
int main() {
yylex();
return 0;
}
✁
Ce programme :
– remplace les séquences /* et */ par <SE> et <ASE> ;
– remplace les séquences constituées des caractères \ et n par <ASN> ;
– remplace toute occurrence d’un des caractères (, [ ou { par <PO> ;
– remplace toute occurrence d’un des caractères ), ] ou } par <PF> ;
– remplace toute séquence de points d’interrogation par une séquence <?;N>, où N
représente le nombre de points d’interrogation de la séquence lue ;
– supprime tous les autres caractères, car ils sont lus sans que rien ne soit produit en
sortie.
✁
x Exercice 3. Écriture d’un programme flex
1. Transposer en flex les expressions régulières du premier exercice.
✁
Penser à rappeler que les espaces ont une signification précise en flex et qu’ils ne
peuvent pas être utilisés pour aérer la présentation du code. Présenter la possibilité d’utiliser des variables comme LETTRE, et dire à quoi correspondent les variables
prédéfinies yytext et yyleng.
2
// rappel 1: toujours au moins un espace avant du C
//(par exemple, des commentaires)
// rappel 2: bien sauver un programme flex avec des
// retours chariot style Unix
LETTRE [a-zA-Z]
CHIFFRE [0-9]
%%
({LETTRE}|\_)({LETTRE}|\_|{CHIFFRE})* {printf("ID=$$%s$$\n",yytext);}
"’"([^’]|"’’")*"’" {printf("chaine pascal=%s\n",yytext);}
\"([^"]|\\.)*\" {printf("chaine C=%s\n",yytext);}
"//".* {printf("commentaire C=%s\n",yytext);}
0|([1-9]{CHIFFRE}*) {printf("entier decimal=%s\n",yytext);}
0x([a-fA-F]|{CHIFFRE})+ {printf("entier hexadecimal=%s\n",yytext);}
0[0-7]+ {printf("entier octal=%s\n",yytext);}
0|([1-9]{CHIFFRE}*)"."{CHIFFRE}* {printf("flottant=%s\n",yytext);}
"."{CHIFFRE}+ {printf("flottant=%s\n",yytext);}
{CHIFFRE}"."{CHIFFRE}*e[-+]?{CHIFFRE}+ {printf("flottant=%s\n",yytext);}
. ;
%%
int main() {
yylex();
return 0;
}
✁
2. Améliorer la lisibilité de la reconnaissance des chaı̂nes de caractères et des commentaires en utilisant des start conditions.
✁
// %x X : X est une start condition
%x CHAINEPASCAL
%x CHAINEC
%x COMMENTAIRE
%%
<CHAINEPASCAL>"’" {printf("’\n"); BEGIN INITIAL;}
<CHAINEPASCAL>"’’"|. ECHO;
<CHAINEC>\" {printf("\"\n"); BEGIN INITIAL;}
<CHAINEC>\\?. ECHO;
3
<COMMENTAIRE>. ECHO;
<COMMENTAIRE>"*/" {printf("*/\n"); BEGIN INITIAL;}
’ {printf("chaine Pascal=’"); BEGIN CHAINEPASCAL;}
\" {printf("chaine C=\""); BEGIN CHAINEC;}
"/*" {printf("commentaire C=/*"); BEGIN COMMENTAIRE;}
. ;
%%
int main() {
yylex();
return 0;
}
✁
Extrait de la page man de la commande flex
Les motifs en entrée sont écrits
d’expressions rationnelles. Ce sont :
x
.
[xyz]
[abj-oZ]
[^A-Z]
[^A-Z\n]
r*
r+
r?
r{2,5}
r{2,}
r{4}
{nom}
en
utilisant un ensemble étendu
correspond au caractère ’x’
n’importe quel caractère (octet) sauf le retour
à la ligne
une « classe de caractères » ; dans ce cas, le motif
convient pour un ’x’, un ’y’, ou un ’z’
une « classe de caractères » contenant un intervalle ;
convient pour un ’a’, un ’b’, n’importe quelle lettre
allant de ’j’ à ’o’, ou un ’Z’
une « classe de caractères niée », c.-à-d. tout caractère
sauf ceux dans la classe. Dans cet exemple, tout caractère
SAUF une lettre majuscule.
tout caractère SAUF une lettre majuscule ou un retour
à la ligne
zéro ou plusieurs r, où r est une expression rationnelle
quelconque
un ou plusieurs r
zéro ou un r (c.-à-d. un r optionnel)
entre deux et cinq r
deux r ou plus
exactement 4 r
le développement de la définition de « nom »
4
(voir au dessus)
"[xyz]\"foo"
la cha^
ıne de caractères littérale : [xyz]"foo
\X
si X est ’a’, ’b’, ’f’, ’n’, ’r’, ’t’ ou ’v’, alors la
représentation C ANSI de \x. Sinon, un ’X’ littéral
(utilisé pour protéger des opérateurs comme ’*’)
\0
un caractère NUL (de code ASCII 0)
\123
le caractère de valeur octale 123
\x2a
le caractère de valeur hexadécimale 2a
(r)
reconna^
ıt un r ; les parenthèses sont utilisées pour
surcharger la priorité (voir plus bas)
rs
l’expression rationnelle r suivie de l’expression
rationnelle s ; appelé « concaténation »
r|s
un r ou un s
r/s
un r mais seulement s’il est suivi par un s.
Le texte reconnu par s est inclus quand on détermine si
cette règle est la « correspondance la plus longue », mais
est ensuite renvoyé sur l’entrée avant que l’action ne
soit exécutée. Ainsi, l’action ne voit que le texte auquel
correspond r. Ce type de motif est appelé « contexte de
queue ». (trailing context) (Il y a certaines combinaisons
de r/s que flex ne peut détecter correctement ; voyez les
notes consacrées aux contextes de queue dangereux dans la
section Défectuosités/Bogues.)
^r
un r, mais uniquement au début d’une ligne (c.-à-d. au
début de l’analyse, ou juste après qu’un saut de
ligne ait été détecté).
r$
un r, mais seulement à la fin d’une ligne (c.-à-d. juste
avant un saut de ligne). Équivalent à « r/\n ».
Notez que la notion qu’a flex d’un « saut de ligne »
est exactement celle dont le compilateur C utilisé pour
compiler flex interprète ’\n’ ; en particulier, sur
certains systèmes DOS, vous devez soit filtrer vous-m^
eme
les \r de l’entrée vous-m^
eme, soit utiliser explicitement
r/\r\n pour « r$ ».
5
<s>r
un r, mais seulement dans la condition de démarrage s
(voyez en dessous pour une discussion sur les conditions
de démarrage)
<s1,s2,s3>r
idem, mais dans une des conditions de démarrage s1, s2
ou s3
<*>r
un r dans n’importe quelle condition de démarrage, m^
eme
une exclusive.
<<EOF>>
un end-of-file (fin de fichier)
<s1,s2><<EOF>>
un end-of-file quand on se trouve dans la condition de
démarrage s1 ou s2
Notez qu’à l’intérieur d’une classe de caractères, tous les opérateurs
d’expressions rationnelles perdent leur signification spéciale sauf
l’échappement (’\’) et les opérateurs de classes de caractères, « - »,
« ] » et, au début de la classe, « ^ ».
Les expressions rationnelles listées plus haut sont groupées en fonction de leur priorité, allant de la plus haute au sommet à la plus
basse en bas.
En plus des caractères et des intervalles de caractères, les classes de
caractères peuvent également contenir des expressions de classes de
caractères. Ce sont des expressions enfermées dans des délimiteurs [:
et :] (qui doivent elles-m^
emes appara^
ıtre entre le ’[’ et le ’]’ de la
classe de caractères ; d’autres éléments peuvent également ^
etre
présents dans la classe de caractères). Les expressions valides sont :
[:alnum:]
[:cntrl:]
[:lower:]
[:space:]
[:alpha:]
[:digit:]
[:print:]
[:upper:]
[:blank:]
[:graph:]
[:punct:]
[:xdigit:]
Ces expressions désignent toutes un groupe de caractères
la fonction C standard correspondante isXXX.
6
équivalent
à