From 772c841052c8dd3395baa96a557f81c66db07b14 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Sun, 30 Apr 2017 21:17:50 -0400 Subject: [PATCH] Implemented do, while, and for --- c02.c | 16 +-- common.h | 3 +- cond.c | 31 ++++-- cond.h | 2 +- expr.c | 106 +++++++++++++++----- expr.h | 6 ++ label.c | 59 ++++++++--- label.h | 19 ++-- parse.c | 55 ++++++---- parse.h | 3 + stmnt.c | 300 ++++++++++++++++++++++++++++++++++++------------------- stmnt.h | 7 +- vars.c | 69 ++++++++----- vars.h | 9 +- 14 files changed, 465 insertions(+), 220 deletions(-) diff --git a/c02.c b/c02.c index 5dd90ef..0e2babe 100644 --- a/c02.c +++ b/c02.c @@ -37,6 +37,7 @@ void init() inpfil = srcfil; strcpy(inpnam, srcnam); alcvar = TRUE; + inblck = FALSE; nxtwrd[0] = 0; nxtptr = 0; } @@ -45,7 +46,7 @@ void init() pword() { getwrd(); - SCMNT(word); + ACMNT(word); DEBUG("Parsing Word '%s'\n", word); if (wordis("byte")) pdecl(VTBYTE); //Parse 'byte' declaration @@ -88,17 +89,16 @@ void compile() //DEBUG("Checking next character '%c'\n", nxtchr); if (match(EOF)) break; + else if (match('}')) + endblk(TRUE); //End Multi-Line Program Block else if (match('#')) - pdrctv(); //Process Directive + pdrctv(); //Parse Directive else if (match('/')) - skpcmt(); + skpcmt(); //Skip Comment else if (isalph()) - pword(); + pword(); //Parse Word else - { - printf("Unexpected character '%c'\n", nxtchr); - exterr(EXIT_FAILURE); - } + ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE); } epilog(); } diff --git a/common.h b/common.h index 18836e0..c45dd74 100644 --- a/common.h +++ b/common.h @@ -8,7 +8,8 @@ #define MAXDEF 255 //Maximum Number of Definitions #define VARLEN 6 //Maximum Variable Length #define MAXVAR 255 //Maximum Number of Variables -#define DATASPC 2048 //Space to Allocate for +#define MAXFNS 16 //Maximum Functions in Stack +#define DATASPC 2048 //Space to Allocate for Variable Data #define LABLEN 6 //Maximum Label Length #define LABFMT "L_%04d" //Label Format #define LABSFX ":" //Label Suffix diff --git a/cond.c b/cond.c index a6bdb2c..d798f35 100644 --- a/cond.c +++ b/cond.c @@ -41,16 +41,20 @@ int enccmp(char c) * Args: comparator - Encoded Comparison Operator * * Uses: term - Term Being Compared Against * * label - Branch Target if Comparison is FALSE */ -void prccmp(int cmprtr) +void prccmp() { DEBUG("Processing comparison operator %d\n", cmprtr); + DEBUG("Expression signedness is %d\n", expsgn); switch(cmprtr) { + case 0: // Raw Expression (Skip) + asmlin("BEQ", curlbl); + break; case 1: // = or == asmlin("CMP", term); asmlin("BNE", curlbl); break; case 2: // < - if (cmpsgn) { + if (expsgn) { asmlin("CMP", term); asmlin("BPL", curlbl); } @@ -60,7 +64,7 @@ void prccmp(int cmprtr) } break; case 3: // <= or =< - if (cmpsgn) { + if (expsgn) { asmlin("CMP", term); asmlin("BPL", curlbl); asmlin("BNE", curlbl); @@ -72,7 +76,7 @@ void prccmp(int cmprtr) } break; case 4: // > - if (cmpsgn) { + if (expsgn) { asmlin("CMP", term); asmlin("BMI", curlbl); asmlin("BEQ", curlbl); @@ -84,7 +88,7 @@ void prccmp(int cmprtr) } break; case 5: // >= or => - if (cmpsgn) { + if (expsgn) { asmlin("CMP", term); asmlin("BMI", curlbl); } @@ -97,6 +101,9 @@ void prccmp(int cmprtr) asmlin("CMP", term); asmlin("BEQ", curlbl); break; + case 7: // Raw Expression (Normal) + asmlin("BNE", curlbl); + break; default: printf("Unsupported comparison operator index %d\n", cmprtr); exterr(EXIT_FAILURE); @@ -104,13 +111,13 @@ void prccmp(int cmprtr) } /* Parse Comparison Operator * - * Sets: comparitor - Encoded Comparison Operator */ + * Sets: cmprtr - Encoded Comparison Operator */ int prscmp() { cmpenc = enccmp(nxtchr); //Encode Comparison Character - if (cmpenc == 0) - expctd("comparison operator"); cmprtr = cmpenc; //Set Encoded Comparator + if (cmprtr == 0) //No Comparison + return; cmpenc = enccmp(nxtchr); //Encode Next Comparison Character if (cmpenc != 0) cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator @@ -120,15 +127,17 @@ int prscmp() /* Parse and Compile Conditional Expression * * Condition = */ -void prscnd(char trmntr) +void prscnd(char trmntr, int revrse) { DEBUG("Parsing condition\n", 0); prsxpr(0); skpspc(); prscmp(); - prstrm(); + if (cmprtr) + prstrm(); + cmprtr = cmprtr ^ revrse & 7; + prccmp(); CCMNT(trmntr); - prccmp(cmprtr); expect(trmntr); } diff --git a/cond.h b/cond.h index 31f9efc..e790ac5 100644 --- a/cond.h +++ b/cond.h @@ -4,5 +4,5 @@ int cmpsgn; // Comparison contains signed operands -void prscnd(char trmntr); //Parse Conditional Expression +void prscnd(char trmntr, int revrse); //Parse Conditional Expression diff --git a/expr.c b/expr.c index 0c5c65f..0c580c9 100644 --- a/expr.c +++ b/expr.c @@ -11,8 +11,16 @@ #include "asm.h" #include "parse.h" #include "vars.h" +#include "label.h" #include "expr.h" +/* Set Expession Signedness */ +setsgn(int sgndns) +{ + expsgn = sgndns; + DEBUG("Set Expression Signedness to %d\n", expsgn); +} + /* Parse value (constant or identifier) * * Sets: value - the value (as a string) * * valtyp - value type */ @@ -22,8 +30,11 @@ void prsval() //expdef(); //Check for and expand define -- BROKEN! if (iscpre()) prscon(0xff); //Parse Constant - else if (isalph()) + else if (isalph()) { prsvar(); //Parse Variable + DEBUG("Checking type of variable '%s'\n", value); + if (vartyp[lookup(value)] == VTBYTE) setsgn(TRUE); + } else expctd("constant or variable"); skpspc(); @@ -41,7 +52,7 @@ void prsidx() expect(']'); } -/* Parse term in expression * +/* Parse term in expression * * Sets: term - the term (as a string) * * trmtxt - type of term */ void prstrm() @@ -62,39 +73,80 @@ void prstrm() skpspc(); } -/* Parse and Compile Pointer Dereference */ -void prsadr(char dlmtr) +/* Compile Address Reference */ +void prcadr(char* symbol) { - prsvar(); - DEBUG("Dereferencing variable '%s'\n", value); - ACMNT(value); strcpy(word,"#<"); - strcat(word,value); + strcat(word,symbol); asmlin("LDX", word); strcpy(word,"#>"); - strcat(word,value); + strcat(word,symbol); asmlin("LDY", word); - if (dlmtr) expect(dlmtr); +} + +/* Parse and Compile Address of Operator */ +void prsadr() +{ + prsvar(); + DEBUG("Parsing address of variable '%s'\n", value); + ACMNT(value); + prcadr(value); //Compile Address Reference } - -/* Parse function call in first term of expression * - * Function call may include term as an argument */ -void prsxfn() +/* Parse and Create Anonymous String */ +void prsstr() { - char fnname[255]; /*Function name*/ - DEBUG("Processing expression function call '%s'...\n", term); - strcpy(fnname, term); + DEBUG("Parsing anonymous string\n", 0); + strcpy(tmplbl, curlbl);//Save Current Label + newlbl(); //Generate Label Name + strcpy(word, curlbl); //and Use as Variable Name + value[0] = 0; //Use Variable Size 0 + setvar(VTCHAR); //Set Variable Name, Type, and Size + prsdts(); //Parse Data String + setdat(); //Set Variable Data + varcnt++; //Increment Variable Counter + prcadr(curlbl); //Compile Address Reference + strcpy(curlbl, tmplbl);//Restore Current Label +} + +/* Parse Additional Function Parameters */ +void prsfnp() +{ + if (look(',')) { + if (look('&')) + prsadr(); + else if (match('"')) + prsstr(); + else { + prstrm(); + asmlin("LDY", term); + if (look(',')) { + prsval(); + asmlin("LDX", value); + } + } + } +} + +/* Parse function call */ +void prsfnc() +{ + DEBUG("Processing Function Call '%s'...\n", term); + if (fnscnt >= MAXFNS) + ERROR("Maximum Function Call Depth Exceeded", 0, EXIT_FAILURE); + strcpy(fnstck[fnscnt++], term); skpchr(); //skip open paren CCMNT('('); if (look('&')) - prsadr(0); + prsadr(); + else if (match('"')) + prsstr(); else if (isvpre()) { - prstrm(); - asmlin("LDA", term); - } + prsxpr(0); + prsfnp(); + } expect(')'); - asmlin("JSR", fnname); + asmlin("JSR", fnstck[--fnscnt]); skpspc(); } @@ -107,7 +159,7 @@ void prsftm() strcpy(term, value); trmtxt = valtyp; if (trmtxt == FUNCTION) { - prsxfn(); //Parse Expression Function + prsfnc(); //Parse Expression Function return; } if (trmtxt == ARRAY) { @@ -153,8 +205,12 @@ void prsxpr(char trmntr) { DEBUG("Parsing expression\n", 0); skpspc(); - if (match('-')) - asmlin("LDA", "#$00"); //Handle Unary Minus + setsgn(FALSE); //Default Expression to Unsigned + if (match('-')) { + DEBUG("Processing unary minus", 0); + asmlin("LDA", "#$00"); //Handle Unary Minus + setsgn(TRUE); //Expression is Signed + } else prsftm(); //Parse First Term while (isoper()) diff --git a/expr.h b/expr.h index 9a4057e..c9dbd52 100644 --- a/expr.h +++ b/expr.h @@ -5,7 +5,13 @@ char term[255]; /*Term parsed from equation*/ int trmtxt; /*Term Type*/ +int expsgn; //Expression Contains Signed Term + +char fnstck[MAXFNS][VARLEN+1]; //Function Call Stack +int fnscnt; //Number of Functions in Stack + void prsidx(); //Parse Array Index void prstrm(); //Parse Term in Expression void prsxpr(char trmntr); //Parse Expression + diff --git a/label.c b/label.c index 96a1a8a..4dfeb9f 100644 --- a/label.c +++ b/label.c @@ -13,6 +13,29 @@ #include "parse.h" #include "label.h" +/* Find Last Label of Specified Type * + * Args: lbtype: Label type * + * Sets: tmplbl - Label name * + * Returns: Index into label table * + * (-1 if not found) */ +int lstlbl(int lbtype) +{ + int i; + DEBUG("Searching for label type %d\n", lbtype); + for (i = lblcnt - 1; i>-1; i--) + if (lbltyp[i] == lbtype) break; + DEBUG("Search produced label index %d\n", i); + if (i>=0) + strcpy(tmplbl, lblnam[i]); + return i; +} + +/* Set Block Flag for Last Label */ +void setblk(int blkflg) +{ + lblblk[lblcnt-1] = blkflg; +} + /* Set label for next line of * * Assembly Language Code * * to word */ @@ -21,8 +44,8 @@ void setlbl(char *lblset) DEBUG("Setting Label '%s''\n", lblset); if (strlen(lblasm) > 0) asmlin("",""); //Emit Block End Label on it's own line - if (strlen(word) > LABLEN) - ERROR("Label '%s' exceeds maximum size", word, EXIT_FAILURE); + if (strlen(lblset) > LABLEN) + ERROR("Label '%s' exceeds maximum size\n", word, EXIT_FAILURE); strcpy(lblasm, lblset); } @@ -35,27 +58,35 @@ void prslbl() } /* generate new label */ -void newlbl(int lbtype) +void newlbl() { sprintf(curlbl, LABFMT, lblnxt++); DEBUG("Generated new label '%s'\n", curlbl); - strcpy(lblnam[lblcnt++], curlbl); - lbltyp[lblcnt] = lbtype; } -/* set label to emit on next line and remove from stack */ -void lbllin() +/* Pop Label from Stack and Emit on Next Line */ +int poplbl() { int lbtype = lbltyp[--lblcnt]; - if (lbtype == 1) { - DEBUG("Ending Loop at Level %d'\n", lblcnt); - strcpy(endlbl, lblnam[lblcnt]); //Save End of Loop Label - asmlin("JMP", lblnam[--lblcnt]); //Jump to Beginning of Loop - setlbl(endlbl); //Set End of Loop Label - } + DEBUG("Popped label type %d\n", lbtype); + if (lbtype == LTLOOP) + asmlin("JMP", lblnam[lblcnt--]); //Jump to Beginning of Loop + if (lbtype == LTDO) + strcpy(loplbl, lblnam[lblcnt]); else setlbl(lblnam[lblcnt]); - DEBUG("Set label '%s' to emit on next line\n", lblasm); + inblck = lblblk[lblcnt-1]; + return lbtype; } +/* Push Label onto Stack * + * Args: lbltyp - Label type * + * Uses: curlbl - Label to push */ +void pshlbl(int lbtype) +{ + strcpy(lblnam[lblcnt], curlbl); + lbltyp[lblcnt] = lbtype; + lblblk[lblcnt++] = FALSE; + DEBUG("Pushed label '%s' onto stack\n", curlbl); +} diff --git a/label.h b/label.h index 3d37f50..e0780b1 100644 --- a/label.h +++ b/label.h @@ -2,18 +2,25 @@ * C02 Label Parsing, Generation, and Lookup Routines * ******************************************************/ +int inblck; //Multiline Block Flag + char curlbl[LABLEN+1]; //Most recently generated label -char endlbl[LABLEN+1]; //Label at end of block +char endlbl[LABLEN+1]; //End Label +char loplbl[LABLEN+1]; //Skip Increment Label +char skplbl[LABLEN+1]; //Skip Increment Label +char tmplbl[LABLEN+1]; //Temporary Label char lblnam[MAXLAB+1][LABLEN+1]; //Label Name Table int lbltyp[MAXLAB+1]; //Label Type +int lblblk[MAXLAB+1]; //Label Ends Program Block int lblcnt; //Number of Labels in stack int lblnxt; //Sequence of next label to be generated char lbltmp[LABLEN+1]; //Label Temporary Storage -enum ltypes {LTIF, LTLOOP, LTEND}; //Label Types +enum ltypes {LTIF, LTLOOP, LTEND, LTDO}; //Label Types -void prslbl(); //Parse Label From Code -void newlbl(); //Generate New Block Label -void lbllin(); //Pull Last Label and Emit on Next Line -void setlbl(); //Emit word as Label on Next Line +int lstlbl(int lbtype); //Find Last Label of Specified Type +void prslbl(); //Parse Label From Code +void newlbl(); //Generate New Block Label +int poplbl(); //Pull Last Label and Emit on Next Line +void setlbl(); //Emit word as Label on Next Line diff --git a/parse.c b/parse.c index 9bdfa8d..218c08a 100644 --- a/parse.c +++ b/parse.c @@ -15,22 +15,22 @@ char opstr[2]; //Operator as a String /* Various tests against nxtchr */ -int match(char c) {return (nxtchr == c);} -int inbtwn(char mn, char mx) {return nxtchr >= mn && nxtchr <= mx;} +int match(char c) {return TF(nxtchr == c);} +int inbtwn(char mn, char mx) {return TF(nxtchr >= mn && nxtchr <= mx);} int isprnt() {return isprint(nxtchr);} int isalph() {return isalpha(nxtchr);} int isanum() {return isalnum(nxtchr);} int isdec() {return inbtwn('0', '9');} -int ishexd() {return isdec() || inbtwn('A', 'Z');} +int ishexd() {return TF(isdec() || inbtwn('A', 'Z'));} int isbin() {return inbtwn('0', '1');} -int isnl() {return match('\n') || match('\r');} +int isnl() {return TF(match('\n') || match('\r'));} int isspc() {return isspace(nxtchr);} -int isnpre() {return isdec() || match('$') || match('%');} +int isnpre() {return TF(isdec() || match('$') || match('%'));} int isapos() {return match('\'');} -int iscpre() {return isnpre() || isapos();} -int isvpre() {return isalph() || iscpre();} -int isoper() {return (strchr("+-&|^", nxtchr)) ? TRUE : FALSE;} -int ispopr() {return (strchr("+-<>", nxtchr)) ? TRUE : FALSE;} +int iscpre() {return TF(isnpre() || isapos());} +int isvpre() {return TF(isalph() || iscpre());} +int isoper() {return TF(strchr("+-&|^", nxtchr));} +int ispopr() {return TF(strchr("+-<>", nxtchr));} /* if Word is s then return TRUE else return FALSE*/ int wordis(char *s) @@ -182,29 +182,37 @@ void expdef() char escape(char c) { + DEBUG("Escaping character '%c'\n", c); switch (c) { case 'r': return 0x0d; default: return c; } } -void get_string() { - char str_del, tmp_char; - int wrdlen = 0, esc_next = FALSE; +/* Get String */ + +void getstr() { + char strdel, tmpchr; + int wrdlen = 0, escnxt = FALSE; DEBUG("Parsing string\n", 0); - str_del = getnxt(); - while(!match(str_del)) { - if (esc_next) + strdel = getnxt(); //Get String Delimiter + CCMNT(strdel); + while(match(strdel) == escnxt) { + CCMNT(nxtchr); + if (escnxt) { word[wrdlen++] = escape(getnxt()); + escnxt = FALSE; + } else { if (match('\\')) - esc_next = TRUE; + escnxt = TRUE; else word[wrdlen++] = nxtchr; skpchr(); } } - skpchr(); + skpchr(); //Skip End Delimiter + CCMNT(strdel); word[wrdlen++] = 0; } @@ -343,15 +351,18 @@ int prsnum(int maxval) * valtyp - value type (CONSTANT) */ void prscon(int maxval) { - int constant = prsnum(maxval); + cnstnt = prsnum(maxval); valtyp = CONSTANT; if (maxval > 255) - sprintf(value, "#$%04X", constant); + sprintf(value, "#$%04X", cnstnt); else - sprintf(value, "#$%02X", constant); + sprintf(value, "#$%02X", cnstnt); DEBUG("Generated constant '%s'\n", value); } -int get_vartyp() + + +/* Get Value Type */ +int gettyp() { if (match('(')) return FUNCTION; else if (match('[')) return ARRAY; @@ -364,7 +375,7 @@ int get_vartyp() void prsvar() { getwrd(); - valtyp = get_vartyp(); + valtyp = gettyp(); if (valtyp != FUNCTION) chksym(word); strcpy(value, word); DEBUG("Parsed variable '%s'\n", value); diff --git a/parse.h b/parse.h index 3953249..e4cb1ef 100644 --- a/parse.h +++ b/parse.h @@ -2,6 +2,8 @@ * C02 Input File Parsing Routines * *************************************/ +#define TF(x) (x) ? TRUE : FALSE; + enum trmtxts {CONSTANT, VARIABLE, ARRAY, FUNCTION}; enum etypes {ETDEF, ETMAC}; //Definition Types @@ -11,6 +13,7 @@ int nxtptr; //Pointer to next character in nxtwrd char value[LINELEN]; //Term parsed from equation int valtyp; //Value Type char oper; //Arithmetic or Bitwise Operator +int cnstnt; //Value of Parsed Constant char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table char deftxt[MAXDEF+1][DEFLEN+1]; //Definition Text Table diff --git a/stmnt.c b/stmnt.c index 909f3c5..b214043 100644 --- a/stmnt.c +++ b/stmnt.c @@ -11,73 +11,17 @@ #include "asm.h" #include "parse.h" #include "vars.h" -#include "expr.h" #include "label.h" +#include "expr.h" #include "stmnt.h" -/* parse and compile if statement */ -void pif() { - DEBUG("Parsing IF statement '%c'\n", nxtchr); - expect('('); - newlbl(LTIF); - prscnd(')'); //Parse Conditional Expession -} -/* parse and compile else statement */ -void pelse() { - DEBUG("Parsing ELSE statement '%c'\n", nxtchr); - strcpy(lbltmp, lblasm); - lblasm[0] = 0; - newlbl(LTIF); - asmlin("JMP", curlbl); - strcpy(lblasm, lbltmp); -} - -/* parse and compile for statement */ -void pfor() { - ERROR("Unsupported statement FOR encountered",0, EXIT_FAILURE); -} - -/* parse and compile if statement */ -void pgoto() { - DEBUG("Parsing GOTO statement\n", 0); - getwrd(); - ACMNT(word); - asmlin("JMP", word); - expect(';'); -} - -/* parse and compile if statement */ -void pretrn() { - DEBUG("Parsing RETURN statement\n", 0); - if (!look(';')) - prsxpr(';'); - asmlin("RTS", ""); -} - -/* parse and compile while statement */ -void pwhile() { - DEBUG("Parsing WHILE statement '%c'\n", nxtchr); - expect('('); - newlbl(LTLOOP); //create Loop Label - setlbl(curlbl); - newlbl(LTEND); //Create End Label - prscnd(')'); //Parse Conditional Expession -} - -/* generate unimplemented statement error */ -void punimp() { - ERROR("Unimplemented statement '%s' encountered", word, EXIT_FAILURE); -} - - -/* Parse and compile assignment */ -void prsasn() +/* Process Assignment */ +void prcasn(char trmntr) { - DEBUG("Parsing assignment of variable '%s''\n", asnvar); - skpchr(); //skip equals sign - ACMNT("="); - prsxpr(';'); + DEBUG("Processing assignment of variable '%s'\n", asnvar); + expect('='); + prsxpr(trmntr); if (strlen(asnidx)) { asmlin("LDX", asnidx); strcat(asnvar,",X"); @@ -108,50 +52,22 @@ void prcpop() { } /* Parse Post Operator */ -void prspop() { +void prspop(char trmntr) { oper = getnxt(); CCMNT(oper); CCMNT(oper); DEBUG("Checking for post operation '%c'\n", oper); if (nxtchr == oper) { skpchr(); prcpop(); //Process Post-Op - expect(';'); + expect(trmntr); } else expctd("post operator"); } -/* Parse function call in first expression */ -void prsfnc() +/* Process Variable at Beginning of Statement */ +void prcvar(char trmntr) { - char fnname[255]; /*Function name*/ - DEBUG("Processing function call '%s'...\n", term); - strcpy(fnname, word); - skpchr(); //skip open paren - CCMNT('('); - skpspc(); - if (match(')')) //if no arguments - skpchr(); // skip close paren - else { //otherwise - if (look('&')) { - prsadr(')'); - } - else - prsxpr(')'); //parse expression - } - asmlin("JSR", fnname); - expect(';'); -} - -/* parse and compile identifier (variable or function call) */ -void prssym() -{ - DEBUG("Parsing Identifier %s\n", word); - valtyp = get_vartyp(); - if (valtyp == FUNCTION) { - prsfnc(); //Parse Function Call - return; - } chksym(word); strcpy(asnvar, word); //sav variable to assign to if (valtyp == ARRAY) { @@ -161,15 +77,180 @@ void prssym() else asnidx[0] = 0; if (ispopr(nxtchr)) - prspop(); //Parse Post Operator + prspop(trmntr); //Parse Post Operator else - { - skpspc(); - if (match('=')) - prsasn(); //Parse Assignment - else - expctd("="); - } + prcasn(trmntr); +} + +/* Begin Program Block */ +void bgnblk() +{ + DEBUG("Begining program block\n", 0); + inblck = look('{'); + setblk(inblck); +} + +/* Parse and Compile and Assignment */ +void prsasn(char trmntr) +{ + getwrd(); //Get Variable to be Assigned + ACMNT(word); + prcvar(trmntr); +} + +/* parse and compile 'break'/'continue' statement */ +void pbrcnt(int lbtype) { + DEBUG("Parsing BREAK/CONTINUE statement\n", 0); + if (lstlbl(lbtype) < 0) + ERROR("Break/continue statement outside of loop\n", 0, EXIT_FAILURE); + DEBUG("Found Label '%s'\n", tmplbl); + asmlin("JMP", tmplbl); + expect(';'); +} + +/* parse and compile 'do' statement */ +void pdo() { + DEBUG("Parsing DO statement '%c'\n", nxtchr); + newlbl(); //Create Do Loop Label + pshlbl(LTDO); //Push onto Stack + setlbl(curlbl); //Set Label to Emit on Next Line + bgnblk(); //Check For and Begin Block +} + +/* parse and compile 'while' after 'do' statement */ +void pdowhl() { + DEBUG("Parsing WHILE after DO '%c'\n", nxtchr); + getwrd(); //Check for While + ACMNT(word); + if (!wordis("while")) + expctd("while statement"); + expect('('); + newlbl(); //Create Skip Label + prscnd(')', FALSE); //Parse Conditional Expession + asmlin("JMP", loplbl); //Emit Jump to Beginning of Loop + setlbl(curlbl); //and Set Label to Emit on Next Line + expect(';'); //Check for End of Statement +} + + +/* parse and compile for statement */ +void pfor() { + DEBUG("Parsing FOR statement '%c'\n", nxtchr); + expect('('); + prsasn(';'); //Process Initial Assignment + newlbl(); //Create Temporary Label + setlbl(curlbl); //Set to Emit on Next Line + strcpy(tmplbl, curlbl); //and Save it + newlbl(); //Create End Label + pshlbl(LTEND); //and Push onto Stack + strcpy(endlbl, curlbl); //and Save it + newlbl(); //Create Loop Label + strcpy(loplbl, curlbl); //and Save it + pshlbl(LTLOOP); //and Push onto Stack + newlbl(); //Create Skip Increment Label + strcpy(skplbl, curlbl); //and Save it + prscnd(';', TRUE); //Parse Conditional Expession + asmlin("JMP", endlbl); //Jump over Increment + setlbl(loplbl); //Set to Emit on Next Line + prsasn(')'); //Parse Increment Assignment + asmlin("JMP", tmplbl); //Jump to Conditional + setlbl(skplbl); //Emit Label at Start of Loop + bgnblk(); //Check For and Begin Block +} + +/* parse and compile if statement */ +void pif() { + DEBUG("Parsing IF statement '%c'\n", nxtchr); + expect('('); + newlbl(); //Create New Label + pshlbl(LTIF); //Push Onto Stack + prscnd(')', FALSE); //Parse Conditional Expession + bgnblk(); //Check For and Begin Block +} + +/* parse and compile else statement */ +void pelse() { + DEBUG("Parsing ELSE statement '%c'\n", nxtchr); + strcpy(lbltmp, lblasm); + lblasm[0] = 0; + newlbl(); //Create New Label + pshlbl(LTIF); //Push Onto Stack + asmlin("JMP", curlbl); + strcpy(lblasm, lbltmp); + bgnblk(); //Check For and Begin Block +} + +/* parse and compile if statement */ +void pgoto() { + DEBUG("Parsing GOTO statement\n", 0); + getwrd(); + ACMNT(word); + asmlin("JMP", word); + expect(';'); +} + +/* parse and compile if statement */ +void pretrn() { + DEBUG("Parsing RETURN statement\n", 0); + if (!look(';')) + prsxpr(';'); + asmlin("RTS", ""); +} + +/* parse and compile while statement */ +void pwhile() { + DEBUG("Parsing WHILE statement '%c'\n", nxtchr); + expect('('); + newlbl(); //Create End Label + pshlbl(LTEND); //Push onto Stack + strcpy(endlbl, curlbl); //and Save it + newlbl(); //create Loop Label + setlbl(curlbl); //Set to Emit on Next Line + pshlbl(LTLOOP); //Push onto Stack + newlbl(); //Create Conditional Skip Label + prscnd(')', TRUE); //Parse Conditional Expession + asmlin("JMP", endlbl); //Emit Jump to End of Loop + setlbl(curlbl); //and Set Label to Emit on Next Line + bgnblk(); //Check For and Begin Block +} + +/* generate unimplemented statement error */ +void punimp() { + ERROR("Unimplemented statement '%s' encountered\n", word, EXIT_FAILURE); +} + + +/* Parse Function Call as Statement */ +void prsfns() +{ + strcpy(term, word); //Copy Function Name + prsfnc(); //Parse Function Call + expect(';'); + return; +} + +/* parse and compile identifier (variable or function call) */ +void prssym() +{ + DEBUG("Parsing Identifier %s\n", word); + valtyp = gettyp(); + if (valtyp == FUNCTION) + prsfns(); //Parse Statement Function Call + else + prcvar(';'); //Parse Assignment +} + +/* End Program Block * + * Args: blkflg: End of Multiline Block */ +void endblk(int blkflg) +{ + DEBUG("Ending program block with flag %d\n", blkflg); + skpchr(); //Skip '}'; + DEBUG("Found inblck set to %d\n", inblck); + if (inblck != blkflg) + ERROR("Encountered '}' without matching '{'\n",0,EXIT_FAILURE); + if (poplbl() == LTDO) + pdowhl(); //Parse While at End of Do Loop } /* parse and compile program statement */ @@ -180,6 +261,10 @@ void pstmnt() prslbl(); //Parse Label return; } + if (wordis("do")) { + pdo(); + return; + } if (wordis("if")) { pif(); return; @@ -193,17 +278,22 @@ void pstmnt() return; } if (wordis("for")) { - punimp(); + pfor(); return; } + else if (wordis("break")) + pbrcnt(LTEND); + else if (wordis("continue")) + pbrcnt(LTLOOP); else if (wordis("goto")) pgoto(); else if (wordis("return")) pretrn(); else prssym(); - if (lblcnt) { - lbllin(); + if (lblcnt && !inblck) { + if (poplbl() == LTDO) + pdowhl(); //Parse While at End of Do Loop } } diff --git a/stmnt.h b/stmnt.h index 574eecd..4c10d3a 100644 --- a/stmnt.h +++ b/stmnt.h @@ -2,7 +2,8 @@ * C02 Statement Compiling Routines * ************************************/ -char asnvar[VARLEN+1]; /*Assigned Variable Name*/ -char asnidx[VARLEN+1] ; /*Assigned Variable Index*/ - +char asnvar[VARLEN+1]; //Assigned Variable Name +char asnidx[VARLEN+1] ; //Assigned Variable Index +void endblk(); //End Program Block +void pstmnt(); //Parse and Compile Program Statement diff --git a/vars.c b/vars.c index 9729f96..503ebda 100644 --- a/vars.c +++ b/vars.c @@ -45,7 +45,6 @@ void chksym(char *name) ERROR("Undeclared variable '%s' encountered\n", word, EXIT_FAILURE); } - /* Check for Array specifier and get size * * Sets: value - array size (as string) * * "" if not an array */ @@ -76,36 +75,64 @@ void prsdtc() void prsdts() { dtype = DTSTR; - get_string(); + getstr(); strcpy(value, word); DEBUG("Parsed Data String '%s'\n", value); } -/* Parse and store variable data * +/* Store variable data * + * Uses: value - Data to store * * Sets: datvar[] - Variable Data * * datlen[] - Data Length */ +void setdat() +{ + int i; + if (dtype == DTBYTE) { + DEBUG("Setting variable data to '%d'\n", cnstnt); + dlen = 1; + datvar[dsize++] = cnstnt; + } + else { + DEBUG("Setting variable data to '%s'\n", value); + dlen = strlen(value); + for (i=0; i