/* file simple-forth-0.0.2.c author Dr. Ernesto P. Adorio UPDEPP (University of the Philippines, Extension Program in Pampanga Clarkfield, Pampanga email ernesto.adorio@gmail.com version 0.0.1 January 14, 2012 basic interpreter. 0.0.2 January 16, 2012 interactivity added. */ #include#include #include #include enum {E_STACKUNDERFLOW} ERRCODES; enum {L_EMIT, L_DOT,L_DOTT, L_SPACE, L_ADD, L_SUB, L_MUL, L_DIV, L_DROP, L_INT32, L_CR, L_BYE, L_EOS,L_ERROR} OPCODES; const char *stdwords[] = { "emit", ".", ".t", "space", "+", "-", "*", "/", "drop", "int32", "cr", "bye", "\n", }; #define MAXSTKLEN 32 #define MAXFSTKLEN 32 #define MAXTOKENLEN 128 int LENSTDWORDS = sizeof(stdwords)/sizeof(stdwords[0]); char LINEBUFFER[256]; char *goodbye= "bye"; int ERRCODE = 0; int SP = -1; /* stack pointer index */ int stack[MAXSTKLEN]; double fstack[MAXFSTKLEN]; int opcode; char *tokstart; char *tokend; int eval(int opcode) { /* Evaluate opcode */ switch (opcode){ case L_EMIT: //@@printf("opcode L_EMIT %s %d\n", tokstart, SP); if (SP < 0) { ERRCODE = E_STACKUNDERFLOW; } else { printf ("%c", stack[SP--]); } break; case L_DOT: //@@printf("opcode L_EMIT %s %d\n", tokstart, SP); if (SP < 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); } else { printf ("%d", stack[SP--]); } break; case L_DOTT: //@@printf("opcode L_EMIT %s %d\n", tokstart, SP); if (SP < 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); } else { printf ("%d", stack[SP]); } break; case L_SPACE: printf ("%c", 32); break; case L_ADD: //printf("opcode L_ADD %s\n", tokstart); if (SP <= 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); break; } stack[SP-1] += stack[SP]; SP--; break; case L_SUB: //printf("opcode L_SUB %s\n", tokstart); if (SP <= 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); break; } stack[SP-1] -= stack[SP]; SP--; break; case L_MUL: //printf("opcode L_MUL %s\n", tokstart); if (SP <= 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); break; } stack[SP-1] *= stack[SP]; SP--; break; case L_DIV: //printf("opcode L_DIV %s\n", tokstart); if (SP <= 0) { ERRCODE = E_STACKUNDERFLOW; printf("%s", "underflow!"); break; } stack[SP-1] /= stack[SP]; SP--; break; case L_INT32: //printf("opcode L_INT32 %s\n",tokstart); stack[++SP]= atoi(tokstart); break; case L_DROP: //printf("opcode L_DROP %s \n", tokstart); SP=SP -1; break; case L_CR: // printf("opcode L_CR %s \n", tokstart); printf("\n"); break; default: ; break; } } void nexttoken() { tokstart = tokend; //@ printf("inside nexttoken [%s]", tokstart); /* ignore leading white spaces */ while (isspace(*tokstart)) tokstart++; /* find terminating space of end of string */ tokend = tokstart; while (!isspace(*tokend) && *tokend != '\0') tokend++; /* string terminator */ if (*tokend != '\0') { *tokend = '\0'; tokend ++; } /* get opcode */ opcode = -1; if (tokend == tokstart) { opcode = L_EOS; return; } /*@@@ printf("token [%s]\n", tokstart); */ for (int i =0; i < LENSTDWORDS; i++) { if (strcmp(stdwords[i], tokstart) == 0){ opcode = i; //@ printf("opcde [%d]", opcode); break; } } if (opcode == -1){ opcode = L_INT32; } } int main(){ while (1) { // read string. printf("> "); if (fgets(LINEBUFFER, 250, stdin)!= NULL) { tokend=LINEBUFFER; // @@@ printf("input string [%s]", LINEBUFFER); } else { tokend= goodbye; } // eval // printf ("Entering evaluation loop.\n"); while (1) { nexttoken(); //@ printf ("[%d] %s", opcode, tokstart); eval(opcode); if (opcode== L_BYE) { //printf ("%% opcode is L_BYE"); return 0; } if (opcode ==L_EOS) { break; } if (ERRCODE != 0) { printf("ERRORCODE [%d]", ERRCODE); break; }; } // loop back unless BYE! } printf("\n"); return 0; }
Save file to simple-forth-0.0.2.c, then compile it using the following command:
: gcc simple-forth.c -std=c99 -o simple-forth-0.0.2
Then run it by issuing ./simple-forth00.0.2 Here is an uninspired terminal run:
> 2 3 - 1 + . 0> 56 emit 8> 97 emit a> 64 emit @> > > bye
Next, we will add add a floating point computation capabilities using a separate stack.
No comments:
Post a Comment