0
|
1 /*
|
|
2 Simple Calculator
|
|
3 $Id$
|
|
4 */
|
|
5
|
|
6 #include <stdio.h>
|
|
7
|
|
8 char *ptr,*last_ptr;
|
24
|
9 long value,lvalue;
|
|
10 long last_token;
|
|
11 long variable[48];
|
0
|
12
|
24
|
13 static long expr();
|
|
14 static long aexpr();
|
|
15 static long mexpr();
|
|
16 static long term();
|
0
|
17
|
|
18
|
|
19 #define T_EQUAL (0x100|'=')
|
|
20 #define T_NEQUAL (0x100|'!')
|
|
21 #define T_LSHIFT (0x100|'<')
|
|
22 #define T_RSHIFT (0x100|'>')
|
|
23
|
|
24 static void
|
|
25 line_skip()
|
|
26 {
|
|
27 while(*ptr++);
|
|
28 last_ptr = ptr;
|
|
29 last_token = EOF;
|
|
30 }
|
|
31
|
|
32 static void
|
|
33 error(description)
|
|
34 char *description;
|
|
35 {
|
|
36 fprintf(stderr,"%s on %s\n",description,last_ptr);
|
|
37 line_skip();
|
|
38 }
|
|
39
|
24
|
40 static long
|
0
|
41 token()
|
|
42 {
|
24
|
43 long c,d;
|
0
|
44
|
|
45 last_ptr = ptr; /* for error position */
|
|
46 c= *ptr;
|
|
47 while(c<=' ' && c) {
|
|
48 c = *++ptr;
|
|
49 }
|
|
50 if(!c) {
|
|
51 last_token = EOF;
|
|
52 return last_token;
|
|
53 }
|
|
54 ptr++;
|
|
55 if ('/'==c && ('/'== *ptr || '*'== *ptr)) { /* comment */
|
|
56 line_skip();
|
|
57 return EOF;
|
|
58 }
|
|
59 if('1'<=c && c<='9') { /* Decimal */
|
|
60 d = c-'0';
|
17
|
61 while((c= *ptr++)) {
|
0
|
62 if('0'<=c && c<='9') {
|
|
63 d = d*10 + (c - '0');
|
|
64 } else {
|
|
65 break;
|
|
66 }
|
|
67 }
|
|
68 c && ptr--;
|
|
69 value = d;
|
|
70 last_token = '0';
|
|
71 return last_token;
|
|
72 } else if ('0'==c && 'x'== *ptr) { /* Hex */
|
|
73 ptr++;
|
|
74 d = 0;
|
17
|
75 while((c= *ptr++)) {
|
0
|
76 if('0'<=c && c<='9') {
|
|
77 d = d*16 + (c - '0');
|
|
78 } else if('a'<=c && c<='f') {
|
|
79 d = d*16 + (c - 'a' + 10);
|
|
80 } else if('A'<=c && c<='F') {
|
|
81 d = d*16 + (c - 'a' + 10);
|
|
82 } else {
|
|
83 break;
|
|
84 }
|
|
85 }
|
|
86 c && ptr--;
|
|
87 value = d;
|
|
88 last_token = '0';
|
|
89 return last_token;
|
|
90 } else if ('0'==c) { /* Octal */
|
|
91 d = c-'0';
|
17
|
92 while((c= *ptr++)) {
|
0
|
93 if('0'<=c && c<='7') {
|
|
94 d = d*8 + (c - '0');
|
|
95 } else {
|
|
96 break;
|
|
97 }
|
|
98 }
|
|
99 c && ptr--;
|
|
100 value = d;
|
|
101 last_token = '0';
|
|
102 return last_token;
|
|
103 } else if ('\''==c) { /* Ascii */
|
|
104 d = 0;
|
17
|
105 while((c= *ptr++)) {
|
0
|
106 if('\''!=c && c<=0x7f) {
|
|
107 d = d*256 + c;
|
|
108 } else if(c>=0x80 && *ptr) {
|
|
109 d = d*256*256 + c*256 + *ptr++;
|
|
110 } else {
|
|
111 break;
|
|
112 }
|
|
113 }
|
|
114 c && ptr--;
|
|
115 value = d;
|
|
116 last_token = '0';
|
|
117 return last_token;
|
|
118 } else if (('a'<=c && c<='z') || /* variable */
|
|
119 ('A'<=c && c<='Z')) {
|
|
120 value = ((c>'Z')?c-'a'+'Z'-'A'+1:c-'A');
|
|
121 last_token = 'v';
|
|
122 return last_token;
|
|
123 } else if ('='==c && '='== *ptr) { /* equal */
|
|
124 ptr++;
|
|
125 last_token = T_EQUAL;
|
|
126 return last_token;
|
|
127 } else if ('!'==c && '='== *ptr) { /* equal */
|
|
128 ptr++;
|
|
129 last_token = T_NEQUAL;
|
17
|
130 return last_token;
|
0
|
131 } else if ('<'==c && '<'== *ptr) { /* shift */
|
|
132 ptr++;
|
|
133 last_token = T_LSHIFT;
|
|
134 return last_token;
|
|
135 } else if ('>'==c && '>'== *ptr) { /* shift */
|
|
136 ptr++;
|
|
137 last_token = T_RSHIFT;
|
|
138 return last_token;
|
|
139 } else {
|
|
140 last_token = c;
|
|
141 return last_token;
|
|
142 }
|
|
143 }
|
|
144
|
24
|
145 static long
|
0
|
146 expr()
|
|
147 {
|
24
|
148 long d,assign;
|
0
|
149
|
|
150 d = aexpr();
|
|
151 assign = lvalue;
|
|
152 while(last_token!=EOF) {
|
|
153 switch(last_token) {
|
|
154 case '<':
|
|
155 d = (d < aexpr());
|
|
156 break;
|
|
157 case '>':
|
|
158 d = (d > aexpr());
|
|
159 break;
|
|
160 case T_EQUAL:
|
|
161 d = (d == aexpr());
|
|
162 break;
|
|
163 case T_NEQUAL:
|
|
164 d = (d != aexpr());
|
|
165 break;
|
|
166 case T_LSHIFT:
|
|
167 d <<= aexpr();
|
|
168 break;
|
|
169 case T_RSHIFT:
|
|
170 d >>= aexpr();
|
|
171 break;
|
|
172 case '?':
|
|
173 {
|
24
|
174 long true;
|
0
|
175 true = expr();
|
|
176 if(last_token != ':') {
|
|
177 error("? expression not terminated with :");
|
|
178 return true;
|
|
179 }
|
|
180 if(d) {
|
|
181 expr();
|
|
182 return true;
|
|
183 } else {
|
|
184 return expr();
|
|
185 }
|
|
186 }
|
|
187 break;
|
|
188 case '=':
|
|
189 if(assign>=0) {
|
|
190 d = expr();
|
|
191 variable[assign] = d;
|
|
192 return d;
|
|
193 } else {
|
|
194 error("Bad assignment");
|
|
195 return 0;
|
|
196 }
|
|
197 break;
|
|
198 case ':':
|
|
199 case ')':
|
|
200 return d;
|
|
201 default:
|
|
202 error("Bad expression");
|
|
203 token();
|
|
204 }
|
|
205 }
|
|
206 last_token = EOF;
|
|
207 return d;
|
|
208 }
|
|
209
|
24
|
210 static long
|
0
|
211 aexpr()
|
|
212 {
|
24
|
213 long d;
|
0
|
214
|
|
215 d = mexpr();
|
|
216 while(last_token!=EOF) {
|
|
217 switch(last_token) {
|
|
218 case '^':
|
|
219 d ^= mexpr();
|
|
220 break;
|
|
221 case '|':
|
|
222 d |= mexpr();
|
|
223 break;
|
|
224 case '&':
|
|
225 d &= mexpr();
|
|
226 break;
|
|
227 case '-':
|
|
228 d -= mexpr();
|
|
229 break;
|
|
230 case '+':
|
|
231 d += mexpr();
|
|
232 break;
|
|
233 default:
|
|
234 return d;
|
|
235 }
|
|
236 }
|
|
237 return d;
|
|
238 }
|
|
239
|
24
|
240 static long
|
0
|
241 mexpr()
|
|
242 {
|
24
|
243 long d;
|
0
|
244
|
|
245 d = term();
|
|
246 while(last_token!=EOF) {
|
|
247 switch(last_token) {
|
|
248 case '*':
|
|
249 d *= term();
|
|
250 break;
|
|
251 case '/':
|
|
252 d /= term();
|
|
253 break;
|
|
254 case '%':
|
|
255 d %= term();
|
|
256 break;
|
|
257 case '^':
|
|
258 d ^= term();
|
|
259 break;
|
|
260 default:
|
|
261 return d;
|
|
262 }
|
|
263 }
|
|
264 return d;
|
|
265 }
|
|
266
|
24
|
267 static long term()
|
0
|
268 {
|
24
|
269 long d;
|
0
|
270
|
|
271 lvalue= -1;
|
|
272 token();
|
|
273 if(last_token==EOF) {
|
|
274 error("Term expected");
|
|
275 }
|
|
276 switch(last_token) {
|
|
277 case '0':
|
|
278 d = value;
|
|
279 token();
|
|
280 return d;
|
|
281 case 'v':
|
|
282 d = lvalue = value;
|
|
283 token();
|
|
284 return variable[d];
|
|
285 case '-':
|
|
286 return - term();
|
|
287 case '!':
|
|
288 return ! term();
|
|
289 case '(':
|
|
290 d = expr();
|
|
291 if(last_token != ')') {
|
|
292 error("Unbalanced parenthsis");
|
|
293 }
|
|
294 token();
|
|
295 return d;
|
|
296 default:
|
|
297 token();
|
|
298 error("Unknown term");
|
|
299 return 0;
|
|
300 }
|
|
301 }
|
|
302
|
|
303 int
|
|
304 main(int ac,char *av[])
|
|
305 {
|
24
|
306 long d;
|
0
|
307 char buf[BUFSIZ];
|
|
308
|
|
309 while (fgets(buf,BUFSIZ,stdin)) {
|
|
310 ptr = buf;
|
|
311 d = expr();
|
24
|
312 printf("%s = 0x%016lx = %ld\n",buf,d,d);
|
0
|
313 fflush(stdout);
|
|
314 }
|
|
315 return 0;
|
|
316 }
|
|
317
|
|
318 /* end */
|