For today, we add most of the standard C math library functions to the basic four function calculator oriented interpreter.
#includeHere is a simple compilation and execution run.#include #include #include #include /* day 1 - basic day 2 - tokenizing. day 3 - basic function calculator. day 4 - more math functions. November 15, 2014. */ #define MAXBUFFSIZE 128 #define MAXFSTACKSIZE 32 double FSTACK[MAXFSTACKSIZE]; int FP = 0; // index to FSTACK; char BUFF[MAXBUFFSIZE]; // input string buffer. char delims[] = " \t\n"; // delimiters. double fval = 0.0; enum Dtypes{ERROR, FNUM, FADD,FSUB, FMUL, FDIV, FPRINT, FPI, FE, FABS,FNEG, FEXP, FLN, FLOG10, FSIN, FCOS, FTAN, FSINH, FCOSH, FTANH, FDOWN, FUP, ECR, 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; } // A simplistic individual brute force string comparisons if (strcmp(tok, "pi")==0) return FPI; if (strcmp(tok, "e")==0) return FE; if (strcmp(tok, "abs")==0) return FABS; if (strcmp(tok, "neg")==0) return FNEG; if (strcmp(tok, "exp")==0) return FEXP; if (strcmp(tok, "ln")==0) return FLN; if (strcmp(tok, "log10")==0) return FLOG10; if (strcmp(tok, "sin")==0) return FSIN; if (strcmp(tok, "cos")==0) return FCOS; if (strcmp(tok, "tan")==0) return FTAN; if (strcmp(tok, "sinh")==0) return FSINH; if (strcmp(tok, "cosh")==0) return FCOSH; if (strcmp(tok, "tanh")==0) return FTANH; if (strcmp(tok, "fdown")==0) return FDOWN; if (strcmp(tok, "fup")==0) return FUP; if (strcmp(tok, "quit")== 0) { return QUIT; }; if (strcmp(tok, "ecr") == 0) { return ECR; } if (getnumber(tok) == 0) { return FNUM; }; 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) { // basic floating point operations. case FNUM: FSTACK[++FP]= fval; break; case FADD: FP--; FSTACK[FP]+= FSTACK[FP+1]; break; case FSUB: FP--; FSTACK[FP]-= FSTACK[FP+1]; break; case FMUL: FP--; FSTACK[FP]*= FSTACK[FP+1]; break; case FDIV: FP--; FSTACK[FP]/= FSTACK[FP+1]; break; case FPRINT: printf("%f", FSTACK[FP]); break; case ECR: // prints new line printf("\n"); break; // Constants and One argument math functions. case FPI: // constant pi FSTACK[++FP] = M_PI; break; case FE: // constant e FSTACK[++FP] = exp(1.0); break; case FABS: FSTACK[FP] = fabs(FSTACK[FP]); break; case FNEG: FSTACK[FP] = -FSTACK[FP]; break; case FEXP: FSTACK[FP] = exp(FSTACK[FP]); break; case FLN: FSTACK[FP] = log(FSTACK[FP]); break; case FLOG10:FSTACK[FP] = log10(FSTACK[FP]); break; case FSIN: FSTACK[FP] = sin(FSTACK[FP]); break; case FCOS: FSTACK[FP] = cos(FSTACK[FP]); break; case FTAN: FSTACK[FP] = tan(FSTACK[FP]); break; case FSINH: FSTACK[FP] = sinh(FSTACK[FP]); break; case FCOSH: FSTACK[FP] = cosh(FSTACK[FP]); break; case FTANH: FSTACK[FP] = tanh(FSTACK[FP]); break; case FUP: if (FP < MAXFSTACKSIZE-1) FP++; break; case FDOWN: if (FP) FP--; break; case ERROR: printf("ERROR\n"); break; case QUIT: printf("quitting...\n"); exitnow = 1; break; }; tok = strtok(NULL, delims); } if (exitnow) { puts("Thanks for using easyforth!\n"); break; } }; return 0; };
toto@toto-VirtualBox:~/Projects/forth$ gcc day4-easyforth.c -lm toto@toto-VirtualBox:~/Projects/forth$ ./a.out >>pi 2 / sin . 1.000000>>1.0 exp . 2.718282>>