├── .gitignore ├── Makefile ├── include ├── functions.h └── intermediare.h ├── parser ├── compiler.l └── compiler.y ├── script.sh ├── src ├── functions.c └── intermediare.c └── test.tex /.gitignore: -------------------------------------------------------------------------------- 1 | expr.asm 2 | test.gv 3 | test.py 4 | expr 5 | .gdb_history 6 | peda-session-test.txt 7 | err.asipro.log 8 | *.o 9 | gmon.out 10 | lex.* 11 | test.tab* 12 | test -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/sh 2 | LEX=flex 3 | YACC=bison 4 | CC=gcc 5 | CFLAGS=-g -std=c11 -pedantic -Wall -D_POSIX_C_SOURCE=200809L 6 | 7 | # Répertoires du projet 8 | SRC_DIR = ./src 9 | INC_DIR = ./include 10 | PARSER_DIR = ./parser 11 | BUILD_DIR = ./build 12 | 13 | # Options 14 | LDFLAGS= 15 | LEXOPTS= -D_POSIX_C_SOURCE=200809L -DYY_NO_INPUT --nounput 16 | YACCOPTS= -Wcounterexamples 17 | 18 | # Nom du programme final 19 | PROG=compiler 20 | 21 | # Chemins de recherche 22 | vpath %.h $(INC_DIR) 23 | vpath %.c $(SRC_DIR) 24 | vpath %.l $(PARSER_DIR) 25 | vpath %.y $(PARSER_DIR) 26 | 27 | # Règle par défaut 28 | all: directories $(BUILD_DIR)/$(PROG) 29 | 30 | # Création des répertoires s'ils n'existent pas 31 | directories: 32 | mkdir -p $(BUILD_DIR) $(SRC_DIR) $(INC_DIR) $(PARSER_DIR) 33 | 34 | # Compilation du programme final 35 | $(BUILD_DIR)/$(PROG): $(BUILD_DIR)/lex.yy.o $(BUILD_DIR)/$(PROG).tab.o $(BUILD_DIR)/functions.o $(BUILD_DIR)/intermediare.o 36 | $(CC) $^ -o $@ $(LDFLAGS) 37 | 38 | # Génération du lexer (flex) 39 | $(BUILD_DIR)/lex.yy.c: $(PARSER_DIR)/$(PROG).l $(BUILD_DIR)/$(PROG).tab.h 40 | $(LEX) $(LEXOPTS) -o $@ $< 41 | 42 | $(BUILD_DIR)/lex.yy.h: $(PARSER_DIR)/$(PROG).l 43 | $(LEX) $(LEXOPTS) --header-file=$@ $< 44 | 45 | # Génération du parser (bison) 46 | $(BUILD_DIR)/$(PROG).tab.c $(BUILD_DIR)/$(PROG).tab.h: $(PARSER_DIR)/$(PROG).y $(BUILD_DIR)/lex.yy.h 47 | $(YACC) $(YACCOPTS) $< -d -v --graph -o $(BUILD_DIR)/$(PROG).tab.c 48 | 49 | # Compilation des sources 50 | $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c 51 | $(CC) -DYYDEBUG $(CFLAGS) -I$(INC_DIR) -I$(BUILD_DIR) -c $< -o $@ 52 | 53 | # Règle spéciale pour les fichiers générés 54 | $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c 55 | $(CC) -DYYDEBUG $(CFLAGS) -I$(INC_DIR) -I$(BUILD_DIR) -c $< -o $@ 56 | 57 | # Nettoyage 58 | clean: 59 | rm -rf $(BUILD_DIR) 60 | rm -f *.err *.log *.output *.out *.dot *.gv exp* 61 | rm lex.yy.c 62 | 63 | .PHONY: all clean directories -------------------------------------------------------------------------------- /include/functions.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTIONS_H 2 | #define FUNCTIONS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef enum 9 | { 10 | LOCAL_VAR, 11 | PARAM_VAR 12 | } TYPE_VAR; 13 | 14 | typedef enum 15 | { 16 | NUM_T, 17 | BOOL_T, 18 | ERR_T 19 | } TYPE_SYNTH; 20 | 21 | extern int param_number, local_number,label; 22 | 23 | typedef struct func_sym 24 | { 25 | char* nom_func; 26 | int nbr_params; 27 | int nbr_locals; 28 | struct sym *table; 29 | struct func_sym *ptr; 30 | } func_tab; 31 | 32 | typedef struct sym 33 | { 34 | char *nom_idf; 35 | TYPE_VAR type; 36 | int num_var; 37 | struct sym *ptr; 38 | } sym_tab; 39 | 40 | 41 | 42 | /* 43 | Fonction en assembleur qui gère l'erreur de division par 0. 44 | */ 45 | void err_div(); 46 | 47 | /* 48 | Fonction en assembleur qui gère l'erreur de dépassement 49 | de capacité. 50 | */ 51 | void err_overflow(); 52 | 53 | /* 54 | Ecrit en assembleur tout ce dont le programme a besoin 55 | en entête. 56 | */ 57 | void start_asm(); 58 | 59 | /* 60 | Permet de lancer le programme en exécutant la fonction donné. 61 | */ 62 | void main_asm(); 63 | 64 | /* 65 | Affiche le haut de la pile et termine le programme. 66 | */ 67 | void end_asm(); 68 | 69 | /* 70 | Teste si les deux paramètres sont de types NUM_T. 71 | RETOUR: NUM_T si oui, ERR_T sinon. 72 | */ 73 | int test_expr_int(int first, int second); 74 | 75 | /* 76 | Teste si les deux paramètres sont de types BOOL_T. 77 | RETOUR: BOOL_T si oui, ERR_T sinon. 78 | */ 79 | int test_expr_bool(int first, int second); 80 | 81 | /* 82 | Fait l'addition des 2 premières valeurs sur la pile. 83 | UTILISE : ax,bx,cx 84 | RESULTAT: en haut de la pile 85 | */ 86 | void addition(); 87 | 88 | /* 89 | Fait la soustraction des 2 premières valeurs sur la pile. 90 | UTILISE : ax,bx 91 | RESULTAT: en haut de la pile 92 | */ 93 | void soustraction(); 94 | 95 | /* 96 | Fait la multiplication des 2 premières valeurs sur la pile. 97 | UTILISE : ax,bx,cx 98 | RESULTAT: en haut de la pile 99 | */ 100 | void multiplication(); 101 | 102 | /* 103 | Fait la division des 2 premières valeurs sur la pile. 104 | UTILISE : ax,bx,cx 105 | RESULTAT: en haut de la pile 106 | */ 107 | void division(); 108 | 109 | /* 110 | Fait le or logique des 2 premières valeurs sur la pile. 111 | UTILISE : ax,bx,cx 112 | RESULTAT: en haut de la pile 113 | Incrémente label. 114 | */ 115 | void or(); 116 | 117 | 118 | /* 119 | Fait le not logique de la 1ère valeur sur la pile. 120 | UTILISE : ax,bx 121 | RESULTAT: en haut de la pile 122 | */ 123 | void not(); 124 | 125 | /* 126 | Fait l'égalité entre les deux premières valeurs sur la pile. 127 | UTILISE : ax,bx,cx 128 | RESULTAT: en haut de la pile 129 | Incrémente label. 130 | */ 131 | void egal(); 132 | 133 | /* 134 | Fait la différence entre les deux premières valeurs sur la pile. 135 | UTILISE : ax,bx,cx 136 | RESULTAT: en haut de la pile 137 | Incrémente label. 138 | */ 139 | void diff(); 140 | 141 | /* 142 | Fait la comparaison si la première valeur est supérieure à la deuxième valeur sur la pile. 143 | UTILISE : ax,bx,cx 144 | RESULTAT: en haut de la pile 145 | Incrémente label. 146 | */ 147 | void sup(); 148 | 149 | /* 150 | Fait la comparaison si la première valeur est inférieure à la deuxième valeur sur la pile. 151 | UTILISE : ax,bx,cx 152 | RESULTAT: en haut de la pile 153 | Incrémente label. 154 | */ 155 | void inf(); 156 | 157 | /* 158 | Fait la comparaison si la première valeur est supérieure ou égale à la deuxième valeur sur la pile. 159 | UTILISE : ax,bx,cx 160 | RESULTAT: en haut de la pile 161 | Incrémente label. 162 | */ 163 | void supeq(); 164 | 165 | /* 166 | Fait la comparaison si la première valeur est inférieure ou égale à la deuxième valeur sur la pile. 167 | UTILISE : ax,bx,cx 168 | RESULTAT: en haut de la pile 169 | Incrémente label. 170 | */ 171 | void infeq(); 172 | 173 | /* 174 | Met sur la pile la constante à utiliser 175 | UTILISE: ax 176 | */ 177 | void num(int number); 178 | 179 | /* 180 | Affecte la valeur qui se trouve sur le haut de la pile dans 181 | la variable nom. 182 | UTILISE: ax,bx,dx 183 | */ 184 | void affect_from_top_stack(char *nom,func_tab* head); 185 | 186 | /* 187 | Incremente la valeur de la variable nom. 188 | UTILISE: ax,bx,dx 189 | */ 190 | void increment(char *nom, func_tab *head); 191 | 192 | /* 193 | Décremente la valeur de la variable nom. 194 | UTILISE: ax,bx,dx 195 | */ 196 | void decrement(char *nom, func_tab *head); 197 | 198 | 199 | 200 | 201 | /* 202 | RETOUR : la nouvelle cellule de sym_tab crée par malloc (la gestion d'erreur se fait dans ajouter) 203 | */ 204 | sym_tab *nouvelle_cellule(); 205 | 206 | /* 207 | RETOUR : la nouvelle cellule de func_tab crée par malloc (la gestion d'erreur se fait dans ajouter) 208 | */ 209 | func_tab *nouvelle_cellule_func(); 210 | 211 | /* 212 | Ajoute en tête de liste la nouvelle cellule qui contient l'identifiant 213 | */ 214 | void ajouter(int val, char *nom, char* nom_func,func_tab* head); 215 | 216 | /* 217 | Traverse la table des fonctions et la table des symboles de chacunes d'elles 218 | 219 | */ 220 | void traverse_func_tab(func_tab *head); 221 | 222 | /* 223 | Ajoute en tête de liste la nouvelle cellule qui contient la fonction 224 | */ 225 | void ajouter_func(char *nom, int nbr_p, int nbr_v,func_tab **head); 226 | 227 | /* 228 | Recherche l'identifiant dans la table des symboles 229 | RETOUR : la cellule si existe, NULL sinon 230 | */ 231 | sym_tab *recherche(char *nom, sym_tab *head); 232 | 233 | /* 234 | Recherche la fonction dans la table des symboles 235 | RETOUR : la cellule si existe, NULL sinon 236 | */ 237 | func_tab *recherche_func(char *nom, func_tab *head); 238 | 239 | 240 | /* 241 | Affiche la table des symboles 242 | */ 243 | void print_sym_tab(sym_tab *head); 244 | 245 | 246 | 247 | /* 248 | récupère depuis la pile un des paramètres (si il y en a) de l'algo. 249 | à partir de la base de la pile (qui contient le dernier paramètre), on ajoute 250 | le nombre de mot machines nécessaire pour atteindre l'adresse mémoire du paramètre. 251 | RESULTAT : DANS dx 252 | ADRESSE DE LA VAR : DANS bx 253 | UTILISE : ax,bx,dx 254 | */ 255 | void get_param_from_stack(char *nom, func_tab *head); 256 | 257 | 258 | /* 259 | Recupère la position du paramètre sur la pile en utilisant la table des symboles 260 | */ 261 | int get_param_location(char *nom, func_tab *head); 262 | 263 | /* 264 | Affiche un paramètre depuis la pile 265 | UTILISE: bx, cx 266 | */ 267 | void print_param(char *nom, func_tab *head); 268 | 269 | /* 270 | affiche le registre dont l'adresse est contenue dans le paramètre nom. 271 | UTILISE: cx et le registre contenue dans nom 272 | */ 273 | void print_reg(char *nom); 274 | 275 | /* 276 | Prépare la 1ère partie de la pile d'execution avant un appel de fonction: 277 | - Empile 0 pour la valeur de retour 278 | - Empile les variables locales de la fonction 279 | */ 280 | void prepare_stack_locals(func_tab *func); 281 | 282 | /* 283 | Prépare la 3ème partie de la pile d'execution après un appel de fonction: 284 | - Empile le retour de la fonction (fait automatiquement par asipro) 285 | - Empile l'ancienne base de la pile 286 | - Monter la base de la pile 287 | */ 288 | void prepare_stack_func(func_tab *func); 289 | 290 | /* 291 | Execute la fin de l'appel de fonction: 292 | - Mettre la valeur de retour dans son emplacement 293 | - Mettre sp au même niveau que bp 294 | - Restaurer la base de la pile 295 | - Retourner à l'appelant 296 | */ 297 | void return_from_func(func_tab *func); 298 | // Fonction pour libérer la structure sym_tab 299 | void free_sym(sym_tab *head); 300 | // Fonction pour libérer la structure func_tab 301 | void free_func(func_tab *head); 302 | // création du label des conditions 303 | char* create_label(char* label_name, int number); 304 | #endif -------------------------------------------------------------------------------- /include/intermediare.h: -------------------------------------------------------------------------------- 1 | // un fichier .h qui contient la structure de la liste chainée et les prototypes 2 | // des fonctions qui permettent de manipuler cette liste du code intermédiaire 3 | // l'insertion se fait en fin de liste (FIFO) 4 | #ifndef INTERMEDIAIRE_H 5 | #define INTERMEDIAIRE_H 6 | #include 7 | #include 8 | #include 9 | #include "functions.h" 10 | // enumération des types des opérations 11 | 12 | typedef enum operation{ 13 | // opérations arithmétiques 14 | ADD_OP, //0 15 | SUB_OP, //1 16 | MUL_OP, //2 17 | DIV_OP, //3 18 | // opérations logiques 19 | AND_OP, //4 20 | OR_OP, //5 21 | NOT_OP, //6 22 | EGAL_OP, //21 23 | DIF_OP, //22 24 | INF_OP, //23 25 | SUP_OP, //24 26 | INFEQ_OP, //25 27 | SUPEQ_OP, //26 28 | SET_OP, //7 29 | INCR_OP, //8 30 | DECR_OP, //9 31 | IDF_OP, //10 32 | NUM_OP, //11 33 | NUL_OP, //12 34 | FUNC_OP, //13 35 | CALL_OP, //14 36 | CALL_PARAM_END_OP, //15 37 | RET_OP, //16 38 | TEST_OP, //17 39 | ARG_OP, //18 40 | CALL_EXP_OP, //19 41 | CALL_EXP_PARAM_END_OP, //20 42 | IF_OP, //22 43 | FI_OP, //23 44 | ELSE_OP, //24 45 | ELSE_2_OP, //25 46 | DOWHILE_1_OP, //26 47 | DOWHILE_2_OP, //27 48 | OD_1_OP, //28 49 | OD_2_OP, //29 50 | DOFORI_1_OP, //30 51 | DOFORI_2_OP, //31 52 | DOFORI_3_OP, //32 53 | OD_FORI_1_OP, //33 54 | OD_FORI_2_OP, //34 55 | } operation; 56 | 57 | // enum pour différencier entre les deux types d'arguments 58 | typedef enum arg_type{ 59 | OP, 60 | ARG, 61 | } arg_type; 62 | 63 | // union pour indiquer qu'un argument peut être soit une operation soit une chaine de caractères 64 | 65 | 66 | // structure de la liste chainée 67 | typedef struct intermediare{ 68 | operation op; 69 | arg_type type; 70 | char *arg; 71 | func_tab *function; 72 | struct intermediare *next; 73 | } intermediare; 74 | 75 | 76 | // structure pour gérer les appels de if 77 | typedef struct cond_tab{ 78 | int cond_id; 79 | struct cond_tab *next; 80 | } cond_tab; 81 | 82 | // ------prototypes des fonctions-------- 83 | /* 84 | ajoute en fin de liste un élément de la liste chainée 85 | argumetns: 86 | - head: pointeur vers le pointeur de la tête de la liste 87 | - op: l'opération à ajouter 88 | - type: le type de l'argument (OP ou ARG) 89 | - arg: l'argument de l'opération (vide si type == OP) 90 | - func: la fonction actuelle 91 | 92 | */ 93 | // fonction qui ajoute un élément à la liste des cond en fin de queue 94 | void add_cond(cond_tab **head, int id); 95 | // fonction qui supprime un élément de la liste des cond en fin de queue 96 | int pop_cond(cond_tab **head); 97 | // fonction qui libère la mémoire allouée pour la liste des cond 98 | void free_cond(cond_tab **head); 99 | 100 | void add_intermediare(intermediare **head, operation op,arg_type type, char *arg,func_tab* func); 101 | 102 | /* 103 | Parcours la liste et génère du code assembleur 104 | */ 105 | void generate_intermediare(intermediare* head); 106 | 107 | /* 108 | Affiche le code intermédiaire 109 | */ 110 | void print_intermediare(intermediare *head); 111 | 112 | /* 113 | Choisit l'opération à effectuer pendant le parcours 114 | */ 115 | void choose_op(intermediare *node); 116 | /* 117 | Libère la mémoire allouée pour la liste chainée 118 | */ 119 | void free_intermediare(intermediare *head); 120 | 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /parser/compiler.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "functions.h" 3 | #include "../build/compiler.tab.h" 4 | #include 5 | #include 6 | #include 7 | %} 8 | 9 | %option noyywrap 10 | 11 | %% 12 | "\\begin{algo}" {return BEG;} 13 | "\\end{algo}" {return END;} 14 | "\\SET" {return SET;} 15 | "\\INCR" {return INCR;} 16 | "\\DECR" {return DECR;} 17 | "\\CALL" {return CALL;} 18 | "\\RETURN" {return RET;} 19 | "\\IF" {return IF;} 20 | "\\FI" {return FI;} 21 | "\\ELSE" {return ELSE;} 22 | "\\DOWHILE" {return DOWHILE;} 23 | "\\OD" {return OD;} 24 | "\\DOFORI" {return DOFORI;} 25 | 26 | "," {return VIRGULE;} 27 | 28 | "{" {return OPEN_ACCO;} 29 | "}" {return CLOSE_ACCO;} 30 | "(" {return OPEN_PARENT;} 31 | ")" {return CLOSE_PARENT;} 32 | 33 | "+" {return ADD;} 34 | "-" {return SUB;} 35 | "*" {return MULT;} 36 | "/" {return DIV;} 37 | 38 | "!=" {return DIF;} 39 | "&&" {return AND;} 40 | "==" {return EGAL;} 41 | "||" {return OR;} 42 | "!" {return NOT;} 43 | "<" {return INF;} 44 | "<=" {return INFEQ;} 45 | ">" {return SUP;} 46 | ">=" {return SUPEQ;} 47 | 48 | "true" {return TRUE;} 49 | "false" {return FALSE;} 50 | 51 | [0-9]+ {yylval.entier=atoi(yytext);return NUM;} 52 | 53 | [a-zA-Z][a-zA-Z0-9]* {yylval.idf=strdup(yytext);return IDF;} 54 | 55 | [[:blank:]]+ {;} 56 | \r {;} 57 | 58 | . {fprintf(stderr, "ERREUR: Token '%s' (code ASCII %d) non reconnu à la position %d\n", 59 | yytext, (int)yytext[0], yylineno);} 60 | %% 61 | -------------------------------------------------------------------------------- /parser/compiler.y: -------------------------------------------------------------------------------- 1 | %{ 2 | #include 3 | #include 4 | #include 5 | #include "functions.h" 6 | #include "intermediare.h" 7 | 8 | func_tab *liste; 9 | func_tab *current_fct, *current_call; 10 | intermediare *inter; 11 | int param_number,local_number; 12 | int if_label,while_label,do_label; 13 | cond_tab *if_table, *while_table, *do_table; 14 | 15 | 16 | char tmp[256], tmp2[256]; 17 | 18 | int yylex(); 19 | void yyerror(const char* s){ 20 | fprintf(stderr,"yyerror :%s\n",s); 21 | } 22 | 23 | %} 24 | 25 | %define parse.error verbose 26 | 27 | %union{ 28 | int entier; 29 | char *idf; 30 | TYPE_SYNTH synth; 31 | } 32 | 33 | %type EXPR 34 | 35 | %token NUM 36 | %token IDF 37 | 38 | %token BEG END SET INCR DECR CALL RET IF FI ELSE DOWHILE OD DOFORI; 39 | %token OPEN_ACCO CLOSE_ACCO VIRGULE OPEN_PARENT CLOSE_PARENT; 40 | %token ADD SUB MULT DIV; 41 | %token DIF AND EGAL OR NOT TRUE FALSE INF INFEQ SUP SUPEQ; 42 | 43 | %left EGAL DIF INF INFEQ SUP SUPEQ 44 | %left OR 45 | %left AND 46 | %left NOT 47 | %left ADD SUB 48 | %left MULT DIV 49 | 50 | %start S 51 | 52 | %% 53 | 54 | S : | 55 | function parameters code END S call_final; 56 | 57 | function : BEG OPEN_ACCO IDF CLOSE_ACCO 58 | { 59 | ajouter_func($3,0,0,&liste); 60 | current_fct=recherche_func($3,liste); 61 | add_intermediare(&inter,FUNC_OP,ARG,$3,current_fct); 62 | 63 | param_number=0; 64 | local_number=0; 65 | }; 66 | 67 | 68 | 69 | parameters : OPEN_ACCO list_parameters CLOSE_ACCO { 70 | current_fct->nbr_params=param_number; 71 | add_intermediare(&inter,NUL_OP,OP,NULL,current_fct); 72 | }; 73 | 74 | list_parameters: 75 | | IDF 76 | { 77 | ajouter(PARAM_VAR,$1,current_fct->nom_func,liste); 78 | param_number++; 79 | add_intermediare(&inter,TEST_OP,OP,NULL,current_fct); 80 | } 81 | | list_parameters VIRGULE IDF 82 | { 83 | ajouter(PARAM_VAR,$3,current_fct->nom_func,liste); 84 | param_number++; 85 | add_intermediare(&inter,TEST_OP,OP,NULL,current_fct); 86 | } 87 | ; 88 | 89 | code: instr code | ; 90 | 91 | instr: 92 | // Affectation d'une variable 93 | SET OPEN_ACCO IDF CLOSE_ACCO OPEN_ACCO EXPR CLOSE_ACCO{ 94 | if(recherche($3,current_fct->table) == NULL){ 95 | ajouter(LOCAL_VAR,$3,current_fct->nom_func 96 | ,current_fct); 97 | local_number++; 98 | current_fct->nbr_locals++; 99 | } 100 | add_intermediare(&inter,SET_OP,ARG,$3,current_fct); 101 | }; 102 | // Incrémnetation d'une variable 103 | |INCR OPEN_ACCO IDF CLOSE_ACCO{ 104 | if(recherche($3,current_fct->table) == NULL){ 105 | fprintf(stderr,"La variable \"%s\" n'existe pas\n",$3); 106 | exit(EXIT_FAILURE); 107 | } 108 | add_intermediare(&inter,INCR_OP,ARG,$3,current_fct); 109 | }; 110 | // Décrémentation d'une variable 111 | |DECR OPEN_ACCO IDF CLOSE_ACCO{ 112 | if(recherche($3,current_fct->table) == NULL){ 113 | fprintf(stderr,"La variable \"%s\" n'existe pas\n",$3); 114 | exit(EXIT_FAILURE); 115 | } 116 | add_intermediare(&inter,DECR_OP,ARG,$3,current_fct); 117 | }; 118 | // Condition if 119 | | IF OPEN_ACCO EXPR{ 120 | snprintf(tmp,256,"%d",if_label); 121 | add_cond(&if_table,if_label); 122 | if_label++; 123 | add_intermediare(&inter,IF_OP,ARG,tmp,current_fct); 124 | } 125 | CLOSE_ACCO code ELSE_F; 126 | // Boucle While 127 | | DOWHILE { 128 | snprintf(tmp,256,"%d",while_label); 129 | add_cond(&while_table,while_label); 130 | while_label++; 131 | add_intermediare(&inter,DOWHILE_1_OP,ARG,tmp,current_fct); 132 | }OPEN_ACCO EXPR CLOSE_ACCO { 133 | snprintf(tmp,256,"%d",while_label); 134 | add_cond(&while_table,while_label); 135 | while_label++; 136 | add_intermediare(&inter,DOWHILE_2_OP,ARG,tmp,current_fct); 137 | } code OD { 138 | //récupérer le label pour la fin du while 139 | snprintf(tmp2,256,"%d",pop_cond(&while_table)); 140 | //récupérer le label pour revenir au while 141 | snprintf(tmp,256,"%d",pop_cond(&while_table)); 142 | add_intermediare(&inter,OD_1_OP,ARG,tmp,current_fct); 143 | //pour ajouter le label de la fin 144 | add_intermediare(&inter,OD_2_OP,ARG,tmp2,current_fct); 145 | } 146 | ; 147 | // Retour de fonction 148 | | RET OPEN_ACCO EXPR CLOSE_ACCO { 149 | add_intermediare(&inter,RET_OP,OP,NULL,current_fct); 150 | }; 151 | // Boucle for 152 | | DOFORI OPEN_ACCO IDF CLOSE_ACCO OPEN_ACCO EXPR CLOSE_ACCO { 153 | if(recherche($3,current_fct->table) == NULL){ 154 | ajouter(LOCAL_VAR,$3,current_fct->nom_func 155 | ,current_fct); 156 | local_number++; 157 | current_fct->nbr_locals++; 158 | } 159 | // Pour faire le set de la variable de début 160 | add_intermediare(&inter,DOFORI_1_OP,ARG,$3,current_fct); 161 | 162 | // Création du label pour revenir au for 163 | snprintf(tmp,256,"%d",do_label); 164 | add_cond(&do_table,do_label); 165 | do_label++; 166 | add_intermediare(&inter,DOFORI_2_OP,ARG,tmp,current_fct); 167 | 168 | } 169 | OPEN_ACCO EXPR CLOSE_ACCO { 170 | // Création du jump pour sortir du for 171 | snprintf(tmp,256,"%d",do_label); 172 | add_cond(&do_table,do_label); 173 | do_label++; 174 | add_intermediare(&inter,DOFORI_3_OP,ARG,tmp,current_fct); 175 | } code OD { 176 | // récupérer le label de sortie du for 177 | snprintf(tmp2,256,"%d",pop_cond(&do_table)); 178 | // récupérer le label pour revenir au for 179 | snprintf(tmp,256,"%d",pop_cond(&do_table)); 180 | 181 | add_intermediare(&inter,OD_FORI_1_OP,ARG,tmp,current_fct); 182 | add_intermediare(&inter,OD_FORI_2_OP,ARG,tmp2,current_fct); 183 | } 184 | ; 185 | // Condition else 186 | ELSE_F : ELSE { 187 | // récupérer le label pour le if qui saute juste avant le else 188 | snprintf(tmp2,256,"%d",pop_cond(&if_table)); 189 | // ajouter le label de la fin du code du if 190 | snprintf(tmp,256,"%d",if_label); 191 | add_cond(&if_table,if_label); 192 | if_label++; 193 | add_intermediare(&inter,ELSE_OP,ARG,tmp,current_fct); 194 | 195 | add_intermediare(&inter,ELSE_2_OP,ARG,tmp2,current_fct); 196 | } code FI { 197 | snprintf(tmp,256,"%d",pop_cond(&if_table)); 198 | add_intermediare(&inter,FI_OP,ARG,tmp,current_fct); 199 | } 200 | |FI { 201 | snprintf(tmp,256,"%d",pop_cond(&if_table)); 202 | add_intermediare(&inter,FI_OP,ARG,tmp,current_fct); 203 | 204 | } 205 | ; 206 | // Les expressions 207 | EXPR: 208 | EXPR ADD EXPR { 209 | if(test_expr_int($1,$3) == ERR_T){ 210 | fprintf(stderr,"Type non compatible\n"); 211 | exit(EXIT_FAILURE); 212 | } else { 213 | $$=NUM_T; 214 | 215 | add_intermediare(&inter,ADD_OP,OP,NULL,current_fct); 216 | //addition(); 217 | } 218 | } 219 | 220 | | EXPR SUB EXPR { 221 | if(test_expr_int($1,$3) == ERR_T){ 222 | fprintf(stderr,"Type non compatible\n"); 223 | exit(EXIT_FAILURE); 224 | } else { 225 | $$=NUM_T; 226 | //soustraction(); 227 | add_intermediare(&inter,SUB_OP,OP,NULL,current_fct); 228 | } 229 | } 230 | 231 | | EXPR MULT EXPR { 232 | if(test_expr_int($1,$3) == ERR_T){ 233 | fprintf(stderr,"Type non compatible\n"); 234 | exit(EXIT_FAILURE); 235 | } else { 236 | $$=NUM_T; 237 | //multiplication(); 238 | 239 | add_intermediare(&inter,MUL_OP,OP,NULL,current_fct); 240 | } 241 | } 242 | 243 | | EXPR DIV EXPR { 244 | if(test_expr_int($1,$3) == ERR_T){ 245 | fprintf(stderr,"Type non compatible\n"); 246 | exit(EXIT_FAILURE); 247 | } else { 248 | $$=NUM_T; 249 | add_intermediare(&inter,DIV_OP,OP,NULL,current_fct); 250 | } 251 | } 252 | 253 | | EXPR AND EXPR { 254 | if(test_expr_bool($1,$3) == ERR_T){ 255 | $$=ERR_T; 256 | } else { 257 | $$=BOOL_T; 258 | add_intermediare(&inter,AND_OP,OP,NULL,current_fct); 259 | } 260 | } 261 | 262 | | EXPR OR EXPR { 263 | if(test_expr_bool($1,$3) == ERR_T){ 264 | $$=ERR_T; 265 | } else { 266 | $$=BOOL_T; 267 | add_intermediare(&inter,OR_OP,OP,NULL,current_fct); 268 | } 269 | } 270 | 271 | | EXPR EGAL EXPR { 272 | if($1 != $3){ 273 | fprintf(stderr,"Type non compatible\n"); 274 | exit(EXIT_FAILURE); 275 | } 276 | $$=BOOL_T; 277 | add_intermediare(&inter,EGAL_OP,OP,NULL,current_fct); 278 | } 279 | 280 | | EXPR DIF EXPR { 281 | if($1 != $3){ 282 | fprintf(stderr,"Type non compatible\n"); 283 | exit(EXIT_FAILURE); 284 | } 285 | $$=BOOL_T; 286 | add_intermediare(&inter,DIF_OP,OP,NULL,current_fct); 287 | } 288 | 289 | | EXPR INF EXPR { 290 | if($1 != NUM_T || $3 != NUM_T){ 291 | fprintf(stderr,"Type non compatible\n"); 292 | exit(EXIT_FAILURE); 293 | } 294 | $$=BOOL_T; 295 | add_intermediare(&inter,INF_OP,OP,NULL,current_fct); 296 | } 297 | 298 | | EXPR INFEQ EXPR { 299 | if($1 != NUM_T || $3 != NUM_T){ 300 | fprintf(stderr,"Type non compatible\n"); 301 | exit(EXIT_FAILURE); 302 | } 303 | $$=BOOL_T; 304 | add_intermediare(&inter,INFEQ_OP,OP,NULL,current_fct); 305 | } 306 | 307 | | EXPR SUP EXPR { 308 | if($1 != NUM_T || $3 != NUM_T){ 309 | fprintf(stderr,"Type non compatible\n"); 310 | exit(EXIT_FAILURE); 311 | } 312 | $$=BOOL_T; 313 | add_intermediare(&inter,SUP_OP,OP,NULL,current_fct); 314 | } 315 | 316 | | EXPR SUPEQ EXPR { 317 | if($1 != NUM_T || $3 != NUM_T){ 318 | fprintf(stderr,"Type non compatible\n"); 319 | exit(EXIT_FAILURE); 320 | } 321 | $$=BOOL_T; 322 | add_intermediare(&inter,SUPEQ_OP,OP,NULL,current_fct); 323 | } 324 | 325 | | NOT OPEN_PARENT EXPR CLOSE_PARENT { 326 | if($3 != BOOL_T){ 327 | fprintf(stderr,"Type non compatible\n"); 328 | exit(EXIT_FAILURE); 329 | } 330 | $$=BOOL_T; 331 | add_intermediare(&inter,NOT_OP,OP,NULL,current_fct); 332 | } 333 | 334 | | OPEN_PARENT EXPR CLOSE_PARENT{ 335 | $$=$2; 336 | } 337 | 338 | | NUM { 339 | $$=NUM_T; 340 | //num($1); 341 | sprintf(tmp,"%d",$1); 342 | add_intermediare(&inter,NUM_OP,ARG,tmp,current_fct); 343 | }; 344 | 345 | | FALSE { 346 | $$=BOOL_T; 347 | add_intermediare(&inter,NUM_OP,ARG,"0",current_fct); 348 | } 349 | 350 | | TRUE { 351 | $$=BOOL_T; 352 | add_intermediare(&inter,NUM_OP,ARG,"1",current_fct); 353 | } 354 | 355 | | IDF { 356 | $$=NUM_T; 357 | if(recherche($1,current_fct->table) == NULL){ 358 | fprintf(stderr,"La variable \"%s\" n'existe pas\n",$1); 359 | exit(EXIT_FAILURE); 360 | } 361 | 362 | add_intermediare(&inter,IDF_OP,ARG,$1,current_fct); 363 | } 364 | 365 | | call_expr{ 366 | $$=NUM_T; 367 | } 368 | ; 369 | // Appel de fonction dans le code 370 | call_expr : call_e call_expr_params; 371 | 372 | call_e : CALL OPEN_ACCO IDF CLOSE_ACCO{ 373 | param_number=0; 374 | if(recherche_func($3,liste) == NULL){ 375 | fprintf(stderr,"La fonction \"%s\" n'existe pas\n",$3); 376 | exit(EXIT_FAILURE); 377 | } 378 | current_call=recherche_func($3,liste); 379 | 380 | add_intermediare(&inter,CALL_EXP_OP,OP,NULL,current_call); 381 | }; 382 | 383 | call_expr_params : OPEN_ACCO call_expr_param CLOSE_ACCO{ 384 | // if(param_number != current_call->nbr_params){ 385 | // fprintf(stderr,"Nombre de parametres incorrect pour %s:%d\n",current_call->nom_func,param_number); 386 | // exit(EXIT_FAILURE);} 387 | add_intermediare(&inter,CALL_EXP_PARAM_END_OP,OP,NULL,current_call); 388 | }; 389 | 390 | call_expr_param: EXPR { 391 | param_number++; 392 | } 393 | 394 | | call_expr_param VIRGULE EXPR{ 395 | param_number++; 396 | } 397 | ; 398 | 399 | 400 | call_final : call_f call_params; 401 | 402 | call_f : CALL OPEN_ACCO IDF CLOSE_ACCO{ 403 | if(recherche_func($3,liste) == NULL){ 404 | 405 | fprintf(stderr,"La fonction \"%s\" n'existe pas\n",$3); 406 | exit(EXIT_FAILURE); 407 | } 408 | param_number=0; 409 | current_call=recherche_func($3,liste); 410 | 411 | add_intermediare(&inter,CALL_OP,OP,NULL,current_call); 412 | }; 413 | call_params : OPEN_ACCO call_param CLOSE_ACCO{ 414 | 415 | if(param_number != current_call->nbr_params){ 416 | fprintf(stderr,"Nombre de parametres incorrect\n"); 417 | exit(EXIT_FAILURE);} 418 | add_intermediare(&inter,CALL_PARAM_END_OP,OP,NULL,current_call); 419 | // Dépiler le nombre de variables locales + paramètres 420 | }; 421 | 422 | call_param: EXPR { 423 | param_number++; 424 | } 425 | | call_param VIRGULE EXPR{ 426 | param_number++; 427 | } 428 | ; 429 | %% 430 | 431 | int main(void){ 432 | liste=NULL; 433 | inter=NULL; 434 | yyparse(); 435 | traverse_func_tab(liste); 436 | generate_intermediare(inter); 437 | free_intermediare(inter); 438 | return 0; 439 | } 440 | -------------------------------------------------------------------------------- /script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ $# -eq 0 ]; then 3 | echo -e "Usage : ./script fichier.tex" 4 | echo -e "[!] Compilation aborted" 5 | exit 1 6 | fi 7 | 8 | echo -e "[-] Compiling ..." 9 | 10 | if ! make; then 11 | echo -e "[!] Compilation failed" 12 | exit 1 13 | fi 14 | 15 | echo -e "\n[+] Compiling ended" 16 | 17 | 18 | echo -e "[-] Generating the .asm file \n Table of symbols : \n" 19 | ./build/compiler > expr.asm < "$1" 20 | echo -e "" 21 | 22 | if [ ! -f asipro ] || [ ! -f sipro ]; then 23 | echo -e "[!] 'asipro' or 'sipro' not found in current directory." 24 | read -p "Clone and build them from GitHub? (Y/n): " choice 25 | 26 | if [[ "$choice" == "Y" || "$choice" == "y" || "$choice" == "" ]]; then 27 | echo -e "[-] Cloning asipro repo..." 28 | git clone https://github.com/NicolasBedon/asipro.git temp_asipro || { echo "[!] Git clone failed"; exit 1; } 29 | 30 | echo -e "[-] Building asipro and sipro..." 31 | make -C temp_asipro/emul || { echo "[!] Make of sipro failed"; exit 1; } 32 | make -C temp_asipro/asm || { echo "[!] Make of asipro failed"; exit 1; } 33 | 34 | cp temp_asipro/emul/sipro ./ || { echo "[!] Copy of sipro failed"; exit 1; } 35 | cp temp_asipro/asm/asipro ./ || { echo "[!] Copy of asipro failed"; exit 1; } 36 | 37 | echo -e "[+] asipro and sipro are ready" 38 | rm -rf temp_asipro 39 | else 40 | echo -e "[!] Required tools not found. Aborting." 41 | exit 1 42 | fi 43 | fi 44 | 45 | # Une fois qu'on est sûr qu'on a les bons binaires : 46 | echo -e "[-] Running asipro..." 47 | ./asipro expr.asm expr 2> err.asipro.log 48 | echo -e "[+] Executable generated" 49 | 50 | echo -e "\n[-] Executing with sipro...\n" 51 | ./sipro expr 52 | 53 | -------------------------------------------------------------------------------- /src/functions.c: -------------------------------------------------------------------------------- 1 | #include"functions.h" 2 | 3 | 4 | int label = 0; 5 | 6 | void err_div(){ 7 | printf(":msgErrDiv0\n"); 8 | printf("@string \"Erreur division par 0\\n\"\n"); 9 | printf(":errDiv0\n"); 10 | printf("\tconst ax,msgErrDiv0\n"); 11 | printf("\tcallprintfs ax\n"); 12 | printf("\tend\n"); 13 | } 14 | 15 | void err_overflow(){ 16 | printf(":msgErrOverflow\n"); 17 | printf("@string \"Erreur dépassement de capacité\\n\"\n"); 18 | printf(":errOverflow\n"); 19 | printf("\tconst ax,msgErrOverflow\n"); 20 | printf("\tcallprintfs ax\n"); 21 | printf("\tend\n"); 22 | } 23 | 24 | void start_asm(){ 25 | printf("\tconst ax,debut\n"); 26 | printf("\tjmp ax\n"); 27 | printf(":nl\n"); 28 | printf("@string \"\\n\"\n"); 29 | err_div(); 30 | err_overflow(); 31 | /*Mettre toutes les fonctions ici*/ 32 | 33 | } 34 | 35 | void main_asm(){ 36 | printf(":debut\n"); 37 | printf("\tconst bp,pile\n"); 38 | printf("\tconst sp,pile\n"); 39 | printf("\tconst ax,2\n"); 40 | printf("\tsub sp,ax\n"); 41 | } 42 | 43 | void end_asm(){ 44 | printf("\tcp ax,sp\n"); 45 | printf("\tcallprintfd ax\n"); 46 | printf("\tconst ax,nl\n"); 47 | printf("\tcallprintfs ax\n"); 48 | printf("\tpop ax\n"); 49 | printf("\tend\n"); 50 | printf(":pile\n"); 51 | printf("@int 0\n"); 52 | } 53 | 54 | void prepare_stack_locals(func_tab *func){ 55 | // Variables locales 56 | printf(";Variables locales\n"); 57 | for (int i = 0; i < func->nbr_locals; i++){ 58 | printf(";ajout de la v_loc : %d\n",i); 59 | printf("\tconst ax,0\n"); 60 | printf("\tpush ax\n"); 61 | } 62 | 63 | } 64 | 65 | 66 | void prepare_stack_func(func_tab *func){ 67 | printf("\tpush bp\n"); 68 | printf("\tcp bp,sp\n"); 69 | } 70 | 71 | int test_expr_int(int first, int second){ 72 | if(first != NUM_T || second != NUM_T) 73 | return ERR_T; 74 | return NUM_T; 75 | } 76 | 77 | int test_expr_bool(int first, int second){ 78 | if(first != BOOL_T || second != BOOL_T) 79 | return ERR_T; 80 | return BOOL_T; 81 | } 82 | 83 | void addition(){ 84 | printf("\tpop ax\n"); 85 | printf("\tpop bx\n"); 86 | printf("\tconst cx,errOverflow\n"); 87 | printf("\tadd ax,bx\n"); 88 | printf("\tjmpe cx\n"); 89 | printf("\tpush ax\n"); 90 | } 91 | 92 | void soustraction() 93 | { 94 | printf("\tpop bx\n"); 95 | printf("\tpop ax\n"); 96 | printf("\tsub ax,bx\n"); 97 | printf("\tpush ax\n"); 98 | } 99 | 100 | void multiplication(){ 101 | printf("\tpop ax\n"); 102 | printf("\tpop bx\n"); 103 | printf("\tconst cx,errOverflow\n"); 104 | printf("\tmul ax,bx\n"); 105 | printf("\tjmpe cx\n"); 106 | printf("\tpush ax\n"); 107 | } 108 | 109 | void division(){ 110 | printf("\tpop bx\n"); 111 | printf("\tpop ax\n"); 112 | printf("\tconst cx,errDiv0\n"); 113 | printf("\tdiv ax,bx\n"); 114 | printf("\tjmpe cx\n"); 115 | printf("\tpush ax\n"); 116 | } 117 | 118 | void or(){ 119 | printf(";Debut or\n"); 120 | char *jump = create_label("jump_or",label); 121 | char *end = create_label("end_or",label); 122 | printf("\tpop ax\n"); 123 | printf("\tpop bx\n"); 124 | printf("\tadd ax,bx\n"); 125 | printf("\tconst cx,%s\n",jump); 126 | printf("\tconst bx,0\n"); 127 | printf("\tcmp ax,bx\n"); 128 | printf("\tjmpc cx\n"); 129 | printf("\tconst ax,1\n"); 130 | printf("\tpush ax\n"); 131 | printf("\tconst ax,%s\n",end); 132 | printf("\tjmp ax\n"); 133 | printf(":%s\n",jump); 134 | printf("\tpush ax\n"); 135 | printf(":%s\n",end); 136 | label++; 137 | free(jump); 138 | free(end); 139 | printf(";Debut or\n"); 140 | } 141 | 142 | void not(){ 143 | printf(";Debut not\n"); 144 | 145 | printf("\tpop bx\n"); 146 | printf("\tconst ax,1\n"); 147 | printf("\tsub ax,bx\n"); 148 | printf("\tpush ax\n"); 149 | 150 | printf(";Fin not\n"); 151 | } 152 | 153 | void egal(){ 154 | printf(";Debut égalité\n"); 155 | char *jump = create_label("jump_egal",label); 156 | char *end = create_label("end_egal",label); 157 | printf("\tpop ax\n"); 158 | printf("\tpop bx\n"); 159 | printf("\tconst cx,%s\n",jump); 160 | printf("\tcmp ax,bx\n"); 161 | printf("\tjmpc cx\n"); 162 | printf("\tconst ax,0\n"); 163 | printf("\tpush ax\n"); 164 | printf("\tconst cx,%s\n",end); 165 | printf("\tjmp cx\n"); 166 | printf(":%s\n",jump); 167 | printf("\tconst ax,1\n"); 168 | printf("\tpush ax\n"); 169 | printf(":%s\n",end); 170 | printf(";Fin égalité\n"); 171 | label++; 172 | free(jump); 173 | free(end); 174 | } 175 | 176 | void diff(){ 177 | printf(";Debut différence\n"); 178 | char *jump = create_label("jump_diff",label); 179 | char *end = create_label("end_diff",label); 180 | printf("\tpop ax\n"); 181 | printf("\tpop bx\n"); 182 | printf("\tconst cx,%s\n",jump); 183 | printf("\tcmp ax,bx\n"); 184 | printf("\tjmpc cx\n"); 185 | printf("\tconst ax,1\n"); 186 | printf("\tpush ax\n"); 187 | printf("\tconst cx,%s\n",end); 188 | printf("\tjmp cx\n"); 189 | printf(":%s\n",jump); 190 | printf("\tconst ax,0\n"); 191 | printf("\tpush ax\n"); 192 | printf(":%s\n",end); 193 | printf(";Fin différence\n"); 194 | label++; 195 | free(jump); 196 | free(end); 197 | 198 | } 199 | 200 | void inf(){ 201 | printf(";Debut inf\n"); 202 | char *jump = create_label("jump_inf",label); 203 | char *end = create_label("end_inf",label); 204 | //pop les deux valeurs 205 | printf("\tpop bx\n"); 206 | printf("\tpop ax\n"); 207 | 208 | printf("\tconst cx,%s\n", jump); 209 | printf("\tsless ax,bx\n"); 210 | printf("\tjmpc cx\n"); 211 | 212 | printf("\tconst ax,0\n"); 213 | printf("\tpush ax\n"); 214 | printf("\tconst dx,%s\n", end); 215 | printf("\tjmp dx\n"); 216 | 217 | printf(":%s\n", jump); 218 | printf("\tconst ax,1\n"); 219 | printf("\tpush ax\n"); 220 | 221 | printf(":%s\n", end); 222 | 223 | printf(";Fin inf\n"); 224 | label++; 225 | free(jump); 226 | free(end); 227 | } 228 | 229 | void sup(){ 230 | printf(";Debut sup\n"); 231 | char *jump = create_label("jump_sup",label); 232 | char *end = create_label("end_sup",label); 233 | //pop les deux valeurs 234 | printf("\tpop bx\n"); 235 | printf("\tpop ax\n"); 236 | 237 | printf("\tconst cx,%s\n", jump); 238 | printf("\tsless bx,ax\n"); 239 | printf("\tjmpc cx\n"); 240 | 241 | printf("\tconst ax,0\n"); 242 | printf("\tpush ax\n"); 243 | printf("\tconst dx,%s\n", end); 244 | printf("\tjmp dx\n"); 245 | 246 | printf(":%s\n", jump); 247 | printf("\tconst ax,1\n"); 248 | printf("\tpush ax\n"); 249 | 250 | printf(":%s\n", end); 251 | 252 | printf(";Fin sup\n"); 253 | label++; 254 | free(jump); 255 | free(end); 256 | } 257 | 258 | void infeq(){ 259 | printf(";Debut infeq\n"); 260 | char *jump = create_label("jump_infeq",label); 261 | char *end = create_label("end_infeq",label); 262 | //pop les deux valeurs 263 | printf("\tpop bx\n"); 264 | printf("\tpop ax\n"); 265 | 266 | printf("\tconst cx,%s\n", jump); 267 | printf("\tcmp ax,bx\n"); 268 | printf("\tjmpc cx\n"); 269 | printf("\tsless ax,bx\n"); 270 | printf("\tjmpc cx\n"); 271 | 272 | printf("\tconst ax,0\n"); 273 | printf("\tpush ax\n"); 274 | printf("\tconst dx,%s\n", end); 275 | printf("\tjmp dx\n"); 276 | 277 | printf(":%s\n", jump); 278 | printf("\tconst ax,1\n"); 279 | printf("\tpush ax\n"); 280 | 281 | printf(":%s\n", end); 282 | 283 | printf(";Fin infeq\n"); 284 | label++; 285 | free(jump); 286 | free(end); 287 | } 288 | 289 | void supeq(){ 290 | printf(";Debut supeq\n"); 291 | char *jump = create_label("jump_supeq",label); 292 | char *end = create_label("end_supeq",label); 293 | //pop les deux valeurs 294 | printf("\tpop bx\n"); 295 | printf("\tpop ax\n"); 296 | 297 | printf("\tconst cx,%s\n", jump); 298 | printf("\tcmp ax,bx\n"); 299 | printf("\tjmpc cx\n"); 300 | printf("\tsless bx,ax\n"); 301 | printf("\tjmpc cx\n"); 302 | 303 | printf("\tconst ax,0\n"); 304 | printf("\tpush ax\n"); 305 | printf("\tconst dx,%s\n", end); 306 | printf("\tjmp dx\n"); 307 | 308 | printf(":%s\n", jump); 309 | printf("\tconst ax,1\n"); 310 | printf("\tpush ax\n"); 311 | 312 | printf(":%s\n", end); 313 | 314 | printf(";Fin supeq\n"); 315 | label++; 316 | free(jump); 317 | free(end); 318 | } 319 | 320 | void num(int number){ 321 | printf("\tconst ax,%d\n",number); 322 | printf("\tpush ax\n"); 323 | } 324 | 325 | void affect_from_top_stack(char *nom,func_tab* head){ 326 | printf(";Affectation de %s\n",nom); 327 | printf("\tpop dx\n"); 328 | printf("\tcp bx,bp\n"); 329 | printf("\tconst ax,%d\n",get_param_location(nom,head)); 330 | printf("\tsub bx,ax\n"); 331 | printf("\tstorew dx,bx\n"); 332 | printf(";Fin de l'affectation de %s\n",nom); 333 | } 334 | 335 | void increment(char* nom,func_tab* head){ 336 | printf(";increment : %s\n",nom); 337 | get_param_from_stack(nom,head); 338 | printf("\tpop dx\n"); 339 | printf("\tconst ax,1\n"); 340 | printf("\tadd dx,ax\n"); 341 | printf("\tstorew dx,bx\n"); 342 | printf(";end increment\n"); 343 | } 344 | 345 | void decrement(char* nom,func_tab* head){ 346 | printf(";decrement : %s\n",nom); 347 | get_param_from_stack(nom,head); 348 | //print_reg("bx"); 349 | printf("\tpop dx\n"); 350 | printf("\tconst ax,1\n"); 351 | printf("\tsub dx,ax\n"); 352 | printf("\tstorew dx,bx\n"); 353 | //affiche le registre qui contient nom; print_reg("bx"); 354 | printf(";end decrement\n"); 355 | } 356 | 357 | 358 | sym_tab* nouvelle_cellule() { 359 | sym_tab* cel = (sym_tab*)malloc(sizeof(sym_tab)); 360 | return cel; 361 | } 362 | 363 | func_tab *nouvelle_cellule_func(){ 364 | func_tab *cel = (func_tab*)malloc(sizeof(func_tab)); 365 | return cel; 366 | } 367 | 368 | void ajouter(int val, char* nom, char* nom_func, func_tab* head){ 369 | 370 | sym_tab *cel = nouvelle_cellule(); 371 | if(cel == NULL){ 372 | perror("malloc"); 373 | exit(EXIT_FAILURE); 374 | } 375 | func_tab *func = recherche_func(nom_func,head); 376 | if (func == NULL) { 377 | fprintf(stderr,"Function %s not found!",nom_func); 378 | exit(EXIT_FAILURE); 379 | } 380 | 381 | cel->nom_idf=strdup(nom); 382 | cel->type = val; 383 | cel->num_var = (val == PARAM_VAR) ? param_number : local_number; 384 | cel->ptr = func->table; 385 | func->table = cel; 386 | 387 | } 388 | 389 | void ajouter_func(char *nom, int nbr_p, int nbr_v,func_tab **head){ 390 | func_tab *cel = nouvelle_cellule_func(); 391 | if(cel == NULL){ 392 | perror("malloc"); 393 | exit(EXIT_FAILURE); 394 | } 395 | 396 | 397 | cel->nom_func=strdup(nom); 398 | cel->nbr_params = nbr_p; 399 | cel->nbr_locals = nbr_v; 400 | cel->table = NULL; 401 | cel->ptr = *head; 402 | *head = cel; 403 | } 404 | 405 | sym_tab* recherche(char* nom, sym_tab* head){ 406 | while (head != NULL){ 407 | if (!strcmp(head->nom_idf,nom)){ 408 | break; 409 | } 410 | head=head->ptr; 411 | } 412 | return head; 413 | } 414 | 415 | func_tab *recherche_func(char *nom, func_tab *head){ 416 | while (head != NULL){ 417 | if (!strcmp(head->nom_func,nom)){ 418 | break; 419 | } 420 | head=head->ptr; 421 | } 422 | return head; 423 | } 424 | 425 | void print_sym_tab(sym_tab *head){ 426 | printf(";------------------------\n"); 427 | //printf("--idf---------type-------\n"); 428 | while(head != NULL) 429 | { 430 | fprintf(stderr,";name %s--type %d--num_val %d\n",head->nom_idf,head->type,head->num_var); 431 | head=head->ptr; 432 | } 433 | } 434 | 435 | // génère du code pour une fonction qui parcours la strcuture func_tab en profondeur 436 | void traverse_func_tab(func_tab *head) { 437 | if (head == NULL) { 438 | return; 439 | } 440 | fprintf(stderr, "--------Function: %s---------\n", head->nom_func); 441 | fprintf(stderr, "Number of parameters: %d\n", head->nbr_params); 442 | fprintf(stderr, "Number of locals: %d\n", head->nbr_locals); 443 | fprintf(stderr, "Symbol Table:\n"); 444 | print_sym_tab(head->table); 445 | traverse_func_tab(head->ptr); 446 | } 447 | 448 | 449 | void get_param_from_stack(char *nom,func_tab *head){ 450 | printf(";Récupérer le paramètre:%s\n",nom); 451 | printf("\tcp bx,bp\n"); 452 | printf("\tconst ax,%d\n",get_param_location(nom,head)); 453 | printf("\tsub bx,ax\n"); 454 | printf("\tloadw dx,bx\n"); 455 | printf("\tpush dx\n"); 456 | printf(";Fin de la récupération de:%s\n",nom); 457 | } 458 | 459 | int get_param_location(char *nom,func_tab *head){ 460 | sym_tab *node = recherche(nom,head->table); 461 | if(node == NULL){ 462 | perror("recherche"); 463 | exit(EXIT_FAILURE); 464 | } 465 | if(node->type == PARAM_VAR) 466 | return 2 + 2*head->nbr_locals + 2*head->nbr_params - node->num_var*2; 467 | return 2 + 2*head->nbr_locals - node->num_var*2; 468 | } 469 | 470 | 471 | void print_param(char* nom,func_tab* head){ 472 | printf(";start print_param\n"); 473 | printf("\tcp bx,bp\n"); 474 | printf("\tconst cx,%d\n",get_param_location(nom,head)); 475 | printf("\tadd bx,cx\n"); 476 | printf("\tcallprintfd bx\n"); 477 | printf("\tconst cx,nl\n"); 478 | printf("\tcallprintfs cx\n"); 479 | printf(";end print_param\n"); 480 | } 481 | 482 | void print_reg(char *nom){ 483 | printf(";printing %s register\n",nom); 484 | printf("\tcallprintfd %s\n",nom); 485 | printf("\tconst cx,nl\n"); 486 | printf("\tcallprintfs cx\n"); 487 | printf(";%s register printed\n",nom); 488 | } 489 | 490 | void return_from_func(func_tab *head){ 491 | // Mettre la valeur de retour 492 | printf(";Mettre la valeur de retour\n"); 493 | printf("\tcp bx,bp\n"); 494 | printf("\tpop ax\n"); 495 | int n = 4 + head->nbr_locals * 2 + head->nbr_params * 2; 496 | printf("\tconst cx,%d\n",n); 497 | printf("\tsub bx,cx\n"); 498 | printf("\tstorew ax,bx\n"); 499 | 500 | // Restaurer la base de la pile 501 | printf(";Restaurer la base de la pile et mettre sp à bp\n"); 502 | printf("\tcp sp,bp\n"); 503 | printf("\tpop bp\n"); 504 | printf("\tret\n"); 505 | } 506 | 507 | 508 | void free_sym(sym_tab *sym) { 509 | if (sym == NULL) 510 | return; 511 | free(sym->nom_idf); 512 | free(sym); 513 | } 514 | 515 | 516 | void free_func(func_tab *func) { 517 | if (func == NULL) 518 | return; 519 | free(func->nom_func); 520 | free_sym(func->table); // libérer la table de symboles 521 | free_func(func->ptr); // libérer le prochain élément dans la liste 522 | free(func); 523 | } 524 | char* create_label(char* label_name, int number){ 525 | char* buffer = (char*)malloc(128 * sizeof(char)); 526 | if(buffer == NULL){ 527 | perror("malloc"); 528 | exit(EXIT_FAILURE); 529 | } 530 | if(snprintf(buffer,128,"%s:%d",label_name,number) == -1){ 531 | perror("snprintf"); 532 | exit(EXIT_FAILURE); 533 | } 534 | return buffer; 535 | } -------------------------------------------------------------------------------- /src/intermediare.c: -------------------------------------------------------------------------------- 1 | #include "intermediare.h" 2 | #include "functions.h" 3 | 4 | 5 | //corps des fonctions 6 | 7 | void add_cond(cond_tab **head, int id){ 8 | cond_tab *new = (cond_tab *)malloc(sizeof(cond_tab)); 9 | if(new == NULL){ 10 | perror("malloc"); 11 | exit(EXIT_FAILURE); 12 | } 13 | new->cond_id = id; 14 | new->next = NULL; 15 | 16 | if(*head == NULL){ 17 | *head = new; 18 | }else{ 19 | cond_tab *current = *head; 20 | while(current->next != NULL){ 21 | current = current->next; 22 | } 23 | current->next = new; 24 | } 25 | } 26 | 27 | int pop_cond(cond_tab **head){ 28 | cond_tab *current = *head; 29 | if(current == NULL){ 30 | return -1; 31 | } 32 | cond_tab *prev = NULL; 33 | while(current->next != NULL){ 34 | prev = current; 35 | current = current->next; 36 | } 37 | int id = current->cond_id; 38 | if(prev != NULL){ 39 | prev->next = NULL; 40 | }else{ 41 | *head = NULL; 42 | } 43 | free(current); 44 | return id; 45 | } 46 | 47 | void free_cond(cond_tab **head){ 48 | cond_tab *current = *head; 49 | cond_tab *tmp = current; 50 | while(tmp != NULL){ 51 | tmp = current->next; 52 | free(tmp); 53 | current = tmp; 54 | } 55 | *head = NULL; 56 | } 57 | 58 | void add_intermediare(intermediare **head, operation op, arg_type type, char *arg, func_tab* func){ 59 | intermediare *new = (intermediare *)malloc(sizeof(intermediare)); 60 | //fprintf(stderr,"je vais ajouter %d\n",op); 61 | if(new == NULL){ 62 | perror("malloc"); 63 | exit(EXIT_FAILURE); 64 | } 65 | new->type = type; 66 | if(type == OP){ 67 | new->arg = NULL; 68 | }else{ 69 | new->arg = strdup(arg); 70 | } 71 | 72 | new->op = op; 73 | new->function = func; 74 | new->next = NULL; 75 | if(*head == NULL){ 76 | *head = new; 77 | }else{ 78 | intermediare *current = *head; 79 | while(current->next != NULL){ 80 | current = current->next; 81 | } 82 | current->next = new; 83 | } 84 | } 85 | 86 | 87 | void generate_intermediare(intermediare *head){ 88 | start_asm(); 89 | while(head != NULL){ 90 | choose_op(head); 91 | head = head->next; 92 | } 93 | } 94 | 95 | void free_intermediare(intermediare *head){ 96 | intermediare *current = head; 97 | while(current != NULL){ 98 | intermediare *tmp = current; 99 | current = current->next; 100 | if(tmp->type == ARG){ 101 | free(tmp->arg); 102 | } 103 | free(tmp); 104 | } 105 | head = NULL; 106 | } 107 | 108 | 109 | void print_intermediare(intermediare *head){ 110 | fprintf(stderr,"------------\n"); 111 | while(head != NULL){ 112 | if(head->type == OP){ 113 | fprintf(stderr,"Opération: %d -- no arg\n",head->op); 114 | } 115 | if(head->type == ARG){ 116 | fprintf(stderr,"Opération: %d -- arg1 : %s\n",head->op,head->arg); 117 | } 118 | head=head->next; 119 | } 120 | fprintf(stderr,"------------\n"); 121 | } 122 | 123 | 124 | void choose_op(intermediare *node){ 125 | switch(node->op){ 126 | case ADD_OP: 127 | addition(); 128 | break; 129 | case SUB_OP: 130 | soustraction(); 131 | break; 132 | case MUL_OP: 133 | multiplication(); 134 | break; 135 | case DIV_OP: 136 | division(); 137 | break; 138 | case AND_OP: 139 | multiplication(); 140 | break; 141 | case OR_OP: 142 | or(); 143 | break; 144 | case NOT_OP: 145 | not(); 146 | break; 147 | case EGAL_OP: 148 | egal(); 149 | break; 150 | case DIF_OP: 151 | diff(); 152 | break; 153 | case INF_OP: 154 | inf(); 155 | break; 156 | case SUP_OP: 157 | sup(); 158 | break; 159 | case INFEQ_OP: 160 | infeq(); 161 | break; 162 | case SUPEQ_OP: 163 | supeq(); 164 | break; 165 | case SET_OP: 166 | affect_from_top_stack(node->arg,node->function); 167 | break; 168 | case INCR_OP: 169 | increment(node->arg,node->function); 170 | break; 171 | case DECR_OP: 172 | decrement(node->arg,node->function); 173 | break; 174 | case IDF_OP: 175 | get_param_from_stack(node->arg,node->function); 176 | break; 177 | case NUM_OP: 178 | num(atoi(node->arg)); 179 | break; 180 | case NUL_OP: 181 | break; 182 | case FUNC_OP: 183 | printf(":%s\n",node->function->nom_func); 184 | prepare_stack_func(node->function); 185 | break; 186 | case CALL_OP: 187 | main_asm(); 188 | // Valeur de retour 189 | printf(";Valeur de retour\n"); 190 | printf("\tconst ax,0\n"); 191 | printf("\tpush ax\n"); 192 | printf(";Paramètres\n"); 193 | break; 194 | case CALL_EXP_OP: 195 | printf(";préparation de l'appel de %s\n",node->function->nom_func); 196 | printf(";Valeur de retour\n"); 197 | printf("\tconst ax,0\n"); 198 | printf("\tpush ax\n"); 199 | printf(";Paramètres\n"); 200 | break; 201 | 202 | case CALL_EXP_PARAM_END_OP: 203 | printf(";Fin des paramètres\n"); 204 | prepare_stack_locals(node->function); 205 | printf(";Appel de la fonction %s\n",node->function->nom_func); 206 | printf("\tconst ax,%s\n",node->function->nom_func); 207 | printf("\tcall ax\n"); 208 | printf(";Dépiler le nombre de variables locales + paramètres\n"); 209 | for (int i = 0; i < node->function->nbr_locals + node->function->nbr_params; i++) 210 | printf("\tpop ax\n"); 211 | printf(";Fin de la dépilement\n"); 212 | break; 213 | case CALL_PARAM_END_OP: 214 | prepare_stack_locals(node->function); 215 | printf(";Appel de la fonction %s\n",node->function->nom_func); 216 | printf("\tconst ax,%s\n",node->function->nom_func); 217 | printf("\tcall ax\n"); 218 | printf(";Dépiler le nombre de variables locales + paramètres\n"); 219 | for (int i = 0; i < node->function->nbr_locals + node->function->nbr_params; i++) 220 | printf("\tpop ax\n"); 221 | printf(";Fin de la dépilement\n"); 222 | end_asm(); 223 | break; 224 | case RET_OP: 225 | return_from_func(node->function); 226 | break; 227 | case ARG_OP: 228 | break; 229 | case IF_OP: 230 | printf(";If statement\n"); 231 | char *if_jump=create_label("if_jump",atoi(node->arg)); 232 | 233 | printf("\tpop ax\n"); 234 | printf("\tconst bx,0\n"); 235 | printf("\tconst cx,%s\n",if_jump); 236 | printf("\tcmp ax,bx\n"); 237 | printf("\tjmpz cx\n"); 238 | 239 | break; 240 | case FI_OP: 241 | printf(":%s\n",create_label("if_jump",atoi(node->arg))); 242 | break; 243 | 244 | case ELSE_OP: 245 | printf(";If jumping after Else\n"); 246 | printf("\tconst ax,%s\n",create_label("if_jump",atoi(node->arg))); 247 | printf("\tjmp ax\n"); 248 | break; 249 | case ELSE_2_OP: 250 | printf(";Else statement\n"); 251 | char *else_jump=create_label("if_jump",atoi(node->arg)); 252 | printf(":%s\n",else_jump); 253 | break; 254 | case DOWHILE_1_OP: 255 | printf(";Do while statement\n"); 256 | char *do_while=create_label("do_while",atoi(node->arg)); 257 | printf(":%s\n",do_while); 258 | break; 259 | case DOWHILE_2_OP: 260 | printf(";Testing condition\n"); 261 | printf("\tpop ax\n"); 262 | printf("\tconst bx,0\n"); 263 | printf("\tconst cx,%s\n",create_label("do_while",atoi(node->arg))); 264 | printf("\tcmp ax,bx\n"); 265 | printf("\tjmpz cx\n"); 266 | break; 267 | case OD_1_OP: 268 | printf(";Jumping to the while\n"); 269 | printf("\tconst ax,%s\n",create_label("do_while",atoi(node->arg))); 270 | printf("\tjmp ax\n"); 271 | break; 272 | case OD_2_OP: 273 | printf(";End of the do while\n"); 274 | printf(":%s\n",create_label("do_while",atoi(node->arg))); 275 | break; 276 | case DOFORI_1_OP: 277 | printf(";Affecting the start of the loop\n"); 278 | affect_from_top_stack(node->arg,node->function); 279 | printf(";Push the adress of the var used for iteration\n"); 280 | printf("\tpush bx\n"); 281 | break; 282 | case DOFORI_2_OP: 283 | printf(":%s\n",create_label("for_loop",atoi(node->arg))); 284 | printf(";Calculating the end value\n"); 285 | break; 286 | case DOFORI_3_OP: 287 | printf(";Comparing the end value\n"); 288 | printf("\tpop ax\n"); 289 | printf("\tpop bx\n"); 290 | printf("\tloadw cx,bx\n"); 291 | printf(";Push the address back\n"); 292 | printf("\tpush bx\n"); 293 | printf("\tconst dx,%s\n",create_label("for_loop",atoi(node->arg))); 294 | printf("\tsless ax,cx\n"); 295 | printf("\tjmpc dx\n"); 296 | break; 297 | case OD_FORI_1_OP: 298 | printf(";Incrementing the value\n"); 299 | printf("\tpop bx\n"); 300 | printf("\tloadw ax,bx\n"); 301 | printf("\tconst cx,1\n"); 302 | printf("\tadd ax,cx\n"); 303 | printf("\tstorew ax,bx\n"); 304 | printf(";Push the address back\n"); 305 | printf("\tpush bx\n"); 306 | printf(";Jumping to for\n"); 307 | printf("\tconst ax,%s\n",create_label("for_loop",atoi(node->arg))); 308 | printf("\tjmp ax\n"); 309 | break; 310 | case OD_FORI_2_OP: 311 | printf(";End of the for loop\n"); 312 | printf(":%s\n",create_label("for_loop",atoi(node->arg))); 313 | break; 314 | default: 315 | break; 316 | } 317 | } -------------------------------------------------------------------------------- /test.tex: -------------------------------------------------------------------------------- 1 | \begin{algo}{main}{a,b} 2 | \SET{d}{a+5} 3 | \INCR{d} 4 | \RETURN{d} 5 | \end{algo} 6 | \CALL{main}{1,9} --------------------------------------------------------------------------------