En cours de clean

This commit is contained in:
Paul Faure 2021-06-14 09:04:23 +02:00
parent afbc1461c4
commit bbd3585d96
14 changed files with 543 additions and 1353 deletions

1
.gitignore vendored
View file

@ -9,3 +9,4 @@ Tables/Fonctions/test
Lex_Yacc/as.output Lex_Yacc/as.output
Lex_Yacc/as.tab.* Lex_Yacc/as.tab.*
Lex_Yacc/lex.yy.* Lex_Yacc/lex.yy.*
Lex_Yacc/as.dot

View file

@ -1,52 +0,0 @@
les fonctions (avec parametres)
le if
le while
les declarations
les affectations
les operations arith.
le retour de fonction
l'invocation de fonctions
C : Fonctions ;
Fonctions : Fonction Fonctions | Fonction ;
Fonction : tInt tID tPO Params tPF Body ;
Params : | Param SuiteParams ;
Param : tInt tID ;
SuiteParams : tVirgule Param SuiteParams | ;
// Ps : P Ps | ;
// P : tInt tID tVirgule
// Ps =>* tInt tID tVirgule tInt tID tVirgule
// Ps => P Ps => P P Ps ...
Body : tAO Instructions tAF ;
Instructions : Instruction Instructions | ;
Instruction : Aff | If | While | Return | Decl | Invocation tPV ;
Aff : tID tEQ E tPV ;
E : tNB | tID | E tADD E | E tMUL E | E tMINUS E | E tDIV E | Invocation | tPO E tPF | tMINUS E ;
// E : tID tADD tID | ...
If : tIF tPO Cond tPF Body ;
Cond : Cond tAND Cond | Cond tOR Cond | E tEQ2 E | E tINF E | tNOT Cond ;
Invocation : tID tPO Args tPF ;
Args : .... cf params
Return : tRET E tPV ;

View file

@ -30,17 +30,17 @@ Copie la valeur val à l'adresse @X
Copie la valeur contenue dans @C à l'adresse @X en considérant que ce qui est copié est une adresse (et donc il faut ajouter BP) Copie la valeur contenue dans @C à l'adresse @X en considérant que ce qui est copié est une adresse (et donc il faut ajouter BP)
## AFCA @X addr ## AFCA @X val
Copie la valeur addr à l'adresse @X en considérant que ce qui est copié est une adresse (et donc il faut ajouter BP) Copie la val à l'adresse @X en considérant que ce qui est copié est une adresse (et donc il faut ajouter BP)
## JMP lig ## JMP ins
Saute vers la ligne lig dans le code sans condition Saute vers la ligne ins dans le code sans condition
## JMF @X lig ## JMF @X ins
Saute vers la ligne lig dans le code si la valeur à l'adresse @X est 0 Saute vers la ligne ins dans le code si la valeur à l'adresse @X est 0
## INF @X @A @B ## INF @X @A @B
@ -62,14 +62,15 @@ Va mettre à l'adresse @X ce qui est à l'addresse contenue à l'adresse @Y (on
Va mettre le contenu de @Y dans l'adresse qui est la valeur dans @X (on considère que @X est un pointeur et on écrit dans l'adresse qui est contenue dans @X). Attention, considérer des addresses globales (pas relatives). Va mettre le contenu de @Y dans l'adresse qui est la valeur dans @X (on considère que @X est un pointeur et on écrit dans l'adresse qui est contenue dans @X). Attention, considérer des addresses globales (pas relatives).
##CALL lig taille_pile_fonction_appelante ##CALL ins taille_pile_fonction_appelante
Appelle la fonction dont la première ligne est ins et taille_pile_fonction_appelante est la taille de la zone mémoire utilisée par la fonction appelante (avant le push des arguments !)
Appelle la fonction dont la première ligne est lig et taille_pile_fonction_appelante est la taille de la zone mémoire utilisée par la fonction appelante (avant le push des args !)
##RET ##RET
Bouge BP et saute à l'adresse de retour (selon les valeur qui sont dans la pile de contrôle). Restore BP et saute à l'adresse de retour (selon les valeur qui sont dans la pile de contrôle).
##STOP ##STOP val
Arrete le processeur (à mettre à la fin de l'ASM) Arrete le processeur si val vaut 0 (à mettre à la fin de l'ASM), ou, arrete le processeur pour val tick d'horloge (si val > 0)

View file

