On our second day, we analyze each token, determine if it is a number or an operator.
/ #include#include #include #include /* day 2 - tokenizing. */ #define MAXBUFFSIZE 128 char BUFF[MAXBUFFSIZE]; // input string buffer. char delims[] = " \t\n"; double fval = 0; enum Dtypes{ERROR, FNUM, FADD,FSUB, FMUL, FDIV, FPRINT, QUIT}; int lexer(char* tok) { int n = strlen(tok); char c = *tok; if (n == 1){ if (c == '+') return FADD; if (c == '-') return FSUB; if (c == '*') return FMUL; if (c == '/') return FDIV; if (c == '.') return FPRINT; } if (getnumber(tok) == 0) { return FNUM; }; if (strcmp(tok, "quit")== 0) { return QUIT; } return ERROR; } int checknumber(char *s) { /* Description Returns 0 if s is a double real number, otherwise nonzero value. It is assumed that leading and trailing white spaces are removed from s. 1 illegal character after '.' 2 illegal starting character. 3 illegal character after 'e' 4 expected a '\0' 5 empty string. */ char* t = s; /* empty string */ if (*t == '\0') return 5; /* starts with an optional sign? */ if ((*t == '-') || (*t == '+'))t++; // block of digits starting with a digit if (isdigit(*t)) { /* starts with a digit? */ while (isdigit(*t)) t++; if (*t == '.'){ /* a block starting with a .? */ t++; if (*t == '\0') return 0; // a number ending with a '.' while (isdigit(*t)) t++; } }else if (*t == '.'){ /* a number starting with a .? */ t++; if (! isdigit(*t)) return 1; while (isdigit(*t)) t++; } else return 2; /* illegal starting value! */ /* optional exponent */ if (tolower(*t) == 'e') { t++; if ((*t == '-') || (*t == '+')) { t++; } if (!isdigit(*t))return 3; while isdigit(*t) t++; } /* illegal character */ if (*t != '\0') return 4; return 0; }; int getnumber(char *s){ int i = checknumber(s); if (i==0) { fval = atof(s); } return i; }; int main() { int i =0; int exitnow = 0; while (1) { fputs(">>", stdout); fgets(BUFF, MAXBUFFSIZE-1, stdin); char *tok = strtok(BUFF, delims); while (tok) { printf("%d %s", ++i, tok); if (tok == NULL) break; // process token. int dtype = lexer(tok); switch(dtype) { case FNUM: printf("FNUM %f\n",fval); break; case FADD: case FSUB: case FMUL: case FDIV: case FPRINT: printf("[%s]\n", tok); break; case QUIT: printf("quitting...\n"); exitnow = 1; break; case ERROR: printf("ERROR\n"); break; }; tok = strtok(NULL, delims); } if (exitnow) { puts("Thanks for using easyforth!\n"); break; } }; return 0; };
Here is a compilation-run of our recent program version.
toto@toto-VirtualBox:~/Projects/forth$ gcc day2-easyforth.c toto@toto-VirtualBox:~/Projects/forth$ ./a.out >>-1.2345 320 7 + * - 1 -1.2345FNUM -1.234500 2 320FNUM 320.000000 3 7FNUM 7.000000 4 +[+] 5 *[*] 6 -[-] >>quit 7 quitquitting... Thanks for using easyforth!
In the next installment we add a simple working calculator.
No comments:
Post a Comment