Académique Documents
Professionnel Documents
Culture Documents
Analyse syntaxique
Un analyseur syntaxique Bison est un fichier avec l’extension .y, une fois écrit
nous le compilerons à l’aide de la commande bison -d. Cela va nous générer un
descripteur de notre analyseur syntaxique écrit en C, qui une fois compilé va
créer l’exécutable de notre analyseur syntaxique.
Il est constitué de trois sections tout comme l’analyseur lexical Flex. Pour
séparer deux sections différente nous utiliserons %%
%{
Définition des variables C
%}
%token liste des tokens
%%
Règles de la grammaire
%%
Redéfinition des fonctions de Bison
Lancement de l’analyseur
Exemples :
Pour les exemples suivants nous allons utiliser le même langage que nous
avons défini pour l’analyse lexicale.
Dans le premier exemple nous allons définir un analyseur syntaxique qui vérifie
uniquement l’instruction d’affichage printf, cette instruction ne s’exécutera
qu’une seul fois. Le code Bison correspondant est donné comme suit :
Dans cet exemple, vu que nous n’avons pas eu besoin de variable la première
partie de la première section a été omise, l’ensemble des tokens a été listé
juste après le mot clé %token.
En vert sont représentés les terminaux, en bleu les non terminaux et en rouge
le membre gauche (l’axiome dans notre cas). Le : sert à séparer la partie
gauche et la partie droite (équivalent de la flèche) et le ; marque la fin d’une
règle.
Et dans la dernière section nous faisons appel à la fonction yyparse pour lancer
l’analyseur syntaxique, dans cet exemple nous n’avons eu besoin de redéfinir
de Bison.
Dans le deuxième exemple, nous accepterons l’écriture de la fonction printf
plusieurs fois dans le code à analyser.
Le code Bison correspondant est le suivant :
La différence entre les deux codes présentés réside dans la partie des règles de
production. En effet dans le deuxième code nous avons ajouté une nouvelle
règle récursive qui nous permet d’accepter de répéter l’exécution de
l’instruction printf. Pour représenter l’epsilon nous n’écrivons rien après la
barre.
%{
extern ligne;
int nb_err_syn=0;
extern nb_err_lex;
extern yytext;
%}
%token Mc_Int Mc_For Mc_Print IDF STR Affect PV Par_Ouv Par_Fer CST_Int
Opr_Inf Opr_Plus err
%%
S:PlsDec PlsInst
;
PlsDec:Dec PlsDec|
;
Dec:Mc_Int IDF Affect CST_Int PV
;
PlsInst: Inst PlsInst |
;
Inst : InstFor InstAffich|InstAffich
;
InstFor:Mc_For Par_Ouv InitFor CondFor IDF Opr_Plus Opr_Plus Par_Fer
;
InitFor:IDF Affect CST_Int PV
;
CondFor:IDF Opr_Inf CST_Int PV
;
InstAffich:Mc_Print Par_Ouv MessAffich Par_Fer PV
;
MessAffich:STR|IDF
;
%%
yyerror()
{
nb_err_syn++;
printf("erreur syntaxique a la ligne %d generee par %s\n",ligne,yytext);
return 1;
}
int main()
{
yyparse();
if (nb_err_syn==0 && nb_err_lex==0)
printf("Syntaxe correcte");
else
printf("Syntaxe incorrecte");
return 0;
}
Avant de décrire ce qui a été ajouté dans le troisième code par rapport aux
deux premiers, certains points importants doivent être expliqués.
Comme nous l’avons mentionné ci-haut, l’analyseur syntaxique aura comme
input la suite des entités lexicales issue de l’étape précédente. Par conséquent
l’analyseur lexical que nous avons déjà conçu doit retourner cette suite de
tokens à l’analyseur syntaxique. Ce qui fait que nous devons effectuer des
changements dans le code source qui défini notre analyseur lexical afin de
pouvoir faire le lien entre les deux analyseurs. Mais surtout, il faut compiler les
deux fichiers .c correspondants (celui de l’analyseur lexical et celui de
l’analyseur syntaxique) à la fois en seule ligne de commande comme nous
allons le voir à la fin de ce document.
La première chose à modifier dans le code de l’analyseur lexical que nous avons
déjà écrit est la deuxième section. En effet, l’ajout des noms des entités
lexicales à la chaine de caractère avait pour but de simuler le passage de la
suite d’entités lexicales à l’analyseur syntaxique ce qui n’est plus pertinent vu
que cette fois-ci nous allons effectuer l’analyse syntaxique. Ainsi nous
remplacerons chaque instruction strcat(NomChaine,NomEntite) par
l’instruction return NomEntite. Il faut bien notez que ces noms d’entités que
nous allons retourner sont les mêmes qui doivent se trouver dans la partie
%token dans l’analyseur syntaxique. Pour pouvoir faire cela il faut ajouter le
nom du fichier contant la description de l’analyseur syntaxique suivi d’un
.tab.h, comme suit : #include "nomFichier.tab.h" dans la première partie de la
première section.
La deuxième chose à modifier, c’est d’enlever la fonction main de l’analyseur
lexical. En effet lors de l’analyse syntaxique, la fonction yyparse que nous avons
décrite ci-dessus (qui est dans le main de l’analyseur syntaxique) lancera
l’analyseur lexical et si nous n’enlevons pas le main de l’analyseur lexical nous
aurons deux main dans notre programme ce qui provoquera des erreurs.
Dans La deuxième section nous avons ajouté d’autres règles afin d’enrichir la
grammaire.
Pour finir, nous avons redéfini la fonction yyerror pour modifier le message
d’erreur syntaxique et bien préciser la ligne sur laquelle apparait l’erreur, nous
incrémentons aussi la variable nb_err_syn à ce niveau. Mais ce traitement
reste facultatif et vous pouvez ne pas le faire.
Une fois que l’analyseur syntaxique est écrit, nous devons le compiler en
utilisant la commande bison.
Pour cela il faut ouvrir l’invité de commande là ou se trouve le fichier contenant
votre analyseur syntaxique et taper :
bison -d nom_fichier.y
Cette commande va nous générer deux fichiers le premier est nommé :
nom_fichier.tab.c, c’est ce fichier qui sera compilé afin de lancer l’analyse
syntaxique et le deuxième nommé: nom_fichier.tab.h que nous ajouterons au
début du fichier flex. Nous devons ainsi compiler le premier fichier à l’aide de la
commande gcc, mais comme nous devons aussi lancer l’analyseur lexical nous
devons compiler le fichier qui le décrit i-e le fichier .l avec la commande flex et
compiler ensuite le fichier lex.yy.c avec la commande gcc, notez bien qu’il faut
compiler ces deux fichiers à la fois avec une seule commande comme nous
l’avons mentionné dans les paragraphes précédents:
gcc lex.yy.c nom_fichier.tab.c -lfl -ly
Notons que lfl et ly sont des bibliothèque de bison que nous devons utiliser
pour que nous puissions compiler le fichier nom_fichier.tab.c en raison de
l’utilisation de certains fonctions appartenant à ces bibliothèque et que le
compilateur gcc ne connait pas.
Par défaut le nom du fichier exécutable générée sera nommé a.exe, si vous
voulez changer ce nom veuillez ajouter à la fin de la commande précédente ce
qui suit : -o nom_ fichier.exe.
Pour tester votre analyseur syntaxique, vous aller soit le lancer en tapant le
nom de l’exécutable dans l’invité de commande et ensuite saisir le code que
vous voulez tester manuellement. Soit lui passer en paramètre un fichier .txt
contenant le code à analyser en utilisant la commande suivante :
nom_ fichier.exe<nom_fichier.txt
Notons qu’il est préférable de regrouper toute les instructions que vous allez
utiliser dans l’invité de commande, dans un seul fichier .bat et exécuter ce
fichier à chaque fois que vous aurez besoin de recompiler votre analyseur
syntaxique. Cela vous évitera de devoir écrire ces commandes plusieurs fois et
toutes les erreurs qui vont avec.
BON COURAGE