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

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