Recent Changes - Search:

My Projects

Courses

Writings

Source Code

Social Networks

Histoires

Live Traffic !

Évolution 1 : Opérateurs de comparaison

Créer son propre langage de programmation de A à Z

<< Arbre syntaxique abstrait et Génération de code | Évolution 1 : Opérateurs de comparaison | Évolution 2 : If/Else >>

L'évolution 1 consiste à implémenter les opérateurs de comparaison. On va agrandir le nombre de règles syntaxiques pour le non terminal représentant les expressions booléennes.

Évolution 1 du langage :

  1. <expression_booleenne> ::= variable | "vrai" | "faux" | <et> | <ou> | <non> | "(" <expression_booleenne> ")" | <egal> | <inferieur> | <superieur> | <different> | <inclus> | <inferieur_egal> | <superieur_egal>
  2.  
  3. <egal> ::= <expression_booleenne> "==" <expression_booleenne> | <expression_arithmetique> "==" <expression_arithmetique> | <expression_booleenne> "egal a" <expression_booleenne> | <expression_arithmetique> "egal a" <expression_arithmetique>
  4.  
  5. <inferieur> ::= <expression_arithmetique> "<" <expression_arithmetique> | <expression_arithmetique> "inferieur a" <expression_arithmetique>
  6.  
  7. <superieur> ::= <expression_arithmetique> ">" <expression_arithmetique> | <expression_arithmetique> "superieur a" <expression_arithmetique>
  8.  
  9. <different> ::= <expression_booleenne> "!=" <expression_booleenne> | <expression_arithmetique> "!=" <expression_arithmetique> | <expression_booleenne> "<>" <expression_booleenne> | <expression_arithmetique> "<>" <expression_arithmetique> | <expression_booleenne> "different de" <expression_booleenne> | <expression_arithmetique> "different de" <expression_arithmetique>
  10.  
  11. <inferieur_egal> ::= <expression_arithmetique> "<=" <expression_arithmetique> | <expression_arithmetique> "inferieur ou egal a" <expression_arithmetique>
  12.  
  13. <superieur_egal> ::= <expression_arithmetique> ">=" <expression_arithmetique> | <expression_arithmetique> "superieur ou egal a" <expression_arithmetique>
  14.  
  15. <inclus> ::= <expression_arithmetique> "dans" <crochet> <expression_arithmetique> ";" <expression_arithmetique> <crochet> | <expression_arithmetique> "compris dans" <crochet> <expression_arithmetique> ";" <expression_arithmetique> <crochet>
  16.  
  17. <crochet> ::= "[" | "]"

On donne à l'analyseur lexical connaissance des nouveaux lexèmes :

lexique_simple.lex
  1. %{
  2.  
  3. #include "simple.h"
  4. unsigned int lineno=1;
  5. bool error_lexical=false;
  6.  
  7. %}
  8.  
  9. %option noyywrap
  10.  
  11. nombre 0|[1-9][[:digit:]]*
  12. variable_booleenne b(_|[[:alnum:]])*
  13. variable_arithmetique e(_|[[:alnum:]])*
  14.  
  15. %%
  16.  
  17. {nombre} {
  18.     sscanf(yytext, "%ld", &yylval.nombre);
  19.     return TOK_NOMBRE;
  20. }
  21.  
  22. "egal a"|"equivalent a"|"=="        {return TOK_EQU;}
  23.  
  24. "different de"|"!="|"<>"            {return TOK_DIFF;}
  25.  
  26. "superieur a"|"plus grand que"|">"  {return TOK_SUP;}
  27.  
  28. "inferieur a"|"plus petit que"|"<"  {return TOK_INF;}
  29.  
  30. "superieur ou egal a"|">="          {return TOK_SUPEQU;}
  31.  
  32. "inferieur ou egal a"|"<="          {return TOK_INFEQU;}
  33.  
  34. "compris dans"|"dans"               {return TOK_IN;}
  35.  
  36. "afficher"      {return TOK_AFFICHER;}
  37.  
  38. "="             {return TOK_AFFECT;}
  39.  
  40. "+"             {return TOK_PLUS;}
  41.  
  42. "-"             {return TOK_MOINS;}
  43.  
  44. "*"             {return TOK_MUL;}
  45.  
  46. "/"             {return TOK_DIV;}
  47.  
  48. "("             {return TOK_PARG;}
  49.  
  50. ")"             {return TOK_PARD;}
  51.  
  52. "["             {return TOK_CROG;}
  53.  
  54. "]"             {return TOK_CROD;}
  55.  
  56. "et"            {return TOK_ET;}
  57.  
  58. "ou"            {return TOK_OU;}
  59.  
  60. "non"           {return TOK_NON;}
  61.  
  62. ";"             {return TOK_FINSTR;}
  63.  
  64. "vrai"          {return TOK_VRAI;}
  65.  
  66. "faux"          {return TOK_FAUX;}
  67.  
  68. "\n"            {lineno++;}
  69.  
  70. {variable_booleenne} {
  71.     yylval.texte = yytext;
  72.     return TOK_VARB;
  73. }
  74.  
  75.  
  76. {variable_arithmetique} {
  77.     yylval.texte = yytext;
  78.     return TOK_VARE;
  79. }
  80.  
  81. " "|"\t" {}
  82.  
  83. . {
  84.     fprintf(stderr,"\tERREUR : Lexeme inconnu a la ligne %d. Il s'agit de %s et comporte %d lettre(s)\n",lineno,yytext,yyleng);
  85.     error_lexical=true;
  86.     return yytext[0];
  87. }
  88.  
  89. %%

