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 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. %code requires {
  2. #include "../Tables/Symboles/table_symboles.h"
  3. struct while_t {
  4. int n_ins_cond;
  5. int n_ins_jmf;
  6. };
  7. }
  8. %union {
  9. int nombre;
  10. struct symbole_t symbole;
  11. char id[30];
  12. char str[300];
  13. struct while_t my_while;
  14. }
  15. %{
  16. #include "../Tables/Fonctions/tab_fonctions.h"
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include "../Tables/Instructions/tab_instruc.h"
  21. #define TAILLE 1024
  22. #define SECURED (1)
  23. struct type_t type_courant;
  24. struct type_t return_type_fonc;
  25. // Tableau pour le management des patchs des JMP
  26. int instructions_ligne_to_patch[10][20];
  27. int nbs_instructions_to_patch[10];
  28. // Utile a l'affectation avec des pointeurs
  29. int first_etoile = 1;
  30. %}
  31. // Récupération des tokens
  32. %token tMAIN
  33. %token tOBRACKET tCBRACKET
  34. %token<nombre> tOBRACE tCBRACE
  35. %token tOCROCH tCCROCH
  36. %token tINT
  37. %token tCONST
  38. %token tPV tCOMA
  39. %token tMUL tDIV tADD tSUB tEQ
  40. %token<nombre> tNB tNBEXP
  41. %token<id> tID
  42. %token<str> tSTR
  43. %token tPRINT tGET tSTOP
  44. %token<nombre> tIF tELSE
  45. %token<my_while> tWHILE
  46. %token tRETURN
  47. %token tLT tGT tEQCOND
  48. %token tAND tOR
  49. %token tADDR
  50. %left tLT tGT
  51. %left tEQCOND
  52. %left tAND tOR
  53. %left tNOT
  54. %left tADD tSUB
  55. %left tMUL tDIV
  56. %right tINT tMAIN
  57. %type<symbole> SymboleAffectation
  58. %type<nombre> E EBis Invocation Args ArgSuite Arg SuiteParams Params Get InitTab SuiteInitTab
  59. %%
  60. /*************************************/
  61. /*************************************/
  62. /*********** Programme C *************/
  63. /*************************************/
  64. /*************************************/
  65. // 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.
  66. C : Fonctions {add_operation(STOP,0,0,0);
  67. create_asm();
  68. };
  69. // Le main, renvoi un int, possède le mot clé main, des arguments et un body
  70. // Dès que le main est reconnu (token main) on met en place le JMP
  71. Main : tINT tMAIN {create_jump_to_main(get_current_index());
  72. }
  73. tOBRACE Args tCBRACE Body;
  74. /*************************************/
  75. /*************************************/
  76. /************ Fonctions **************/
  77. /*************************************/
  78. /*************************************/
  79. // Des fonctions sont une suite de fonctions (possiblement nulle)
  80. Fonctions : Main ;
  81. Fonctions : Fonction Fonctions ;
  82. // Une fonction possède un Type , un identifiant
  83. Fonction : Type tID {return_type_fonc = type_courant; // On récupère le ype de la fonction
  84. }
  85. tOBRACE {inc_prof(); // On incrémente la profondeur pour les arguments, ils font parti de la fonction
  86. }
  87. Args {decrement_prof(); // Quand les arguments sont passés, on peur décrémenter la profondeur (sans effacer les variables)
  88. push_fonction($2,return_type_fonc,get_current_index(), $6); // On enregistre la fonction dans la table des fonctions
  89. }
  90. tCBRACE Body {add_operation(RET,0,0,0); // On ajoute le RET
  91. };
  92. // Get, une fonction particulière -> renvoi l'adresse de la valeur getée
  93. Get : tGET tOBRACE tCBRACE {int addr = push("0_TEMPORARY", 0, integer); // On déclare la var temporelle
  94. add_operation(GET,addr,0,0); // On ajoute le GET
  95. $$ = addr; // On renvoi l'adresse
  96. };
  97. // Print, une fonction particulière
  98. Print : tPRINT tOBRACE E tCBRACE {add_operation(PRI,$3,0,0); // On ajoute l'instruction PRI
  99. pop(); // On supprime la variable temporaire
  100. };
  101. // Print, une fonction particulière
  102. Print : tPRINT tOBRACE tSTR tCBRACE {int i = 0;
  103. int decalage = 0;
  104. char previous = 'a';
  105. while ($3[i] != '\0') {
  106. if (previous == '\\' && $3[i] == 'n') {
  107. $3[i - decalage - 1] = '\n';
  108. previous = 'a';
  109. decalage++;
  110. } else if (previous == '\\' && $3[i] == '0') {
  111. $3[i - decalage - 1] = '\0';
  112. previous = 'a';
  113. decalage++;
  114. } else {
  115. $3[i-decalage] = $3[i];
  116. previous = $3[i];
  117. }
  118. i++;
  119. }
  120. $3[i-decalage] = $3[i];
  121. i=0;
  122. int termine = $3[i+1] == '"';
  123. int addr = push("0_TEMPORARY", 0, integer);
  124. while (!termine) {
  125. if ($3[i+1] != '"') {
  126. add_operation(AFC, addr + i, $3[i+1], 0);
  127. } else {
  128. termine = 1;
  129. }
  130. i++;
  131. if (!termine && $3[i+1] != '"') {
  132. add_operation(AFC, addr + i, $3[i+1], 0);
  133. } else {
  134. termine = 1;
  135. }
  136. i++;
  137. if (!termine && $3[i+1] != '"') {
  138. add_operation(AFC, addr + i, $3[i+1], 0);
  139. } else {
  140. termine = 1;
  141. }
  142. i++;
  143. if (!termine && $3[i+1] != '"') {
  144. add_operation(AFC, addr + i, $3[i+1], 0);
  145. } else {
  146. termine = 1;
  147. }
  148. i = i - 3;
  149. termine = 0;
  150. if ($3[i+1] != '"') {
  151. add_operation(PRIC, addr + i, 0, 0);
  152. } else {
  153. termine = 1;
  154. }
  155. i++;
  156. if (!termine && $3[i+1] != '"') {
  157. add_operation(PRIC, addr + i, 0, 0);
  158. } else {
  159. termine = 1;
  160. }
  161. i++;
  162. if (!termine && $3[i+1] != '"') {
  163. add_operation(PRIC, addr + i, 0, 0);
  164. } else {
  165. termine = 1;
  166. }
  167. i++;
  168. if (!termine && $3[i+1] != '"') {
  169. add_operation(PRIC, addr + i, 0, 0);
  170. } else {
  171. termine = 1;
  172. }
  173. i++;
  174. }
  175. pop(); // On supprime la variable temporaire
  176. };
  177. // Stop, une fonction particulière
  178. Stop : tSTOP tOBRACE tNB tCBRACE {add_operation(STOP,$3,0,0); // On ajoute juste l'instruction stop
  179. };
  180. // Return, etape clé d'une fonction
  181. Return : tRETURN E tPV {add_operation(COP,0,$2,0); // On copie la valeur retournée à l'adresse 0 de la frame
  182. pop(); // On pop la variable temporaire
  183. };
  184. /*************************************/
  185. /*************************************/
  186. /************ Arguments **************/
  187. /*************************************/
  188. /*************************************/
  189. // Les arguments : Args, Arg, ArgSuite renvoient la taille dans la pile des arguments déjà reconnus
  190. // Des argmuments correspondent à : un argument, puis la suite d'arguments
  191. Args : Arg ArgSuite {$$ = $1 + $2; // La taille des arguments est la taille du premier argument plus celle des suivants
  192. };
  193. Args : {$$ = 0; // Il peut ne pas y avoir d'arguments, alors la taille est 0
  194. };
  195. // Un argument possède un type et un identifiant (nom)
  196. Arg : Type tID {type_courant.nb_blocs = 1;
  197. int addr = push($2,1, type_courant); // On stocke l'argument dans la pile des symboles
  198. if (type_courant.pointeur_level > 0) {
  199. $$ = taille_types[ADDR];
  200. } else {
  201. $$ = taille_types[type_courant.base];
  202. }
  203. };
  204. // Un argument peut aussi être un tableau (argument classique et crochets) il est considéré comme un pointeur
  205. Arg : Type tID tOCROCH tCCROCH {type_courant.nb_blocs = 1;
  206. type_courant.pointeur_level++; // Considéré comme un simple pointeur
  207. int addr = push($2,1, type_courant);
  208. $$ = taille_types[ADDR];
  209. };
  210. // La suite d'un argument, une virgule, un argument, et d'autres arguments
  211. ArgSuite : tCOMA Arg ArgSuite {$$ = $2 + $3;
  212. };
  213. // Cela peut être aucun arguments
  214. ArgSuite : {$$ = 0;
  215. };
  216. /*************************************/
  217. /*************************************/
  218. /*************** Body ****************/
  219. /*************************************/
  220. /*************************************/
  221. // Un body n'est rien d'autre qu'une suite d'instructions entre deux accolades
  222. Body : tOBRACKET {inc_prof(); // Lors de l'ouverture de l'accolade la profondeur augmente
  223. }
  224. Instructions tCBRACKET {reset_prof(); // A la sortie d'un body, on détruit toutes les variables locales de ce body
  225. };
  226. /*************************************/
  227. /*************************************/
  228. /*********** Instructions ************/
  229. /*************************************/
  230. /*************************************/
  231. // Des instructions sont une instruction suivie d'autres instructions, ou, rien
  232. Instructions : Instruction Instructions ;
  233. Instructions : ;
  234. // Un instruction peut être : une affectation, une déclaration, une invocation, un if, un while, un return, une fonction particulière
  235. Instruction : Aff;
  236. Instruction : Decl;
  237. Instruction : Invocation tPV {pop();};
  238. Instruction : If;
  239. Instruction : While;
  240. Instruction : Return;
  241. Instruction : Stop tPV;
  242. Instruction : Print tPV;
  243. /*************************************/
  244. /*************************************/
  245. /************ Invocation *************/
  246. /*************************************/
  247. /*************************************/
  248. Invocation : tID tOBRACE {if (!SECURED) {
  249. push("0_TEMPORARY_CTX", 0, integer); // On reserve la place du contexte
  250. push("0_TEMPORARY_ADDR_RT", 0, pointer); // On reserve la place de l'adresse de retour
  251. }
  252. }
  253. Params tCBRACE {struct fonction_t fonc = get_fonction($1); // On récupère la fonction
  254. if (!SECURED) {
  255. multiple_pop($4 + 2); // On pop les paramètres de la table des symboles
  256. } else {
  257. multiple_pop($4); // On pop les paramètres de la table des symboles
  258. }
  259. add_operation(CALL,fonc.first_instruction_line, get_last_addr(),0); // On écrit le CALL
  260. // On renvoi l'adresse de la valeur retour de la fonction
  261. if (fonc.return_type.pointeur_level > 0 || fonc.return_type.isTab) {
  262. $$ = push("0_TEMPORARY_RETURN", 0, pointer);
  263. } else {
  264. $$ = push("0_TEMPORARY_RETURN", 0, fonc.return_type);
  265. }
  266. };
  267. /*************************************/
  268. /*************************************/
  269. /************ Paramètres *************/
  270. /*************************************/
  271. /*************************************/
  272. // 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
  273. Params : {$$ = 0;
  274. };
  275. Params : Param SuiteParams {$$ = $2 + 1;
  276. };
  277. Param : E
  278. SuiteParams : tCOMA Param SuiteParams {$$ = $3 + 1;};
  279. SuiteParams : {$$ = 0;};
  280. /*************************************/
  281. /*************************************/
  282. /******** Sauts conditionnels ********/
  283. /*************************************/
  284. /*************************************/
  285. // Un if : le token, une expression entre parenthèse suivie d'un body et d'un else
  286. If : tIF tOBRACE E tCBRACE {add_operation(JMF,$3,0,0); // On ajoute le JMF sans préciser la ligne du saut
  287. $1 = get_current_index() - 1; // On stocke le numéro d'instruction à patcher
  288. }
  289. Body {int current = get_current_index(); // On récupère le numéro d'instrcution
  290. patch($1,current + 1); // On patch le Jump en cas d'instruction fausse
  291. add_operation(JMP,0,0,0); // JMP pour skip le else si on devait faire le body
  292. instructions_ligne_to_patch[get_prof()][nbs_instructions_to_patch[get_prof()]] = current; // On spécifie que le JMP est a patcher
  293. nbs_instructions_to_patch[get_prof()]++;
  294. pop(); // On pop la condition du if
  295. }
  296. Else
  297. // Elsif
  298. Else : tELSE If;
  299. // Else
  300. Else : tELSE Body {int current = get_current_index();
  301. for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++) {
  302. patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
  303. }
  304. nbs_instructions_to_patch[get_prof()] = 0;
  305. };
  306. // If sans else
  307. Else : {int current = get_current_index();
  308. for (int i = 0; i< nbs_instructions_to_patch[get_prof()]; i++){
  309. patch(instructions_ligne_to_patch[get_prof()][i],current); // On patch après le else
  310. }
  311. nbs_instructions_to_patch[get_prof()] = 0;
  312. };
  313. /*************************************/
  314. /*************************************/
  315. /************** Boucles **************/
  316. /*************************************/
  317. /*************************************/
  318. While : tWHILE {$1.n_ins_cond = get_current_index(); // On enregistre l'endroit de la condition (pour le JMP en fin de while)
  319. }
  320. tOBRACE E tCBRACE {add_operation(JMF,$4,0,0); // Ecriture du JMF
  321. $1.n_ins_jmf = get_current_index() - 1; // Enregistrement du numero d'instruction du jmf à patch
  322. pop(); // Pop de la condition
  323. }
  324. Body {int current = get_current_index(); // Patch du JMF apres le body
  325. patch($1.n_ins_jmf,current + 1);
  326. add_operation(JMP,$1.n_ins_cond,0,0); // JMP au debut de la boucle
  327. };
  328. /*************************************/
  329. /*************************************/
  330. /************ Affectations ***********/
  331. /*************************************/
  332. /*************************************/
  333. // Affectation simple
  334. Aff : tID tEQ E tPV {struct symbole_t * symbole = get_variable($1);
  335. symbole->initialized = 1;
  336. if (symbole->type.isConst == 1 && symbole->type.pointeur_level == 0 || symbole->type.isTab) {
  337. printf("\033[31;01m ERROR : \033[00m %s est READ-ONLY\n", symbole->nom);
  338. exit(2);
  339. } else {
  340. add_operation(COP,symbole->adresse,$3,0); // On affecte la valeur
  341. pop(); // On pop l'expression
  342. first_etoile = 1; // On reinitialise first_etoile
  343. }
  344. };
  345. // Affectation sur un pointeur
  346. Aff : SymboleAffectation tEQ E tPV {if ($1.type.isConst == 1 && $1.type.pointeur_level == 0 || $1.type.isTab) {
  347. printf("\033[31;01m ERROR : \033[00m %s ou un de ses déréférencement est READ-ONLY\n", $1.nom);
  348. exit(2);
  349. } else {
  350. add_operation(WR,$1.adresse,$3,0); // On affecte la valeur
  351. pop(); // On pop l'expression
  352. pop(); // On pop la variable temporaire de l'adresse
  353. }
  354. };
  355. // Debut d'une affectation avec déreférencement de pointeur
  356. SymboleAffectation : tID {struct symbole_t * symbole = get_variable($1);
  357. symbole->initialized = 1;
  358. int addr = push("0_TEMPORARY", 1, pointer);
  359. if (symbole->type.isTab) {
  360. add_operation(AFCA, addr, symbole->adresse,0); // Si tableau AFCA
  361. } else {
  362. add_operation(COP, addr, symbole->adresse,0); // Si pointeur COP
  363. }
  364. struct symbole_t symbolebis = *symbole;
  365. symbolebis.adresse = addr;
  366. $$ = symbolebis; // On renvoi un symbole pointant sur la copie de l'adresse
  367. };
  368. SymboleAffectation : SymboleAffectation tOCROCH E tCCROCH {if ($1.type.pointeur_level == 0) { // Check déréférençable
  369. printf("\033[35;01m WARNING : \033[00m déréférencement exessif\n");
  370. } else {
  371. $1.type.pointeur_level--; // On baisse le niveau de pointeur
  372. int addr = push("0_TEMPORARY", 1, integer); // On alloue la place pour stocker la taille du type pointé
  373. if ($1.type.pointeur_level > 0) {
  374. add_operation(AFC, addr, taille_types[ADDR],0); // Si on est encore un pointeur, la taille d'un adresse
  375. } else {
  376. add_operation(AFC, addr, taille_types[$1.type.base],0); // Sinon le type de base
  377. }
  378. add_operation(MUL,$3,addr,$3); // On multiple le nombre de décalage par la taille du type
  379. add_operation(ADD,$1.adresse,$1.adresse,$3); // On l'ajoute a l'adresse de base
  380. $1.type.isTab = 0;
  381. $$=$1;
  382. pop();
  383. pop();
  384. }
  385. };
  386. SymboleAffectation : tMUL SymboleAffectation {if ($2.type.pointeur_level == 0) { // Check déréférençable
  387. printf("\033[35;01m WARNING : \033[00m déréférencement exessif\n");
  388. } else {
  389. $2.type.pointeur_level--; // On baisse le niveau de pointeur
  390. $2.type.isTab = 0;
  391. if (first_etoile) {
  392. first_etoile = 0; // Le premier déréférencement doit être skip a cause du WR
  393. } else {
  394. add_operation(READ, $2.adresse, $2.adresse,0); //
  395. $$=$2;
  396. }
  397. }
  398. };
  399. /*************************************/
  400. /*************************************/
  401. /***** Expressions Arithmetiques *****/
  402. /*************************************/
  403. /*************************************/
  404. // Pour une expression arithmétique, nous renvoyons toujours l'adresse du resultat
  405. // Un simple nombre
  406. E : tNB {int addr = push("0_TEMPORARY", 1, integer); // On reserve la place de la variable temporaire
  407. add_operation(AFC, addr,$1,0); // On Affecte la valeur a cette adresse
  408. $$ = addr; // On renvoi l'adresse
  409. };
  410. // Un nombre sous forme XeY, même traitement qu'un nombre classique
  411. E : tNBEXP {int addr = push("0_TEMPORARY", 1, integer);
  412. add_operation(AFC, addr,$1,0);
  413. $$ = addr;
  414. };
  415. // Une Multiplication
  416. 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
  417. $$ = $1; // On renvoi l'adresse du resultat
  418. pop(); // On libère la seconde variable temporaire
  419. };
  420. // Une Division (idem multiplication)
  421. E : E tDIV E {add_operation(DIV, $1,$1,$3);
  422. $$ = $1;
  423. pop();
  424. };
  425. // Une Soustraction (idem multiplication)
  426. E : E tSUB E {add_operation(SOU,$1,$1,$3);
  427. $$ = $1;
  428. pop();
  429. };
  430. // Une Addition (idem multiplication)
  431. E : E tADD E {add_operation(ADD,$1,$1,$3);
  432. $$ = $1;
  433. pop();
  434. };
  435. // Une invocation
  436. E : Invocation {$$ = $1; // Une invocation renvoi déjà l'adresse, cette règle n'est qu'un cast d'Invocation en E
  437. };
  438. // Consomation de parenthèses
  439. E : tOBRACE E tCBRACE {$$ = $2; // Cela permet de garantir la prioricité des expressions entre parenthèse
  440. };
  441. // Négatif --> -E <=> 0-E
  442. E : tSUB E {int addr = push("0_TEMPORARY", 1, integer); // On réserve la variable temporaire pour le 0
  443. add_operation(AFC, addr,0,0); // On affecte le 0
  444. add_operation(SOU, $2, addr, $2); // On applique le 0-E
  445. $$ = $2; // On renvoi l'adresse
  446. pop(); // On libère la mémoire temporaire utilisée par 0
  447. };
  448. // Opérateur == (idem multiplication)
  449. E : E tEQCOND E {add_operation(EQU,$1,$1,$3);
  450. $$ = $1;
  451. pop();
  452. };
  453. // Opérateur > (idem multiplication)
  454. E : E tGT E {add_operation(SUP,$1,$1,$3);
  455. $$ = $1;
  456. pop();
  457. };
  458. // Opérateur < (idem multiplication)
  459. E : E tLT E {add_operation(INF,$1,$1,$3);
  460. $$ = $1;
  461. pop();
  462. };
  463. // Opérateur !E <=> E==0
  464. E : tNOT E {int addr = push("0_TEMPORARY", 1, integer); // On réserve la variable temporaire pour le 0
  465. add_operation(AFC, addr,0,0); // On affecte le 0
  466. add_operation(EQU, $2, addr, $2); // On applique le 0==E
  467. $$ = $2; // On renvoi l'adresse
  468. pop();
  469. };
  470. // Opérateur E && E' <=> E*E' (idem multiplication)
  471. E : E tAND E {add_operation(MUL,$1,$1,$3);
  472. $$ = $1;
  473. pop();
  474. };
  475. // Opérateur E || E' <=> E+E' (idem multiplication)
  476. E : E tOR E {add_operation(ADD,$1,$1,$3);
  477. $$ = $1;
  478. pop();
  479. };
  480. // Déréférencement de pointeur
  481. E : tMUL E {add_operation(READ, $2, $2, 0); // Extraction en mémoire
  482. $$=$2;
  483. };
  484. // Une variable
  485. E : tID {struct symbole_t * symbole = get_variable($1); // On cherche la variable dans la table des symboles
  486. struct type_t type = symbole->type; // On récupère le type
  487. type.nb_blocs = 1;
  488. int addr = push("0_TEMPORARY", 1, type); // On créé la variable temporaire
  489. if (symbole->type.isTab == 1) {
  490. add_operation(AFCA, addr,symbole->adresse,0); // Si c'est un tableau on affecte l'adresse du début
  491. } else {
  492. add_operation(COP, addr,symbole->adresse,0); // Si c'est autre chose, on copie la valeur
  493. }
  494. $$ = addr;
  495. };
  496. // Une variable sous forme de tableau
  497. E : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1); // On récupère le symbole
  498. struct type_t type = symbole->type; // On récupère le type
  499. type.nb_blocs = 1;
  500. int addr = push("0_TEMPORARY", 1, type); // On créé la variable temporaire
  501. if (type.isTab) {
  502. add_operation(AFCA, addr,symbole->adresse,0);
  503. } else {
  504. add_operation(COP, addr,symbole->adresse,0);
  505. }
  506. int addr2 = push("0_TEMPORARY", 1, integer);
  507. add_operation(AFC, addr2, taille_types[symbole->type.base],0);
  508. add_operation(MUL,$3,addr2,$3);
  509. add_operation(ADD,$3,addr,$3);
  510. add_operation(READ,$3,$3,0);
  511. $$=$3;
  512. pop();
  513. pop();
  514. };
  515. E : tADDR EBis {$$=$2;};
  516. E : Get {$$ = $1;};
  517. EBis : tID tOCROCH E tCCROCH {struct symbole_t * symbole = get_variable($1);
  518. struct type_t type = symbole->type;
  519. type.nb_blocs = 1;
  520. int addr = push("0_TEMPORARY", 1, type);
  521. if(type.isTab) {
  522. add_operation(AFCA, addr,symbole->adresse,0);
  523. } else {
  524. add_operation(COP, addr,symbole->adresse,0);
  525. }
  526. int addr2 = push("0_TEMPORARY", 1, integer);
  527. add_operation(AFC, addr2, taille_types[symbole->type.base],0);
  528. add_operation(MUL,$3,addr2,$3);
  529. add_operation(ADD,$3,addr,$3);
  530. $$=$3;
  531. pop();
  532. pop();
  533. };
  534. EBis : tID { 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;};
  535. /*************************************/
  536. /*************************************/
  537. /*************** Types ***************/
  538. /*************************************/
  539. /*************************************/
  540. // Type INT
  541. Type : tINT {type_courant.base = INT;
  542. type_courant.pointeur_level = 0;
  543. type_courant.isConst = 0;
  544. };
  545. // Type pointeur
  546. Type : Type tMUL {type_courant.pointeur_level++; // On ajoute un niveau de pointeur
  547. };
  548. // Constante
  549. Type : tCONST Type {type_courant.isConst = 1;
  550. };
  551. /*
  552. Type : tINT TypeNext
  553. Type : tCONST tINT TypeNext
  554. TypeNext :
  555. | tMUL TypeNext
  556. */
  557. /*************************************/
  558. /*************************************/
  559. /************ Déclaration ************/
  560. /*************************************/
  561. /*************************************/
  562. // Une déclaration est un type, un identifiant eventuellement initialisé, et fin de déclaration (une autre ou un ;);
  563. Decl : Type UneDecl FinDecl ;
  564. // Une déclaration d'une simple variable sans initialisation
  565. UneDecl : tID {type_courant.isTab = 0; // On est pas un tableau
  566. type_courant.nb_blocs = 1; // On fixe le nombre de blocs
  567. push($1, 0, type_courant);
  568. };
  569. // Une déclaration d'une simple variable avec initialisation
  570. UneDecl : tID tEQ E {pop(); // On pop l'expression
  571. type_courant.isTab = 0; // On est pas un tableau
  572. type_courant.nb_blocs = 1; // On fixe le nombre de blocs
  573. int addr = push($1,1, type_courant); // On déclare la variable qui a la même adresse que la variable temporaire, et, a donc déjà la valeur
  574. };
  575. // Une déclaration d'un tableau sans initialisation
  576. UneDecl : tID tOCROCH tNB tCCROCH {type_courant.isTab = 1; // On est un tableau
  577. type_courant.pointeur_level++; // On augmente le niveau de pointeur (un tableau est un pointeur)
  578. type_courant.nb_blocs = $3; // On fixe le nombre de blocs
  579. push($1, 0, type_courant);
  580. };
  581. // Une déclaration d'un tableau avec initialisation
  582. UneDecl : tID tOCROCH tNB tCCROCH tEQ tOBRACKET InitTab tCBRACKET {if ($3 != $7) {
  583. printf("\033[31;01m ERROR : \033[00m Initialisation de %s : %d éléments donnés, %d éléments requis\n", $1, $7, $3);
  584. exit(2);
  585. } else {
  586. type_courant.isTab = 1;
  587. type_courant.pointeur_level++; // On augmente le niveau de pointeur (un tableau est un pointeur)
  588. type_courant.nb_blocs = $3;
  589. int i;
  590. for (i=0;i<$3;i++) {
  591. pop();
  592. }
  593. push($1, 1, type_courant);
  594. }
  595. };
  596. // Un ; ou une autre déclaration
  597. FinDecl : tPV;
  598. FinDecl : tCOMA UneDecl FinDecl ;
  599. // Initialisation des tableau
  600. InitTab : E SuiteInitTab {$$ = $2 + 1;
  601. };
  602. SuiteInitTab : tCOMA E SuiteInitTab {$$ = $3 + 1;
  603. };
  604. SuiteInitTab : {$$ = 0;
  605. };
  606. %%
  607. void main(void) {
  608. init();
  609. yyparse();
  610. }