diff --git a/main.c b/main.c index 8e4f248..b5caf7e 100644 --- a/main.c +++ b/main.c @@ -44,26 +44,21 @@ int main(int argc, char* argv[]) { return errno; } - // info gathering - int lncount, widestln, maxtokens; - getinfo(input, &lncount, &widestln, &maxtokens); - // parsing - struct line** lns = parse(input, lncount, widestln, maxtokens); - fclose(input); + struct Parser* p = mkparser(input); + parse(p); // translating - translate(lns, lncount, fname); - - // freeing lns - freelns(lns, lncount); + struct Translator* t = mktranslator(p->lns, fname); + translate(t); + freeparser(p); // printing - printasmlns(); + printasmlns(t); // freeing asmlns free(fname); - freeasmlns(); + freetranslator(t); return 0; } diff --git a/parser.c b/parser.c index 076c507..abae979 100644 --- a/parser.c +++ b/parser.c @@ -4,18 +4,24 @@ #include #include "parser.h" -void freelns(struct line** lns, int lnscount) { - for(int i = 0; i < lnscount; i++) { - int tkcount = lns[i]->tokenscount; +void freelns(struct lnarray* lns) { + for(int i = 0; i < lns->count; i++) { + int tkcount = lns->lns[i]->tokenscount; for(int j = 0; j < tkcount; j++) { - free(lns[i]->tokens[j]); + free(lns->lns[i]->tokens[j]); } - free(lns[i]->tokens); - free(lns[i]); + free(lns->lns[i]->tokens); + free(lns->lns[i]); } + free(lns->lns); free(lns); } +void freeparser(struct Parser* p) { + freelns(p->lns); + free(p); +} + void gountilbrk (FILE* input) { char c; while(c = fgetc(input), c != -1) { @@ -26,15 +32,16 @@ void gountilbrk (FILE* input) { } } -void getinfo(FILE* input, int* lncount, int* widestln, int* maxtokens) { +void getinfo(struct Parser* p) { + p->lns->count = 0; + p->maxtokens = 0; + p->widestln = 0; char c, nc; - int lns = 0; int widest = 0; int currsz = 0; int tokens = 0; - int maxtoks = 0; short readsmt = 0; - while(c = fgetc(input), c != -1) { + while(c = fgetc(p->input), c != -1) { currsz++; if(isspace(c)) { if(readsmt) { @@ -42,11 +49,11 @@ void getinfo(FILE* input, int* lncount, int* widestln, int* maxtokens) { readsmt = 0; } if(c == '\n' && tokens > 0) { - lns++; - if(currsz > widest) - widest = currsz; - if(tokens > maxtoks) - maxtoks = tokens; + p->lns->count++; + if(currsz > p->widestln) + p->widestln = currsz; + if(tokens > p->maxtokens) + p->maxtokens = tokens; currsz = 0; tokens = 0; } @@ -54,33 +61,43 @@ void getinfo(FILE* input, int* lncount, int* widestln, int* maxtokens) { } if(c == '/') { - nc = fgetc(input); + nc = fgetc(p->input); if(nc == '/') { - gountilbrk(input); + gountilbrk(p->input); continue; } - ungetc(nc, input); + ungetc(nc, p->input); } readsmt = 1; } - rewind(input); - (*lncount) = lns; - (*widestln) = widest; - (*maxtokens) = maxtoks; + rewind(p->input); } -struct line** parse(FILE* input, int lncount, int widestln, int maxtokens) { - struct line** lns = (struct line**)malloc(sizeof(struct line*)*lncount); +struct Parser* mkparser(FILE* input) { + struct Parser* p = (struct Parser*)malloc(sizeof(struct Parser)); + struct lnarray* lns = (struct lnarray*)malloc(sizeof(struct lnarray)); + p->input = input; + p->lns = lns; + getinfo(p); + return p; +} + +void parse(struct Parser* p) { + struct line** lns = (struct line**)malloc(sizeof(struct line*)*p->lns->count); + p->lns->lns = lns; + p->lns->count = 0; + + char tmp[p->widestln]; + char* tokens[p->maxtokens]; + char c, nc; short readsmt = 0; - char tmp[widestln]; - char* tokens[maxtokens]; int tmpind = 0; - int lnsind = 0; int tokensind = 0; int truelncount = 0; - while(c = fgetc(input), c != -1) { + + while(c = fgetc(p->input), c != -1) { if(isspace(c)) { if(readsmt) { tmp[tmpind] = '\0'; @@ -101,8 +118,8 @@ struct line** parse(FILE* input, int lncount, int widestln, int maxtokens) { } newln->tokenscount = tokensind; newln->truen = truelncount; - lns[lnsind] = newln; - lnsind++; + lns[p->lns->count] = newln; + p->lns->count++; tokensind = 0; } } @@ -110,17 +127,17 @@ struct line** parse(FILE* input, int lncount, int widestln, int maxtokens) { } if(c == '/') { - nc = fgetc(input); + nc = fgetc(p->input); if(nc == '/') { - gountilbrk(input); + gountilbrk(p->input); continue; } - ungetc(nc, input); + ungetc(nc, p->input); } tmp[tmpind] = c; tmpind++; readsmt = 1; } - return lns; + fclose(p->input); } diff --git a/parser.h b/parser.h index 4c69a97..5b0c338 100644 --- a/parser.h +++ b/parser.h @@ -6,7 +6,19 @@ struct line { int truen; }; -void getinfo(FILE* input, int* lncount, int* widestln, int* maxtokens); -void freelns(struct line** lns, int lnscount); -struct line** parse(FILE* input, int lncount, int widestln, int maxtokens); +struct lnarray { + struct line** lns; + int count; +}; + +struct Parser { + FILE* input; + struct lnarray* lns; + int widestln; + int maxtokens; +}; + +struct Parser* mkparser(FILE* input); +void freeparser(struct Parser* p); +void parse(struct Parser* p); #endif diff --git a/translator.c b/translator.c index 5199ac0..9727c75 100644 --- a/translator.c +++ b/translator.c @@ -5,119 +5,113 @@ #include "translator.h" #include "templates.h" -struct asmln** asmlns; -int asmind; -int asmsize; -char** toclean; -int tocleansize; -int tocleanind; - -void pushtoclean(char* topush) { - int nextsz = sizeof(char*)*(tocleanind+1); - if(nextsz >= tocleansize) { - tocleansize = nextsz * 2; - toclean = realloc(toclean, tocleansize); +void pushtoclean(struct Translator* t, char* topush) { + int nextsz = sizeof(char*)*(t->tocleanind+1); + if(nextsz >= t->tocleansize) { + t->tocleansize = nextsz * 2; + t->toclean = realloc(t->toclean, t->tocleansize); } - toclean[tocleanind] = topush; - tocleanind++; + t->toclean[t->tocleanind] = topush; + t->tocleanind++; } -void freetoclean() { - for(int i = 0; i < tocleanind; i++) { - free(toclean[i]); - } - free(toclean); - tocleansize = 0; - tocleanind = 0; +void freetoclean(struct Translator* t) { + for(int i = 0; i < t->tocleanind; i++) + free(t->toclean[i]); + free(t->toclean); + t->tocleansize = 0; + t->tocleanind = 0; } -void freeasmlns() { - for(int i = 0; i < asmind; i++) { - free(asmlns[i]); - } - free(asmlns); - asmsize = 0; - asmind = 0; - freetoclean(); +void freeasmlns(struct Translator* t) { + for(int i = 0; i < t->asmind; i++) + free(t->asmlns[i]); + free(t->asmlns); + t->asmsize = 0; + t->asmind = 0; } -void printasmlns() { - for(int i = 0; i < asmind; i++) { - printf("%s\n", asmlns[i]->instr); - } +void freetranslator(struct Translator* t) { + freeasmlns(t); + freetoclean(t); + free(t); } -char* heapstr(const char* input) { +void printasmlns(struct Translator* t) { + for(int i = 0; i < t->asmind; i++) + printf("%s\n", t->asmlns[i]->instr); +} + +char* heapstr(struct Translator* t, const char* input) { char* newstr = (char*)malloc(sizeof(char)*(strlen(input)+1)); strcpy(newstr, input); - pushtoclean(newstr); + pushtoclean(t, newstr); return newstr; } -char* switchseg(struct line* ln) { +char* switchseg(struct Translator* t, struct line* ln) { char* seg = ln->tokens[1]; if(strcmp(seg, "local") == 0) - return heapstr("@LCL"); + return heapstr(t, "@LCL"); if(strcmp(seg, "argument") == 0) - return heapstr("@ARG"); + return heapstr(t, "@ARG"); if(strcmp(seg, "this") == 0) - return heapstr("@THIS"); + return heapstr(t, "@THIS"); if(strcmp(seg, "that") == 0) - return heapstr("@THAT"); + return heapstr(t, "@THAT"); fprintf(stderr, "Unrecognized segment '%s'; line %i\n", seg, ln->truen); exit(1); } // produce comment as follows: // pop/push segment i -char* mkcom(struct line* ln, int indlen) { +char* mkcom(struct Translator* t, struct line* ln, int indlen) { int comlen = sizeof(char) * (strlen(ln->tokens[0]) + strlen(ln->tokens[1]) + indlen + 6); char* comment = (char*)malloc(comlen); snprintf(comment, comlen, "// %s %s %s", ln->tokens[0], ln->tokens[1], ln->tokens[2]); - pushtoclean(comment); + pushtoclean(t, comment); return comment; } void checkind(struct line* ln, int indsz) { - for(int i = 0; i < indsz; i++) { + for(int i = 0; i < indsz; i++) if(!isdigit(ln->tokens[2][i])) { fprintf(stderr, "Invalid index '%s'; line %i\n", ln->tokens[2], ln->truen); exit(1); } - } } -char* mkind(struct line* ln, int indsz) { +char* mkind(struct Translator* t, struct line* ln, int indsz) { int newsz = sizeof(char) * (indsz + 2); char* newind = (char*)malloc(newsz); snprintf(newind, newsz, "@%s", ln->tokens[2]); - pushtoclean(newind); + pushtoclean(t, newind); return newind; } -char* mkstatind(struct line* ln, int indsz, char* fname) { - int fnamelen = strlen(fname); +char* mkstatind(struct Translator* t, struct line* ln, int indsz) { + int fnamelen = strlen(t->fname); int newsz = sizeof(char) * (fnamelen + indsz + 3); char* newind = (char*)malloc(newsz); - snprintf(newind, newsz, "@%s.%s", fname, ln->tokens[2]); - pushtoclean(newind); + snprintf(newind, newsz, "@%s.%s", t->fname, ln->tokens[2]); + pushtoclean(t, newind); return newind; } -char* mktempind(struct line* ln, int indsz) { +char* mktempind(struct Translator* t, struct line* ln, int indsz) { int intind = atoi(ln->tokens[2]); int newsz = sizeof(char) * (indsz + 3); char* newind = (char*)malloc(newsz); snprintf(newind, newsz, "@%i", intind+5); - pushtoclean(newind); + pushtoclean(t, newind); return newind; } -void checkasmsize(int toadd) { - int targ = sizeof(struct asmln*)*(asmind+toadd); - if(targ >= asmsize) { - asmsize = targ * 2; - asmlns = (struct asmln**)realloc(asmlns, asmsize); +void checkasmsize(struct Translator* t, int toadd) { + int targ = sizeof(struct asmln*)*(t->asmind+toadd); + if(targ >= t->asmsize) { + t->asmsize = targ * 2; + t->asmlns = (struct asmln**)realloc(t->asmlns, t->asmsize); } } @@ -140,116 +134,116 @@ void checkopamnt(int amnt, struct line* ln) { } } -void addasmlns(struct line* ln, char** insts, int instcount) { +void addasmlns(struct Translator* t, struct line* ln, char** insts, int instcount) { for(int i = 0; i < instcount; i++) { - asmlns[asmind] = mkasmln(ln, insts[i]); - asmind++; + t->asmlns[t->asmind] = mkasmln(ln, insts[i]); + t->asmind++; } } -void startpoppush(struct line* ln, int indlen, char** insts) { +void startpoppush(struct Translator* t, struct line* ln, int indlen, char** insts) { // // operation segment i - insts[0] = mkcom(ln, indlen); + insts[0] = mkcom(t, ln, indlen); // @segment - insts[1] = switchseg(ln); + insts[1] = switchseg(t, ln); // D=M - insts[2] = heapstr("D=M"); + insts[2] = heapstr(t, "D=M"); // @i checkind(ln, indlen); - insts[3] = mkind(ln, indlen); + insts[3] = mkind(t, ln, indlen); } -void pushcons(struct line* ln, int indlen) { - checkasmsize(TPUSHCONSN); +void pushcons(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPUSHCONSN); // // push constant i - tpushcons[0] = mkcom(ln, indlen); + tpushcons[0] = mkcom(t, ln, indlen); // @i checkind(ln, indlen); - tpushcons[1] = mkind(ln, indlen); + tpushcons[1] = mkind(t, ln, indlen); - addasmlns(ln, tpushcons, TPUSHCONSN); + addasmlns(t, ln, tpushcons, TPUSHCONSN); } -void pushstat(struct line* ln, int indlen, char* fname) { - checkasmsize(TPUSHSTATN); +void pushstat(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPUSHSTATN); // // push static i - tpushstat[0] = mkcom(ln, indlen); + tpushstat[0] = mkcom(t, ln, indlen); // @fname.i checkind(ln, indlen); - tpushstat[1] = mkstatind(ln, indlen, fname); + tpushstat[1] = mkstatind(t, ln, indlen); - addasmlns(ln, tpushstat, TPUSHSTATN); + addasmlns(t, ln, tpushstat, TPUSHSTATN); } -void pushtemp(struct line* ln, int indlen) { - checkasmsize(TPUSHSTATN); +void pushtemp(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPUSHSTATN); // // pop static i - tpushtemp[0] = mkcom(ln, indlen); + tpushtemp[0] = mkcom(t, ln, indlen); // @5+i checkind(ln, indlen); - tpushtemp[1] = mktempind(ln, indlen); + tpushtemp[1] = mktempind(t, ln, indlen); - addasmlns(ln, tpushtemp, TPUSHTEMP); + addasmlns(t, ln, tpushtemp, TPUSHTEMP); } -void mkpush(struct line* ln, int indlen) { - checkasmsize(TPUSHN); +void push(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPUSHN); - startpoppush(ln, indlen, tpush); + startpoppush(t, ln, indlen, tpush); - addasmlns(ln, tpush, TPUSHN); + addasmlns(t, ln, tpush, TPUSHN); } -void popstat(struct line* ln, int indlen, char* fname) { - checkasmsize(TPOPSTATN); +void popstat(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPOPSTATN); // // pop static i - tpopstat[0] = mkcom(ln, indlen); + tpopstat[0] = mkcom(t, ln, indlen); // @fname.i checkind(ln, indlen); - tpopstat[6] = mkstatind(ln, indlen, fname); + tpopstat[6] = mkstatind(t, ln, indlen); // M=D - tpopstat[7] = heapstr("M=D"); + tpopstat[7] = heapstr(t, "M=D"); - addasmlns(ln, tpopstat, TPOPSTATN); + addasmlns(t, ln, tpopstat, TPOPSTATN); } -void poptemp(struct line* ln, int indlen) { - checkasmsize(TPOPTEMPN); +void poptemp(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPOPTEMPN); // // pop static i - tpoptemp[0] = mkcom(ln, indlen); + tpoptemp[0] = mkcom(t, ln, indlen); // @5+i checkind(ln, indlen); - tpoptemp[5] = mktempind(ln, indlen); + tpoptemp[5] = mktempind(t, ln, indlen); // M=D - tpoptemp[6] = heapstr("M=D"); + tpoptemp[6] = heapstr(t, "M=D"); - addasmlns(ln, tpoptemp, TPOPTEMPN); + addasmlns(t, ln, tpoptemp, TPOPTEMPN); } -void mkpop(struct line* ln, int indlen) { - checkasmsize(TPOPN); +void pop(struct Translator* t, struct line* ln, int indlen) { + checkasmsize(t, TPOPN); - startpoppush(ln, indlen, tpop); + startpoppush(t, ln, indlen, tpop); - addasmlns(ln, tpop, TPOPN); + addasmlns(t, ln, tpop, TPOPN); } -void switchop(struct line* ln, char* fname) { +void switchop(struct Translator* t, struct line* ln) { char* op = ln->tokens[0]; if(strcmp(op, "push") == 0) { @@ -258,16 +252,16 @@ void switchop(struct line* ln, char* fname) { int indlen = strlen(ln->tokens[2]); if(strcmp(seg, "constant") == 0) - pushcons(ln, indlen); + pushcons(t, ln, indlen); else if(strcmp(seg, "static") == 0) - pushstat(ln, indlen, fname); + pushstat(t, ln, indlen); else if(strcmp(seg, "temp") == 0) - pushtemp(ln, indlen); + pushtemp(t, ln, indlen); else - mkpush(ln, indlen); + push(t, ln, indlen); } else if(strcmp(op, "pop") == 0) { checkopamnt(3, ln); @@ -275,27 +269,33 @@ void switchop(struct line* ln, char* fname) { int indlen = strlen(ln->tokens[2]); if(strcmp(seg, "static") == 0) - popstat(ln, indlen, fname); + popstat(t, ln, indlen); else if(strcmp(seg, "temp") == 0) - poptemp(ln, indlen); + poptemp(t, ln, indlen); else - mkpop(ln, indlen); + pop(t, ln, indlen); } } -void translate(struct line** lns, int lnscount, char* fname) { - asmsize = sizeof(struct asmln*)*(lnscount * 15); - asmind = 0; - asmlns = (struct asmln**)malloc(asmsize); - - tocleanind = 0; - tocleansize = sizeof(char*)*(lnscount * 5); - toclean = (char**)malloc(tocleansize); - - for(int i = 0; i < lnscount; i++) { - struct line* ln = lns[i]; - switchop(ln, fname); - } +void translate(struct Translator* t) { + for(int i = 0; i < t->lns->count; i++) + switchop(t, t->lns->lns[i]); +} + +struct Translator* mktranslator(struct lnarray* lns, char* fname) { + struct Translator* t = (struct Translator*)malloc(sizeof(struct Translator)); + t->asmsize = sizeof(struct asmln*)*(lns->count * 15); + t->asmind = 0; + t->asmlns = (struct asmln**)malloc(t->asmsize); + + t->tocleanind = 0; + t->tocleansize = sizeof(char*)*(lns->count * 5); + t->toclean = (char**)malloc(t->tocleansize); + + t->lns = lns; + t->fname = fname; + + return t; } diff --git a/translator.h b/translator.h index 2cdcc81..41ba43a 100644 --- a/translator.h +++ b/translator.h @@ -7,7 +7,19 @@ struct asmln { int truen; }; -void freeasmlns(); -void printasmlns(); -void translate(struct line** lns, int lnscount, char* fname); +struct Translator { + struct asmln** asmlns; + int asmind; + int asmsize; + char** toclean; + int tocleansize; + int tocleanind; + struct lnarray* lns; + char* fname; +}; + +void freetranslator(struct Translator* t); +void printasmlns(struct Translator* t); +void translate(struct Translator* t); +struct Translator* mktranslator(struct lnarray* lns, char* fname); #endif