On ajoute ces nouvelles déclarations à la fin du fichier d'entête :

simple.h
  1. #define EGALITE         19
  2. #define DIFFERENT       20
  3. #define SUPERIEUR       21
  4. #define INFERIEUR       22
  5. #define SUPEGAL         23
  6. #define INFEGAL         24
  7. #define DANSII          25      /* inclus-inclus */
  8. #define DANSEI          26      /* exclus-inclus */
  9. #define DANSIE          27      /* inclus-exclus */
  10. #define DANSEE          28      /* exclus-exclus */

On met à jour l'analyseur syntaxique Bison :

syntaxe_simple.y
  1. %{
  2.  
  3. #include "simple.h"
  4. bool error_syntaxical=false;
  5. bool error_semantical=false;
  6. /* Notre table de hachage */
  7. GHashTable* table_variable;
  8.  
  9. /* Notre structure Variable qui a comme membre le type et un pointeur generique vers la valeur */
  10. typedef struct Variable Variable;
  11.  
  12. struct Variable{
  13.         char* type;
  14.         GNode* value;
  15. };
  16.  
  17. %}
  18.  
  19. /* L'union dans Bison est utilisee pour typer nos tokens ainsi que nos non terminaux. Ici nous avons declare une union avec trois types : nombre de type int, texte de type pointeur de char (char*) et noeud d'arbre syntaxique (AST) de type (GNode*) */
  20.  
  21. %union {
  22.         long nombre;
  23.         char* texte;
  24.         GNode*  noeud;
  25. }
  26.  
  27. /* Nous avons ici les operateurs, ils sont definis par leur ordre de priorite. Si je definis par exemple la multiplication en premier et l'addition apres, le + l'emportera alors sur le * dans le langage. Les parenthese sont prioritaires avec %right */
  28.  
  29. %left                   TOK_PLUS        TOK_MOINS       /* +- */
  30. %left                   TOK_MUL         TOK_DIV         /* /* */
  31. %left                   TOK_ET          TOK_OU          TOK_NON         /* et ou non */
  32. %left                   TOK_EQU         TOK_DIFF        TOK_SUP         TOK_INF         TOK_SUPEQU      TOK_INFEQU      /* comparaisons */
  33. %right                  TOK_PARG        TOK_PARD        /* () */
  34.  
  35. /* Nous avons la liste de nos expressions (les non terminaux). Nous les typons tous en noeud de l'arbre syntaxique (GNode*) */
  36.  
  37. %type<noeud>            code
  38. %type<noeud>            instruction
  39. %type<noeud>            variable_arithmetique
  40. %type<noeud>            variable_booleenne
  41. %type<noeud>            affectation
  42. %type<noeud>            affichage
  43. %type<noeud>            expression_arithmetique
  44. %type<noeud>            expression_booleenne
  45. %type<noeud>            addition
  46. %type<noeud>            soustraction
  47. %type<noeud>            multiplication
  48. %type<noeud>            division
  49.  
  50. /* Nous avons la liste de nos tokens (les terminaux de notre grammaire) */
  51.  
  52. %token<nombre>          TOK_NOMBRE
  53. %token                  TOK_VRAI        /* true */
  54. %token                  TOK_FAUX        /* false */
  55. %token                  TOK_AFFECT      /* = */
  56. %token                  TOK_FINSTR      /* ; */
  57. %token                  TOK_IN          /* dans */
  58. %token                  TOK_CROG    TOK_CROD    /* [] */
  59. %token                  TOK_AFFICHER    /* afficher */
  60. %token<texte>           TOK_VARB        /* variable booleenne */
  61. %token<texte>           TOK_VARE        /* variable arithmetique */
  62.  
  63. %%
  64.  
  65. /* Nous definissons toutes les regles grammaticales de chaque non terminal de notre langage. Par defaut on commence a definir l'axiome, c'est a dire ici le non terminal code. Si nous le definissons pas en premier nous devons le specifier en option dans Bison avec %start */
  66.  
  67. entree:         code{
  68.                         genere_code($1);
  69.                         g_node_destroy($1);
  70.                 };
  71.  
  72. code:           %empty{$$=g_node_new((gpointer)CODE_VIDE);}
  73.                 |
  74.                 code instruction{
  75.                         printf("Resultat : C'est une instruction valide !\n\n");
  76.                         $$=g_node_new((gpointer)SEQUENCE);
  77.                         g_node_append($$,$1);
  78.                         g_node_append($$,$2);
  79.                 }
  80.                 |
  81.                 code error{
  82.                         fprintf(stderr,"\tERREUR : Erreur de syntaxe a la ligne %d.\n",lineno);
  83.                         error_syntaxical=true;
  84.                 };
  85.  
  86. instruction:    affectation{
  87.                         printf("\tInstruction type Affectation\n");
  88.                         $$=$1;
  89.                 }
  90.                 |
  91.                 affichage{
  92.                         printf("\tInstruction type Affichage\n");
  93.                         $$=$1;
  94.                 };
  95.  
  96. variable_arithmetique:  TOK_VARE{
  97.                                 printf("\t\t\tVariable entiere %s\n",$1);
  98.                                 $$=g_node_new((gpointer)VARIABLE);
  99.                                 g_node_append_data($$,strdup($1));
  100.                         };
  101.  
  102. variable_booleenne:     TOK_VARB{
  103.                                 printf("\t\t\tVariable booleenne %s\n",$1);
  104.                                 $$=g_node_new((gpointer)VARIABLE);
  105.                                 g_node_append_data($$,strdup($1));
  106.                         };
  107.  
  108. affectation:    variable_arithmetique TOK_AFFECT expression_arithmetique TOK_FINSTR{
  109.                         /* $1 est la valeur du premier non terminal. Ici c'est la valeur du non terminal variable. $3 est la valeur du 2nd non terminal. */
  110.                         printf("\t\tAffectation sur la variable\n");
  111.                         Variable* var=g_hash_table_lookup(table_variable,(char*)g_node_nth_child($1,0)->data);
  112.                         if(var==NULL){
  113.                                 /* On cree une Variable et on lui affecte le type que nous connaissons et la valeur */
  114.                                 var=malloc(sizeof(Variable));
  115.                                 if(var!=NULL){
  116.                                         var->type=strdup("entier");
  117.                                         var->value=$3;
  118.                                         /* On l'insere dans la table de hachage (cle: <nom_variable> / valeur: <(type,valeur)>) */
  119.                                         if(g_hash_table_insert(table_variable,g_node_nth_child($1,0)->data,var)){
  120.                                                 $$=g_node_new((gpointer)AFFECTATIONE);
  121.                                                 g_node_append($$,$1);
  122.                                                 g_node_append($$,$3);
  123.                                         }else{
  124.                                                 fprintf(stderr,"ERREUR - PROBLEME CREATION VARIABLE !\n");
  125.                                                 exit(-1);
  126.                                         }
  127.                                 }else{
  128.                                         fprintf(stderr,"ERREUR - PROBLEME ALLOCATION MEMOIRE VARIABLE !\n");
  129.                                         exit(-1);
  130.                                 }
  131.                         }else{
  132.                                 $$=g_node_new((gpointer)AFFECTATION);
  133.                                 g_node_append_data($$,$1);
  134.                                 g_node_append($$,$3);
  135.                         }
  136.                 }
  137.                 |
  138.                 variable_booleenne TOK_AFFECT expression_booleenne TOK_FINSTR{
  139.                         /* $1 est la valeur du premier non terminal. Ici c'est la valeur du non terminal variable. $3 est la valeur du 2nd non terminal. */
  140.                         printf("\t\tAffectation sur la variable\n");
  141.                         Variable* var=g_hash_table_lookup(table_variable,(char*)g_node_nth_child($1,0)->data);
  142.                         if(var==NULL){
  143.                                 /* On cree une Variable et on lui affecte le type que nous connaissons et la valeur */
  144.                                 var=malloc(sizeof(Variable));
  145.                                 if(var!=NULL){
  146.                                         var->type=strdup("booleen");
  147.                                         var->value=$3;
  148.                                         /* On l'insere dans la table de hachage (cle: <nom_variable> / valeur: <(type,valeur)>) */
  149.                                         if(g_hash_table_insert(table_variable,g_node_nth_child($1,0)->data,var)){
  150.                                                 $$=g_node_new((gpointer)AFFECTATIONE);
  151.                                                 g_node_append($$,$1);
  152.                                                 g_node_append($$,$3);
  153.                                         }else{
  154.                                                 fprintf(stderr,"ERREUR - PROBLEME CREATION VARIABLE !\n");
  155.                                                 exit(-1);
  156.                                         }
  157.                                 }else{
  158.                                         fprintf(stderr,"ERREUR - PROBLEME ALLOCATION MEMOIRE VARIABLE !\n");
  159.                                         exit(-1);
  160.                                 }
  161.                         }else{
  162.                                 $$=g_node_new((gpointer)AFFECTATION);
  163.                                 g_node_append($$,$1);
  164.                                 g_node_append($$,$3);
  165.                         }
  166.                 };
  167.  
  168. affichage:      TOK_AFFICHER expression_arithmetique TOK_FINSTR{
  169.                         printf("\t\tAffichage de la valeur de l'expression arithmetique\n");
  170.                         $$=g_node_new((gpointer)AFFICHAGEE);
  171.                         g_node_append($$,$2);
  172.                 }
  173.                 |
  174.                 TOK_AFFICHER expression_booleenne TOK_FINSTR{
  175.                         printf("\t\tAffichage de la valeur de l'expression booleenne\n");
  176.                         $$=g_node_new((gpointer)AFFICHAGEB);
  177.                         g_node_append($$,$2);
  178.                 };
  179.  
  180.  
  181. expression_arithmetique:        TOK_NOMBRE{
  182.                                         printf("\t\t\tNombre : %ld\n",$1);
  183.                                         /* Comme le token TOK_NOMBRE est de type entier et que on a type expression_arithmetique comme du texte, il nous faut convertir la valeur en texte. */
  184.                                         int length=snprintf(NULL,0,"%ld",$1);
  185.                                         char* str=malloc(length+1);
  186.                                         snprintf(str,length+1,"%ld",$1);
  187.                                         $$=g_node_new((gpointer)ENTIER);
  188.                                         g_node_append_data($$,strdup(str));
  189.                                         free(str);
  190.                                 }
  191.                                 |
  192.                                 variable_arithmetique{
  193.                                         /* On recupere un pointeur vers la structure Variable */
  194.                                         Variable* var=g_hash_table_lookup(table_variable,(char*)g_node_nth_child($1,0)->data);
  195.                                         /* Si on a trouve un pointeur valable */
  196.                                         if(var!=NULL){
  197.                                                 /* On verifie que le type est bien un entier - Inutile car impose a l'analyse syntaxique */
  198.                                                 if(strcmp(var->type,"entier")==0){
  199.                                                         $$=$1;
  200.                                                 }else{
  201.                                                         fprintf(stderr,"\tERREUR : Erreur de semantique a la ligne %d. Type incompatible (entier attendu - valeur : %s) !\n",lineno,(char*)g_node_nth_child($1,0)->data);
  202.                                                         error_semantical=true;
  203.                                                 }
  204.                                         /* Sinon on conclue que la variable n'a jamais ete declaree car absente de la table */
  205.                                         }else{
  206.                                                 fprintf(stderr,"\tERREUR : Erreur de semantique a la ligne %d. Variable %s jamais declaree !\n",lineno,(char*)g_node_nth_child($1,0)->data);
  207.                                                 error_semantical=true;
  208.                                         }
  209.                                 }
  210.                                 |
  211.                                 addition{
  212.                                         $$=$1;
  213.                                 }
  214.                                 |
  215.                                 soustraction{
  216.                                         $$=$1;
  217.                                 }
  218.                                 |
  219.                                 multiplication{
  220.                                         $$=$1;
  221.                                 }
  222.                                 |
  223.                                 division{
  224.                                         $$=$1;
  225.                                 }
  226.                                 |
  227.                                 TOK_PARG expression_arithmetique TOK_PARD{
  228.                                         printf("\t\t\tC'est une expression artihmetique entre parentheses\n");
  229.                                         $$=g_node_new((gpointer)EXPR_PAR);
  230.                                         g_node_append($$,$2);
  231.                                 };
  232.  
  233. expression_booleenne:           TOK_VRAI{
  234.                                         printf("\t\t\tBooleen Vrai\n");
  235.                                         $$=g_node_new((gpointer)VRAI);
  236.                                 }
  237.                                 |
  238.                                 TOK_FAUX{
  239.                                         printf("\t\t\tBooleen Faux\n");
  240.                                         $$=g_node_new((gpointer)FAUX);
  241.                                 }
  242.                                 |
  243.                                 variable_booleenne{
  244.                                         /* On recupere un pointeur vers la structure Variable */
  245.                                         Variable* var=g_hash_table_lookup(table_variable,(char*)g_node_nth_child($1,0)->data);
  246.                                         /* Si on a trouve un pointeur valable */
  247.                                         if(var!=NULL){
  248.                                                 /* On verifie que le type est bien un entier - Inutile car impose a l'analyse syntaxique */
  249.                                                 if(strcmp(var->type,"booleen")==0){
  250.                                                         $$=$1;
  251.                                                 }else{
  252.                                                         fprintf(stderr,"\tERREUR : Erreur de semantique a la ligne %d. Type incompatible (booleen attendu - valeur : %s) !\n",lineno,(char*)g_node_nth_child($1,0)->data);
  253.                                                         error_semantical=true;
  254.                                                 }
  255.                                         /* Sinon on conclue que la variable n'a jamais ete declaree car absente de la table */
  256.                                         }else{
  257.                                                 fprintf(stderr,"\tERREUR : Erreur de semantique a la ligne %d. Variable %s jamais declaree !\n",lineno,(char*)g_node_nth_child($1,0)->data);
  258.                                                 error_semantical=true;
  259.                                         }
  260.                                 }
  261.                                 |
  262.                                 TOK_NON expression_booleenne{
  263.                                         printf("\t\t\tOperation booleenne Non\n");
  264.                                         $$=g_node_new((gpointer)NON);
  265.                                         g_node_append($$,$2);
  266.                                 }
  267.                                 |
  268.                                 expression_booleenne TOK_ET expression_booleenne{
  269.                                         printf("\t\t\tOperation booleenne Et\n");
  270.                                         $$=g_node_new((gpointer)ET);
  271.                                         g_node_append($$,$1);
  272.                                         g_node_append($$,$3);
  273.                                 }
  274.                                 |
  275.                                 expression_booleenne TOK_OU expression_booleenne{
  276.                                         printf("\t\t\tOperation booleenne Ou\n");
  277.                                         $$=g_node_new((gpointer)OU);
  278.                                         g_node_append($$,$1);
  279.                                         g_node_append($$,$3);
  280.                                 }
  281.                                 |
  282.                                 TOK_PARG expression_booleenne TOK_PARD{
  283.                                         printf("\t\t\tC'est une expression booleenne entre parentheses\n");
  284.                                         $$=g_node_new((gpointer)EXPR_PAR);
  285.                                         g_node_append($$,$2);
  286.                                 }
  287.                                 |
  288.                                 expression_booleenne TOK_EQU expression_booleenne{
  289.                                         printf("\t\t\tOperateur d'egalite ==\n");
  290.                                         $$=g_node_new((gpointer)EGALITE);
  291.                                         g_node_append($$,$1);
  292.                                         g_node_append($$,$3);
  293.                                 }
  294.                                 |
  295.                                 expression_booleenne TOK_DIFF expression_booleenne{
  296.                                         printf("\t\t\tOperateur d'inegalite !=\n");
  297.                                         $$=g_node_new((gpointer)DIFFERENT);
  298.                                         g_node_append($$,$1);
  299.                                         g_node_append($$,$3);
  300.                                 }
  301.                                 |
  302.                                 expression_arithmetique TOK_EQU expression_arithmetique{
  303.                                         printf("\t\t\tOperateur d'egalite ==\n");
  304.                                         $$=g_node_new((gpointer)EGALITE);
  305.                                         g_node_append($$,$1);
  306.                                         g_node_append($$,$3);
  307.                                 }
  308.                                 |
  309.                                 expression_arithmetique TOK_DIFF expression_arithmetique{
  310.                                         printf("\t\t\tOperateur d'inegalite !=\n");
  311.                                         $$=g_node_new((gpointer)DIFFERENT);
  312.                                         g_node_append($$,$1);
  313.                                         g_node_append($$,$3);
  314.                                 }
  315.                                 |
  316.                                 expression_arithmetique TOK_SUP expression_arithmetique{
  317.                                         printf("\t\t\tOperateur de superiorite >\n");
  318.                                         $$=g_node_new((gpointer)SUPERIEUR);
  319.                                         g_node_append($$,$1);
  320.                                         g_node_append($$,$3);
  321.                                 }
  322.                                 |
  323.                                 expression_arithmetique TOK_INF expression_arithmetique{
  324.                                         printf("\t\t\tOperateur d'inferiorite <\n");
  325.                                         $$=g_node_new((gpointer)INFERIEUR);
  326.                                         g_node_append($$,$1);
  327.                                         g_node_append($$,$3);
  328.                                 }
  329.                                 |
  330.                                 expression_arithmetique TOK_SUPEQU expression_arithmetique{
  331.                                         printf("\t\t\tOperateur >=\n");
  332.                                         $$=g_node_new((gpointer)SUPEGAL);
  333.                                         g_node_append($$,$1);
  334.                                         g_node_append($$,$3);
  335.                                 }
  336.                                 |
  337.                                 expression_arithmetique TOK_INFEQU expression_arithmetique{
  338.                                         printf("\t\t\tOperateur <=\n");
  339.                                         $$=g_node_new((gpointer)INFEGAL);
  340.                                         g_node_append($$,$1);
  341.                                         g_node_append($$,$3);
  342.                                 }
  343.                                 |
  344.                                 expression_arithmetique TOK_IN TOK_CROG expression_arithmetique TOK_FINSTR expression_arithmetique TOK_CROD{
  345.                                         printf("\t\t\tOperateur dans\n");
  346.                                         $$=g_node_new((gpointer)DANSII);
  347.                                         g_node_append($$,$1);
  348.                                         g_node_append($$,$4);
  349.                                         g_node_append($$,$6);
  350.                                 }
  351.                                 |
  352.                                 expression_arithmetique TOK_IN TOK_CROD expression_arithmetique TOK_FINSTR expression_arithmetique TOK_CROD{
  353.                                         printf("\t\t\tOperateur dans\n");
  354.                                         $$=g_node_new((gpointer)DANSEI);
  355.                                         g_node_append($$,$1);
  356.                                         g_node_append($$,$4);
  357.                                         g_node_append($$,$6);
  358.                                 }
  359.                                 |
  360.                                 expression_arithmetique TOK_IN TOK_CROG expression_arithmetique TOK_FINSTR expression_arithmetique TOK_CROG{
  361.                                         printf("\t\t\tOperateur dans\n");
  362.                                         $$=g_node_new((gpointer)DANSIE);
  363.                                         g_node_append($$,$1);
  364.                                         g_node_append($$,$4);
  365.                                         g_node_append($$,$6);
  366.                                 }
  367.                                 |
  368.                                 expression_arithmetique TOK_IN TOK_CROD expression_arithmetique TOK_FINSTR expression_arithmetique TOK_CROG{
  369.                                         printf("\t\t\tOperateur dans\n");
  370.                                         $$=g_node_new((gpointer)DANSEE);
  371.                                         g_node_append($$,$1);
  372.                                         g_node_append($$,$4);
  373.                                         g_node_append($$,$6);
  374.                                 };
  375.  
  376. addition:       expression_arithmetique TOK_PLUS expression_arithmetique{
  377.                         printf("\t\t\tAddition\n");
  378.                         $$=g_node_new((gpointer)ADDITION);
  379.                         g_node_append($$,$1);
  380.                         g_node_append($$,$3);
  381.                 };
  382.  
  383. soustraction:   expression_arithmetique TOK_MOINS expression_arithmetique{
  384.                         printf("\t\t\tSoustraction\n");
  385.                         $$=g_node_new((gpointer)SOUSTRACTION);
  386.                         g_node_append($$,$1);
  387.                         g_node_append($$,$3);
  388.                 };
  389.  
  390. multiplication: expression_arithmetique TOK_MUL expression_arithmetique{
  391.                         printf("\t\t\tMultiplication\n");
  392.                         $$=g_node_new((gpointer)MULTIPLICATION);
  393.                         g_node_append($$,$1);
  394.                         g_node_append($$,$3);
  395.                 };
  396.  
  397. division:       expression_arithmetique TOK_DIV expression_arithmetique{
  398.                         printf("\t\t\tDivision\n");
  399.                         $$=g_node_new((gpointer)DIVISION);
  400.                         g_node_append($$,$1);
  401.                         g_node_append($$,$3);
  402.                 };
  403.  
  404. %%
  405.  
  406. /* Dans la fonction main on appelle bien la routine yyparse() qui sera genere par Bison. Cette routine appellera yylex() de notre analyseur lexical. */
  407.  
  408. int main(int argc, char** argv){
  409.         /* recuperation du nom de fichier d'entree (langage Simple) donne en parametre */
  410.         char* fichier_entree=strdup(argv[1]);
  411.         /* ouverture du fichier en lecture dans le flux d'entree stdin */
  412.         stdin=fopen(fichier_entree,"r");
  413.         /* creation fichier de sortie (langage C) */
  414.         char* fichier_sortie=strdup(argv[1]);
  415.         /* remplace l'extension par .c */
  416.         strcpy(rindex(fichier_sortie, '.'), ".c");
  417.         /* ouvre le fichier cree en ecriture */
  418.         fichier=fopen(fichier_sortie, "w");
  419.         /* Creation de la table de hachage */
  420.         table_variable=g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
  421.         printf("Debut de l'analyse syntaxique :\n");
  422.         debut_code();
  423.         yyparse();
  424.         fin_code();
  425.         printf("Fin de l'analyse !\n");
  426.         printf("Resultat :\n");
  427.         if(error_lexical){
  428.                 printf("\t-- Echec : Certains lexemes ne font pas partie du lexique du langage ! --\n");
  429.                 printf("\t-- Echec a l'analyse lexicale --\n");
  430.         }
  431.         else{
  432.                 printf("\t-- Succes a l'analyse lexicale ! --\n");
  433.         }
  434.         if(error_syntaxical){
  435.                 printf("\t-- Echec : Certaines phrases sont syntaxiquement incorrectes ! --\n");
  436.                 printf("\t-- Echec a l'analyse syntaxique --\n");
  437.         }
  438.         else{
  439.                 printf("\t-- Succes a l'analyse syntaxique ! --\n");
  440.                 if(error_semantical){
  441.                         printf("\t-- Echec : Certaines phrases sont semantiquement incorrectes ! --\n");
  442.                         printf("\t-- Echec a l'analyse semantique --\n");
  443.                 }
  444.                 else{
  445.                         printf("\t-- Succes a l'analyse semantique ! --\n");
  446.                 }
  447.         }
  448.         /* Suppression du fichier genere si erreurs analyse */
  449.         if(error_lexical||error_syntaxical||error_semantical){
  450.                 remove(fichier_sortie);
  451.                 printf("ECHEC GENERATION CODE !\n");
  452.         }
  453.         else{
  454.                 printf("Le fichier \"%s\" a ete genere !\n",fichier_sortie);
  455.         }
  456.         /* Fermeture des flux */
  457.         fclose(fichier);
  458.         fclose(stdin);
  459.         /* Liberation memoire */
  460.         free(fichier_entree);
  461.         free(fichier_sortie);
  462.         g_hash_table_destroy(table_variable);
  463.         return EXIT_SUCCESS;
  464. }
  465.  
  466. void yyerror(char *s) {
  467.         fprintf(stderr, "Erreur de syntaxe a la ligne %d: %s\n", lineno, s);
  468. }

