No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

as.y 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. %union {
  2. int nombre;
  3. char id[30];
  4. }
  5. %{
  6. #include "../Tables/Fonctions/tab_fonctions.h"
  7. #include "../Tables/Symboles/table_symboles.h"
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include "../Tables/Instructions/tab_instruc.h"
  12. #define TAILLE 1024
  13. struct type_t type_courant;
  14. struct type_t return_type_fonc;
  15. // Tableau pour le management des patchs des JMP
  16. int instructions_ligne_to_patch[10][20];
  17. int nbs_instructions_to_patch[10];
  18. %}
  19. // Récupération des tokens
  20. %token tMAIN
  21. %token tOBRACKET tCBRACKET
  22. %token<nombre> tOBRACE tCBRACE
  23. %token tOCROCH tCCROCH
  24. %token tINT
  25. %token tCONST
  26. %token tPV tCOMA
  27. %token tMUL tDIV tADD tSUB tEQ
  28. %token<nombre> tNB tNBEXP
  29. %token<id> tID
  30. %token tPRINTF tGET tSTOP
  31. %token tERROR
  32. %token<nombre> tIF tWHILE tELSE
  33. %token tRETURN
  34. %token tLT tGT tEQCOND
  35. %token tAND tOR
  36. %token tADDR
  37. %left tLT tGT
  38. %left tEQCOND
  39. %left tAND tOR
  40. %left tNOT
  41. %left tADD tSUB
  42. %left tMUL tDIV
  43. %type<nombre> E SuiteAffPointeur DebutAffPointeur EBis Invocation Args ArgSuite Arg SuiteParams Params Get
  44. %%
  45. /*************************************/
  46. /*************************************/
  47. /*********** Programme C *************/
  48. /*************************************/
  49. /*************************************/
  50. // 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.
  51. C : Fonctions Main {add_operation(STOP,0,0,0);
  52. create_asm();
  53. };
  54. /*************************************/
  55. /*************************************/
  56. /************ Fonctions **************/
  57. /*************************************/
  58. /*************************************/
  59. // Des fonctions sont une suite de fonctions (possiblement nulle)
  60. Fonctions : Fonction Fonctions;
  61. Fonctions : ;
  62. /*************************************/
  63. /*************************************/
  64. /************** Main *****************/
  65. /*************************************/
  66. /*************************************/
  67. // Le main, renvoi un int, possède le mot clé main, des arguments et un body
  68. // Dès que le main est reconnu (token main) on met en place le JMP
  69. Main : tINT tMAIN {printf("Déclaration du main\n");
  70. create_jump_to_main(get_current_index());
  71. }
  72. tOBRACE Args tCBRACE Body;
  73. // Une fonction possède un Type , un identifiant
  74. Fonction : Type tID {return_type_fonc = type_courant; // On récupère le ype de la fonction
  75. printf("Déclaration de la fonction %s\n", $2);
  76. }
  77. tOBRACE {inc_prof(); // On incrémente la profondeur pour les arguments, ils font parti de la fonction
  78. }
  79. Args {decrement_prof(); // Quand les arguments sont passés, on peur décrémenter la profondeur (sans effacer les variables)
  80. push_fonction($2,return_type_fonc,get_current_index(), $6); // On enregistre la fonction dans la table des fonctions
  81. }
  82. tCBRACE Body {add_operation(RET,0,0,0); // On ajoute le RET
  83. };
  84. // Get, une fonction particulière -> renvoi l'adresse de la valeur getée
  85. Get : tGET tOBRACE tCBRACE {int addr = push("0_TEMPORARY", 0, integer); // On déclare la var temporelle
  86. add_operation(GET,addr,0,0); // On ajoute le GET
  87. $$ = addr; // On renvoi l'adresse
  88. };
  89. // Print, une fonction particulière
  90. Print : tPRINTF tOBRACE E tCBRACE {add_operation(PRI,$3,0,0); // On ajoute l'instruction PRI
  91. pop(); // On supprime la variable temporaire
  92. };
  93. // Stop, une fonction particulière
  94. Stop : tSTOP tOBRACE tNB tCBRACE {add_operation(STOP,$3,0,0); // On ajoute juste l'instruction stop
  95. };
  96. // Return, etape clé d'une fonction
  97. Return : tRETURN E tPV {add_operation(COP,0,$2,0); // On copie la valeur retournée à l'adresse 0 de la frame
  98. pop(); // On pop la variable temporaire
  99. };
  100. /*************************************/
  101. /*************************************/
  102. /************ Arguments **************/
  103. /*************************************/
  104. /*************************************/
  105. // Les arguments : Args, Arg, ArgSuite renvoient la taille dans la pile des arguments déjà reconnus
  106. // Des argmuments correspondent à : un argument, puis la suite d'arguments
  107. Args : Arg ArgSuite {$$ = $1 + $2; // La taille des arguments est la taille du premier argument plus celle des suivants
  108. };
  109. Args : {$$ = 0; // Il peut ne pas y avoir d'arguments, alors la taille est 0
  110. };
  111. // Un argument possède un type et un identifiant (nom)
  112. Arg : Type tID { int addr = push($2,1, type_courant); // On stocke l'argument dans la pile des symboles
  113. if (type_courant.pointeur_level > 0) {
  114. $$ = taille_types[ADDR];
  115. } else {
  116. $$ = taille_types[type_courant.base];
  117. }
  118. };
  119. // Un argument peut aussi être un tableau (argument classique et crochets) il est considéré comme un pointeur
  120. Arg : Type tID tOCROCH tCCROCH {type_courant.pointeur_level++; // Considéré comme un simple pointeur
  121. int addr = push($2,1, type_courant);
  122. $$ = taille_types[ADDR];
  123. };
  124. // La suite d'un argument, une virgule, un argument, et d'autres arguments
  125. ArgSuite : tCOMA Arg ArgSuite {$$ = $2 + $3;
  126. };
  127. // Cela peut être aucun arguments
  128. ArgSuite : {$$ = 0;
  129. };
  130. /*************************************/
  131. /*************************************/
  132. /*************** Body ****************/
  133. /*************************************/
  134. /*************************************/
  135. // Un body n'est rien d'autre qu'une suite d'instructions entre deux accolades
  136. Body : tOBRACKET {inc_prof(); // Lors de l'ouverture de l'accolade la profondeur augmente
  137. }
  138. Instructions tCBRACKET {reset_prof(); // A la sortie d'un body, on détruit toutes les variables locales de ce body
  139. };
  140. /*************************************/
  141. /*************************************/
  142. /*********** Instructions ************/
  143. /*************************************/
  144. /*************************************/
  145. // Des instructions sont une instruction suivie d'autres instructions, ou, rien
  146. Instructions : Instruction Instructions ;
  147. Instructions : ;
  148. // Un instruction peut être : une affectation, une déclaration, une invocation, un if, un while, un return, une fonction particulière
  149. Instruction : Aff;
  150. Instruction : Decl;
  151. Instruction : Invocation tPV {pop();};
  152. Instruction : If;
  153. Instruction : While;
  154. Instruction : Return;
  155. Instruction : Stop tPV;
  156. Instruction : Print tPV;
  157. /*************************************/
  158. /*************************************/
  159. /************ Invocation *************/
  160. /*************************************/
  161. /*************************************/
  162. Invocation : tID tOBRACE Params tCBRACE {struct fonction_t fonc = get_fonction($1); // On récupère la fonction
  163. multiple_pop($3); // On pop les paramètres de la table des symboles
  164. add_operation(CALL,fonc.first_instruction_line, get_last_addr(),0); // On écrit le CALL
  165. // On renvoi l'adresse de la valeur retour de la fonction
  166. if (fonc.return_type.pointeur_level > 0 || fonc.return_type.isTab) {
  167. $$ = push("0_TEMPORARY_RETURN", 0, pointer);
  168. } else {
  169. $$ = push("0_TEMPORARY_RETURN", 0, fonc.return_type);
  170. }
  171. };
  172. /*************************************/
  173. /*************************************/
  174. /************ Paramètres *************/
  175. /*************************************/
  176. /*************************************/
  177. // 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
  178. Params : {$$ = 0;
  179. };
  180. Params : Param SuiteParams {$$ = $2 + 1;
  181. };
  182. Param : E
  183. SuiteParams : tCOMA Param SuiteParams {$$ = $3 + 1;};
  184. SuiteParams : {$$ = 0;};
  185. /*************************************/
  186. /*************************************/
  187. /******** Sauts conditionnels ********/
  188. /*************************************/
  189. /*************************************/
  190. // Un if : le token, une expression entre parenthèse suivie d'un body et d'un else
  191. If : tIF tOBRACE E tCBRACE {add_operation(JMF,$3,0,0); // On ajoute le JMF sans préciser la ligne du saut
  192. $1 = get_current_index() - 1; // On stocke le numéro d'instruction à patcher
  193. }
  194. Body {int current = get_current_index(); // On récupère le numéro d'instrcution
  195. patch($1,current + 1); // On patch le Jump en cas d'instruction fausse
  196. add_operation(JMP,0,0,0); // JMP pour skip le else si on devait faire le body
  197. instructions_ligne_to_patch[get_prof()][nbs_instructions_to_patch[get_prof()]] = current; // On spécifie que le JMP est a patcher
  198. nbs_instructions_to_patch[get_prof()]++;
  199. pop(); // On pop la condition du if
  200. }
  201. Else
  202. // Elsif
  203. Else : tELSE If;
  204. // Else
  205. Else : tELSE Body {int current = get_current_index();
  206. for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++) {
  207. patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
  208. }
  209. nbs_instructions_to_patch[get_prof()] = 0;
  210. };
  211. // If sans else
  212. Else : {int current = get_current_index();
  213. for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++){
  214. patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
  215. }
  216. nbs_instructions_to_patch[get_prof()] = 0;
  217. };
  218. /*************************************/
  219. /*************************************/
  220. /************** Boucles **************/
  221. /*************************************/
  222. /*************************************/
  223. While : tWHILE tOBRACE E tCBRACE {add_operation(JMF,$3,0,0); // Ecriture du JMF
  224. $1 = get_current_index() - 1; // Enregistrement de la ligne a patch
  225. pop(); // Pop de la condition
  226. }
  227. Body {int current = get_current_index(); // Patch du JMF apres le body
  228. patch($1,current + 1);
  229. add_operation(JMP,$1,0,0); // JMP au debut de la boucle
  230. };
  231. /*************************************/
  232. /*************************************/
  233. /************ Affectations ***********/ // A RETRAVAILLER
  234. /*************************************/
  235. /*************************************/
  236. // Affectation simple
  237. Aff : tID tEQ E tPV {struct symbole_t * symbole = get_variable($1); // On récupère le symbole
  238. symbole->initialized = 1; // Le symbole devient initialisé
  239. add_operation(COP, symbole->adresse, $3,0); // On affecte la valeur
  240. pop(); // On pop l'expression
  241. };
  242. // Debut d'une affectation avec déreférencement de pointeur //////// A RETRAVAILLERRRRRR
  243. DebutAffPointeur : tMUL SuiteAffPointeur {add_operation(READ, $2, $2, 0);
  244. $$=$2;
  245. };
  246. DebutAffPointeur : SuiteAffPointeur {$$=$1;
  247. };
  248. SuiteAffPointeur : tMUL tID {struct symbole_t * symbole = get_variable($2);
  249. int addr = push("0_TEMPORARY", 1, symbole->type);
  250. add_operation(COP, addr,symbole->adresse,0);
  251. $$=addr;
  252. };
  253. SuiteAffPointeur : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1);
  254. int addr = push("0_TEMPORARY", 1, symbole->type);
  255. if (symbole->type.isTab == 2) {
  256. add_operation(COP, addr,symbole->adresse,0);
  257. } else {
  258. add_operation(AFCA, addr,symbole->adresse,0);
  259. }
  260. int addr2 = push("0_TEMPORARY", 1, integer);
  261. add_operation(AFC, addr2, taille_types[symbole->type.base],0);
  262. add_operation(MUL,$3,addr2,$3);
  263. add_operation(ADD,$3,addr,$3);
  264. $$=$3;
  265. pop();
  266. pop();
  267. };
  268. // Affectation sur un pointeur
  269. Aff : DebutAffPointeur tEQ E tPV {add_operation(WR,$1,$3,0);
  270. pop();
  271. pop();
  272. };
  273. /*************************************/
  274. /*************************************/
  275. /***** Expressions Arithmetiques *****/
  276. /*************************************/
  277. /*************************************/
  278. // Pour une expression arithmétique, nous renvoyons toujours l'adresse du resultat
  279. // Un simple nombre
  280. E : tNB {int addr = push("0_TEMPORARY", 1, integer); // On reserve la place de la variable temporaire
  281. add_operation(AFC, addr,$1,0); // On Affecte la valeur a cette adresse
  282. $$ = addr; // On renvoi l'adresse
  283. };
  284. // Un nombre sous forme XeY, même traitement qu'un nombre classique
  285. E : tNBEXP {int addr = push("0_TEMPORARY", 1, integer);
  286. add_operation(AFC, addr,$1,0);
  287. $$ = addr;
  288. };
  289. // Une Multiplication
  290. 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
  291. $$ = $1; // On renvoi l'adresse du resultat
  292. pop(); // On libère la seconde variable temporaire
  293. };
  294. // Une Division (idem multiplication)
  295. E : E tDIV E {add_operation(DIV, $1,$1,$3);
  296. $$ = $1;
  297. pop();
  298. };
  299. // Une Soustraction (idem multiplication)
  300. E : E tSUB E {add_operation(SOU,$1,$1,$3);
  301. $$ = $1;
  302. pop();
  303. };
  304. // Une Addition (idem multiplication)
  305. E : E tADD E {add_operation(ADD,$1,$1,$3);
  306. $$ = $1;
  307. pop();
  308. };
  309. // Une invocation
  310. E : Invocation {$$ = $1; // Une invocation renvoi déjà l'adresse, cette règle n'est qu'un cast d'Invocation en E
  311. };
  312. // Consomation de parenthèses
  313. E : tOBRACE E tCBRACE {$$ = $2; // Cela permet de garantir la prioricité des expressions entre parenthèse
  314. };
  315. // Négatif --> -E <=> 0-E
  316. E : tSUB E {int addr = push("0_TEMPORARY", 1, integer); // On réserve la variable temporaire pour le 0
  317. add_operation(AFC, addr,0,0); // On affecte le 0
  318. add_operation(SOU, $2, addr, $2); // On applique le 0-E
  319. $$ = $2; // On renvoi l'adresse
  320. pop(); // On libère la mémoire temporaire utilisée par 0
  321. };
  322. E : E tEQCOND E {add_operation(EQU,$1,$1,$3);
  323. $$ = $1;
  324. pop();
  325. };
  326. E : E tGT E {add_operation(SUP,$1,$1,$3);
  327. $$ = $1;
  328. pop();
  329. };
  330. E : E tLT E {add_operation(INF,$1,$1,$3);
  331. $$ = $1;
  332. pop();
  333. };
  334. E : tNOT E { printf("!\n"); };
  335. E : E tAND E {add_operation(MUL,$1,$1,$3); $$ = $1; pop();};
  336. E : E tOR E {add_operation(ADD,$1,$1,$3); $$ = $1; pop();} ;
  337. E : tMUL E { add_operation(READ, $2, $2, 0); $$=$2;};
  338. E : tID { printf("Id\n"); struct symbole_t * symbole = get_variable($1); struct type_t type = symbole->type; type.nb_blocs = 1; int addr = push("0_TEMPORARY", 1, type); if (symbole->type.isTab == 1){add_operation(AFCA, addr,symbole->adresse,0);} else{add_operation(COP, addr,symbole->adresse,0);} $$=addr;};
  339. E : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1); struct type_t type = symbole->type; type.nb_blocs = 1; int addr = push("0_TEMPORARY", 1, type); if(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);
  340. add_operation(ADD,$3,addr,$3); add_operation(READ,$3,$3,0); $$=$3; pop(); pop();};
  341. E : tADDR EBis {$$=$2;};
  342. E : Get {$$ = $1;};
  343. EBis : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1);
  344. struct type_t type = symbole->type; type.nb_blocs = 1;
  345. int addr = push("0_TEMPORARY", 1, type);
  346. if(type.isTab == 2) {
  347. add_operation(COP, addr,symbole->adresse,0);
  348. }
  349. else{
  350. add_operation(AFCA, addr,symbole->adresse,0);
  351. }
  352. int addr2 = push("0_TEMPORARY", 1, integer);
  353. add_operation(AFC, addr2, taille_types[symbole->type.base],0);
  354. add_operation(MUL,$3,addr2,$3);
  355. add_operation(ADD,$3,addr,$3); $$=$3;
  356. pop(); pop();};
  357. EBis : tID { printf("Id\n"); struct symbole_t * symbole = get_variable($1); struct type_t type = symbole->type; type.nb_blocs = 1; int addr = push("0_TEMPORARY", 1, type); add_operation(AFCA, addr,symbole->adresse,0); $$=addr;};
  358. //Créer un champ isConst dans la table des symboles
  359. Type : tINT {type_courant.base = INT; type_courant.pointeur_level = 0; type_courant.isTab = 0; type_courant.nb_blocs = 1; printf("Type int\n");} ;
  360. Type : Type tMUL {type_courant.pointeur_level++; printf("Type int *\n");};
  361. Decl : Type SuiteDecl FinDecl ;
  362. Decl : tCONST Type SuiteDeclConst FinDeclConst;
  363. SuiteDecl : tID {push($1, 0, type_courant); printf("Suite Decl\n");};
  364. SuiteDecl : tID tEQ E {pop(); int addr = push($1,1, type_courant);};
  365. SuiteDecl : tID tOCROCH tNB tCCROCH {type_courant.isTab = 1; type_courant.nb_blocs = $3; push($1, 0, type_courant);} ;
  366. FinDecl : tPV { printf("Fin Decl\n");};
  367. FinDecl : tCOMA SuiteDecl FinDecl ;
  368. SuiteDeclConst : tID tEQ E {pop(); int addr = push($1,1, type_courant);};
  369. FinDeclConst : tPV;
  370. FinDeclConst : tCOMA SuiteDeclConst FinDeclConst;
  371. %%
  372. void main(void) {
  373. init();
  374. yyparse();
  375. }