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

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