Et on doit mettre à jour aussi le générateur de code C. A rajouter dans le switch de la fonction genere_code() :

generation_code.c
  1. case EGALITE:
  2.         genere_code(g_node_nth_child(ast,0));
  3.         fprintf(fichier,"==");
  4.         genere_code(g_node_nth_child(ast,1));
  5.         break;
  6. case DIFFERENT:
  7.         genere_code(g_node_nth_child(ast,0));
  8.         fprintf(fichier,"!=");
  9.         genere_code(g_node_nth_child(ast,1));
  10.         break;
  11. case INFERIEUR:
  12.         genere_code(g_node_nth_child(ast,0));
  13.         fprintf(fichier,"<");
  14.         genere_code(g_node_nth_child(ast,1));
  15.         break;
  16. case SUPERIEUR:
  17.         genere_code(g_node_nth_child(ast,0));
  18.         fprintf(fichier,">");
  19.         genere_code(g_node_nth_child(ast,1));
  20.         break;
  21. case INFEGAL:
  22.         genere_code(g_node_nth_child(ast,0));
  23.         fprintf(fichier,"<=");
  24.         genere_code(g_node_nth_child(ast,1));
  25.         break;
  26. case SUPEGAL:
  27.         genere_code(g_node_nth_child(ast,0));
  28.         fprintf(fichier,">=");
  29.         genere_code(g_node_nth_child(ast,1));
  30.         break;
  31. case DANSII:
  32.         genere_code(g_node_nth_child(ast,0));
  33.         fprintf(fichier,">=");
  34.         genere_code(g_node_nth_child(ast,1));
  35.         fprintf(fichier,"&&");
  36.         genere_code(g_node_nth_child(ast,0));
  37.         fprintf(fichier,"<=");
  38.         genere_code(g_node_nth_child(ast,2));
  39.         break;
  40. case DANSEI:
  41.         genere_code(g_node_nth_child(ast,0));
  42.         fprintf(fichier,">");
  43.         genere_code(g_node_nth_child(ast,1));
  44.         fprintf(fichier,"&&");
  45.         genere_code(g_node_nth_child(ast,0));
  46.         fprintf(fichier,"<=");
  47.         genere_code(g_node_nth_child(ast,2));
  48.         break;
  49. case DANSIE:
  50.         genere_code(g_node_nth_child(ast,0));
  51.         fprintf(fichier,">=");
  52.         genere_code(g_node_nth_child(ast,1));
  53.         fprintf(fichier,"&&");
  54.         genere_code(g_node_nth_child(ast,0));
  55.         fprintf(fichier,"<");
  56.         genere_code(g_node_nth_child(ast,2));
  57.         break;
  58. case DANSEE:
  59.         genere_code(g_node_nth_child(ast,0));
  60.         fprintf(fichier,">");
  61.         genere_code(g_node_nth_child(ast,1));
  62.         fprintf(fichier,"&&");
  63.         genere_code(g_node_nth_child(ast,0));
  64.         fprintf(fichier,"<");
  65.         genere_code(g_node_nth_child(ast,2));
  66.         break;

