Institut Supérieur de Gestion de Tunis
Les Générateurs d·analyseurs lexicaux et syntaxiques Elaboré par : Sassi Najla
I.
Générateurs d¶analyseurs lexicaux
[email protected]
1.
Définition
Le générateur d¶analyseur lexical accepte en entrée des spécifications d¶unités lexicales sous forme de définitions régulières et produit un programme écrit dans un langage de haut niveau qui, une fois compilé, reconnait ces unités lexicales. Parmi ces générateurs nous pouvons citer : Lex(unix),Flex(windows)
2.
Structure du fichier de spécifications (flex)
%{ Déclaration (en C) de variables, constantes,... %} Déclaration de définition régulières r égulières %% Règles de traduction %% Bloc principal et fonctions auxiliaires
défintion reguliere permet d¶asocier un nom à une expression réguliere et de se referer par la Suite dans la section des règles à ce nom plutot qu¶à l¶expression réguliere. Les règles de traduction sont des suites d¶instructions de la forme Exp1 action1 Exp2 action2 Les exp sont des expression regulieres, les actions sont des bloc d¶instruction d¶instruction en C si elle comporte plusieurs instructions alors ils doivent etre entre {}. La derniere section est facultative. y
Une
y
y
3.
Variables et fonctions prédéfinies
Char yytext[] : tableau de caracteres qui contient la cha ine d¶entrée Int yyleng : longueure de chaine Int yylex() : fonction qui lance l¶analyseur Int main() par dfaut contient juste un appel à yylex(). L¶utilisateur peut la redefinir dans la section des fonctions auxiliaire. 4.
Exemple de fichier.lex
Reconnait les nombres binaires %% (0|1)+ printf(« oh un nombre binaire binair e !\n ») ; Compte le nombre de voyelles, consonnes et caracteres de ponctuations d¶un texte entré au clavier. %{ Int nbvoy,nbcol,nbponct ; %} Consonne [b-df-hj-np-xz]
Ponctuation [, ;:?!\.] Voyelle [aeiouy] %% Voyelle nbvoy++ ; {consonne} nbconsonnes++ ; {ponctuation} nbponct++ ; %% Main() { Nbvoy=nbcons=nbponct=0 ; Yylex() ; Printf(µil ya %d voyelles,%d consonnes et %d signes de ponctuation.\n »,nbvoy,nbcol,nbponct) ; } /* partie pour les déclarations de include et autres concernant tout ce que nous voudrions écrire
en C dans les actions sémantiques*/ sémantiques*/ %{ #include "global.h" #include "compiler.h" #include
%} /* ici, vous spécifiez vos définitions régulières pour reconnaître des unités lexicales ou tokens*/ blancs [ \t]+ espace \040+ chiffre [0-9] entier {chiffre}+ exposant [eE][+-]?{entier} lettre [A-Za-z] id {lettre}(_|({lettre}|{chiffre})*) reel {entier}("."{entier})?{exposant}? %% /*ici actions mises entre accolades à faire quand lautomate atteindra un état final*/ "while" {printf("UL reconnue : %s\n","WHILE");return(WHILE);}; {blancs} { /* On ignore */ } {reel} {printf("UL {printf(" UL reconnue : %s\n","NOMBRE");return(NOMBRE);}; {id} {printf(" UL reconnue : %s\n","ID");return(ID);}; "{" {printf("UL reconnue : %s\n","ACCGAUCHE");return(ACCGAUCHE);}; "}" {printf("UL reconnue : %s\n","ACCDROITE");return(A %s\n","ACCDROITE");return(ACCDROITE);}; CCDROITE);}; "+" {printf("UL reconnue : %s\n","PLUS");return(PLUS);}; %s\n","PLUS");return (PLUS);}; "-" {printf("UL reconnue : %s\n","MOINS");return(MOINS);}; "*" {printf("UL reconnue : %s\n","FOIS");return(FOIS);}; "/" {printf("UL reconnue : %s\n","DIVISE");return(DIVISE);}; ";" {printf("UL reconnue : %s\n","PV");return (PV);}; "^" {printf("UL reconnue : %s\n","PUISSANCE");return(PUISS %s\n","PUISSANCE");return(PUISSANCE);}; ANCE);}; "(" {printf("UL reconnue : %s\n","PARENTHESE_GAUCHE");return( PARENTHESE_GAUCHE);}; ")" {printf("UL reconnue : %s\n","PARENTHESE_DROITE");return(PARENTHESE %s\n","PARENTHESE_DROITE");return(PARENTHESE_DROITE);}; _DROITE);}; "=" {printf("UL reconnue : %s\n","AFFECTATION");return(AFFECTATION);}; "<" {printf("UL reconnue : %s\n","OPEREL");return(O %s\n","OPEREL");return(OPEREL);}; PEREL);}; ">" {printf("UL reconnue : %s\n","OPEREL");return(OPEREL); %s\n","OPEREL");return(OPEREL);}; }; "<=" {printf("UL reconnue : %s\n","OPEREL");return %s\n","OPEREL");return(OPEREL);}; (OPEREL);}; ">=" {printf("UL reconnue : %s\n","OPEREL");return %s\n","OPEREL");return(OPEREL);}; (OPEREL);}; "==" {printf("UL reconnue : %s\n","OPEREL");return(OPE %s\n","OPEREL");return(OPEREL);}; REL);}; "<>" {printf("UL reconnue : %s\n","OPEREL");return(OPEREL);}; "\n" {printf("UL reconnue : %s\n","FIN");return(FIN);}; %s\n","FIN");return(F IN);};
II.
Générateurs d¶analyseurs syntaxiques 1. Rappel 2.
Définition
Un
générateur d¶analyseur syntaxique accepte en entrée la description d¶un langage sous forme de règles de productions et produit un programme programme écrit dans un langage de haut niveau qui, une fois compilé, reconnait des phrases de ce langage. Parmi ces générateurs nous pouvons citer : YACC (unix), BISON (windows)
3.
Structure du fichier fichier de spécifications ( Bison)
%{ (1)Déclaration(en (1)Déclaration(en C) de variables, constantes... %} (2)Déclaration des unités lexicales utilisées %% (3)Règles de production avec éventuellement des actions sémantiques %% (4)Bloc principal(fonction main) et fonctions C supplémentaires
a. Les règles de production (la grammaire) Non-terminal : prod1 | prod2 ...... | prodn ; Les symboles terminaux utilisables dans l a description du langage sont o Des unités lexicales que l¶on doit impérativement déclarer (2) par %token nom Des caractères entre quotes o La partie (4) doit contenir une fonction yylex() effectuant l¶analyse lexicale du texte, car l¶anal yseur sémantique chaque fois qu¶il a besoin du s ymbole terminal. terminal. b. Actions sémantiques Les actions sémantiques sont des instructions en C i nsérées dans les règles de production. Elles sont exécutées chaque fois qu¶il y a réduction par la production associée.
c.
Variables, fonctions et actions prédéfinies
Int yyparse() : fonction qui lance l¶analyseur l¶a nalyseur syntaxique YYACCEPT YYACCEPT :instruction permettant de stopper l¶analyseur syntaxique Int main() contient par defaut un appel à yylex() Exemples : %% Mot :S µ$¶{printf(« mot accepté ») ;YYACCEPT ; } ; S :¶a¶ S µa¶ |¶b¶ S µb¶ | µc¶ ; %% Int yylex() { Char c=getchar(); If(c==¶a¶||c==¶b¶||c==¶c¶||c==¶$¶)return(c); Else printf(³erreur: caractere non reconnu: %c »,c) ; }
Spécification FLEX
Spécification BISON
*.lex
FLEX
BISON
YYLEX ( )
YYPARSE ()
main () +
Analyseur
Analyseur syntaxique
actions+
lexical
CC
*.c
Librairies
MinGW
Programme
d. Exemple complet La grammaire :
G
Programme ListInst Instruction Expression Terme
Facteur
ListInst FIN Instruction PV ListInst | Instruction ID AFFECTATION Expression Expression + Terme Terme | Terme Terme * Facteur | Facteur ID | NB
Contenu Fichier compiler.y %{ #include "global.h" #include #include %} /* Ici, rappel des unités lexicales ou tokens générés par lanalyseur lexicale*/ %token NOMBRE %token AFFECTATION %token PLUS MOINS FOIS DIVISE PUISSANCE %token PARENTHESE_GAUCHE PARENTHESE_DROITE %token FIN %token OPEREL %token WHILE %token ID %token PV %token ACCGAUCHE ACCDROITE %left PLUS MOINS %left FOIS DIVISE %left NEG %right PUISSANCE %start Input %% Input: Input Programme | Programme ; /* Ici, spécification de la grammaire*/ Programme: ListInst FIN {printf("Analyses lexicales et syntaxiques réussies!\n"); printf("Tapez Enter pour terminer ou entrez une nouvelle chaine à analyser!\n"); } ; ListInst: Instruction PV ListInst | Instruction
; Instruction: ID AFFECTATION Expression {} ; Expression: Expression PLUS Terme Terme { } | Terme {} ; Terme: Terme FOIS Facteur {} | Facteur {} ; Facteur: NOMBRE {} | ID { } ; %% int yyerror(char *s) { printf("%s\n",s); } int main(void) {printf("Entrer la chaine des lexemes à analyser\n"); /* au départ, une action pour demander de rentrer linput constitué dune suite de lexemes*/ yyparse(); }