@ -1,4 +1,4 @@
%{ %{ // Ne pas toucher
#include "as.tab.h" #include "as.tab.h"
int yywrap(void){return 1;} int yywrap(void){return 1;}
void void
@ -11,44 +11,57 @@ yyerror (char const *s)
%% %%
"main" { return tMAIN ;}
"{" { return tOBRACKET;} "main" { return tMAIN; } // Token de la fonction main
"}" { return tCBRACKET; }
"(" { return tOBRACE; } "{" { return tOBRACKET; } // Token accolade ouvrante
")" { return tCBRACE; } "}" { return tCBRACKET; } // Token accolade fermante
"const" { return tCONST; } "(" { return tOBRACE; } // Token parenthèse ouvrante
"int" { return tINT; } ")" { return tCBRACE; } // Token parenthèse fermante
"printf" { return tPRINTF; } //Degeu mais à degager
"if" { return tIF; } "const" { return tCONST; } // Token constante
"while" { return tWHILE; } "int" { return tINT; } // Token type int
"return" {return tRETURN; }
"<" { return tLT; } "if" { return tIF; } // Token if
">" { return tGT; } "else" { return tELSE; } // Token else
"==" { return tEQCOND; } "while" { return tWHILE; } // Token while
"&&" { return tAND; }
"||" { return tOR; } "return" {return tRETURN; } // Token return
"else" { return tELSE;}
"&" { return tADDR;} "<" { return tLT; } // Token plus petit que
"[" { return tOCROCH;} ">" { return tGT; } // Token plus grand que
"]" { return tCCROCH;} "==" { return tEQCOND; } // Token égal comparaison
"get" { return tGET;}
"stop" { return tSTOP;} "&&" { return tAND; } // Token ET
"||" { return tOR; } // Token OU
"&" { return tADDR; } // Token adresse
"[" { return tOCROCH; } // Token crochet ouvrante
"]" { return tCCROCH; } // Token crochet ouvrante
"get" { return tGET; } // Token fonction get
"printf" { return tPRINTF; } // Token fonction print
"stop" { return tSTOP; } // Token fonction stop
"+" { return tADD; } // Token addition
"-" { return tSUB; } // Token soustraction
"*" { return tMUL; } // Token multiplication
"/" { return tDIV; } // Token division
"=" { return tEQ; } // Token egal affectation
";" { return tPV; }
"," { return tCOMA; }
[0-9]+ { yylval.nombre = atoi(yytext); return tNB; } // Token nombre au format classique
[0-9]+e[0-9]+ { yylval.nombre = -1; return tNB; } // Token nombre au format exponentiel
[a-zA-Z][a-zA-Z0-9_]* { strcpy(yylval.id, yytext); return tID; } // Chaine de caractère (identifiant variable, fonction..)
[0-9]+ { yylval.nombre = atoi(yytext); return tNB; } " " {} //Ne pas les retourner à Yacc (espace)
[0-9]+e[0-9]+ { yylval.nombre = -1; return tNBEXP; } //Renvoyer le token tNB et pas tNBEXP " " {} //Ne pas les retourner à Yacc (tabulation)
"+" { return tADD; } "\n" {} //Ne pas les retourner à Yacc (retour chariot)
"-" { return tSUB; }
"*" { return tMUL; }
"/" { return tDIV; }
"=" { return tEQ; }
";" { return tPV; }
" " {} //Ne pas les retourner à Yacc
" " {} //Ne pas les retourner à Yacc
"," { return tCOMA; }
"\n" {} //Ne pas les retourner à Yacc
[a-zA-Z][a-zA-Z0-9_]* { strcpy(yylval.id, yytext); return tID; }
. { }//return tERROR; }
%% %%

File diff suppressed because it is too large Load diff

View file

@ -14,12 +14,13 @@
struct type_t type_courant; struct type_t type_courant;
struct type_t return_type_fonc; struct type_t return_type_fonc;
// Tableau pour le management des patchs des JMP
int instructions_ligne_to_patch[10][20]; int instructions_ligne_to_patch[10][20];
int nbs_instructions_to_patch[10]; int nbs_instructions_to_patch[10];
%} %}
// Récupération des tokens
%token tMAIN %token tMAIN
%token tOBRACKET tCBRACKET %token tOBRACKET tCBRACKET
%token<nombre> tOBRACE tCBRACE %token<nombre> tOBRACE tCBRACE
@ -45,134 +46,411 @@ int nbs_instructions_to_patch[10];
%left tADD tSUB %left tADD tSUB
%left tMUL tDIV %left tMUL tDIV
%type<nombre> E DebutAff SuiteAffPointeur DebutAffPointeur EBis Invocation Args ArgSuite Arg SuiteParams Params Get %type<nombre> E SuiteAffPointeur DebutAffPointeur EBis Invocation Args ArgSuite Arg SuiteParams Params Get
//%type<nombre> E
/******************************************** FAIRE LA GENERATION DU CODE ASSEMBLEUR DANS UN TABLEAU AVEC UN FPRINTF *******************/
%% %%
/*************************************/
/*************************************/
/*********** Programme C *************/
/*************************************/
/*************************************/
// Un programme C correspond a des focntion et un main, une fois que le programme est compilé, on ajoute le STOP et l'on exporte l'assembleur.
C : Fonctions Main {add_operation(STOP,0,0,0);
create_asm();
};
C : Fonction Fonctions {add_operation(STOP,0,0,0); create_asm();};
/*************************************/
/*************************************/
/************ Fonctions **************/
/*************************************/
/*************************************/
// Des fonctions sont une suite de fonctions (possiblement nulle)
Fonctions : Fonction Fonctions; Fonctions : Fonction Fonctions;
Fonctions : ; Fonctions : ;
Main : tINT {printf("Déclaration du main\n"); create_jump_to_main(get_current_index());} tMAIN tOBRACE Args tCBRACE Body { print(); } ;
Fonction : Type tID {return_type_fonc = type_courant; printf("Déclaration de la fonction %s\n", $2);} tOBRACE {inc_prof();} Args {decrement_prof(); push_fonction($2,return_type_fonc,get_current_index(), $6);} tCBRACE Body { print_fonctions(); add_operation(RET,0,0,0);} ;
Fonction : Main {print_fonctions();};
Get : tGET tOBRACE tCBRACE {int addr = push("0_TEMPORARY", 0, integer); add_operation(GET,addr,0,0); $$ = addr;};
Stop : tSTOP tOBRACE tNB tCBRACE {add_operation(STOP,$3,0,0);};
Return : tRETURN E tPV {add_operation(COP,0,$2,0); pop(); };
Args : Arg ArgSuite {$$ = $1 + $2; printf("Les arguments de la fonctions vont avoir une taille dans la pile de : %d\n",$$);};
Args : {$$ = 0;};
Arg : Type tID {int addr = push($2,1, type_courant); if (type_courant.pointeur_level > 0){$$ = taille_types[INT];} else{$$ = taille_types[type_courant.base];}};
Arg : Type tID tOCROCH tCCROCH {type_courant.isTab = 2; int addr = push($2,1, type_courant); $$ = taille_types[INT];};
ArgSuite : tCOMA Arg ArgSuite {$$ = $2 + $3;} ;
ArgSuite : {$$ = 0;};
Body : tOBRACKET {inc_prof();} Instructions tCBRACKET {print(); reset_prof();};
/*************************************/
/*************************************/
/************** Main *****************/
/*************************************/
/*************************************/
// Le main, renvoi un int, possède le mot clé main, des arguments et un body
// Dès que le main est reconnu (token main) on met en place le JMP
Main : tINT tMAIN {printf("Déclaration du main\n");
create_jump_to_main(get_current_index());
}
tOBRACE Args tCBRACE Body;
// Une fonction possède un Type , un identifiant
Fonction : Type tID {return_type_fonc = type_courant; // On récupère le ype de la fonction
printf("Déclaration de la fonction %s\n", $2);
}
tOBRACE {inc_prof(); // On incrémente la profondeur pour les arguments, ils font parti de la fonction
}
Args {decrement_prof(); // Quand les arguments sont passés, on peur décrémenter la profondeur (sans effacer les variables)
push_fonction($2,return_type_fonc,get_current_index(), $6); // On enregistre la fonction dans la table des fonctions
}
tCBRACE Body {add_operation(RET,0,0,0); // On ajoute le RET
};
// Get, une fonction particulière -> renvoi l'adresse de la valeur getée
Get : tGET tOBRACE tCBRACE {int addr = push("0_TEMPORARY", 0, integer); // On déclare la var temporelle
add_operation(GET,addr,0,0); // On ajoute le GET
$$ = addr; // On renvoi l'adresse
};
// Print, une fonction particulière
Print : tPRINTF tOBRACE E tCBRACE {add_operation(PRI,$3,0,0); // On ajoute l'instruction PRI
pop(); // On supprime la variable temporaire
};
// Stop, une fonction particulière
Stop : tSTOP tOBRACE tNB tCBRACE {add_operation(STOP,$3,0,0); // On ajoute juste l'instruction stop
};
// Return, etape clé d'une fonction
Return : tRETURN E tPV {add_operation(COP,0,$2,0); // On copie la valeur retournée à l'adresse 0 de la frame
pop(); // On pop la variable temporaire
};
/*************************************/
/*************************************/
/************ Arguments **************/
/*************************************/
/*************************************/
// Les arguments : Args, Arg, ArgSuite renvoient la taille dans la pile des arguments déjà reconnus
// Des argmuments correspondent à : un argument, puis la suite d'arguments
Args : Arg ArgSuite {$$ = $1 + $2; // La taille des arguments est la taille du premier argument plus celle des suivants
};
Args : {$$ = 0; // Il peut ne pas y avoir d'arguments, alors la taille est 0
};
// Un argument possède un type et un identifiant (nom)
Arg : Type tID { int addr = push($2,1, type_courant); // On stocke l'argument dans la pile des symboles
if (type_courant.pointeur_level > 0) {
$$ = taille_types[ADDR];
} else {
$$ = taille_types[type_courant.base];
}
};
// Un argument peut aussi être un tableau (argument classique et crochets) il est considéré comme un pointeur
Arg : Type tID tOCROCH tCCROCH {type_courant.pointeur_level++; // Considéré comme un simple pointeur
int addr = push($2,1, type_courant);
$$ = taille_types[ADDR];
};
// La suite d'un argument, une virgule, un argument, et d'autres arguments
ArgSuite : tCOMA Arg ArgSuite {$$ = $2 + $3;
};
// Cela peut être aucun arguments
ArgSuite : {$$ = 0;
};
/*************************************/
/*************************************/
/*************** Body ****************/
/*************************************/
/*************************************/
// Un body n'est rien d'autre qu'une suite d'instructions entre deux accolades
Body : tOBRACKET {inc_prof(); // Lors de l'ouverture de l'accolade la profondeur augmente
}
Instructions tCBRACKET {reset_prof(); // A la sortie d'un body, on détruit toutes les variables locales de ce body
};
/*************************************/
/*************************************/
/*********** Instructions ************/
/*************************************/
/*************************************/
// Des instructions sont une instruction suivie d'autres instructions, ou, rien
Instructions : Instruction Instructions ; Instructions : Instruction Instructions ;
Instructions : ; Instructions : ;
Instruction : Aff {};
Instruction : Decl {};
Instruction : Invocation tPV{pop();};
Instruction : If {};
Instruction : While {};
Instruction : Return {};
Instruction : Stop tPV {};
// Un instruction peut être : une affectation, une déclaration, une invocation, un if, un while, un return, une fonction particulière
Invocation : tID tOBRACE {struct fonction_t fonc = get_fonction($1);} Instruction : Aff;
Params tCBRACE {struct fonction_t fonc = get_fonction($1); multiple_pop($4); Instruction : Decl;
add_operation(CALL,fonc.first_instruction_line, get_last_addr(),0); if (fonc.return_type.pointeur_level > 0 || fonc.return_type.isTab){ Instruction : Invocation tPV {pop();};
$$ = push("0_TEMPORARY_RETURN", 0, integer); Instruction : If;
} Instruction : While;
else{ Instruction : Return;
$$ = push("0_TEMPORARY_RETURN", 0, fonc.return_type); Instruction : Stop tPV;
}}; Instruction : Print tPV;
Invocation : tPRINTF tOBRACE E tCBRACE{add_operation(PRI,$3,0,0);};
Params : {$$ = 0; printf("Sans Params\n"); } ;
Params : Param SuiteParams {$$ = $2 + 1;};
Param : E {printf("Parametre : %d\n", $1);};
SuiteParams : tCOMA Param SuiteParams {$$ = $3 + 1;};
SuiteParams : {$$ = 0;};
//On considère que la première ligne du code en ASM est la ligne 0
If : tIF tOBRACE E tCBRACE {
add_operation(JMF,$3,0,0); $1 = get_current_index() - 1;}
Body {int current = get_current_index();
patch($1,current + 1);
add_operation(JMP,0,0,0);
instructions_ligne_to_patch[get_prof()][nbs_instructions_to_patch[get_prof()]] = current;
nbs_instructions_to_patch[get_prof()]++;
pop();}
Else {printf("If reconnu\n");};
Else : tELSE If { printf("Else if reconnu\n"); }; /*************************************/
Else : tELSE Body { printf("Else reconnu\n"); int current = get_current_index(); /*************************************/
for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++){ /************ Invocation *************/
patch(instructions_ligne_to_patch[get_prof()][i],current); /*************************************/
} /*************************************/
nbs_instructions_to_patch[get_prof()] = 0;
};
Else : {int current = get_current_index();
for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++){
patch(instructions_ligne_to_patch[get_prof()][i],current);
}
nbs_instructions_to_patch[get_prof()] = 0;};
While : tWHILE tOBRACE E tCBRACE {
add_operation(JMF,$3,0,0);
$1 = get_current_index() - 1;
pop();}
Body { printf("While reconnu\n"); Invocation : tID tOBRACE Params tCBRACE {struct fonction_t fonc = get_fonction($1); // On récupère la fonction
int current = get_current_index(); multiple_pop($3); // On pop les paramètres de la table des symboles
patch($1,current + 1); add_operation(CALL,fonc.first_instruction_line, get_last_addr(),0); // On écrit le CALL
add_operation(JMP,$1,0,0);}; // On renvoi l'adresse de la valeur retour de la fonction
if (fonc.return_type.pointeur_level > 0 || fonc.return_type.isTab) {
$$ = push("0_TEMPORARY_RETURN", 0, pointer);
} else {
$$ = push("0_TEMPORARY_RETURN", 0, fonc.return_type);
}
};
Aff : DebutAff tEQ E tPV {add_operation(COP, $1, $3,0); pop();} ;
Aff : DebutAffPointeur tEQ E tPV {add_operation(WR,$1,$3,0); pop(); pop();};
DebutAff : tID {struct symbole_t * symbole = get_variable($1); symbole->initialized = 1; $$=symbole->adresse; printf("%s prend une valeur\n", $1);};
DebutAffPointeur : tMUL SuiteAffPointeur {add_operation(READ, $2, $2, 0); $$=$2;};
DebutAffPointeur : SuiteAffPointeur {$$=$1;};
SuiteAffPointeur : tMUL tID {struct symbole_t * symbole = get_variable($2); int addr = push("0_TEMPORARY", 1, symbole->type); add_operation(COP, addr,symbole->adresse,0); $$=addr;};
SuiteAffPointeur : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1); int addr = push("0_TEMPORARY", 1, symbole->type); if (symbole->type.isTab == 2){add_operation(COP, addr,symbole->adresse,0);} else{add_operation(AFCA, addr,symbole->adresse,0);} int addr2 = push("0_TEMPORARY", 1, integer); add_operation(AFC, addr2, taille_types[symbole->type.base],0); add_operation(MUL,$3,addr2,$3); add_operation(ADD,$3,addr,$3); $$=$3; pop(); pop();};
E : tNB { int addr = push("0_TEMPORARY", 1, integer); add_operation(AFC, addr,$1,0); $$ = addr;};
E : tNBEXP { printf("Nombre exp\n"); int addr = push("0_TEMPORARY", 1, integer); add_operation(AFC, addr,$1,0); $$ = addr;}; /*************************************/
E : E tMUL E { printf("Mul\n"); add_operation(MUL,$1,$1,$3); $$ = $1; pop();}; /*************************************/
E : E tDIV E { printf("Div\n"); add_operation(DIV, $1,$1,$3); $$ = $1; pop();}; /************ Paramètres *************/
E : E tSUB E { printf("Sub\n"); add_operation(SOU,$1,$1,$3); $$ = $1; pop();}; /*************************************/
E : E tADD E { printf("Add\n"); add_operation(ADD,$1,$1,$3); $$ = $1; pop();}; /*************************************/
E : Invocation {$$ = $1;};
E : tOBRACE E tCBRACE { printf("Parentheses\n"); $$=$2;}; // Ici aussi, 0, 1 ou plusieurs paramètres avec une suite paramètre pour prendre en compte la virgule, on renvoi le nombre de paramètres
E : tSUB E { printf("Moins\n"); int addr = push("0_TEMPORARY", 1, integer); add_operation(AFC, addr,0,0); add_operation(SOU, $2,$2,addr); $$ = $2; pop();}; Params : {$$ = 0;
E : E tEQCOND E { printf("==\n"); add_operation(EQU,$1,$1,$3); $$ = $1; pop();}; };
E : E tGT E { printf(">\n"); add_operation(SUP,$1,$1,$3); $$ = $1; pop();}; Params : Param SuiteParams {$$ = $2 + 1;
E : E tLT E { printf("<\n"); add_operation(INF,$1,$1,$3); $$ = $1; pop();}; };
E : tNOT E { printf("!\n"); }; Param : E
SuiteParams : tCOMA Param SuiteParams {$$ = $3 + 1;};
SuiteParams : {$$ = 0;};
/*************************************/
/*************************************/
/******** Sauts conditionnels ********/
/*************************************/
/*************************************/
// Un if : le token, une expression entre parenthèse suivie d'un body et d'un else
If : tIF tOBRACE E tCBRACE {add_operation(JMF,$3,0,0); // On ajoute le JMF sans préciser la ligne du saut
$1 = get_current_index() - 1; // On stocke le numéro d'instruction à patcher
}
Body {int current = get_current_index(); // On récupère le numéro d'instrcution
patch($1,current + 1); // On patch le Jump en cas d'instruction fausse
add_operation(JMP,0,0,0); // JMP pour skip le else si on devait faire le body
instructions_ligne_to_patch[get_prof()][nbs_instructions_to_patch[get_prof()]] = current; // On spécifie que le JMP est a patcher
nbs_instructions_to_patch[get_prof()]++;
pop(); // On pop la condition du if
}
Else
// Elsif
Else : tELSE If;
// Else
Else : tELSE Body {int current = get_current_index();
for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++) {
patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
}
nbs_instructions_to_patch[get_prof()] = 0;
};
// If sans else
Else : {int current = get_current_index();
for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++){
patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
}
nbs_instructions_to_patch[get_prof()] = 0;
};
/*************************************/
/*************************************/
/************** Boucles **************/
/*************************************/
/*************************************/
While : tWHILE tOBRACE E tCBRACE {add_operation(JMF,$3,0,0); // Ecriture du JMF
$1 = get_current_index() - 1; // Enregistrement de la ligne a patch
pop(); // Pop de la condition
}
Body {int current = get_current_index(); // Patch du JMF apres le body
patch($1,current + 1);
add_operation(JMP,$1,0,0); // JMP au debut de la boucle
};
/*************************************/
/*************************************/
/************ Affectations ***********/ // A RETRAVAILLER
/*************************************/
/*************************************/
// Affectation simple
Aff : tID tEQ E tPV {struct symbole_t * symbole = get_variable($1); // On récupère le symbole
symbole->initialized = 1; // Le symbole devient initialisé
add_operation(COP, symbole->adresse, $3,0); // On affecte la valeur
pop(); // On pop l'expression
};
// Debut d'une affectation avec déreférencement de pointeur //////// A RETRAVAILLERRRRRR
DebutAffPointeur : tMUL SuiteAffPointeur {add_operation(READ, $2, $2, 0);
$$=$2;
};
DebutAffPointeur : SuiteAffPointeur {$$=$1;
};
SuiteAffPointeur : tMUL tID {struct symbole_t * symbole = get_variable($2);
int addr = push("0_TEMPORARY", 1, symbole->type);
add_operation(COP, addr,symbole->adresse,0);
$$=addr;
};
SuiteAffPointeur : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1);
int addr = push("0_TEMPORARY", 1, symbole->type);
if (symbole->type.isTab == 2) {
add_operation(COP, addr,symbole->adresse,0);
} else {
add_operation(AFCA, addr,symbole->adresse,0);
}
int addr2 = push("0_TEMPORARY", 1, integer);
add_operation(AFC, addr2, taille_types[symbole->type.base],0);
add_operation(MUL,$3,addr2,$3);
add_operation(ADD,$3,addr,$3);
$$=$3;
pop();
pop();
};
// Affectation sur un pointeur
Aff : DebutAffPointeur tEQ E tPV {add_operation(WR,$1,$3,0);
pop();
pop();
};
/*************************************/
/*************************************/
/***** Expressions Arithmetiques *****/
/*************************************/
/*************************************/
// Pour une expression arithmétique, nous renvoyons toujours l'adresse du resultat
// Un simple nombre
E : tNB {int addr = push("0_TEMPORARY", 1, integer); // On reserve la place de la variable temporaire
add_operation(AFC, addr,$1,0); // On Affecte la valeur a cette adresse
$$ = addr; // On renvoi l'adresse
};
// Un nombre sous forme XeY, même traitement qu'un nombre classique
E : tNBEXP {int addr = push("0_TEMPORARY", 1, integer);
add_operation(AFC, addr,$1,0);
$$ = addr;
};
// Une Multiplication
E : E tMUL E {add_operation(MUL,$1,$1,$3); // On Multiplie les valeurs et stockons le résultat dans la première variable temporaire
$$ = $1; // On renvoi l'adresse du resultat
pop(); // On libère la seconde variable temporaire
};
// Une Division (idem multiplication)
E : E tDIV E {add_operation(DIV, $1,$1,$3);
$$ = $1;
pop();
};
// Une Soustraction (idem multiplication)
E : E tSUB E {add_operation(SOU,$1,$1,$3);
$$ = $1;
pop();
};
// Une Addition (idem multiplication)
E : E tADD E {add_operation(ADD,$1,$1,$3);
$$ = $1;
pop();
};
// Une invocation
E : Invocation {$$ = $1; // Une invocation renvoi déjà l'adresse, cette règle n'est qu'un cast d'Invocation en E
};
// Consomation de parenthèses
E : tOBRACE E tCBRACE {$$ = $2; // Cela permet de garantir la prioricité des expressions entre parenthèse
};
// Négatif --> -E <=> 0-E
E : tSUB E {int addr = push("0_TEMPORARY", 1, integer); // On réserve la variable temporaire pour le 0
add_operation(AFC, addr,0,0); // On affecte le 0
add_operation(SOU, $2, addr, $2); // On applique le 0-E
$$ = $2; // On renvoi l'adresse
pop(); // On libère la mémoire temporaire utilisée par 0
};
E : E tEQCOND E {add_operation(EQU,$1,$1,$3);
$$ = $1;
pop();
};
E : E tGT E {add_operation(SUP,$1,$1,$3);
$$ = $1;
pop();
};
E : E tLT E {add_operation(INF,$1,$1,$3);
$$ = $1;
pop();
};
E : tNOT E { printf("!\n"); };
E : E tAND E {add_operation(MUL,$1,$1,$3); $$ = $1; pop();}; E : E tAND E {add_operation(MUL,$1,$1,$3); $$ = $1; pop();};
E : E tOR E {add_operation(ADD,$1,$1,$3); $$ = $1; pop();} ; E : E tOR E {add_operation(ADD,$1,$1,$3); $$ = $1; pop();} ;
E : tMUL E { add_operation(READ, $2, $2, 0); $$=$2;}; E : tMUL E { add_operation(READ, $2, $2, 0); $$=$2;};

