%{ #include #include #include #include #include "table_sym.h" SAVOIR PLUS SUR LES FONCTIONS, VOIR LE FICHIER "table_sym.c" OU TOUT EST EXPLIQUE*/ int yylex(); void yyerror(char *); int lineno; void print_function(char *ident, int type); %} %union { int num; Type typ %token IDENT %token NUM %token EQ %token ADDSUB %token DIVSTAR %token ORDERC ORDERD %token TYPE %token CARACTERE %token WHILE PRINT IF CONST ELSE RETURN READC READE OR AND %precedence ')' %precedence ELSE %type Litteral %type LValue %type JUMPF JUMP LABEL1 JUMPF1 %type Exp EB TB FB FBS FBC FBD E T F /*--------------bison----------------*/ %% Prog: {status_actuel = 1;} DeclConsts DeclVars DeclFoncts { /*METTRE LE STATUS_ACTUEL A 1 SIGNIFIE QU'ON EST DANS LE CAS "VARIABLE GLOBALE*/ if(search_sym_fonction("main") == -1){ /*si la fonction main n'est pas présente, alors -> cas d'erreur */ yyerror("Erreur : La fonction main est absente du programme"); } } ; DeclConsts: DeclConsts CONST ListConst ';' | ; ListConst: ListConst ',' IDENT '=' Litteral { int index; if(status_actuel == 1){ /*CAS VARIABLE GLOBALE*/ if((index = search_sym_variable_glob($3)) == -1){ /*CHERCHE "IDENT" DANS LA TABLE DES SYMBOLES GLOBALE*/ printf("ALLOC 1\n"); insert_symb_variable_glob(($5).type, $3, nbVariableGlob,1,1); /*INSERTION TABLE DES SYMBOLES GLOBALE*/ printf("SET %d\nSWAP\n", nbVariableGlob); if(($5.type) == CHAR) /*CAS CARACTERE*/ printf("SET %d\nSAVE\n", ($5).caractere); else /*CAS ENTIER*/ printf("SET %d\nSAVE\n", ($5).num); nbVariableGlob+=1; /*INCREMENTE LE NB DE VARIABLE GLOBALE DE 1 */ } else{ /*Si il est déjà utilisé, alors on envoie un message d'erreur*/ fprintf(stderr,"Erreur : La constante \"%s\" est déjà défini",$3); yyerror(""); } } else{ /* CAS VARIABLE LOCALE*/ if((index = search_sym_variable_loc($3,nb_bloc)) == -1){ /*CHERCHE "IDENT" DANS LA TABLE DES SYMBOLES LOCALE*/ printf("ALLOC 1\n"); insert_symb_variable_loc(($5).type, $3, nbVariableLoc, nb_bloc,1,1); /*INSERTION TABLE DES SYMBOLES LOCALE*/ printf("SET %d\nSWAP\n", nbVariableLoc); if(($5.type) == CHAR) /*CAS CARACTERE*/ printf("SET %d\nSAVER\n", ($5).caractere); else /*CAS ENTIER*/ printf("SET %d\nSAVER\n", ($5).num); nbVariableLoc += 1; /*INCREMENTE LE NB DE VARIABLE LOCALE DE 1 */ } else{ /*Si il est déjà utilisé, alors on envoie un message d'erreur*/ fprintf(stderr,"Erreur : La constante \"%s\" est déjà défini",$3); yyerror(""); } } } | IDENT '=' Litteral { int index; if(status_actuel == 1){ /*CAS VARIABLE GLOBALE*/ if((index = search_sym_variable_glob($1)) == -1){ /*CHERCHE "IDENT" DANS LA TABLE DES SYMBOLES GLOBALE*/ printf("ALLOC 1\n"); insert_symb_variable_glob(($3).type, $1, nbVariableGlob,1,1); /*INSERTION TABLE DES SYMBOLES GLOBALE*/ printf("SET %d\nSWAP\n", nbVariableGlob); if(($3.type) == CHAR) /*CAS CARACTERE*/ printf("SET %d\nSAVE\n", ($3).caractere); else /*CAS ENTIER*/ printf("SET %d\nSAVE\n", ($3).num); nbVariableGlob+=1; } else{ /*Si il est déjà utilisé, alors on envoie un message d'erreur*/ fprintf(stderr,"Erreur : La constante \"%s\" est déjà défini",$1); yyerror(""); } } else{ /* CAS VARIABLE LOCALE*/ if((index = search_sym_variable_loc($1,nb_bloc)) == -1){ /*CHERCHE "IDENT" DANS LA TABLE DES SYMBOLES LOCALE*/ printf("ALLOC 1\n"); insert_symb_variable_loc(($3).type, $1,nbVariableLoc,nb_bloc,1,1); /*INSERTION TABLE DES SYMBOLES LOCALE*/ printf("SET %d\nSWAP\n", nbVariableLoc); if(($3.type) == CHAR) /*CAS CARACTERE*/ printf("SET %d\nSAVER\n", ($3).caractere); else /*CAS ENTIER*/ printf("SET %d\nSAVER\n", ($3).num); nbVariableLoc += 1; } else{ /*Si il est déjà utilisé, alors on envoie un message d'erreur*/ fprintf(stderr,"Erreur : La constante \"%s\" est déjà défini",$1); yyerror(""); } } } ; Litteral: NombreSigne { printf("#Litteral (Constante) : NombreSigne = %d de type %s\n",$1,"ENTIER"); $$.type = INT; /*ON MET LE TYPE DE LITTERAL A "INT" */ $$.num = $1; /* ON MET LA VALEUR DE NombreSigne A LITTERAL */ } | CARACTERE { printf("#Litteral (Constante) : Caractere = %c de type %s\n",($1),"CARACTERE"); $$.type=CHAR; /*ON MET LE TYPE DE LITTERAL A "CHAR" */ $$.caractere = $1; /* ON MET LA VALEUR DE "CARACTERE" A LITTERAL */ } ; NombreSigne: NUM { $$=$1; } | ADDSUB NUM { if( '-' == $1 ) $$=-$2; else $$=$2; } ; DeclVars: DeclVars TYPE Declarateurs ';' { int i; if(status_actuel == 1){ /*CAS VARIABLE GLOBALE*/ for(i=index_tab_glob-1; i>(index_tab_glob-indexValue-1); i--) tab_sym_variable_glob[i].type = $2; /*MET Connexion en mousse A JOUR LE TYPE DES DECLARATIONS DE VARIABLE QUI N'ONT PAS ENCORE DE TYPE (GLOBALE)*/ indexValue = 0; /*ON REMET LE COMPTEUR DE VARIABLE SANS TYPE A ZERO*/ } else{ /*CAS VARIABLE LOCALE*/ for(i=index_tab_var-1; i>(index_tab_var-indexValue-1); i--) tab_sym_variable_loc[i].type = $2; /*MET A JOUR LE TYPE DES DECLARATIONS DE VARIABLE QUI N'ONT PAS ENCORE DE TYPE (LOCALE)*/ indexValue = 0; /*ON REMET LE COMPTEUR DE VARIABLE SANS TYPE A ZERO*/ } } | ; Declarateurs: Declarateurs ',' Declarateur | Declarateur ; Declarateur: IDENT { if(status_actuel == 1){ /*CAS VARIABLE GLOBALE*/ printf("#Declarateur (Variable) : Variable simple Globale \"%s\"\n",$1); insert_symb_variable_glob(7, $1, nbVariableGlob, 1, 0); /*INSERTION TABLE DES SYMBOLES GLOBALE*/ printf("ALLOC 1\n"); nbVariableGlob+=1; /*AUGMENTE LE NOMBRE DE VARIALE GLOBALE DE 1*/ indexValue++; /*AUGMENTE LE NOMBRE DE VARIALE SANS TYPE DE 1*/ } else{ /*CAS VARIABLE LOCALE*/ printf("#Declarateur (Variable) : Variable simple Locale \"%s\"\n",$1); insert_symb_variable_loc(7, $1, nbVariableLoc,nb_bloc, 1, 0); /*INSERTION TABLE DES SYMBOLES LOCALE*/ printf("ALLOC 1\n"); nbVariableLoc += 1; /*AUGMENTE LE NOMBRE DE VARIALE LOCALE DE 1*/ indexValue++; /*AUGMENTE LE NOMBRE DE VARIALE SANS TYPE DE 1*/ } } | IDENT '[' NUM ']' { if(status_actuel == 1){ /*CAS VARIABLE GLOBALE*/ printf("#Declarateur (Variable) : Tableau Globale \"%s\" contenant %d élement(s)\n",$1, $3); insert_symb_variable_glob(7, $1, nbVariableGlob, $3, 0); /*INSERTION TABLE DES SYMBOLES GLOBALE*/ printf("ALLOC %d\n", $3); nbVariableGlob+=$3; /*AUGMENTE LE NOMBRE DE VARIALE LOCALE DE "NUM" (GESTION DE PILE)*/ indexValue++; /*AUGMENTE LE NOMBRE DE VARIALE SANS TYPE DE 1 (TABLE DES SYMBOLES)*/ } else{ /*CAS VARIABLE LOCALE*/ printf("#Decalarateur (Variable) : Tableau Locale \"%s\" contenant %d élement(s)\n",$1, $3); insert_symb_variable_loc(7, $1, nbVariableLoc, nb_bloc,$3, 0); /*INSERTION TABLE DES SYMBOLES LOCALE*/ printf("ALLOC %d\n", $3); nbVariableLoc += $3; /*AUGMENTE LE NOMBRE DE VARIALE LOCALE DE "NUM" (GESTION DE PILE)*/ indexValue++; /*AUGMENTE LE NOMBRE DE VARIALE SANS TYPE DE 1 (TABLE DES SYMBOLES)*/ } } ; DeclFoncts: DeclFoncts DeclFonct | DeclFonct ; DeclFonct: EnTeteFonct { status_actuel = 0; } Corps /*LE FAIT DE PASSER LE STATUS_ACTUEL A 0 SIGNIFIE QU'ON PASSE EN VARIABLE LOCALE*/ EnTeteFonct: TYPE IDENT '(' { nbVariableLoc = 0; /*PERMET DE SAVOIR QU'ON EST DANS LA FONCTION MAIN POUR LA GESTION DES DECLARATIONS DE PARAMETRES*/ if(strcmp($-2, "main") == 0) { main_status = 1; } /*PERMET DE METTRE "CALL 0" AVANT LA PREMIERE FONCTION QUI PERMETTRA D'APPELER LE MAIN */ if(test_call_0 == 0) { printf("CALL 0\nJUMP 1\n");test_call_0=1; } print_function(($2), $1); nb_bloc++;;/*POUR UNE MEILLEUR GESTION DE PARAMETRE, ON SUPPOSE QUE LES PARAMETRES SONT DANS LE BLOC PRINCIPAL D'UNE FONCTION*/ } Parametres { nb_bloc--; } ')' { /*PERMET DE REMPLIR LE TABLEAU DE TYPE ET D'IDENT DE LA FONCTION EN QUESTION*/ int i; insert_symb_fonction($1, $2, nbFonction, recupere_currentLabel($2)); cur_fonc_adr = search_sym_fonction($2); for(i = 0; i < index_type; i++){ insert_type_tab_fonction($2, Tempo_type[i].type, Tempo_type[i].ident, -index_type+i-2); } index_type = 0;/*ON REMET L'INDEX DE TYPE A ZERO POUR LES PROCHAINS APPELS DE FONCTION*/ main_status = 0;/*ON SORT DU STATUS "MAIN" CAR QUAND ON EST DANS LE MAIN, ON NE DOIT PAS UTILISER DES ADRESSES NEGATIVES ALORS QUE SI CE N'EST PAS LE CAS, ON DOIT UTILISER -3, -4 ETC ETC */ } ; Parametres: TYPE { if ( $1 != VOID ) yyerror("Erreur, vous ne pouvez pas déclarer de type en argument");} | ListTypVar { int i; for(i = index_type-1; i >= 0; i--){ if(main_status == 1){ /* SI ON EST DANS LE MAIN */ printf("ALLOC 1\n"); insert_symb_variable_loc(Tempo_type[i].type,Tempo_type[i].ident,nbVariableLoc,nb_bloc,1, 0); /*INITIALISE LES ADRESSES NORMALEMENT POUR LE MAIN*/ nbVariableLoc += 1; /*AUGMENTE LE NOMBRE DE VARIABLE LOCALE DE 1*/ } else { /* SI ON N'EST PAS DANS LE MAIN */ printf("ALLOC 1\n"); insert_symb_variable_loc(Tempo_type[i].type,Tempo_type[i].ident,-index_type+i-2,nb_bloc,1, 0); /*PERMET DE PREVOIR A L'AVANCE L'ADRESSE DES ARGUMENTS DES FONCTIONS AUTRE QUE MAIN*/ nbVariableLoc += 1; /*AUGMENTE LE NOMBRE DE VARIABLE LOCALE DE 1*/ } } } ; ListTypVar: ListTypVar ',' TYPE IDENT { /*PERMET DE RECUPERER PLUSIEURS INFOS QU'ON A BESOIN PLUS HAUT (ON ENREGISTRE LES ARGUMENTS DANS LA TABLE DES SYMBOLES)*/ Tempo_type[index_type].type = $3; /*RECUPERE LE TYPE*/ strcpy(Tempo_type[index_type].ident,$4); /*RECUPERE L'IDENT*/ index_type++; } | TYPE IDENT { /*PERMET DE RECUPERER PLUSIEURS INFOS QU'ON A BESOIN PLUS HAUT (ON ENREGISTRE LES ARGUMENTS DANS LA TABLE DES SYMBOLES)*/ Tempo_type[index_type].type = $1; /*RECUPERE LE TYPE*/ strcpy(Tempo_type[index_type].ident,$2); /*RECUPERE L'IDENT*/ index_type++; } ; Corps: '{' {nb_bloc++;} DeclConsts DeclVars SuiteInstr '}' { nb_bloc--; delete_under_num_bloc_variable(); nbVariableLoc = 0;/*REMET LE NOMBRE DE VARIABLE A ZERO (PREVENTION)*/ if(label_main_trouver == 1){ /*TEST SI LE MAIN EST TROUVE*/ label_main_trouver-=1; /*SI OUI, ON DECREMENTE LA VARIABLE GLOBALE DE 1*/ printf("RETURN\n"); } else{ printf("RETURN\n"); /*SINON ON NE FAIT RIEN ET ON LA LAISSE A 1*/ } index_tab_var=0; /*REMET L'INDEX DE VARIABLE LOCALE A ZERO (PREVENTION)*/ } ; SuiteInstr: SuiteInstr Instr | ; JUMPF: { currentLabel++; printf("JUMPF %d\n", currentLabel); $$=currentLabel; } LABEL: { printf("LABEL %d\n",($-2)); } JUMP: { currentLabel++; printf("JUMP %d\n", currentLabel); $$=currentLabel; } LABEL1: { currentLabel++; printf("LABEL %d\n",currentLabel); $$=currentLabel; } JUMPF1: { currentLabel++; printf("JUMPF %d\n",currentLabel); $$=currentLabel; } Instr: Exp ';' {} | ';' {} | RETURN Exp ';' { verif_type_retour(cur_fonc_adr,$2.type); if_return = 1; printf("SWAP\nSET 0\nSWAP\nSAVER\nRETURN\n"); /*ON PLACE LA VALEUR DE "Exp" DANS REG1 AVANT*/ } | RETURN ';' {} | READE '(' IDENT ')' ';' { printf("READ\nPUSH\n"); } | READC '(' IDENT ')' ';' { printf("READCH\nPUSH\n"); } | PRINT '(' Exp ')' ';' { printf("WRITE\n"); } | IF '(' Exp ')' JUMPF Instr JUMP LABEL {printf("LABEL %d\n", $7);} | IF '(' Exp ')' JUMPF Instr JUMP LABEL ELSE Instr {printf("LABEL %d\n", $7);} | WHILE LABEL1 '(' Exp ')'JUMPF1 Instr { printf("JUMP %d\nLABEL %d\n",$2,$6); } | '{' SuiteInstr '}' ; Exp : LValue '=' Exp { $$ = $3; int index; if((index = search_sym_variable_loc($1.ident, nb_bloc)) != -1){ /* ON REGARDE SI LValue EST BIEN DANS LA TABLE DES SYMBOLES LOCALE*/ if(tab_sym_variable_loc[index].is_const == 0){ if(tab_sym_variable_loc[index].type == $3.type){ printf("POP\nSWAP\nPOP\nSWAP\nSAVER\n"); break; } else yyerror("Erreur : Incompatibilité au niveau des types de l'affectation"); } else yyerror("Erreur : Vous ne pouvez pas modifier la valeur d'une contante"); } else if((index = search_sym_variable_glob($1.ident)) != -1){ /* ON REGARDE SI LValue EST BIEN DANS LA TABLE DES SYMBOLES GLOBALE*/ if(tab_sym_variable_glob[index].is_const == 0){ if(tab_sym_variable_loc[index].type == $3.type) printf("POP\nSWAP\nPOP\nSWAP\nSAVE\n"); else yyerror("Erreur : Incompatibilité au niveau des types de l'affectation"); } else yyerror("Erreur : Vous ne pouvez pas modifier la valeur d'une contante"); } else{ /*CAS OU LValue N'EST PAS TROUVE -> ERREUR*/ fprintf(stderr,"Erreur : \"%s\" n'a pas pu être chargé ",$1.ident); yyerror(""); } } | EB { $$ = $1; } ; EB : EB OR TB { if($1.value == 0){ /*GESTION DES "OU", ON SUPPOSE QUE =0 -> FAUX ET >0 -> VRAI */ if($3.value == 0) $$.value=0; else $$.value=1; } else $$.value=1; } | TB { $$ = $1; } ; TB : TB AND FB { if($1.value == 0) /*GESTION DES "ET", ON SUPPOSE QUE =0 -> FAUX ET >0 -> VRAI */ $$.value=0; else{ if($3.value == 0) $$.value=0; else $$.value=1; } } | FB { $$ = $1; } ; FB : FBS { $$ = $1; } | FBC { $$ = $1; } | FBD { $$ = $1; } ; FBS : FBS EQ E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,"==") == 0) printf("EQUAL\n"); else printf("NOTEQ\n"); printf("PUSH\n"); } | E { $$ = $1; } ; FBC : FBC EQ E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,"==") == 0) printf("EQUAL\n"); else printf("NOTEQ\n"); printf("PUSH\n"); } | FBC ORDERC E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,"<") == 0) printf("LESS\n"); else printf("LEQ\n"); printf("PUSH\n"); } | FBS ORDERC E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,"<") == 0) printf("LESS\n"); else printf("LEQ\n"); printf("PUSH\n"); } ; FBD : FBD EQ E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,"==") == 0) printf("EQUAL\n"); else printf("NOTEQ\n"); printf("PUSH\n"); } | FBD ORDERD E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,">") == 0) printf("GREATER\n"); else printf("GEQ\n"); printf("PUSH\n"); } | FBS ORDERD E { printf("POP\nSWAP\nPOP\n"); if(strcmp($2,">") == 0) printf("GREATER\n"); else printf("GEQ\n"); printf("PUSH\n"); } ; E : E ADDSUB T { if($2 == '+') printf("POP\nSWAP\nPOP\nADD\nPUSH\n"); else printf("POP\nSWAP\nPOP\nSUB\nPUSH\n"); } | T { $$ = $1; } ; T : T DIVSTAR F { if($2 == '*') printf("POP\nSWAP\nPOP\nMUL\nPUSH\n"); else if($2 == '/')printf("POP\nSWAP\nPOP\nDIV\nPUSH\n"); else printf("POP\nSWAP\nPOP\nMOD\nPUSH\n"); } | F {$$ = $1; } ; F : ADDSUB F { if($1 != '+') printf("POP\nSWAP\nSET 0\nSUB\nPUSH\n"); } | '!' F { $$=$2; printf("POP\nNEG\nPUSH\n"); } | '(' Exp ')' { $$=$2; } | LValue { $$=$1; int index; if((index = search_sym_variable_loc($1.ident,nb_bloc)) != -1){ /* ON REGARDE SI LValue EST BIEN DANS LA TABLE DES SYMBOLES LOCALE*/ printf("POP\nLOADR\nPUSH\n"); break; } else if((index = search_sym_variable_glob($1.ident)) != -1){ /* ON REGARDE SI LValue EST BIEN DANS LA TABLE DES SYMBOLES GLOBALE*/ printf("POP\nLOAD\nPUSH\n"); break; } else{ /*CAS OU LValue N'EST PAS TROUVE -> ERREUR*/ fprintf(stderr,"Erreur, \"%s\" n'a pas pu être chargé",$1.ident); yyerror(""); } } | NUM { $$.nb_value = 1; $$.value = $1; $$.type = INT; printf("SET %d\nPUSH\n", $1); } | CARACTERE { $$.nb_value = 1; $$.value = $1; $$.type = CHAR; printf("SET %d\nPUSH\n", $1); } | IDENT '(' Arguments ')' { int index = search_sym_fonction($1); $$.type = tab_sym_fonction[index].type; int i; if(compare_nb_arg(index,index_arg) == 1){ /*REGARDE SI LE NOMBRE D'ARGUMENTS DE LA FONCTION EST BON*/ for(i = 0;i