/* MasC interpreter/compiler (Master Assembly Script Container) written by Jared Bruni After reading Writing Compilers and Interpreters A approach using C++ by Ronald Mak and the Dragon Book code completly re-written but using concepts teached in this book */ // output C source code implementation file #include "output_c.h" struct symNode *cmp_node_ptr = 0, *sloop_node_ptr = 0; int cmp_inc_index = 0; char *convertEscapeCharacters(char *src, char *ptmp_buf) { char *ptr_c = src, *tmp_buf = ptmp_buf; while (*ptr_c != 0) { switch(*ptr_c) { case '\n': *tmp_buf = '\\'; tmp_buf++; *tmp_buf = 'n'; tmp_buf++; break; case '\t': *tmp_buf = '\\'; tmp_buf++; *tmp_buf = 't'; tmp_buf++; break; case '\"': *tmp_buf = '\\'; tmp_buf++; *tmp_buf = '\"'; tmp_buf++; break; default: *tmp_buf = *ptr_c; tmp_buf++; break; } ptr_c++; } *tmp_buf = 0; if(ptmp_buf[strlen(ptmp_buf)-1] == '\"') ptmp_buf[strlen(ptmp_buf)-2] = 0; if(*ptmp_buf == '\\') { ptmp_buf+=2; } return ptmp_buf; } void _PROCcessInc(FILE *pfile, struct BackEnd *bend, struct Token *tokens, int flip) { char tmp_buf[max_string_size]; struct symNode *node_ptr = 0; do { switch(tokens[flip].code) { case MOV: fprintf(pfile, "%s = %s;\n", tokens[flip+1].text,tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case INC: fprintf(pfile, "%s++;\n", tokens[flip+1].text); break; case DEC: fprintf(pfile, "%s--;\n", tokens[flip+1].text); break; case ADD: fprintf(pfile, "%s += %s;\n", tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case SUB: fprintf(pfile, "%s -= %s;\n", tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case MUL: fprintf(pfile, "%s *= %s;\n", tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case XOR: fprintf(pfile, "%s = %s ^ %s;\n",tokens[flip+1].text, tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case OR: fprintf(pfile, "%s = %s | %s;\n", tokens[flip+1].text, tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case NOT: fprintf(pfile, "%s = !%s;\n", tokens[flip+1].text,tokens[flip+1].text); break; case AND: fprintf(pfile, "%s = %s & %s;\n", tokens[flip+1].text,tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case DIV: fprintf(pfile, "%s /= %s;\n", tokens[flip+1].text, tokens[flip+2].code == 99 ? tokens[flip+2].num_text : tokens[flip+2].text); break; case PUSH: { if(tokens[flip+1].code == 99) { fprintf(pfile, "Push(&masc__st, %s);\n", tokens[flip+1].num_text); } else { node_ptr = Search(&bend->g_stable.root,tokens[flip+1].text); switch(node_ptr->vtype) { case tVAR_INT: fprintf(pfile,"Push(&masc__st, (int) %s);\n", node_ptr->str); break; default: fprintf(pfile, "Push(&masc__st, %s);\n", tokens[flip+1].text); } } } break; case POP: { node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(node_ptr->vtype == tVAR_INT) { fprintf(pfile,"%s = (int) Pop(&masc__st);\n", tokens[flip+1].text); } else { fprintf(pfile,"%s = Pop(&masc__st);\n", tokens[flip+1].text); } } break; case SCAT: { int sip = flip+2; node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(!node_ptr) { printf("Error. variable %s not found\n", tokens[flip+1].text); return; } fprintf(pfile,"sprintf(%s, \"", node_ptr->str); do { sip++; node_ptr = Search(&bend->g_stable.root, tokens[sip].text); if(!node_ptr && tokens[sip].text[0] != '\"') { //printError("Error during compilation print function couldnt find variable\n") } if(isdigit(tokens[sip].text[0])) { fputc('%',pfile); fputc('d',pfile); } else if(tokens[sip].text[0] == '"') { fputc('%',pfile); fputc('s',pfile); } else { switch(node_ptr->vtype) { case tVAR_INT: case tVAR_CINT: fputc('%', pfile); fputc('d', pfile); break; case tVAR_CSTR: case tVAR_STR: fputc('%', pfile); fputc('s', pfile); break; case tVAR_FLOAT: case tVAR_CFLOAT: fputc('%',pfile); fputc('f',pfile); break; default: { //printf("%d %s\n", node_ptr->vtype, tokens[sip].text); } } } sip++; } while (tokens[sip].code == OSTREAM); sip = flip+2; fprintf(pfile,"%%c\","); do { sip++; if(tokens[sip].vtype == tVAR_CSTR) fprintf(pfile,"\"%s\",",convertEscapeCharacters(tokens[sip].text,tmp_buf)); else if(tokens[sip].code == 100) { node_ptr = Search(&bend->g_stable.root, tokens[sip].text); if(!node_ptr) { return; } fprintf(pfile, "%s,", tokens[sip].text); } else if(tokens[sip].code == 99) fprintf(pfile, "%s,", tokens[sip].num_text); sip++; } while(tokens[sip].code == OSTREAM); fprintf(pfile,"\"\""); fprintf(pfile,");\n"); } break; case PRINT: if(tokens[flip+1].code != OSTREAM && tokens[flip+1].vtype == tVAR_CSTR) fprintf(pfile, "printf(\"%s\");\n", convertEscapeCharacters(tokens[flip+1].text,tmp_buf)); else if(tokens[flip+1].code == 99) { fprintf(pfile, "printf(\"%s\");\n", tokens[flip+1].num_text); } else if(tokens[flip+1].code == 100) { node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(!node_ptr) { return; } switch(node_ptr->vtype) { case tVAR_INT: fprintf(pfile,"printf(\"%%d\",%s);\n", node_ptr->str); break; case tVAR_STR: fprintf(pfile,"printf(%s);\n", node_ptr->str); break; case tVAR_FLOAT: fprintf(pfile,"printf(\"%f\", %s);\n", node_ptr->str); break; } } else { int sip = flip+1; fprintf(pfile,"printf(\""); do { sip++; node_ptr = Search(&bend->g_stable.root, tokens[sip].text); if(!node_ptr && tokens[sip].text[0] != '\"') { //printError("Error during compilation print function couldnt find variable\n") } if(isdigit(tokens[sip].text[0])) { fputc('%',pfile); fputc('d',pfile); } else if(tokens[sip].text[0] == '"') { fputc('%',pfile); fputc('s',pfile); } else { switch(node_ptr->vtype) { case tVAR_INT: case tVAR_CINT: fputc('%', pfile); fputc('d', pfile); break; case tVAR_CSTR: case tVAR_STR: fputc('%', pfile); fputc('s', pfile); break; case tVAR_FLOAT: case tVAR_CFLOAT: fputc('%',pfile); fputc('f',pfile); break; default: { //printf("%d %s\n", node_ptr->vtype, tokens[sip].text); } } } sip++; } while (tokens[sip].code == OSTREAM); sip = flip+1; fprintf(pfile,"%%s\","); do { sip++; if(tokens[sip].vtype == tVAR_CSTR) fprintf(pfile,"\"%s\",",convertEscapeCharacters(tokens[sip].text,tmp_buf)); else if(tokens[sip].code == 100) { node_ptr = Search(&bend->g_stable.root, tokens[sip].text); if(!node_ptr) { return; } fprintf(pfile, "%s,", tokens[sip].text); } else if(tokens[sip].code == 99) fprintf(pfile, "%s,", tokens[sip].num_text); sip++; } while(tokens[sip].code == OSTREAM); fprintf(pfile,"\"\""); fprintf(pfile,");\n"); } break; case CALL: { fprintf(pfile,"masc_%s();\n", tokens[flip+1].text); } break; case IN: { node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(!node_ptr) { return; } switch(node_ptr->vtype) { case tVAR_STR: fprintf(pfile,"scanf(\"%%s\", %s);\n", node_ptr->str); break; case tVAR_INT: fprintf(pfile,"scanf(\"%%d\", &%s);\n", node_ptr->str); break; case tVAR_FLOAT: fprintf(pfile,"scanf(\"%%f\", &f);\n", node_ptr->str); break; } } break; case CMP: { cmp_node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(!cmp_node_ptr) { return; } cmp_inc_index = flip+2; } break; case JE: { if(!cmp_node_ptr || cmp_inc_index == 0) { return; } switch(cmp_node_ptr->vtype) { case tVAR_INT: case tVAR_FLOAT: fprintf(pfile,"if(%s == %s) goto %s;\n", cmp_node_ptr->str, tokens[cmp_inc_index].vtype == tVAR_CINT ? tokens[cmp_inc_index].num_text : tokens[cmp_inc_index].text, tokens[flip+1].text); break; case tVAR_STR: fprintf(pfile,"if(strcmp(%s,%s%s%s) == 0) goto %s;\n", cmp_node_ptr->str, tokens[cmp_inc_index].vtype == tVAR_CSTR ? "\"" : "", convertEscapeCharacters(tokens[cmp_inc_index].text,tmp_buf),tokens[cmp_inc_index].vtype == tVAR_CSTR ? "\"" : "",tokens[flip+1].text); break; } } break; case JNE: { if(!cmp_node_ptr || cmp_inc_index == 0) { return; } switch(cmp_node_ptr->vtype) { case tVAR_INT: case tVAR_FLOAT: fprintf(pfile,"if(%s != %s) goto %s;\n", cmp_node_ptr->str, tokens[cmp_inc_index].vtype == tVAR_CINT ? tokens[cmp_inc_index].num_text : tokens[cmp_inc_index].text, tokens[flip+1].text); break; case tVAR_STR: fprintf(pfile,"if(strcmp(%s,%s%s%s)) goto %s;\n", cmp_node_ptr->str, tokens[cmp_inc_index].vtype == tVAR_CSTR ? "\"" : "", convertEscapeCharacters(tokens[cmp_inc_index].text,tmp_buf),tokens[cmp_inc_index].vtype == tVAR_CSTR ? "\"" : "",tokens[flip+1].text); break; } } break; case JG: case JLE: case JGE: case JL: { char tmp[25]; switch(tokens[flip].code) { case JG: strcpy(tmp,">"); break; case JL: strcpy(tmp,"<"); break; case JGE: strcpy(tmp,">="); break; case JLE: strcpy(tmp, "<="); break; } fprintf(pfile, "if(%s %s %s) goto %s;\n", cmp_node_ptr->str, tmp, tokens[cmp_inc_index].vtype == tVAR_CINT ? tokens[cmp_inc_index].num_text : tokens[cmp_inc_index].text, tokens[flip+1].text); } break; case JMP: { fprintf(pfile,"goto %s;\n", tokens[flip+1].text); } break; case RET: { fprintf(pfile,"return 0;\n"); } break; case EXIT: { fprintf(pfile,"exit(0);\n"); } break; case RESET: { fprintf(pfile,"main();\n"); break; } case SLOOP: { node_ptr = Search(&bend->g_stable.root, tokens[flip+1].text); if(!node_ptr) { return; } sloop_node_ptr = node_ptr; fprintf(pfile, "do {\n"); } break; case LOOP: { if(sloop_node_ptr == 0) return; fprintf(pfile,"\n} while(%s > 1);\n",sloop_node_ptr->str); } break; case LOOPN0: { if(sloop_node_ptr == 0) return; fprintf(pfile,"} while(%s != 0);\n", sloop_node_ptr->str); break; } default: { if(tokens[flip].vtype == tVAR_LABEL && strstr(tokens[flip].text, ":")) { fprintf(pfile,"%s\n", tokens[flip].text); } } break; } flip++; } while (tokens[flip].code != CB); } void _PROCcess_PROC(FILE *pfile, struct BackEnd *bend, struct Token *tokens, int flip) { do { if(tokens[flip].code == End) { return; } switch(tokens[flip].code) { case _PROC: { fprintf(pfile,"int masc_%s();\n", tokens[flip+1].text); } break; } flip++; } while (tokens[flip].code != End); } void put_PROC(FILE *pfile, struct BackEnd *bend, struct Token *tokens, int flip) { do { switch(tokens[flip].code) { case _PROC: { fprintf(pfile, "int masc_%s () {\n",tokens[flip+1].text); _PROCcessInc(pfile,bend,tokens,flip); fprintf(pfile, "}\n"); } break; } flip++; } while(tokens[flip].code != End); } // translate intermediate code to C source code void translateMasc_C(struct BackEnd *bend, struct Token *tokens) { int i_p = 0; int cip = 0; int tip = 0; int flip = 0; FILE *pfile = fopen(outfile, "w"); if(!pfile) { printf("Error could not open file for output.\n"); return; } fprintf(pfile, "#include\n#include\n#include\n"); fprintf(pfile, "struct Stack {\nfloat stack[%d];\nint stack_ptr;\n};\n", max_string_size); fprintf(pfile, "void initStack(struct Stack *st)\n{\nst->stack_ptr = 0;\n}"); fprintf(pfile, "\nvoid Push(struct Stack *st, float var)\n{\nif(st->stack_ptr < %d)\nst->stack[st->stack_ptr++] = var;\nelse\nprintf(\"Stack overflow\\n\");\n}\n", max_string_size); fprintf(pfile, "\nfloat Pop(struct Stack *st)\n{\nif(st->stack_ptr >= 0)\nreturn st->stack[--st->stack_ptr];\nelse\nprintf(\"Stack Underflow\\n\");return 0;\n}\n"); fprintf(pfile, "\nstruct Stack masc__st;\n"); _PROCcess_PROC(pfile,bend,tokens,flip); while(i_p < bend->inc_len && tokens[i_p].code != End) { switch(tokens[i_p].code) { case VAR: { cip = tip = i_p; do { switch(tokens[cip].code) { case VAR_INT: if(tokens[cip+2].code == EQ) { fprintf(pfile, "int %s = %d;\n", tokens[cip+1].text, (int)tokens[cip+3].value); } else { fprintf(pfile, "int %s = 0;\n", tokens[cip+1].text); } break; case VAR_FLOAT: { if(tokens[cip+2].code == EQ) { fprintf(pfile, "float %s = %d;\n", tokens[cip+1].text, tokens[cip+3].value); } else fprintf(pfile, "float %s = 0;\n", tokens[cip+1].text); } break; case VAR_STR: { fprintf(pfile,"char %s[%d];\n", tokens[cip+1].text, max_string_size); } break; } cip++; } while(tokens[cip].code != CB); } break; case BEGIN: fprintf(pfile, "int main() {\n"); fprintf(pfile,"initStack(&masc__st);\n"); // first print out the variables do { if(tokens[tip+2].code == EQ) { switch(tokens[tip].code) { case VAR_STR: fprintf(pfile,"strncpy(%s,%s,%d);\n", tokens[tip+1].text,tokens[tip+3].text,max_string_size); fprintf(pfile,"%s[%d] = 0;\n", tokens[tip+1].text, strlen(tokens[tip+3].text)-2); break; } } tip++; } while(tokens[tip].code != CB); fprintf(pfile, "begin:\n"); flip = i_p; // begin instructions here _PROCcessInc(pfile,bend,tokens,flip); // goto the end fprintf(pfile, "goto end;\n"); break; case END: fprintf(pfile, "end:\n"); flip = i_p; _PROCcessInc(pfile,bend,tokens,flip); // end instructions here break; } i_p++; } fprintf(pfile, "\nreturn 0;\n}\n"); put_PROC(pfile,bend,tokens,0); fclose(pfile); } // please dont spoil my day im miles away