#include #include #include #include #include "calc.h" void usage (char * p) { fprintf (stderr, "usage: %s 'expression'\n", p); fprintf (stderr, "Note: Don't forget the sinlge quotes ('(3+4)')\n"); exit (1); } #define STACKLEN 100000 char opstack[STACKLEN]; int opos = 0; int valstack[STACKLEN]; int vpos = 0; #define ANY 1 #define NUMBER 2 #define OP 3 #define PARENOPEN 4 #define PARENCLOSE 5 int state = ANY; int depth = 0; void pop () { assert (opos > 0); opos--; assert (vpos >= 2); vpos--; switch (opstack[opos]) { case '*': valstack[vpos-1] = domul (valstack[vpos-1], valstack[vpos]); break; case '/': valstack[vpos-1] = dodiv (valstack[vpos-1], valstack[vpos]); break; case '+': valstack[vpos-1] = doadd (valstack[vpos-1], valstack[vpos]); break; case '-': valstack[vpos-1] = dosub (valstack[vpos-1], valstack[vpos]); break; default: assert (0); } } int main (int argc, char ** argv) { int val, count; char * p = argv[1]; char ch, ch2; if (argc != 2) usage (argv[0]); while (*p) { if (isspace ((int)(*p))) { p++; continue; } if ((state != NUMBER) && (state != PARENCLOSE) && (sscanf (p, "%d%n", &val, &count) >= 1)) { assert (vpos < STACKLEN); state = NUMBER; valstack[vpos] = val; vpos++; p += count; continue; } if (sscanf (p, "%c", &ch) == 1) { p++; switch (ch) { case '*': case '+': case '/': case '-': assert ((state == NUMBER) || (state == ANY) || (state == PARENCLOSE)); state = OP; break; case '(': assert ((state == ANY) || (state == OP) || (state == PARENOPEN)); state = PARENOPEN; depth++; break; case ')': assert (depth); depth--; assert ((state == NUMBER) || (state == PARENCLOSE)); state = PARENCLOSE; break; } if ((ch == '+') || (ch == '-')) { while (opos > 0) { ch2 = opstack[opos-1]; if (ch2 == '(') break; pop (); } assert (opos < STACKLEN); opstack[opos] = ch; opos++; } else if ((ch == '/') || (ch == '*')) { while (opos > 0) { ch2 = opstack[opos-1]; if (ch2 == '(') break; if ((ch2 == '+') || (ch2 == '-')) break; pop (); } assert (opos < STACKLEN); opstack[opos] = ch; opos++; } else if (ch == ')') { assert (opos > 0); while (opstack[opos-1] != '(') { pop (); assert (opos > 0); } opos--; } else if (ch == '(') { assert (opos < STACKLEN); opstack[opos] = ch; opos++; } continue; } assert (0); } while (opos) pop (); assert (vpos == 1); printf ("%s=%d\n", argv[1], valstack[0]); return 0; }