123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- %{
- /*
- * Andrea Di Biagio
- * Politecnico di Milano, 2007
- *
- * assembler.y
- * Formal Languages & Compilers Machine, 2007/2008
- *
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include "asm_struct.h"
- #include "asm_engine.h"
- /* Variables declared for error tracking */
- int line_num;
- int num_error;
- /* other global variables */
- t_translation_infos *infos;
- /* functions declared into assembler.y */
- char * AsmErrorToString(int errorcode);
- %}
- %expect 3
-
- %union{
- char *svalue;
- int immediate;
- int opcode;
- t_asm_address *address;
- t_asm_data *dataVal;
- t_asm_instruction *instr;
- t_asm_label *label;
- t_asm_register *reg;
- }
- %start asm
- /* definitions */
- %token <opcode> OPCODE3
- %token <opcode> OPCODE2
- %token <opcode> OPCODEI
- %token <opcode> CCODE
- %token <opcode> HALT
- %token <opcode> NOP
- %token _WORD
- %token _SPACE
- %token <immediate>REG
- %token LPAR
- %token RPAR
- %token COLON
- %token MINUS
- %token BEGIN_IMMEDIATE
- %token BEGIN_COMMENT
- %token END_COMMENT
- %token <svalue> COMMENT
- %token <svalue> ETI
- %token <immediate> IMM
- %type <dataVal> data_value
- %type <reg> register
- %type <immediate> immediate
- %type <address> address
- %type <svalue> comment
- %type <label> label_decl
- %type <instr> instr
- %%
- asm : asm data_segm instruction_segm { /* DOES NOTHING */}
- | data_segm instruction_segm { /* DOES NOTHING */}
- | instruction_segm { /* DOES NOTHING */}
- ;
- instruction_segm : instruction_segm instruction { line_num++; }
- | instruction { line_num++; }
- ;
- instruction : instr comment { /* DOES NOTHING */}
- | label_decl instr comment {
- /* assign the label to the current instruction */
- $1->data = (void *) $2;
- }
- | instr { /* DOES NOTHING */}
- | label_decl instr {
- /* assign the label to the current instruction */
- $1->data = (void *) $2;
- }
- ;
- instr : OPCODE3 register REG register {
- t_asm_register *reg;
- int asm_errorcode;
-
- /* alloc memory for a register info. */
- reg = allocRegister($3, 0);
-
- /* register shouldn't be a NULL pointer */
- if (reg == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* initialize an instruction with three operands' */
- $$ = init_opcode3($1, $2, reg, $4);
-
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- | OPCODE2 REG REG immediate {
- t_asm_register *register_1;
- t_asm_register *register_2;
- int asm_errorcode;
-
- /* alloc memory for a register info. */
- register_1 = allocRegister($2, 0);
- register_2 = allocRegister($3, 0);
-
- /* registers shouldn't be a NULL pointer */
- if (register_1 == NULL || register_2 == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* initialize an instruction with two operands' */
- $$ = init_opcode2($1, register_1, register_2, $4);
-
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- | OPCODEI REG address {
- t_asm_register *reg;
- int asm_errorcode;
-
- /* alloc memory for a register info. */
- reg = allocRegister($2, 0);
-
- /* register shouldn't be a NULL pointer */
- if (reg == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* initialize an instruction with a single operand' */
- $$ = init_opcodeI($1, reg, $3);
-
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- | CCODE address {
- int asm_errorcode;
-
- /* initialize a branch instruction */
- $$ = init_ccode($1, $2);
-
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- | HALT {
- int asm_errorcode;
-
- /* initialize a HALT instruction */
- $$ = init_halt();
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- | NOP {
- int asm_errorcode;
-
- /* initialize a NOP instruction */
- $$ = init_nop();
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* add the newly created instruction to the code segment */
- asm_errorcode = addInstruction(infos, $$);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- ;
- data_segm : data_segm data_def { line_num++; }
- | data_def comment { line_num++; }
- | data_def { line_num++; }
- ;
- data_def : label_decl data_value {
- int asm_errorcode;
- /* insert data into the data segment */
- asm_errorcode = addData(infos, $2);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- /* assign the label to the current block of data */
- $1->data = (void *) $2;
- }
- | data_value {
- int asm_errorcode;
- /* insert data into the data segment */
- asm_errorcode = addData(infos, $1);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
- }
- ;
- label_decl : ETI COLON {
- int asm_errorcode;
-
- /* look for the requested label */
- $$ = findLabel(infos, $1, &asm_errorcode);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
-
- if ($$ == NULL)
- {
- t_asm_label *label;
-
- /* label was never defined before */
- label = allocLabel($1, NULL);
- /* label shouldn't be a NULL pointer */
- if (label == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* insert the new label */
- asm_errorcode = insertLabel(infos, label);
- /* set the $$ value */
- $$ = label;
- }
- else
- free($1);
- /* notify if an error occurred */
- if (asm_errorcode != ASM_OK)
- yyerror(AsmErrorToString(asm_errorcode));
- }
- ;
- data_value : _WORD IMM {
- /* create an instance of `t_asm_data' */
- $$ = allocData(ASM_WORD, $2);
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- | _SPACE IMM {
- /* create an instance of `t_asm_data' */
- $$ = allocData(ASM_SPACE, $2);
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- ;
-
- register : REG {
- /* alloc memory for a register info. */
- $$ = allocRegister($1, 0);
-
- /* $$ shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- | LPAR REG RPAR {
- /* alloc memory for a register info. */
- $$ = allocRegister($2, 1);
-
- /* label shouldn't be a NULL pointer */
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- ;
- immediate : BEGIN_IMMEDIATE IMM { $$ = $2; }
- | BEGIN_IMMEDIATE MINUS IMM {$$ = - $3; }
- ;
- address : ETI {
- int asm_errorcode;
- t_asm_label *label_found;
-
- /* look for the requested label */
- label_found = findLabel(infos, $1, &asm_errorcode);
- if (asm_errorcode != ASM_OK)
- {
- /* an error occurred */
- yyerror(AsmErrorToString(asm_errorcode));
- }
-
- if (label_found == NULL)
- {
- /* label was never defined before */
- label_found = allocLabel($1, NULL);
- /* label shouldn't be a NULL pointer */
- if (label_found == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- /* insert the new label */
- asm_errorcode = insertLabel(infos, label_found);
- /* notify if an error occurred */
- if (asm_errorcode != ASM_OK)
- yyerror(AsmErrorToString(asm_errorcode));
- }
- else
- free($1);
- /* set the $$ value */
- $$ = allocAddress(0, label_found);
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- | IMM {
- $$ = allocAddress($1, NULL);
- if ($$ == NULL)
- {
- /* an out of memory occurred */
- yyerror(AsmErrorToString(ASM_OUT_OF_MEMORY));
-
- /* stop the parser */
- YYABORT;
- }
- }
- ;
- comment : BEGIN_COMMENT COMMENT END_COMMENT { $$ = $2; }
- ;
- %%
-
- int yyerror(const char* errmsg)
- {
- fprintf(stdout, "line %d , error: %s \n", line_num, errmsg);
- num_error++;
- return 0;
- }
- int main (int argc, char **argv)
- {
- int errorcode;
- char *filename;
- FILE *input_file;
- extern FILE *yyin;
- argc--;
- argv++;
-
- if (argc > 0)
- {
- input_file = fopen(argv[0], "r");
- if (input_file == NULL)
- {
- fprintf( stdout, "File not found : %s.\n", argv[0]);
- exit(-1);
- }
- yyin = input_file;
- }
- else
- yyin = stdin;
-
- if (argc <= 1)
- filename = "output.o";
- else
- filename = argv[1];
-
- #ifndef NDEBUG
- fprintf(stdout, "Initializing the assembler data structures.\n");
- #endif
- /* initialize the translation infos */
- infos = initStructures(&errorcode);
- /* test if an error occurred */
- if (errorcode != ASM_OK)
- {
- fprintf( stdout, "An error occurred while initializing the assembler.\n"
- "%s. \n", AsmErrorToString(errorcode));
- /* we can't start the parsing procedure since a critical error occurred */
- abort();
- }
- /* initialize the global variables */
- line_num = 1;
- num_error = 0;
-
- #ifndef NDEBUG
- if (argc > 0)
- fprintf(stdout, "Starting the parsing process. "
- "Input file : %s.\n", argv[0]);
- else
- fprintf(stdout, "Starting the parsing process. "
- "Input file : standard input.\n");
- #endif
- /* start the parsing procedure */
- yyparse();
- #ifndef NDEBUG
- fprintf(stdout, "Parsing complete. \n");
- #endif
-
- /* test if the parsing job found some errors */
- if (num_error == 0)
- {
- #ifndef NDEBUG
- fprintf(stdout, "Output will be written on file : %s. \n", filename);
- #endif
- errorcode = asm_writeObjectFile(infos, filename);
- if (errorcode != ASM_OK)
- {
- fprintf( stdout, "An error occurred while writing the object file.\n"
- "%s. \n", AsmErrorToString(errorcode));
- }
- #ifndef NDEBUG
- else
- fprintf(stdout, "Output written on file \"%s\".\n", filename);
- #endif
- }
- else {
- fprintf(stdout, "\nInput file contains some error(s). No object file written\n");
- fprintf(stdout, "**%d errors found \n\n", num_error);
- }
- #ifndef NDEBUG
- fprintf(stdout, "Finalizing the data structures. \n");
- #endif
- /* shutdown the asm engine */
- if (infos != NULL)
- {
- errorcode = finalizeStructures(infos);
- if (errorcode != ASM_OK)
- {
- fprintf(stdout, "SHUTDOWN:: error while finalizing "
- "the data structures. \n%s. \n", AsmErrorToString(errorcode));
- }
- }
- #ifndef NDEBUG
- fprintf(stdout, "Done. \n");
- #endif
-
- return 0;
- }
- char * AsmErrorToString(int errorcode)
- {
- switch(errorcode)
- {
- case ASM_NOT_INITIALIZED_INFO : return "global infos not initialized";
- case ASM_UNDEFINED_INSTRUCTION : return "invalid instruction found";
- case ASM_INVALID_LABEL_FOUND : return "invalid label found";
- case ASM_LABEL_ALREADY_PRESENT : return "label already defined";
- case ASM_UNDEFINED_DATA : return "invalid data found";
- case ASM_INVALID_DATA_FORMAT : return "invalid data format";
- case ASM_FOPEN_ERROR : return "fopen failed";
- case ASM_INVALID_INPUT_FILE : return "invalid file pointer";
- case ASM_FWRITE_ERROR : return "fwrite failed";
- case ASM_FCLOSE_ERROR : return "fclose failed";
- case ASM_CODE_NOT_PRESENT : return "code segment is empty";
- case ASM_OUT_OF_MEMORY : return "out of memory";
- case ASM_INVALID_OPCODE : return "invalid opcode found";
- case ASM_UNKNOWN_ERROR : return "unknown error found";
- default : return "<invalid errorcode>";
- }
- }
|