Voilà ! On n'oublie pas de tout compiler :

flex -o lexique_simple.c lexique_simple.lex
bison -d syntaxe_simple.y
gcc lexique_simple.c syntaxe_simple.tab.c generation_code.c `pkg-config --cflags --libs glib-2.0` -o simple

Maintenant passons lui un fichier test :

programme.simple
  1. entier = 6;
  2. epentier = 30;
  3. booleen = vrai;
  4. bnbool = faux;
  5.  
  6. afficher booleen == bnbool;
  7. afficher booleen egal a bnbool;
  8.  
  9. afficher booleen == booleen;
  10. afficher bnbool egal a bnbool;
  11.  
  12.  
  13. afficher booleen != booleen;
  14. afficher bnbool different de bnbool;
  15. afficher bnbool <> bnbool;
  16.  
  17. afficher booleen != bnbool;
  18. afficher booleen different de bnbool;
  19. afficher booleen <> bnbool;
  20.  
  21.  
  22. afficher entier == epentier;
  23. afficher entier egal a epentier;
  24.  
  25. afficher entier == entier;
  26. afficher epentier egal a epentier;
  27.  
  28.  
  29. afficher entier != entier;
  30. afficher epentier different de epentier;
  31. afficher epentier <> epentier;
  32.  
  33. afficher entier != epentier;
  34. afficher entier different de epentier;
  35. afficher entier <> epentier;
  36.  
  37.  
  38. afficher entier > epentier;
  39. afficher entier superieur a epentier;
  40.  
  41. afficher epentier > entier;
  42. afficher epentier superieur a entier;
  43.  
  44.  
  45. afficher epentier < entier;
  46. afficher epentier inferieur a entier;
  47.  
  48. afficher entier < epentier;
  49. afficher entier inferieur a epentier;
  50.  
  51.  
  52. afficher entier >= epentier;
  53. afficher entier superieur ou egal a epentier;
  54.  
  55. afficher epentier >= entier;
  56. afficher epentier superieur ou egal a entier;
  57. afficher epentier >= 30;
  58.  
  59.  
  60. afficher epentier <= entier;
  61. afficher epentier inferieur ou egal a entier;
  62.  
  63. afficher entier <= epentier;
  64. afficher entier inferieur ou egal a epentier;
  65. afficher entier <= 6;
  66.  
  67.  
  68. afficher entier dans [5;6[;
  69. afficher entier dans [4;5];
  70. afficher entier dans ]6;7];
  71.  
  72. afficher entier compris dans [6;7[;
  73. afficher entier compris dans [6;7];
  74. afficher entier compris dans ]5;7];

Normalement la compilation a du bien se passer et vous devez avoir un fichier programme.c de généré. On le lance :

gcc -o programme programme.c
./programme

Et on obtient ceci :

faux
faux
vrai
vrai
faux
faux
faux
vrai
vrai
vrai
faux
faux
vrai
vrai
faux
faux
faux
vrai
vrai
vrai
faux
faux
vrai
vrai
faux
faux
vrai
vrai
faux
faux
vrai
vrai
vrai
faux
faux
vrai
vrai
vrai
faux
faux
faux
vrai
vrai
vrai

Nous avons fini cette première évolution du langage. La prochaine sera la mise en place de conditions if/else. A bientôt donc pour l'évolution 2 !

<< Arbre syntaxique abstrait et Génération de code | Évolution 1 : Opérateurs de comparaison | Évolution 2 : If/Else >>

Thomas - (CC BY-NC-SA 3.0 FR)

Page last modified on July 09, 2017, at 07:45 PM EST

This page has been requested 1182 times (Today : 3) - Total number of requests : 95326

Edit - History - Statistics - Print - Recent Changes - Search

Clin d'oeil aux victimes des attentats survenus dans la soirée du 13 novembre 2015. La nouvelle version du site a été installée quelques heures avant.