Expression evaluation
[nethome.git] / src / ev.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <assert.h>
5
6 #define BUFSIZE 100
7
8 char *arg;
9
10 int istack[BUFSIZE];
11 char opstack[BUFSIZE];
12 int istackp,opstackp;
13
14 static char lex(int *ip)
15 {
16 char c;
17 long l;
18
19         while (isspace(*arg)) arg++;
20         switch (*arg) {
21                 case 0: case '+': case '-': case '*': case '/': case '(': case ')':
22                         c=*arg;
23                         if (c) arg++;
24                         return(c);
25                 case '0' ... '9':
26                         l=strtol(arg,&arg,10);
27                         *ip=l;
28                         return 'n';
29                 default:
30                         fprintf(stderr,"Invalid characted in string: %s\n",arg);
31                         exit(EXIT_FAILURE);
32                 }
33 }
34
35 static int oppri(char op)
36 {
37         switch (op) {
38                 case 0: return(0);
39                 case '+': case '-': return (10);
40                 case '*': case '/': return (20);
41                 case '(': return (2);
42                 case ')': return (5);
43                 default: assert(0);
44                 }
45 }
46
47 static void evalit(void)
48 {
49         assert(opstackp);
50         if (istackp<2) {
51                 fprintf(stderr,"2 arguments for operator required!\n");
52                 exit(EXIT_FAILURE);
53                 }
54         istackp--;
55         switch (opstack[--opstackp]) {
56                 case '+': istack[istackp-1]+=istack[istackp]; break;
57                 case '-': istack[istackp-1]-=istack[istackp]; break;
58                 case '*': istack[istackp-1]*=istack[istackp]; break;
59                 case '/': 
60                         if (!istack[istackp]) {
61                                 fprintf(stderr,"Division of %d by zero not supported!\n",istack[istackp-1]);
62                                 exit(EXIT_FAILURE);
63                                 }
64                         istack[istackp-1]/=istack[istackp];
65                         break;
66                 }
67 }
68
69 static void pushop(char op)
70 {
71 int mypri=oppri(op);
72         while (opstackp && op!='(' && oppri(opstack[opstackp-1])>=mypri)
73                 evalit();
74         if (!op) return;
75         if (op==')') {
76                 if (!opstackp || opstack[opstackp-1]!='(') {
77                         fprintf(stderr,"Not enough content for brackets-inside space!\n");
78                         exit(EXIT_FAILURE);
79                         }
80                 opstackp--;
81                 return;
82                 }
83         assert(opstackp<BUFSIZE);
84         opstack[opstackp++]=op;
85 }
86
87 static void process(void)
88 {
89 char lastop=0,op;
90 int curi;
91
92         istackp=opstackp=0;
93         for (;;) switch ((op=lex(&curi))) {
94                 case 'n':
95                         if (lastop=='n') {
96                                 fprintf(stderr,"Two successive numbers not permitted!\n");
97                                 exit(EXIT_FAILURE);
98                                 }
99                         assert(istackp<BUFSIZE);
100                         istack[istackp++]=curi;
101                         break;
102                 case '(':
103                         if (lastop=='n') {
104                                 fprintf(stderr,"Open-bracket not permitted after number!\n");
105                                 exit(EXIT_FAILURE);
106                                 }
107                         pushop(op);
108                         break;
109                 case '+': case '-': case '*': case '/': case ')': pushop(op); break;
110                 case 0:
111                         pushop(op);
112                         if (istackp!=1||opstackp) {
113                                 fprintf(stderr,"Machine not in sane state on the end of expression, ints=%d,ops=%d!\n",istackp,opstackp);
114                                 exit(EXIT_FAILURE);
115                                 }
116                         printf("%d\n",istack[0]);
117                         return;
118                 default: assert(0);
119                 }
120 }
121
122 int main(int argc,char **argv)
123 {
124 int argn;
125         for (argn=1;argn<argc;argn++) {
126                 arg=argv[argn];
127                 process();
128                 }
129         return(EXIT_SUCCESS);
130 }