Expression evaluation
authorshort <>
Mon, 9 Jul 2001 23:03:00 +0000 (23:03 +0000)
committershort <>
Mon, 9 Jul 2001 23:03:00 +0000 (23:03 +0000)
src/ev.c [new file with mode: 0644]

diff --git a/src/ev.c b/src/ev.c
new file mode 100644 (file)
index 0000000..f8f8d95
--- /dev/null
+++ b/src/ev.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+
+#define BUFSIZE 100
+
+char *arg;
+
+int istack[BUFSIZE];
+char opstack[BUFSIZE];
+int istackp,opstackp;
+
+static char lex(int *ip)
+{
+char c;
+long l;
+
+       while (isspace(*arg)) arg++;
+       switch (*arg) {
+               case 0: case '+': case '-': case '*': case '/': case '(': case ')':
+                       c=*arg;
+                       if (c) arg++;
+                       return(c);
+               case '0' ... '9':
+                       l=strtol(arg,&arg,10);
+                       *ip=l;
+                       return 'n';
+               default:
+                       fprintf(stderr,"Invalid characted in string: %s\n",arg);
+                       exit(EXIT_FAILURE);
+               }
+}
+
+static int oppri(char op)
+{
+       switch (op) {
+               case 0: return(0);
+               case '+': case '-': return (10);
+               case '*': case '/': return (20);
+               case '(': return (2);
+               case ')': return (5);
+               default: assert(0);
+               }
+}
+
+static void evalit(void)
+{
+       assert(opstackp);
+       if (istackp<2) {
+               fprintf(stderr,"2 arguments for operator required!\n");
+               exit(EXIT_FAILURE);
+               }
+       istackp--;
+       switch (opstack[--opstackp]) {
+               case '+': istack[istackp-1]+=istack[istackp]; break;
+               case '-': istack[istackp-1]-=istack[istackp]; break;
+               case '*': istack[istackp-1]*=istack[istackp]; break;
+               case '/': 
+                       if (!istack[istackp]) {
+                               fprintf(stderr,"Division of %d by zero not supported!\n",istack[istackp-1]);
+                               exit(EXIT_FAILURE);
+                               }
+                       istack[istackp-1]/=istack[istackp];
+                       break;
+               }
+}
+
+static void pushop(char op)
+{
+int mypri=oppri(op);
+       while (opstackp && op!='(' && oppri(opstack[opstackp-1])>=mypri)
+               evalit();
+       if (!op) return;
+       if (op==')') {
+               if (!opstackp || opstack[opstackp-1]!='(') {
+                       fprintf(stderr,"Not enough content for brackets-inside space!\n");
+                       exit(EXIT_FAILURE);
+                       }
+               opstackp--;
+               return;
+               }
+       assert(opstackp<BUFSIZE);
+       opstack[opstackp++]=op;
+}
+
+static void process(void)
+{
+char lastop=0,op;
+int curi;
+
+       istackp=opstackp=0;
+       for (;;) switch ((op=lex(&curi))) {
+               case 'n':
+                       if (lastop=='n') {
+                               fprintf(stderr,"Two successive numbers not permitted!\n");
+                               exit(EXIT_FAILURE);
+                               }
+                       assert(istackp<BUFSIZE);
+                       istack[istackp++]=curi;
+                       break;
+               case '(':
+                       if (lastop=='n') {
+                               fprintf(stderr,"Open-bracket not permitted after number!\n");
+                               exit(EXIT_FAILURE);
+                               }
+                       pushop(op);
+                       break;
+               case '+': case '-': case '*': case '/': case ')': pushop(op); break;
+               case 0:
+                       pushop(op);
+                       if (istackp!=1||opstackp) {
+                               fprintf(stderr,"Machine not in sane state on the end of expression, ints=%d,ops=%d!\n",istackp,opstackp);
+                               exit(EXIT_FAILURE);
+                               }
+                       printf("%d\n",istack[0]);
+                       return;
+               default: assert(0);
+               }
+}
+
+int main(int argc,char **argv)
+{
+int argn;
+       for (argn=1;argn<argc;argn++) {
+               arg=argv[argn];
+               process();
+               }
+       return(EXIT_SUCCESS);
+}