Initial import of Maentwrog version 1.0 revision 2007.0930 sources.
Cat's Eye Technologies
10 years ago
0 | #include <stdio.h> | |
1 | #include <string.h> | |
2 | #include <ctype.h> | |
3 | ||
4 | /* | |
5 | * caparse.c | |
6 | * | |
7 | * cellular automata parser handles 1-character values and operators : | |
8 | * | |
9 | * not ! | |
10 | * or | | |
11 | * and & | |
12 | * xor ^ | |
13 | * values a, b, c, ... z | |
14 | * parenthesis (, ) | |
15 | */ | |
16 | ||
17 | #define OP_OR 0 | |
18 | #define OP_AND 1 | |
19 | #define OP_XOR 2 | |
20 | ||
21 | int caparse(char *string, int values[]); | |
22 | int doper(int state, int oper, int modder); | |
23 | ||
24 | main() | |
25 | { | |
26 | int values[26] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
27 | 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
28 | char in[255]; | |
29 | ||
30 | while (!feof(stdin)) | |
31 | { | |
32 | gets(in); | |
33 | if (isalpha(in[0])&&in[1]=='=') | |
34 | values[in[0]-'a']=(in[2]-'0'); | |
35 | else | |
36 | printf("%d\n", caparse(in, values)); | |
37 | } | |
38 | ||
39 | } | |
40 | ||
41 | int caparse(char *string, int values[]) | |
42 | { | |
43 | ||
44 | #define sp string[pos] | |
45 | ||
46 | int negate = 0; | |
47 | int state = 0; | |
48 | int oper = OP_OR; | |
49 | int pos = 0; | |
50 | ||
51 | for (;((sp) && (sp != ')'));pos++) | |
52 | { | |
53 | if (isalpha(sp)) | |
54 | { | |
55 | state = doper(state, oper, negate ? !values[sp-'a'] : values[sp-'a']); | |
56 | negate = 0; | |
57 | } else | |
58 | switch (sp) | |
59 | { | |
60 | case '|' : oper = OP_OR; break; | |
61 | case '&' : oper = OP_AND; break; | |
62 | case '^' : oper = OP_XOR; break; | |
63 | case '!' : negate = 1; break; | |
64 | case '(' : pos++; | |
65 | state = doper(state, oper, | |
66 | negate ? !caparse(&sp, values) : | |
67 | caparse(&sp, values)); | |
68 | { | |
69 | int bra = 1; | |
70 | while (bra) | |
71 | { | |
72 | if (sp=='(') bra++; | |
73 | if (sp==')') bra--; | |
74 | printf("%d\n", bra); | |
75 | if (bra) pos++; | |
76 | } | |
77 | } | |
78 | break; | |
79 | default : break; | |
80 | } | |
81 | } | |
82 | return state; | |
83 | } | |
84 | ||
85 | int doper(int state, int oper, int modder) | |
86 | { | |
87 | switch (oper) | |
88 | { | |
89 | case OP_OR : return(state | modder); break; | |
90 | case OP_AND : return(state & modder); break; | |
91 | case OP_XOR : return(state ^ modder); break; | |
92 | } | |
93 | } | |
94 |
0 | /* | |
1 | * maentw.c | |
2 | * | |
3 | * Maentwrog (RPN calculator & simple interpreted language) | |
4 | * - derived from rpn, Aug 1993 Chris Pressey | |
5 | * - updated Jul 1997 Chris Pressey, fixed minor bugs | |
6 | * - updated Jul 1998 Chris Pressey, fixed more minor bugs | |
7 | * - and ANSI C-ized: now case sensitive | |
8 | * Usage : maentw maentw-expressions executes and exits | |
9 | * maentw goes into interactive mode | |
10 | * maentw <maentwrog-file runs file through maentw | |
11 | * | |
12 | */ | |
13 | ||
14 | #include <stdio.h> | |
15 | #include <stdlib.h> | |
16 | #include <alloc.h> | |
17 | #include <string.h> | |
18 | #include <ctype.h> | |
19 | ||
20 | #define DEFSIZE 1024 | |
21 | ||
22 | struct stack /* stack structure, for values on stack */ | |
23 | { | |
24 | signed long val; | |
25 | struct stack *next; | |
26 | } *head; /* head of stack */ | |
27 | ||
28 | struct word /* word structure, for words (pre- and user- */ | |
29 | { /* defined) */ | |
30 | char name[80]; /* name of word */ | |
31 | char *macro; /* macro (user-defined; only executed if | |
32 | * fcn==0) */ | |
33 | int fcn; /* built-in fcn or 0 for user-defined fcn */ | |
34 | struct word *next; | |
35 | } *whead; /* head of words */ | |
36 | ||
37 | struct vari /* variable structure, for variables */ | |
38 | { | |
39 | char name[80]; /* name of variable */ | |
40 | signed long value; /* values of variable (signed longs only) */ | |
41 | struct vari *next; | |
42 | } *vhead; /* head of variables */ | |
43 | ||
44 | int debug=0; | |
45 | ||
46 | /* prototypes */ | |
47 | ||
48 | /* word-handling */ | |
49 | struct word *addword(char *name, char *macro, int fcn); | |
50 | struct word *lookup(char *name); | |
51 | void initwords(void); | |
52 | void makeword(void); | |
53 | ||
54 | /* variable-handling */ | |
55 | struct vari *addvari(char *name); | |
56 | struct vari *getvari(char *name); | |
57 | void setvari(char *name, signed long value); | |
58 | ||
59 | /* stack-handling */ | |
60 | void push(signed long val); | |
61 | signed long pop(void); | |
62 | ||
63 | /* functions */ | |
64 | void dofunc(struct word * w); | |
65 | void words(void); | |
66 | void vars(void); | |
67 | signed long sizestack(void); | |
68 | ||
69 | /* parsing and interpreting */ | |
70 | void process(char *s); | |
71 | void procstr(char *s); | |
72 | ||
73 | char * strdup(char * s) | |
74 | { | |
75 | char * t; | |
76 | t = (char *)malloc(strlen(s) * sizeof(char)); | |
77 | strcpy(t, s); | |
78 | return t; | |
79 | } | |
80 | ||
81 | int main(argc, argv) | |
82 | int argc; | |
83 | char **argv; | |
84 | { | |
85 | char s[80]; | |
86 | int i; | |
87 | ||
88 | head = NULL; /* init */ | |
89 | whead = NULL; | |
90 | vhead = NULL; | |
91 | initwords(); | |
92 | if (argc != 1) | |
93 | { | |
94 | for(i=2;i<=argc;i++) procstr(argv[i-1]); | |
95 | exit(0); | |
96 | } | |
97 | scanf("%s", s); /* process commands/values from stdin */ | |
98 | while (!feof(stdin)) | |
99 | { | |
100 | process(s); | |
101 | scanf("%s", s); | |
102 | } | |
103 | return 0; | |
104 | } | |
105 | ||
106 | /* | |
107 | * processes the word in s according to parsing rules. | |
108 | * | |
109 | * if word starts with a digit or a -digit, it is converted to a float and put | |
110 | * on the stack. | |
111 | * | |
112 | * if word starts with a = then the variable following equals is assigned the | |
113 | * last value popped off the stack. | |
114 | * | |
115 | * if word starts with a * a variable is defined using that word. | |
116 | * | |
117 | * if word starts with a @, the stack is popped, is checked for the boolean | |
118 | * value, and if true, executes it. (if.) | |
119 | * | |
120 | * if word starts with a $, the stack is popped, and command is repeated | |
121 | * that number of times. | |
122 | * | |
123 | * if word starts with a [, the stack is popped, is checked for the boolean | |
124 | * value, and if true, executes it. Then goes back and pops the stack | |
125 | * again (while.) | |
126 | * | |
127 | * if word is in words list, that function is executed. | |
128 | * | |
129 | * if word is in variables list, the value of it is pushed onto the stack. | |
130 | * | |
131 | * otherwise generates an error. | |
132 | */ | |
133 | void process(char *s) | |
134 | { | |
135 | struct word *w; | |
136 | struct vari *v; | |
137 | int i; | |
138 | ||
139 | if(debug) printf("%s ", s); | |
140 | ||
141 | if (isdigit(s[0]) || ((s[0] == '-') && (isdigit(s[1])))) | |
142 | push(atoi(s)); | |
143 | else if (s[0] == '=') | |
144 | setvari(s + 1, pop()); | |
145 | else if ((s[0] == '*') && (isalpha(s[1]))) | |
146 | addvari(s + 1); | |
147 | else if (s[0] == '@') | |
148 | { | |
149 | if (pop()) | |
150 | if (w = lookup(s + 1)) | |
151 | dofunc(w); | |
152 | } | |
153 | else if (s[0] == '$') | |
154 | { | |
155 | for(i=pop();i;i--) | |
156 | if (w = lookup(s + 1)) | |
157 | dofunc(w); | |
158 | } | |
159 | else if (s[0] == '[') | |
160 | { | |
161 | for(;;) | |
162 | { | |
163 | if (pop()) | |
164 | { | |
165 | if (w = lookup(s + 1)) | |
166 | dofunc(w); | |
167 | } else break; | |
168 | } | |
169 | } | |
170 | else if (w = lookup(s)) | |
171 | dofunc(w); | |
172 | else if (v = getvari(s)) | |
173 | push(v->value); | |
174 | else | |
175 | printf("unknown command '%s'\n", s); | |
176 | } | |
177 | ||
178 | /* | |
179 | * processes each word in the string s. | |
180 | * strtok doesn't work with recursion :-( | |
181 | */ | |
182 | void procstr(char *s) | |
183 | { | |
184 | char *h=strdup(s); | |
185 | char *g, *gg; | |
186 | g = h; | |
187 | ||
188 | for (;;) | |
189 | { | |
190 | gg = g; | |
191 | while (!isspace(gg[0])&&gg[0]) | |
192 | gg++; | |
193 | if (!gg[0]) | |
194 | break; | |
195 | gg[0] = 0; | |
196 | ||
197 | process(g); | |
198 | ||
199 | gg[0] = ' '; | |
200 | g = gg; | |
201 | while (isspace(g[0])&&g[0]) | |
202 | g++; | |
203 | } | |
204 | ||
205 | free(h); /* called with strdup(), so we must free */ | |
206 | } | |
207 | ||
208 | /* | |
209 | * adds a unique word to the list of words. | |
210 | */ | |
211 | struct word *addword(char *name, char *macro, int fcn) | |
212 | { | |
213 | struct word *new; | |
214 | for (new = whead; new; new = new->next) | |
215 | if (!strcmp(new->name, name)) | |
216 | { | |
217 | printf("already exists\n"); | |
218 | return NULL; | |
219 | } | |
220 | new = (struct word *) malloc(sizeof(struct word)); | |
221 | strcpy(new->name, name); | |
222 | new->macro = strdup(macro); | |
223 | new->fcn = fcn; | |
224 | ||
225 | new->next = whead; | |
226 | whead = new; | |
227 | return new; | |
228 | } | |
229 | ||
230 | /* | |
231 | * attempts to find the word 'name' in the words list. returns NULL if it | |
232 | * could not be found. | |
233 | */ | |
234 | struct word *lookup(char *name) | |
235 | { | |
236 | struct word *l = whead; | |
237 | struct word *k = NULL; | |
238 | ||
239 | while (l) | |
240 | { | |
241 | if (!strcmp(name, l->name)) | |
242 | { | |
243 | k = l; | |
244 | l = NULL; | |
245 | } else | |
246 | l = l->next; | |
247 | } | |
248 | return (k); | |
249 | } | |
250 | ||
251 | /* | |
252 | * initialize the words list with all the built-in words. | |
253 | */ | |
254 | void initwords() | |
255 | { | |
256 | addword("bye", "", 200); | |
257 | addword("rem", "", 199); | |
258 | addword("debug", "", 198); | |
259 | addword("vars", "", 101); | |
260 | addword("words", "", 100); | |
261 | ||
262 | addword("free", "", 91); | |
263 | addword("alloc", "", 90); | |
264 | ||
265 | addword(";", "", 81); | |
266 | addword(":", "", 80); | |
267 | ||
268 | addword("size", "", 50); | |
269 | addword("dup", "", 51); | |
270 | addword("swap", "", 52); | |
271 | addword("pop", "", 53); | |
272 | ||
273 | addword("get", "", 45); | |
274 | addword("put", "", 44); | |
275 | ||
276 | addword("rnd", "", 40); | |
277 | ||
278 | addword(">", "", 22); | |
279 | addword("<", "", 21); | |
280 | addword("==", "", 20); | |
281 | ||
282 | addword(".", "", 1); | |
283 | addword("..", "", 6); | |
284 | ||
285 | addword("mod", "", 30); | |
286 | ||
287 | addword("/", "", 5); | |
288 | addword("*", "", 4); | |
289 | addword("-", "", 3); | |
290 | addword("+", "", 2); | |
291 | } | |
292 | ||
293 | /* | |
294 | * makes a word, reading between the : and ;, defining the new word's macro, | |
295 | * and adds it. | |
296 | */ | |
297 | void makeword() | |
298 | { | |
299 | char s[80]; | |
300 | char t[80]; | |
301 | char *y; | |
302 | int size = DEFSIZE; | |
303 | ||
304 | y = (char *)malloc(size); | |
305 | scanf("%s", s); | |
306 | strcpy(y, ""); | |
307 | scanf("%s", t); | |
308 | while (strcmp(t, ";")) | |
309 | { | |
310 | if ((strlen(y)+strlen(t))>size) | |
311 | { | |
312 | printf("out of memory\n"); | |
313 | exit(0); | |
314 | } | |
315 | strcat(y, t); | |
316 | strcat(y, " "); | |
317 | scanf("%s", t); | |
318 | } | |
319 | { | |
320 | char *n = (char *)malloc(strlen(y)+1); | |
321 | /* printf("(usage : %d bytes)\n", strlen(y)+1); */ | |
322 | strcpy(n, y); | |
323 | free(y); | |
324 | y = n; | |
325 | } | |
326 | addword(s, y, 0); | |
327 | } | |
328 | ||
329 | /* | |
330 | * pushes a value onto the stack. | |
331 | */ | |
332 | void push(signed long val) | |
333 | { | |
334 | struct stack *s; | |
335 | s = (struct stack *) malloc(sizeof(struct stack)); | |
336 | s->val = val; | |
337 | s->next = head; | |
338 | head = s; | |
339 | } | |
340 | ||
341 | /* | |
342 | * pops a value off the stack. generates error and returns 0.0 in case of | |
343 | * underflow. | |
344 | */ | |
345 | signed long pop() | |
346 | { | |
347 | signed long v; | |
348 | struct stack *s = head; | |
349 | if (s) | |
350 | { | |
351 | v = head->val; | |
352 | head = head->next; | |
353 | free(s); | |
354 | return v; | |
355 | } else | |
356 | { | |
357 | printf("stack underflow\n"); | |
358 | return 0; | |
359 | } | |
360 | } | |
361 | ||
362 | /* | |
363 | * adds a unique variable to the vari list. | |
364 | */ | |
365 | struct vari *addvari(char *name) | |
366 | { | |
367 | struct vari *v; | |
368 | for (v = vhead; v; v = v->next) | |
369 | if (!strcmp(v->name, name)) | |
370 | { | |
371 | printf("already exists\n"); | |
372 | return NULL; | |
373 | } | |
374 | v = (struct vari *) malloc(sizeof(struct vari)); | |
375 | strcpy(v->name, name); | |
376 | v->next = vhead; | |
377 | vhead = v; | |
378 | return v; | |
379 | } | |
380 | ||
381 | /* | |
382 | * gets the value of a variable off the variable list. | |
383 | */ | |
384 | struct vari *getvari(char *name) | |
385 | { | |
386 | struct vari *l = vhead; | |
387 | struct vari *k = NULL; | |
388 | ||
389 | while (l) | |
390 | { | |
391 | if (!strcmp(name, l->name)) | |
392 | { | |
393 | k = l; | |
394 | l = NULL; | |
395 | } else | |
396 | l = l->next; | |
397 | } | |
398 | return (k); | |
399 | } | |
400 | ||
401 | /* | |
402 | * sets the value of a variable | |
403 | */ | |
404 | void setvari(char *name, signed long value) | |
405 | { | |
406 | struct vari *l = vhead; | |
407 | while (l) | |
408 | { | |
409 | if (!strcmp(name, l->name)) | |
410 | { | |
411 | l->value = value; | |
412 | l = NULL; | |
413 | } else | |
414 | l = l->next; | |
415 | } | |
416 | } | |
417 | ||
418 | /* | |
419 | * lists all words in mw's words list | |
420 | */ | |
421 | void words() | |
422 | { | |
423 | struct word *w; | |
424 | for (w = whead; w; w = w->next) | |
425 | printf("%s ", w->name); | |
426 | printf("\n"); | |
427 | } | |
428 | ||
429 | signed long sizestack() | |
430 | { | |
431 | signed long total = 0; | |
432 | struct stack *s = head; | |
433 | ||
434 | while(s) | |
435 | { | |
436 | total++; | |
437 | s=s->next; | |
438 | } | |
439 | return total; | |
440 | } | |
441 | ||
442 | /* | |
443 | * list all variables in mw's vari list | |
444 | */ | |
445 | void vars() | |
446 | { | |
447 | struct vari *v; | |
448 | for (v = vhead; v; v = v->next) | |
449 | printf("%-16s %ld\n", v->name, v->value); | |
450 | } | |
451 | ||
452 | /* | |
453 | * execute function of a word. if w->fcn is 0, it will run processtr on the | |
454 | * word. otherwise, a built-in function will be called. see the rpn | |
455 | * documentation on built-in functions. | |
456 | */ | |
457 | void dofunc(struct word * w) | |
458 | { | |
459 | signed long a, b; | |
460 | signed long *ax; | |
461 | switch (w->fcn) | |
462 | { | |
463 | case 1: /* output (.) */ | |
464 | printf("%ld\n", pop()); | |
465 | break; | |
466 | case 2: /* add (+) */ | |
467 | push(pop() + pop()); | |
468 | break; | |
469 | case 3: /* subtract (-) */ | |
470 | a = pop(); | |
471 | b = pop(); | |
472 | push(b - a); | |
473 | break; | |
474 | case 4: /* multiply (*) */ | |
475 | push(pop() * pop()); | |
476 | break; | |
477 | case 5: /* divide (/) */ | |
478 | a = pop(); | |
479 | b = pop(); | |
480 | push(b / a); | |
481 | break; | |
482 | case 6: /* output ASCII (..) */ | |
483 | printf("%c", (char)pop()); | |
484 | break; | |
485 | case 20: | |
486 | push(!pop() == !pop()); | |
487 | break; | |
488 | case 21: | |
489 | push(pop()>pop()); | |
490 | break; | |
491 | case 22: | |
492 | push(pop()<pop()); | |
493 | break; | |
494 | case 30: | |
495 | a = pop(); | |
496 | b = pop(); | |
497 | push(b % a); | |
498 | break; | |
499 | case 40: | |
500 | push(a); /* something random */ | |
501 | break; | |
502 | case 44: /* put */ | |
503 | a = pop(); | |
504 | b = pop(); | |
505 | if (b % 4) | |
506 | printf("must be longword boundary\n"); else | |
507 | { | |
508 | ax = (signed long *)b; | |
509 | *ax = a; | |
510 | } | |
511 | break; | |
512 | case 45: | |
513 | a = pop(); | |
514 | if (a % 4) | |
515 | printf("must be longword boundary\n"); else | |
516 | { | |
517 | ax = (signed long *)a; | |
518 | push(*ax); | |
519 | } | |
520 | break; | |
521 | case 50: | |
522 | push(sizestack()); /* size of stack (size) */ | |
523 | break; | |
524 | case 51: /* duplicate top element (dup) */ | |
525 | a = pop(); | |
526 | push(a); push (a); break; | |
527 | case 52: /* swap top elements (swap) */ | |
528 | a = pop(); | |
529 | b = pop(); | |
530 | push(a); push (b); | |
531 | break; | |
532 | case 53: /* pop element (pop) */ | |
533 | pop(); | |
534 | break; | |
535 | case 80: /* define word (: ... ;) */ | |
536 | makeword(); | |
537 | break; | |
538 | case 81: /* null (;) */ | |
539 | break; | |
540 | case 90: | |
541 | a = pop(); | |
542 | push((signed long)malloc(a*sizeof(signed long))); | |
543 | break; | |
544 | case 91: | |
545 | free((void *)pop()); | |
546 | break; | |
547 | case 100: /* list known words (words) */ | |
548 | words(); | |
549 | break; | |
550 | case 101: /* list variables (vars) */ | |
551 | vars(); | |
552 | break; | |
553 | case 198: | |
554 | debug = 1; | |
555 | break; | |
556 | case 199: /* rem */ | |
557 | { | |
558 | char t[80]; | |
559 | scanf("%s", t); | |
560 | while (strcmp(t, ";")) | |
561 | scanf("%s", t); | |
562 | } | |
563 | break; | |
564 | case 200: /* exit mw (bye) */ | |
565 | exit(0); | |
566 | break; | |
567 | default: /* user-defined word */ | |
568 | procstr(w->macro); | |
569 | } | |
570 | } |
0 | /* | |
1 | ||
2 | rdp.c | |
3 | ||
4 | a recursive decent parser (origins now lost, sorry) | |
5 | ||
6 | Chris Pressey, March, like, 7th, 1994 | |
7 | ||
8 | This program is by no means complete, but it's as far as I'll | |
9 | go in the general case. It should be no problem adapting it | |
10 | to do all sorts of really demented things. | |
11 | ||
12 | */ | |
13 | ||
14 | #define THIS_PROGRAM_IS_NOT_REALLY_AS_CRAPPY_AS_YOU_THINK | |
15 | ||
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | #include <ctype.h> | |
19 | ||
20 | #define T_DELIMITER 0 /* delimeter token */ | |
21 | #define T_VARIABLE 1 | |
22 | #define T_CONSTANT 2 | |
23 | ||
24 | #define T_LENGTH 80 | |
25 | ||
26 | int toktype; /* type of last token */ | |
27 | char token[T_LENGTH]; /* what gettoken returns - a token */ | |
28 | char prog[T_LENGTH]; /* the string to parse */ | |
29 | ||
30 | int t; /* a 'pointer' to the pos in prog[] */ | |
31 | int result; /* result of calculations */ | |
32 | int vars[26]; /* variables */ | |
33 | ||
34 | int level2 (int result); /* recursion levels. level 1 is no */ | |
35 | int level3 (int result); /* longer needed (it assigned vars) */ | |
36 | int level4 (int result); | |
37 | int level5 (int result); | |
38 | int level6 (int result); | |
39 | int primitive (int result); | |
40 | ||
41 | /*-------------------------------------------------------------------------*/ | |
42 | ||
43 | int | |
44 | isdelimeter (char ch) | |
45 | { | |
46 | switch (ch) | |
47 | { | |
48 | case ' ': | |
49 | case '+': | |
50 | case '-': | |
51 | case '/': | |
52 | case '*': | |
53 | case '%': | |
54 | case '=': | |
55 | case '>': | |
56 | case '<': | |
57 | case '(': | |
58 | case ')': | |
59 | case '$': | |
60 | case '!': | |
61 | case '&': | |
62 | case '|': | |
63 | case '^': | |
64 | return 1; | |
65 | break; | |
66 | ||
67 | default: | |
68 | return 0; | |
69 | } | |
70 | } | |
71 | ||
72 | void | |
73 | gettoken () | |
74 | { | |
75 | char temp[T_LENGTH]; | |
76 | ||
77 | strcpy (token, ""); | |
78 | token[1] = (char) 0; | |
79 | ||
80 | while (isspace (prog[t])) | |
81 | t++; | |
82 | if (prog[t] == '$') | |
83 | strcpy (token, "$"); | |
84 | if (isdelimeter (prog[t])) | |
85 | { | |
86 | toktype = T_DELIMITER; | |
87 | token[0] = prog[t++]; | |
88 | } | |
89 | else | |
90 | { | |
91 | if (isalpha (prog[t])) | |
92 | { | |
93 | toktype = T_VARIABLE; | |
94 | while (!(isdelimeter (prog[t]))) | |
95 | { | |
96 | token[strlen (token) + 1] = (char) 0; | |
97 | token[strlen (token)] = prog[t++]; | |
98 | } | |
99 | } | |
100 | else if (isdigit (prog[t])) | |
101 | { | |
102 | toktype = T_CONSTANT; | |
103 | while (!(isdelimeter (prog[t]))) | |
104 | { | |
105 | token[strlen (token) + 1] = (char) 0; | |
106 | token[strlen (token)] = prog[t++]; | |
107 | } | |
108 | } | |
109 | } | |
110 | } | |
111 | ||
112 | void | |
113 | putback () | |
114 | { | |
115 | t -= strlen (token); | |
116 | } | |
117 | ||
118 | void | |
119 | serror (int s) | |
120 | { | |
121 | switch (s) | |
122 | { | |
123 | case 1: | |
124 | printf ("syntax error\n"); | |
125 | break; | |
126 | case 2: | |
127 | printf ("mismatched parentheses\n"); | |
128 | break; | |
129 | case 3: | |
130 | printf ("expression absent\n"); | |
131 | break; | |
132 | } | |
133 | } | |
134 | ||
135 | /* | |
136 | if you define a new operator, use | |
137 | ||
138 | return (argument op operand) | |
139 | ||
140 | if you define a function (eg. sin(x)), use | |
141 | ||
142 | return (func(operand)) | |
143 | ||
144 | if you define a backwards function (eg. x!) use | |
145 | ||
146 | return (func(argument)) | |
147 | ||
148 | unary operators (such as -5 and !(a=b)) are not handled here, but are | |
149 | handled in level5() | |
150 | ||
151 | */ | |
152 | int | |
153 | arith (char op, int argument, int operand) | |
154 | { | |
155 | switch (op) | |
156 | { | |
157 | case '+': | |
158 | return (argument + operand); /* addition */ | |
159 | case '-': | |
160 | return (argument - operand); /* subtraction */ | |
161 | case '*': | |
162 | return (argument * operand); /* multiplication */ | |
163 | case '/': | |
164 | return (argument / operand); /* division */ | |
165 | case '%': | |
166 | return (argument % operand); /* modulus */ | |
167 | case '=': | |
168 | return (argument == operand); /* equality */ | |
169 | case '>': | |
170 | return (argument > operand); /* superiority */ | |
171 | case '<': | |
172 | return (argument < operand); /* inferiority */ | |
173 | case '&': | |
174 | return (argument & operand); /* binary AND */ | |
175 | case '|': | |
176 | return (argument | operand); /* binary OR */ | |
177 | case '^': | |
178 | return (argument ^ operand); /* binary XOR */ | |
179 | } | |
180 | } | |
181 | ||
182 | int | |
183 | findvar (char *s) | |
184 | { | |
185 | return vars[(int) toupper (s[0]) - (int) 'A']; | |
186 | } | |
187 | ||
188 | int | |
189 | getexp (int result) | |
190 | { | |
191 | gettoken (); | |
192 | if (strlen (token)) | |
193 | result = level2 (result); | |
194 | else | |
195 | serror (3); | |
196 | return result; | |
197 | } | |
198 | ||
199 | int | |
200 | level2 (int result) | |
201 | { | |
202 | char op; | |
203 | int hold = 0; | |
204 | ||
205 | result = level3 (result); | |
206 | op = token[0]; | |
207 | while ((op == '+') || (op == '-')) | |
208 | { | |
209 | gettoken (); | |
210 | hold = level3 (hold); | |
211 | result = arith (op, result, hold); | |
212 | op = token[0]; | |
213 | } | |
214 | return result; | |
215 | } | |
216 | ||
217 | int | |
218 | level3 (int result) | |
219 | { | |
220 | char op; | |
221 | int hold = 0; | |
222 | ||
223 | result = level4 (result); | |
224 | op = token[0]; | |
225 | while ((op == '*') || (op == '/')) | |
226 | { | |
227 | gettoken (); | |
228 | hold = level4 (hold); | |
229 | result = arith (op, result, hold); | |
230 | op = token[0]; | |
231 | } | |
232 | return result; | |
233 | } | |
234 | ||
235 | int | |
236 | level4 (int result) | |
237 | { | |
238 | int hold = 0; | |
239 | char ch; | |
240 | ||
241 | result = level5 (result); | |
242 | ch = token[0]; | |
243 | switch (ch) | |
244 | { | |
245 | case '=': | |
246 | case '>': | |
247 | case '<': | |
248 | case '&': | |
249 | case '|': | |
250 | case '^': | |
251 | gettoken (); | |
252 | hold = level4 (hold); | |
253 | result = arith (ch, result, hold); | |
254 | break; | |
255 | } | |
256 | return result; | |
257 | } | |
258 | ||
259 | int | |
260 | level5 (int result) | |
261 | { | |
262 | char op; | |
263 | int hold = 0; | |
264 | ||
265 | op = ' '; | |
266 | if ((toktype == T_DELIMITER) && ((token[0] == '+') || (token[0] == '-'))) | |
267 | { | |
268 | op = token[0]; | |
269 | gettoken (); | |
270 | } | |
271 | result = level6 (result); | |
272 | if (op == '-') | |
273 | result *= (-1); | |
274 | if (op == '!') | |
275 | result = !result; | |
276 | return result; | |
277 | } | |
278 | ||
279 | int | |
280 | level6 (int result) | |
281 | { | |
282 | if ((token[0] == '(') && (toktype == T_DELIMITER)) | |
283 | { | |
284 | gettoken (); | |
285 | result = level2 (result); | |
286 | if (token[0] != ')') | |
287 | serror (2); | |
288 | gettoken (); | |
289 | } | |
290 | else | |
291 | result = primitive (result); | |
292 | return result; | |
293 | } | |
294 | ||
295 | int | |
296 | primitive (int result) | |
297 | { | |
298 | if (toktype == T_CONSTANT) | |
299 | result = atoi (token); | |
300 | else if (toktype == T_VARIABLE) | |
301 | result = findvar (token); | |
302 | else | |
303 | serror (1); | |
304 | gettoken (); | |
305 | return result; | |
306 | } | |
307 | ||
308 | int | |
309 | main (int argc, char **argv) | |
310 | { | |
311 | { | |
312 | int c; | |
313 | for (c = 0; c <= 25; c++) | |
314 | vars[c] = 0; | |
315 | } | |
316 | t = 0; | |
317 | ||
318 | strcpy (prog, argv[1]); | |
319 | strcat (prog, "$"); | |
320 | result = getexp (result); | |
321 | printf ("%d\n", result); | |
322 | exit (0); | |
323 | ||
324 | ||
325 | ||
326 | ||
327 | #ifdef THIS_PROGRAM_IS_NOT_REALLY_AS_CRAPPY_AS_YOU_THINK | |
328 | } | |
329 | #else | |
330 | } | |
331 | #endif | |
332 |
0 | /* | |
1 | * rpn.c | |
2 | * | |
3 | * RPN calculator - May 1993 Chris Pressey | |
4 | * | |
5 | * Compilation : acc rpn.c -o rpn | |
6 | * | |
7 | * Usage : rpn rpn-expressions ; executes and exits | |
8 | * rpn ; goes into interactive mode | |
9 | * rpn <rpn-file ; runs rpn-file through rpn | |
10 | * | |
11 | * To do : add size (size stack), sum (sum stack), mean (mean stack), sd (take | |
12 | * standard deviation of stack) | |
13 | * | |
14 | */ | |
15 | ||
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | #include <ctype.h> | |
19 | #include <math.h> | |
20 | ||
21 | struct stack /* stack structure, for values on stack */ | |
22 | { | |
23 | double val; | |
24 | struct stack *next; | |
25 | } *head; /* head of stack */ | |
26 | ||
27 | struct word /* word structure, for words (pre- and user- */ | |
28 | { /* defined) */ | |
29 | char name[80]; /* name of word */ | |
30 | char macro[80]; /* macro (user-defined; only executed if | |
31 | * fcn==0) */ | |
32 | int fcn; /* built-in fcn or 0 for user-defined fcn */ | |
33 | struct word *next; | |
34 | } *whead; /* head of words */ | |
35 | ||
36 | struct vari /* variable structure, for variables */ | |
37 | { | |
38 | char name[80]; /* name of variable */ | |
39 | double value; /* values of variable (doubles only) */ | |
40 | struct vari *next; | |
41 | } *vhead; /* head of variables */ | |
42 | ||
43 | /* prototypes */ | |
44 | ||
45 | /* word-handling */ | |
46 | struct word *addword(char *name, char *macro, int fcn); | |
47 | struct word *lookup(char *name); | |
48 | void initwords(); | |
49 | void makeword(); | |
50 | ||
51 | /* variable-handling */ | |
52 | struct vari *addvari(char *name); | |
53 | struct vari *getvari(char *name); | |
54 | void setvari(char *name, double value); | |
55 | ||
56 | /* stack-handling */ | |
57 | void push(double val); | |
58 | double pop(); | |
59 | ||
60 | /* functions */ | |
61 | void dofunc(struct word * w); | |
62 | double factorial(double p); | |
63 | double fibonacci(double p); | |
64 | void words(); | |
65 | void vars(); | |
66 | ||
67 | /* parsing and interpreting */ | |
68 | void process(char *s); | |
69 | void procstr(char *s); | |
70 | ||
71 | main(argc, argv) | |
72 | int argc; | |
73 | char **argv; | |
74 | { | |
75 | char s[80]; | |
76 | int i; | |
77 | ||
78 | head = NULL; /* init */ | |
79 | whead = NULL; | |
80 | vhead = NULL; | |
81 | initwords(); | |
82 | if (argc != 1) | |
83 | { | |
84 | for(i=2;i<=argc;i++) procstr(argv[i-1]); | |
85 | exit(0); | |
86 | } | |
87 | scanf("%s", s); /* process commands/values from stdin */ | |
88 | while (!feof(stdin)) | |
89 | { | |
90 | process(s); | |
91 | scanf("%s", s); | |
92 | } | |
93 | } | |
94 | ||
95 | /* | |
96 | * processes the word in s according to parsing rules. | |
97 | * | |
98 | * if word starts with a digit or a -digit, it is converted to a float and put | |
99 | * on the stack. | |
100 | * | |
101 | * if word starts with a = then the variable following equals is assigned the | |
102 | * last value popped off the stack. | |
103 | * | |
104 | * if word starts with a * a variable is defined using that word. | |
105 | * | |
106 | * if word is in words list, that function is executed. | |
107 | * | |
108 | * if word is in variables list, the value of it is pushed onto the stack. | |
109 | * | |
110 | * otherwise generates an error. | |
111 | */ | |
112 | void process(char *s) | |
113 | { | |
114 | struct word *w; | |
115 | struct vari *v; | |
116 | ||
117 | if (isdigit(s[0]) || ((s[0] == '-') && (isdigit(s[1])))) | |
118 | push(atof(s)); | |
119 | else if (s[0] == '=') | |
120 | setvari(s + 1, pop()); | |
121 | else if ((s[0] == '*') && (isalpha(s[1]))) | |
122 | addvari(s + 1); | |
123 | else if (w = lookup(s)) | |
124 | dofunc(w); | |
125 | else if (v = getvari(s)) | |
126 | push(v->value); | |
127 | else | |
128 | printf("unknown command '%s'\n", s); | |
129 | } | |
130 | ||
131 | /* | |
132 | * processes each word in the string s. | |
133 | */ | |
134 | void procstr(char *s) | |
135 | { | |
136 | char *h=strdup(s); | |
137 | char *g; | |
138 | g = strtok(h, " "); | |
139 | while (g) | |
140 | { | |
141 | process(g); | |
142 | g = strtok(NULL, " "); | |
143 | } | |
144 | free(h); /* called with strdup(), so we must free */ | |
145 | } | |
146 | ||
147 | /* | |
148 | * adds a unique word to the list of words. | |
149 | */ | |
150 | struct word *addword(char *name, char *macro, int fcn) | |
151 | { | |
152 | struct word *new; | |
153 | for (new = whead; new; new = new->next) | |
154 | if (!strcmp(new->name, name)) | |
155 | { | |
156 | printf("already exists\n"); | |
157 | return NULL; | |
158 | } | |
159 | new = (struct word *) malloc(sizeof(struct word)); | |
160 | strcpy(new->name, name); | |
161 | strcpy(new->macro, macro); | |
162 | new->fcn = fcn; | |
163 | ||
164 | new->next = whead; | |
165 | whead = new; | |
166 | return new; | |
167 | } | |
168 | ||
169 | /* | |
170 | * attempts to find the word 'name' in the words list. returns NULL if it | |
171 | * could not be found. | |
172 | */ | |
173 | struct word *lookup(char *name) | |
174 | { | |
175 | struct word *l = whead; | |
176 | struct word *k = NULL; | |
177 | ||
178 | while (l) | |
179 | { | |
180 | if (!strcmp(name, l->name)) | |
181 | { | |
182 | k = l; | |
183 | l = NULL; | |
184 | } else | |
185 | l = l->next; | |
186 | } | |
187 | return (k); | |
188 | } | |
189 | ||
190 | /* | |
191 | * initialize the words list with all the built-in words. | |
192 | */ | |
193 | void initwords() | |
194 | { | |
195 | addword("bye", "", 200); | |
196 | addword("vars", "", 101); | |
197 | addword("words", "", 100); | |
198 | addword(";", "", 81); | |
199 | addword(":", "", 80); | |
200 | ||
201 | addword("sd", "", 53); | |
202 | addword("mean", "", 52); | |
203 | addword("sum", "", 51); | |
204 | addword("size", "", 50); | |
205 | ||
206 | addword("!", "", 13); | |
207 | addword("fib", "", 14); | |
208 | ||
209 | addword("rnd", "", 40); | |
210 | ||
211 | addword("sign", "", 34); | |
212 | addword("abs", "", 33); | |
213 | addword("round", "", 32); | |
214 | addword("frac", "", 31); | |
215 | addword("int", "", 30); | |
216 | ||
217 | addword("phi", "", 27); | |
218 | addword("pi", "", 26); | |
219 | addword("atan", "", 25); | |
220 | addword("acos", "", 24); | |
221 | addword("asin", "", 23); | |
222 | ||
223 | addword("tan", "", 22); | |
224 | addword("cos", "", 21); | |
225 | addword("sin", "", 20); | |
226 | ||
227 | addword("inv", "", 12); | |
228 | addword("exp", "", 11); | |
229 | addword("log", "", 10); | |
230 | addword("ln", "", 9); | |
231 | addword("sqrt", "", 8); | |
232 | addword("sqr", "", 7); | |
233 | ||
234 | addword("^", "", 6); | |
235 | ||
236 | addword(".", "", 1); | |
237 | ||
238 | addword("/", "", 5); | |
239 | addword("*", "", 4); | |
240 | addword("-", "", 3); | |
241 | addword("+", "", 2); | |
242 | } | |
243 | ||
244 | /* | |
245 | * makes a word, reading between the : and ;, defining the new word's macro, | |
246 | * and adds it. | |
247 | */ | |
248 | void makeword() | |
249 | { | |
250 | char s[80]; | |
251 | char t[80]; | |
252 | char y[180]; | |
253 | scanf("%s", s); | |
254 | strcpy(y, ""); | |
255 | scanf("%s", t); | |
256 | while (strcmp(t, ";")) | |
257 | { | |
258 | strcat(y, t); | |
259 | strcat(y, " "); | |
260 | scanf("%s", t); | |
261 | } | |
262 | addword(s, y, 0); | |
263 | } | |
264 | ||
265 | /* | |
266 | * pushes a value onto the stack. | |
267 | */ | |
268 | void push(double val) | |
269 | { | |
270 | struct stack *s; | |
271 | s = (struct stack *) malloc(sizeof(struct stack)); | |
272 | s->val = val; | |
273 | s->next = head; | |
274 | head = s; | |
275 | } | |
276 | ||
277 | /* | |
278 | * pops a value off the stack. generates error and returns 0.0 in case of | |
279 | * underflow. | |
280 | */ | |
281 | double pop() | |
282 | { | |
283 | double v; | |
284 | struct stack *s = head; | |
285 | if (s) | |
286 | { | |
287 | v = head->val; | |
288 | head = head->next; | |
289 | free(s); | |
290 | return v; | |
291 | } else | |
292 | { | |
293 | printf("stack underflow\n"); | |
294 | return 0.0; | |
295 | } | |
296 | } | |
297 | ||
298 | /* | |
299 | * adds a unique variable to the vari list. | |
300 | */ | |
301 | struct vari *addvari(char *name) | |
302 | { | |
303 | struct vari *v; | |
304 | for (v = vhead; v; v = v->next) | |
305 | if (!strcmp(v->name, name)) | |
306 | { | |
307 | printf("already exists\n"); | |
308 | return NULL; | |
309 | } | |
310 | v = (struct vari *) malloc(sizeof(struct vari)); | |
311 | strcpy(v->name, name); | |
312 | v->next = vhead; | |
313 | vhead = v; | |
314 | } | |
315 | ||
316 | /* | |
317 | * gets the value of a variable off the variable list. | |
318 | */ | |
319 | struct vari *getvari(char *name) | |
320 | { | |
321 | struct vari *l = vhead; | |
322 | struct vari *k = NULL; | |
323 | ||
324 | while (l) | |
325 | { | |
326 | if (!strcmp(name, l->name)) | |
327 | { | |
328 | k = l; | |
329 | l = NULL; | |
330 | } else | |
331 | l = l->next; | |
332 | } | |
333 | return (k); | |
334 | } | |
335 | ||
336 | /* | |
337 | * sets the value of a variable | |
338 | */ | |
339 | void setvari(char *name, double value) | |
340 | { | |
341 | struct vari *l = vhead; | |
342 | while (l) | |
343 | { | |
344 | if (!strcmp(name, l->name)) | |
345 | { | |
346 | l->value = value; | |
347 | l = NULL; | |
348 | } else | |
349 | l = l->next; | |
350 | } | |
351 | } | |
352 | ||
353 | /* | |
354 | * calculates p! | |
355 | */ | |
356 | double factorial(double p) | |
357 | { | |
358 | if (p <= 1.0) | |
359 | return p; | |
360 | else | |
361 | return (p * factorial(p - 1.0)); | |
362 | } | |
363 | ||
364 | /* | |
365 | * calculates fib(p) (fib(1)==1, fib(2)==1, fib(n)==fib(n-1)+fib(n-2)) | |
366 | */ | |
367 | double fibonacci(double p) | |
368 | { | |
369 | if (p <= 2.0) | |
370 | return 1.0; | |
371 | else | |
372 | return (fibonacci(p - 1.0) + fibonacci(p - 2.0)); | |
373 | } | |
374 | ||
375 | /* | |
376 | * lists all words in bf's words list | |
377 | */ | |
378 | void words() | |
379 | { | |
380 | struct word *w; | |
381 | for (w = whead; w; w = w->next) | |
382 | printf("%s ", w->name); | |
383 | printf("\n"); | |
384 | } | |
385 | ||
386 | /* | |
387 | * list all variables in bf's vari list | |
388 | */ | |
389 | void vars() | |
390 | { | |
391 | struct vari *v; | |
392 | for (v = vhead; v; v = v->next) | |
393 | printf("%-16s %f\n", v->name, v->value); | |
394 | } | |
395 | ||
396 | /* | |
397 | * execute function of a word. if w->fcn is 0, it will run processtr on the | |
398 | * word. otherwise, a built-in function will be called. see the rpn | |
399 | * documentation on built-in functions. | |
400 | */ | |
401 | void dofunc(struct word * w) | |
402 | { | |
403 | double a, b; | |
404 | switch (w->fcn) | |
405 | { | |
406 | case 1: /* output (.) */ | |
407 | printf("%f\n", pop()); | |
408 | break; | |
409 | case 2: /* add (+) */ | |
410 | push(pop() + pop()); | |
411 | break; | |
412 | case 3: /* subtract (-) */ | |
413 | a = pop(); | |
414 | b = pop(); | |
415 | push(b - a); | |
416 | break; | |
417 | case 4: /* multiply (*) */ | |
418 | push(pop() * pop()); | |
419 | break; | |
420 | case 5: /* divide (/) */ | |
421 | a = pop(); | |
422 | b = pop(); | |
423 | push(b / a); | |
424 | break; | |
425 | case 6: /* exponential (^) */ | |
426 | a = pop(); | |
427 | b = pop(); | |
428 | push(pow(b, a)); | |
429 | break; | |
430 | case 7: /* square (sqr) */ | |
431 | a = pop(); | |
432 | push(a * a); | |
433 | break; | |
434 | case 8: /* square root (sqrt) */ | |
435 | push(sqrt(pop())); | |
436 | break; | |
437 | case 9: /* natural logarithm (ln) */ | |
438 | push(log(pop())); | |
439 | break; | |
440 | case 10: /* log base 10 (log) */ | |
441 | push(log10(pop())); | |
442 | break; | |
443 | case 11: /* e^x (exp) */ | |
444 | push(exp(pop())); | |
445 | break; | |
446 | case 12: /* inversion (inv) */ | |
447 | push(1.0 / pop()); | |
448 | break; | |
449 | case 13: /* factorial (!) */ | |
450 | push(factorial(pop())); | |
451 | break; | |
452 | case 14: /* fibonacci (fib) */ | |
453 | push(fibonacci(pop())); | |
454 | break; | |
455 | case 20: /* sine (sin) */ | |
456 | push(sin(pop())); | |
457 | break; | |
458 | case 21: /* cosine (cos) */ | |
459 | push(cos(pop())); | |
460 | break; | |
461 | case 22: /* tangent (tan) */ | |
462 | push(tan(pop())); | |
463 | break; | |
464 | case 23: /* arcsine (asin) */ | |
465 | push(asin(pop())); | |
466 | break; | |
467 | case 24: /* arccosine (acos) */ | |
468 | push(acos(pop())); | |
469 | break; | |
470 | case 25: /* arctangent (atan) */ | |
471 | push(atan(pop())); | |
472 | break; | |
473 | case 26: /* pi (pi) */ | |
474 | push(3.1415926); | |
475 | break; | |
476 | case 80: /* define word (: ... ;) */ | |
477 | makeword(); | |
478 | break; | |
479 | case 81: /* null (;) */ | |
480 | break; | |
481 | case 100: /* list known words (words) */ | |
482 | words(); | |
483 | break; | |
484 | case 101: /* list variables (vars) */ | |
485 | vars(); | |
486 | break; | |
487 | case 200: /* exit bf (bye) */ | |
488 | exit(0); | |
489 | break; | |
490 | default: /* user-defined word */ | |
491 | procstr(w->macro); | |
492 | } | |
493 | } |