View file

@ -1,6 +1,11 @@
default : default :
@echo "Spécifiez une cible" @echo "Spécifiez une cible"
###########################
### NETTOYAGE ###
###########################
clean : clean_Symboles clean_Instructions clean_Lex_Yacc clean_Fonctions clean : clean_Symboles clean_Instructions clean_Lex_Yacc clean_Fonctions
@rm -f rondoudou_gcc @rm -f rondoudou_gcc
@rm -f output.txt @rm -f output.txt
@ -20,6 +25,11 @@ clean_Fonctions:
clean_Lex_Yacc: clean_Lex_Yacc:
@rm -f Lex_Yacc/as.output Lex_Yacc/as.tab.* Lex_Yacc/lex.yy.* @rm -f Lex_Yacc/as.output Lex_Yacc/as.tab.* Lex_Yacc/lex.yy.*
###########################
### COMPILATION ###
###########################
build : clean build_Symboles build_Instructions build_Lex_Yacc build_Fonctions build : clean build_Symboles build_Instructions build_Lex_Yacc build_Fonctions
gcc Lex_Yacc/as.tab.o Lex_Yacc/lex.yy.o Tables/Instructions/tab_instruc.o Tables/Symboles/table_symboles.o Tables/Fonctions/tab_fonctions.o -ll -o rondoudou_gcc gcc Lex_Yacc/as.tab.o Lex_Yacc/lex.yy.o Tables/Instructions/tab_instruc.o Tables/Symboles/table_symboles.o Tables/Fonctions/tab_fonctions.o -ll -o rondoudou_gcc
@ -38,6 +48,11 @@ build_Lex_Yacc: clean_Lex_Yacc
gcc -c Lex_Yacc/as.tab.c -o Lex_Yacc/as.tab.o gcc -c Lex_Yacc/as.tab.c -o Lex_Yacc/as.tab.o
gcc -c Lex_Yacc/lex.yy.c -o Lex_Yacc/lex.yy.o gcc -c Lex_Yacc/lex.yy.c -o Lex_Yacc/lex.yy.o
###########################
### TESTS ###
###########################
test_Symboles: build_Symboles test_Symboles: build_Symboles
gcc -c Tables/Symboles/test.c -o Tables/Symboles/test.o gcc -c Tables/Symboles/test.c -o Tables/Symboles/test.o
gcc Tables/Symboles/test.o Tables/Symboles/table_symboles.o -o Tables/Symboles/test gcc Tables/Symboles/test.o Tables/Symboles/table_symboles.o -o Tables/Symboles/test
@ -48,9 +63,19 @@ test_Instructions: build_Instructions
gcc Tables/Instructions/test.o Tables/Instructions/tab_instruc.o -o Tables/Instructions/test gcc Tables/Instructions/test.o Tables/Instructions/tab_instruc.o -o Tables/Instructions/test
Tables/Instructions/test Tables/Instructions/test
test_Fonctions: build_Fonctions
gcc -c Tables/Fonctions/test.c -o Tables/Fonctions/test.o
gcc Tables/Fonctions/test.o Tables/Fonctions/tab_fonctions.o -o Tables/Fonctions/test
Tables/Fonctions/test
test: build test: build
cat Fichiers_Tests/progC | ./rondoudou_gcc cat Fichiers_Tests/progC | ./rondoudou_gcc
###########################
### EDITION ###
###########################
edit_Lex_Yacc: edit_Lex_Yacc:
pluma Lex_Yacc/al.lex Lex_Yacc/as.y & pluma Lex_Yacc/al.lex Lex_Yacc/as.y &

