assembler.y 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. %{
  2. /*
  3. * Andrea Di Biagio
  4. * Politecnico di Milano, 2007
  5. *
  6. * assembler.y
  7. * Formal Languages & Compilers Machine, 2007/2008
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include "asm_struct.h"
  13. #include "asm_engine.h"
  14. /* Variables declared for error tracking */
  15. int line_num;
  16. int num_error;
  17. /* other global variables */
  18. t_translation_infos *infos;
  19. /* functions declared into assembler.y */
  20. char * AsmErrorToString(int errorcode);
  21. %}
  22. %expect 3
  23. %union{
  24. char *svalue;
  25. int immediate;
  26. int opcode;
  27. t_asm_address *address;
  28. t_asm_data *dataVal;
  29. t_asm_instruction *instr;
  30. t_asm_label *label;
  31. t_asm_register *reg;
  32. }
  33. %start asm
  34. /* definitions */
  35. %token <opcode> OPCODE3
  36. %token <opcode> OPCODE2
  37. %token <opcode> OPCODEI
  38. %token <opcode> CCODE
  39. %token <opcode> HALT
  40. %token <opcode> NOP
  41. %token _WORD
  42. %token _SPACE
  43. %token <immediate>REG
  44. %token LPAR
  45. %token RPAR
  46. %token COLON
  47. %token MINUS
  48. %token BEGIN_IMMEDIATE
  49. %token BEGIN_COMMENT
  50. %token END_COMMENT
  51. %token <svalue> COMMENT
  52. %token <svalue> ETI
  53. %token <immediate> IMM
  54. %type <dataVal> data_value
  55. %type <reg> register
  56. %type <immediate> immediate
  57. %type <address> address
  58. %type <svalue> comment
  59. %type <label> label_decl
  60. %type <instr> instr
  61. %%
  62. asm : asm data_segm instruction_segm { /* DOES NOTHING */}
  63. | data_segm instruction_segm { /* DOES NOTHING */}
  64. | instruction_segm { /* DOES NOTHING */}
  65. ;
  66. instruction_segm : instruction_segm instruction { line_num++; }
  67. | instruction { line_num++; }
  68. ;
  69. instruction : instr comment { /* DOES NOTHING */}
  70. | label_decl instr comment {
  71. /* assign the label to the current instruction */
  72. $1->data = (void *) $2;
  73. }
  74. | instr { /* DOES NOTHING */}
  75. | label_decl instr {
  76. /* assign the label to the current instruction */
  77. $1->data = (void *) $2;
  78. }
  79. ;
  80. instr : OPCODE3 register REG register {
  81. t_asm_register *reg;
  82. int asm_errorcode;
  83. /* alloc memory for a register info. */
  84. reg = allocRegister($3, 0);
  85. /* register shouldn't be a NULL pointer */
  86. if (reg == NULL)
  87. {
  88. /* an out of memory occurred */
  89. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  90. /* stop the parser */
  91. YYABORT;
  92. }
  93. /* initialize an instruction with three operands' */
  94. $$ = init_opcode3($1, $2, reg, $4);
  95. /* $$ shouldn't be a NULL pointer */
  96. if ($$ == NULL)
  97. {
  98. /* an out of memory occurred */
  99. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  100. /* stop the parser */
  101. YYABORT;
  102. }
  103. /* add the newly created instruction to the code segment */
  104. asm_errorcode = addInstruction(infos, $$);
  105. if (asm_errorcode != ASM_OK)
  106. {
  107. /* an error occurred */
  108. yyerror(AsmErrorToString(asm_errorcode));
  109. }
  110. }
  111. | OPCODE2 REG REG immediate {
  112. t_asm_register *register_1;
  113. t_asm_register *register_2;
  114. int asm_errorcode;
  115. /* alloc memory for a register info. */
  116. register_1 = allocRegister($2, 0);
  117. register_2 = allocRegister($3, 0);
  118. /* registers shouldn't be a NULL pointer */
  119. if (register_1 == NULL || register_2 == NULL)
  120. {
  121. /* an out of memory occurred */
  122. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  123. /* stop the parser */
  124. YYABORT;
  125. }
  126. /* initialize an instruction with two operands' */
  127. $$ = init_opcode2($1, register_1, register_2, $4);
  128. /* $$ shouldn't be a NULL pointer */
  129. if ($$ == NULL)
  130. {
  131. /* an out of memory occurred */
  132. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  133. /* stop the parser */
  134. YYABORT;
  135. }
  136. /* add the newly created instruction to the code segment */
  137. asm_errorcode = addInstruction(infos, $$);
  138. if (asm_errorcode != ASM_OK)
  139. {
  140. /* an error occurred */
  141. yyerror(AsmErrorToString(asm_errorcode));
  142. }
  143. }
  144. | OPCODEI REG address {
  145. t_asm_register *reg;
  146. int asm_errorcode;
  147. /* alloc memory for a register info. */
  148. reg = allocRegister($2, 0);
  149. /* register shouldn't be a NULL pointer */
  150. if (reg == NULL)
  151. {
  152. /* an out of memory occurred */
  153. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  154. /* stop the parser */
  155. YYABORT;
  156. }
  157. /* initialize an instruction with a single operand' */
  158. $$ = init_opcodeI($1, reg, $3);
  159. /* $$ shouldn't be a NULL pointer */
  160. if ($$ == NULL)
  161. {
  162. /* an out of memory occurred */
  163. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  164. /* stop the parser */
  165. YYABORT;
  166. }
  167. /* add the newly created instruction to the code segment */
  168. asm_errorcode = addInstruction(infos, $$);
  169. if (asm_errorcode != ASM_OK)
  170. {
  171. /* an error occurred */
  172. yyerror(AsmErrorToString(asm_errorcode));
  173. }
  174. }
  175. | CCODE address {
  176. int asm_errorcode;
  177. /* initialize a branch instruction */
  178. $$ = init_ccode($1, $2);
  179. /* $$ shouldn't be a NULL pointer */
  180. if ($$ == NULL)
  181. {
  182. /* an out of memory occurred */
  183. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  184. /* stop the parser */
  185. YYABORT;
  186. }
  187. /* add the newly created instruction to the code segment */
  188. asm_errorcode = addInstruction(infos, $$);
  189. if (asm_errorcode != ASM_OK)
  190. {
  191. /* an error occurred */
  192. yyerror(AsmErrorToString(asm_errorcode));
  193. }
  194. }
  195. | HALT {
  196. int asm_errorcode;
  197. /* initialize a HALT instruction */
  198. $$ = init_halt();
  199. /* $$ shouldn't be a NULL pointer */
  200. if ($$ == NULL)
  201. {
  202. /* an out of memory occurred */
  203. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  204. /* stop the parser */
  205. YYABORT;
  206. }
  207. /* add the newly created instruction to the code segment */
  208. asm_errorcode = addInstruction(infos, $$);
  209. if (asm_errorcode != ASM_OK)
  210. {
  211. /* an error occurred */
  212. yyerror(AsmErrorToString(asm_errorcode));
  213. }
  214. }
  215. | NOP {
  216. int asm_errorcode;
  217. /* initialize a NOP instruction */
  218. $$ = init_nop();
  219. /* $$ shouldn't be a NULL pointer */
  220. if ($$ == NULL)
  221. {
  222. /* an out of memory occurred */
  223. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  224. /* stop the parser */
  225. YYABORT;
  226. }
  227. /* add the newly created instruction to the code segment */
  228. asm_errorcode = addInstruction(infos, $$);
  229. if (asm_errorcode != ASM_OK)
  230. {
  231. /* an error occurred */
  232. yyerror(AsmErrorToString(asm_errorcode));
  233. }
  234. }
  235. ;
  236. data_segm : data_segm data_def { line_num++; }
  237. | data_def comment { line_num++; }
  238. | data_def { line_num++; }
  239. ;
  240. data_def : label_decl data_value {
  241. int asm_errorcode;
  242. /* insert data into the data segment */
  243. asm_errorcode = addData(infos, $2);
  244. if (asm_errorcode != ASM_OK)
  245. {
  246. /* an error occurred */
  247. yyerror(AsmErrorToString(asm_errorcode));
  248. }
  249. /* assign the label to the current block of data */
  250. $1->data = (void *) $2;
  251. }
  252. | data_value {
  253. int asm_errorcode;
  254. /* insert data into the data segment */
  255. asm_errorcode = addData(infos, $1);
  256. if (asm_errorcode != ASM_OK)
  257. {
  258. /* an error occurred */
  259. yyerror(AsmErrorToString(asm_errorcode));
  260. }
  261. }
  262. ;
  263. label_decl : ETI COLON {
  264. int asm_errorcode;
  265. /* look for the requested label */
  266. $$ = findLabel(infos, $1, &asm_errorcode);
  267. if (asm_errorcode != ASM_OK)
  268. {
  269. /* an error occurred */
  270. yyerror(AsmErrorToString(asm_errorcode));
  271. }
  272. if ($$ == NULL)
  273. {
  274. t_asm_label *label;
  275. /* label was never defined before */
  276. label = allocLabel($1, NULL);
  277. /* label shouldn't be a NULL pointer */
  278. if (label == NULL)
  279. {
  280. /* an out of memory occurred */
  281. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  282. /* stop the parser */
  283. YYABORT;
  284. }
  285. /* insert the new label */
  286. asm_errorcode = insertLabel(infos, label);
  287. /* set the $$ value */
  288. $$ = label;
  289. }
  290. else
  291. free($1);
  292. /* notify if an error occurred */
  293. if (asm_errorcode != ASM_OK)
  294. yyerror(AsmErrorToString(asm_errorcode));
  295. }
  296. ;
  297. data_value : _WORD IMM {
  298. /* create an instance of `t_asm_data' */
  299. $$ = allocData(ASM_WORD, $2);
  300. /* $$ shouldn't be a NULL pointer */
  301. if ($$ == NULL)
  302. {
  303. /* an out of memory occurred */
  304. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  305. /* stop the parser */
  306. YYABORT;
  307. }
  308. }
  309. | _SPACE IMM {
  310. /* create an instance of `t_asm_data' */
  311. $$ = allocData(ASM_SPACE, $2);
  312. /* $$ shouldn't be a NULL pointer */
  313. if ($$ == NULL)
  314. {
  315. /* an out of memory occurred */
  316. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  317. /* stop the parser */
  318. YYABORT;
  319. }
  320. }
  321. ;
  322. register : REG {
  323. /* alloc memory for a register info. */
  324. $$ = allocRegister($1, 0);
  325. /* $$ shouldn't be a NULL pointer */
  326. if ($$ == NULL)
  327. {
  328. /* an out of memory occurred */
  329. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  330. /* stop the parser */
  331. YYABORT;
  332. }
  333. }
  334. | LPAR REG RPAR {
  335. /* alloc memory for a register info. */
  336. $$ = allocRegister($2, 1);
  337. /* label shouldn't be a NULL pointer */
  338. if ($$ == NULL)
  339. {
  340. /* an out of memory occurred */
  341. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  342. /* stop the parser */
  343. YYABORT;
  344. }
  345. }
  346. ;
  347. immediate : BEGIN_IMMEDIATE IMM { $$ = $2; }
  348. | BEGIN_IMMEDIATE MINUS IMM {$$ = - $3; }
  349. ;
  350. address : ETI {
  351. int asm_errorcode;
  352. t_asm_label *label_found;
  353. /* look for the requested label */
  354. label_found = findLabel(infos, $1, &asm_errorcode);
  355. if (asm_errorcode != ASM_OK)
  356. {
  357. /* an error occurred */
  358. yyerror(AsmErrorToString(asm_errorcode));
  359. }
  360. if (label_found == NULL)
  361. {
  362. /* label was never defined before */
  363. label_found = allocLabel($1, NULL);
  364. /* label shouldn't be a NULL pointer */
  365. if (label_found == NULL)
  366. {
  367. /* an out of memory occurred */
  368. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  369. /* stop the parser */
  370. YYABORT;
  371. }
  372. /* insert the new label */
  373. asm_errorcode = insertLabel(infos, label_found);
  374. /* notify if an error occurred */
  375. if (asm_errorcode != ASM_OK)
  376. yyerror(AsmErrorToString(asm_errorcode));
  377. }
  378. else
  379. free($1);
  380. /* set the $$ value */
  381. $$ = allocAddress(0, label_found);
  382. if ($$ == NULL)
  383. {
  384. /* an out of memory occurred */
  385. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  386. /* stop the parser */
  387. YYABORT;
  388. }
  389. }
  390. | IMM {
  391. $$ = allocAddress($1, NULL);
  392. if ($$ == NULL)
  393. {
  394. /* an out of memory occurred */
  395. yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
  396. /* stop the parser */
  397. YYABORT;
  398. }
  399. }
  400. ;
  401. comment : BEGIN_COMMENT COMMENT END_COMMENT { $$ = $2; }
  402. ;
  403. %%
  404. int yyerror(const char* errmsg)
  405. {
  406. fprintf(stdout, "line %d , error: %s \n", line_num, errmsg);
  407. num_error++;
  408. return 0;
  409. }
  410. int main (int argc, char **argv)
  411. {
  412. int errorcode;
  413. char *filename;
  414. FILE *input_file;
  415. extern FILE *yyin;
  416. argc--;
  417. argv++;
  418. if (argc > 0)
  419. {
  420. input_file = fopen(argv[0], "r");
  421. if (input_file == NULL)
  422. {
  423. fprintf( stdout, "File not found : %s.\n", argv[0]);
  424. exit(-1);
  425. }
  426. yyin = input_file;
  427. }
  428. else
  429. yyin = stdin;
  430. if (argc <= 1)
  431. filename = "output.o";
  432. else
  433. filename = argv[1];
  434. #ifndef NDEBUG
  435. fprintf(stdout, "Initializing the assembler data structures.\n");
  436. #endif
  437. /* initialize the translation infos */
  438. infos = initStructures(&errorcode);
  439. /* test if an error occurred */
  440. if (errorcode != ASM_OK)
  441. {
  442. fprintf( stdout, "An error occurred while initializing the assembler.\n"
  443. "%s. \n", AsmErrorToString(errorcode));
  444. /* we can't start the parsing procedure since a critical error occurred */
  445. abort();
  446. }
  447. /* initialize the global variables */
  448. line_num = 1;
  449. num_error = 0;
  450. #ifndef NDEBUG
  451. if (argc > 0)
  452. fprintf(stdout, "Starting the parsing process. "
  453. "Input file : %s.\n", argv[0]);
  454. else
  455. fprintf(stdout, "Starting the parsing process. "
  456. "Input file : standard input.\n");
  457. #endif
  458. /* start the parsing procedure */
  459. yyparse();
  460. #ifndef NDEBUG
  461. fprintf(stdout, "Parsing complete. \n");
  462. #endif
  463. /* test if the parsing job found some errors */
  464. if (num_error == 0)
  465. {
  466. #ifndef NDEBUG
  467. fprintf(stdout, "Output will be written on file : %s. \n", filename);
  468. #endif
  469. errorcode = asm_writeObjectFile(infos, filename);
  470. if (errorcode != ASM_OK)
  471. {
  472. fprintf( stdout, "An error occurred while writing the object file.\n"
  473. "%s. \n", AsmErrorToString(errorcode));
  474. }
  475. #ifndef NDEBUG
  476. else
  477. fprintf(stdout, "Output written on file \"%s\".\n", filename);
  478. #endif
  479. }
  480. else {
  481. fprintf(stdout, "\nInput file contains some error(s). No object file written\n");
  482. fprintf(stdout, "**%d errors found \n\n", num_error);
  483. }
  484. #ifndef NDEBUG
  485. fprintf(stdout, "Finalizing the data structures. \n");
  486. #endif
  487. /* shutdown the asm engine */
  488. if (infos != NULL)
  489. {
  490. errorcode = finalizeStructures(infos);
  491. if (errorcode != ASM_OK)
  492. {
  493. fprintf(stdout, "SHUTDOWN:: error while finalizing "
  494. "the data structures. \n%s. \n", AsmErrorToString(errorcode));
  495. }
  496. }
  497. #ifndef NDEBUG
  498. fprintf(stdout, "Done. \n");
  499. #endif
  500. return 0;
  501. }
  502. char * AsmErrorToString(int errorcode)
  503. {
  504. switch(errorcode)
  505. {
  506. case ASM_NOT_INITIALIZED_INFO : return "global infos not initialized";
  507. case ASM_UNDEFINED_INSTRUCTION : return "invalid instruction found";
  508. case ASM_INVALID_LABEL_FOUND : return "invalid label found";
  509. case ASM_LABEL_ALREADY_PRESENT : return "label already defined";
  510. case ASM_UNDEFINED_DATA : return "invalid data found";
  511. case ASM_INVALID_DATA_FORMAT : return "invalid data format";
  512. case ASM_FOPEN_ERROR : return "fopen failed";
  513. case ASM_INVALID_INPUT_FILE : return "invalid file pointer";
  514. case ASM_FWRITE_ERROR : return "fwrite failed";
  515. case ASM_FCLOSE_ERROR : return "fclose failed";
  516. case ASM_CODE_NOT_PRESENT : return "code segment is empty";
  517. case ASM_OUT_OF_MEMORY : return "out of memory";
  518. case ASM_INVALID_OPCODE : return "invalid opcode found";
  519. case ASM_UNKNOWN_ERROR : return "unknown error found";
  520. default : return "<invalid errorcode>";
  521. }
  522. }