View file

@ -1,9 +1,14 @@
#include "tab_fonctions.h" #include "tab_fonctions.h"
#define MAX_TAILLE_FONC 50
// Table des fonctions
struct fonction_t tab_fonctions[MAX_TAILLE_FONC]; struct fonction_t tab_fonctions[MAX_TAILLE_FONC];
// Index dispo dans la table
int indexTab = 0; int indexTab = 0;
// Renvoi une fonction a partir de son nom
struct fonction_t get_fonction(char * name){ struct fonction_t get_fonction(char * name){
int not_found = 1; int not_found = 1;
int i = 0; int i = 0;
@ -18,6 +23,7 @@ struct fonction_t get_fonction(char * name){
return res; return res;
} }
// Insere une fonction
void push_fonction(char * name, struct type_t type, int line, int taille_args){ void push_fonction(char * name, struct type_t type, int line, int taille_args){
if (indexTab < MAX_TAILLE_FONC){ if (indexTab < MAX_TAILLE_FONC){
struct fonction_t fonc; struct fonction_t fonc;
@ -31,6 +37,7 @@ void push_fonction(char * name, struct type_t type, int line, int taille_args){
} }
} }
// Fonction d'affichage des fonctions connues
void print_fonctions(){ void print_fonctions(){
printf("Affichage table des fonctions\n"); printf("Affichage table des fonctions\n");
printf("\t Size : %d\n",indexTab); printf("\t Size : %d\n",indexTab);

View file

@ -7,8 +7,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define MAX_TAILLE_FONC 50
//Struct dans le tableau qui permet d'identifier une fonction //Struct dans le tableau qui permet d'identifier une fonction
struct fonction_t { struct fonction_t {
char * name; char * name;
@ -17,10 +15,11 @@ struct fonction_t {
int taille_args; int taille_args;
}; };
// Renvoi les informations sur une fonction à partir de son nom
struct fonction_t get_fonction(char * name); struct fonction_t get_fonction(char * name);
// Insere une fonction dans la table (déclare une fonction)
void push_fonction(char * name, struct type_t type, int line, int taille_args); void push_fonction(char * name, struct type_t type, int line, int taille_args);
// Fonction d'affichage des fonctions connues
void print_fonctions(); void print_fonctions();
#endif #endif

View file

@ -1,7 +1,20 @@
#include "tab_instruc.h" #include "tab_instruc.h"
#define MAXTAILLE 1024
// Structure représentant une opération
struct operation_t {
enum opcode_t opcode;
int arg1;
int arg2;
int arg3;
};
// Index dans le tableau des instruction
int current_index = 1; int current_index = 1;
// Tableau des instructions (programme en assembleur)
struct operation_t tab_op[MAXTAILLE]; struct operation_t tab_op[MAXTAILLE];
// Insertion d'une opération dans le tableau
void add_operation(enum opcode_t opcode, int arg1, int arg2, int arg3){ void add_operation(enum opcode_t opcode, int arg1, int arg2, int arg3){
if (current_index == MAXTAILLE){ if (current_index == MAXTAILLE){
printf("Taillemax tableau operations atteinte\n"); printf("Taillemax tableau operations atteinte\n");
@ -13,12 +26,13 @@ void add_operation(enum opcode_t opcode, int arg1, int arg2, int arg3){
} }
} }
// Les fonctions étant compilées en premiers, la première instruction du programme doit être un JMP vers le main
void create_jump_to_main(int line){ void create_jump_to_main(int line){
struct operation_t new_op = {JMP,line, 0, 0}; struct operation_t new_op = {JMP,line, 0, 0};
tab_op[0] = new_op; tab_op[0] = new_op;
} }
// Fonction traduisant une opération en assembleur
char * get_asm_line_from_op(struct operation_t op){ char * get_asm_line_from_op(struct operation_t op){
char * buffer = malloc(sizeof(char)*200); char * buffer = malloc(sizeof(char)*200);
switch (op.opcode){ switch (op.opcode){
@ -73,16 +87,17 @@ char * get_asm_line_from_op(struct operation_t op){
case (RET): case (RET):
sprintf(buffer,"RET\n"); sprintf(buffer,"RET\n");
break; break;
case (GET): case (GET):
sprintf(buffer,"GET %d\n",op.arg1); sprintf(buffer,"GET %d\n",op.arg1);
break; break;
case (STOP): case (STOP):
sprintf(buffer,"STOP %d\n", op.arg1); sprintf(buffer,"STOP %d\n", op.arg1);
break; break;
} }
return buffer; return buffer;
} }
// Genere le code asm dans un fichier
void create_asm(){ void create_asm(){
FILE * output = fopen("output.txt","w"); FILE * output = fopen("output.txt","w");
for (int i = 0; i < current_index; i++){ for (int i = 0; i < current_index; i++){
@ -92,10 +107,11 @@ void create_asm(){
} }
} }
// Renvoi l'index courrant dans le tableau
int get_current_index(){return current_index;} int get_current_index(){return current_index;}
// Permet de modifier un instruction à postériorie (pour les JMP)
void patch(int index, int arg){ void patch(int index, int arg){
if (tab_op[index].opcode == JMP){ if (tab_op[index].opcode == JMP){
tab_op[index].arg1 = arg; tab_op[index].arg1 = arg;

View file

@ -1,21 +1,15 @@
#ifndef TAB_INST_H #ifndef TAB_INST_H
#define TAB_INST_H #define TAB_INST_H
#define MAXTAILLE 1024
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
// Liste de codes des instruction
enum opcode_t {ADD,MUL,SOU,DIV,COP,AFC,AFCA,JMP,JMF,INF,SUP,EQU,PRI,READ,WR,CALL,RET,GET,STOP}; enum opcode_t {ADD,MUL,SOU,DIV,COP,AFC,AFCA,JMP,JMF,INF,SUP,EQU,PRI,READ,WR,CALL,RET,GET,STOP};
struct operation_t {
enum opcode_t opcode;
int arg1;
int arg2;
int arg3;
};
//Ajoute une opération dans la table (à la fin) //Ajoute une opération dans la table (à la fin)
void add_operation(enum opcode_t opcode, int arg1, int arg2, int arg3); void add_operation(enum opcode_t opcode, int arg1, int arg2, int arg3);
//Renvoi le prochain slot disponible //Renvoi le prochain slot disponible

View file

@ -1,55 +1,35 @@
/* TABLE DES SYMBOLE DU COMPILATEUR (PILE)
-----------------------------------------------------
| symbole | adresse | type | initialisé |
-----------------------------------------------------
| | | | |
| | | | |
| | | | |
| i | 0x777756b8 | int | false |
| size | 0x777756b8 | int | true |
-----------------------------------------------------
Types pour l'implémentation :
- enum type_t : [int]
- struct symbole : {
char nom[30];
uintptr_t adresse;
enum type_t type;
char initialized;
}
Opérations possible :
- init -> pile * -> void
- push -> symbole -> pile * -> void
- pop -> pile * -> symbole
- exist -> pile * -> symbole -> char
- initialized -> pile * -> symbole -> char */
#include "table_symboles.h" #include "table_symboles.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#define MAXADDR 1024*5
// Première adresse disponible
int last_addr = 0; int last_addr = 0;
int temp_addr = MAXADDR; // Tableau indexé sur les types donnant leur tailles
int taille_types[] = {-1, 1}; int taille_types[] = {-1, 1, 1};
// Pronfondeur dans le code (pour la visibilité des variables)
int profondeur = 0; int profondeur = 0;
int last_temp_var_size; // Constante pour les entiers
const struct type_t integer = {INT, 0, 1}; const struct type_t integer = {INT, 0, 1, 0};
// Constante pour les pointeurs
const struct type_t pointer = {ADDR, 0, 1, 0};
// Structure chainant les symboles
struct element_t { struct element_t {
struct symbole_t symbole; struct symbole_t symbole;
struct element_t * suivant; struct element_t * suivant;
}; };
// Structure de la pile des symboles
struct pile_t { struct pile_t {
int taille; int taille;
struct element_t * first; struct element_t * first;
}; };
// Pile des symboles
struct pile_t * pile; struct pile_t * pile;
// Fonction d'affichage pour un type
char * type_to_string(struct type_t type) { char * type_to_string(struct type_t type) {
char * star = "*"; char * star = "*";
char * resultat = malloc(sizeof(char)*20); char * resultat = malloc(sizeof(char)*20);
@ -64,6 +44,7 @@ char * type_to_string(struct type_t type) {
return resultat; return resultat;
} }
// Fonction d'affichage pour un symbole
void print_symbole(struct symbole_t symbole) { void print_symbole(struct symbole_t symbole) {
char * type = type_to_string(symbole.type); char * type = type_to_string(symbole.type);
if (symbole.initialized) { if (symbole.initialized) {
@ -74,14 +55,14 @@ void print_symbole(struct symbole_t symbole) {
free(type); free(type);
} }
// Initialisation de la pile
void init (void) { void init (void) {
pile = malloc(sizeof(struct pile_t)); pile = malloc(sizeof(struct pile_t));
pile->first = NULL; pile->first = NULL;
pile->taille = 0; pile->taille = 0;
} }
// Fonction d'ajout d'un symbole à la pile
int push(char * nom, int isInit, struct type_t type) { int push(char * nom, int isInit, struct type_t type) {
struct element_t * aux = malloc(sizeof(struct element_t)); struct element_t * aux = malloc(sizeof(struct element_t));
struct symbole_t symbole = {"", last_addr, type, isInit,profondeur}; struct symbole_t symbole = {"", last_addr, type, isInit,profondeur};
@ -95,6 +76,7 @@ int push(char * nom, int isInit, struct type_t type) {
return addr_var; return addr_var;
} }
// Fonction renvoyant et supprimant le premier symbole
struct symbole_t pop() { struct symbole_t pop() {
struct symbole_t retour = {"", 0, UNKNOWN, 0, 0}; struct symbole_t retour = {"", 0, UNKNOWN, 0, 0};
struct element_t * aux; struct element_t * aux;
@ -109,14 +91,14 @@ struct symbole_t pop() {
return retour; return retour;
} }
// Fonction supprimant les n premiers symboles
void multiple_pop(int n){ void multiple_pop(int n){
for (int i =0; i<n; i++){ for (int i =0; i<n; i++){
pop(); pop();
} }
} }
// Fonction d'accès a un symbole par son nom
struct symbole_t * get_variable(char * nom){ struct symbole_t * get_variable(char * nom){
struct symbole_t * retour = NULL; struct symbole_t * retour = NULL;
struct element_t * aux = pile->first; struct element_t * aux = pile->first;
@ -132,6 +114,7 @@ struct symbole_t * get_variable(char * nom){
return retour; return retour;
} }
// Fonction d'affichage de la pile
void print() { void print() {
printf("Affichage de la Table des Symboles\n\tSize : %d\n\tContenu : \n", pile->taille); printf("Affichage de la Table des Symboles\n\tSize : %d\n\tContenu : \n", pile->taille);
struct element_t * aux = pile->first; struct element_t * aux = pile->first;
@ -146,11 +129,17 @@ void print() {
} }
} }
// Getteur sur la première adresse dispo (utile pour le CALL)
int get_last_addr(){ int get_last_addr(){
return last_addr; return last_addr;
} }
/********************************/
/*** GESTION DE LA PROFONDEUR ***/
/********************************/
void inc_prof() { void inc_prof() {
profondeur++; profondeur++;
} }

View file

@ -1,43 +1,9 @@
/* TABLE DES SYMBOLE DU COMPILATEUR (PILE)
-----------------------------------------------------
| symbole | adresse | type | initialisé |
-----------------------------------------------------
| | | | |
| | | | |
| | | | |
| i | 0x777756b8 | int | false |
| size | 0x777756b8 | int | true |
-----------------------------------------------------
Types pour l'implémentation :
- enum type_t : [int]
- struct symbole : {
char nom[30];
uintptr_t adresse;
enum type_t type;
char initialized;
}
Opérations possible :
- init -> pile * -> void
- push -> symbole -> pile * -> void
- pop -> pile * -> symbole
- status -> nom -> pile -> char */
#ifndef TAB_SYMB_H #ifndef TAB_SYMB_H
#define TAB_SYMB_H #define TAB_SYMB_H
#include <stdint.h> #include <stdint.h>
/**************************************/ /**************************************/
/**************************************/ /**************************************/
/**** Gestion des types possibles ****/ /**** Gestion des types possibles ****/
@ -45,7 +11,7 @@ Opérations possible :
/**************************************/ /**************************************/
//Enumération des types de base reconnus //Enumération des types de base reconnus
enum base_type_t {UNKNOWN, INT}; enum base_type_t {UNKNOWN, INT, ADDR};
//Table enregistrant la taille de ces types de bases (indexée sur les types) //Table enregistrant la taille de ces types de bases (indexée sur les types)
extern int taille_types[]; extern int taille_types[];
//Structure gérant les types //Structure gérant les types
@ -54,17 +20,18 @@ struct type_t {
enum base_type_t base; enum base_type_t base;
//Si la variable est un pointeur, on enregitre son niveau (nombre de *) //Si la variable est un pointeur, on enregitre son niveau (nombre de *)
int pointeur_level; int pointeur_level;
//Si il s'agit d'un tableau, on enregistre sa taille (nombre de cases) (même si c'est une variable on met quand même un nb_blocs à) //Si il s'agit d'un tableau, on enregistre sa taille (nombre de cases) (même si c'est une variable on met quand même un nb_blocs à 1)
int nb_blocs; int nb_blocs;
//Si c'est un tableau addressale directement, cette valeur est à 1. Si c'est un pointeur vers un tableau, valeur à 2. //Si c'est un tableau cette valeur est à 1, 0 sinon.
int isTab; int isTab;
}; };
//REtourne la représentation d'un type en string //Retourne la représentation d'un type en string
char * type_to_string(struct type_t type); char * type_to_string(struct type_t type);
//Constante pour les entiers //Constante pour les entiers
extern const struct type_t integer; extern const struct type_t integer;
//Constante pour les pointeurs
extern const struct type_t pointer;
/**************************************/ /**************************************/
@ -100,7 +67,7 @@ struct symbole_t {
//Est il initialisé //Est il initialisé
int initialized; int initialized;
//Sa profondeur de création //Sa profondeur de création
int profondeur; int profondeur;
}; };
//Fonction d'affichage d'un symbole //Fonction d'affichage d'un symbole
@ -124,7 +91,7 @@ void init(void);
int push(char * nom, int isInit, struct type_t type); int push(char * nom, int isInit, struct type_t type);
//Destruction et récupération du premier élément de la table //Destruction et récupération du premier élément de la table
struct symbole_t pop(); struct symbole_t pop();
//Destruction des n premiers elee=ments de la table des symboles //Destruction des n premiers elements de la table des symboles
void multiple_pop(int n); void multiple_pop(int n);
//Retourne la dernière adresse disponible //Retourne la dernière adresse disponible
int get_last_addr(); int get_last_addr();