4da6b6b64b31497d702bffba03a42135cc206e95
[calc.git] / parser.c
1 #include <malloc.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "debug.h"
8
9 #include "parser.h"
10
11 /* global variables */
12
13 double answer = 0;
14
15 #define STORAGE_SIZE 10
16 double storage[STORAGE_SIZE] = {0};
17
18 char *format = NULL;
19
20 /* compare codes */
21
22 int codecmp (char *ref, char *str)
23 {
24 int sig;
25
26 while (*ref != '\0') {
27 if (*ref == '\t') {
28 sig = (*str == '.') ? -1 : ((*str >= '0') && (*str <= '9'));
29 } else {
30 sig = *str - *ref;
31 }
32 if (sig != 0) {
33 return (sig > 0) ? 1 : -1;
34 }
35 str++;
36 ref++;
37 }
38
39 return 0;
40 }
41
42 /* allocate new element */
43
44 element_t *newelement (func_t function, int nbops, int prio)
45 {
46 element_t *new = (element_t *) calloc (1, sizeof (element_t));
47 if (new == NULL) {
48 VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n"));
49 exit (1);
50 }
51 if (nbops) {
52 new->ops = (element_t **) calloc (nbops, sizeof (element_t *));
53 if (new->ops == NULL) {
54 VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n"));
55 exit (1);
56 }
57 }
58 new->func = function;
59 new->nbops = nbops;
60 new->prio = prio;
61
62 return new;
63 }
64
65 /* desallocate element */
66
67 void delelement (element_t *root)
68 {
69 if ((root != NULL) && (root != ERROR_OP)) {
70 int i;
71 for (i = 0; i < root->nbops; i++) {
72 if ((root->ops[i] != NULL) && (root->ops[i] != ERROR_OP)) {
73 delelement (root->ops[i]);
74 }
75 }
76 if (root->nbops) {
77 free (root->ops);
78 }
79 free (root);
80 }
81 }
82
83 /* duplicate element */
84
85 element_t *dupelement (element_t *root)
86 {
87 element_t *tmp = NULL;
88 int i;
89
90 if ((root == NULL) || (root == ERROR_OP)) {
91 return root;
92 }
93 tmp = newelement (root->func, root->nbops, root->prio);
94 tmp->value = root->value;
95 for (i = 0; i < root->nbops; i++) {
96 tmp->ops[i] = dupelement (root->ops[i]);
97 }
98 return tmp;
99 }
100
101 /* functions */
102
103 #define NB_OPERATORS 14
104 keyword_t operators[NB_OPERATORS] = {
105 { "+\t", Add, 2, 1, 1},
106 { "-\t", Sub, 2, 1, 1},
107 { "*", Mul, 2, 1, 2},
108 { "/", Div, 2, 1, 2},
109 { "%", Mod, 2, 1, 3},
110 { "^", Pow, 2, 1, 4},
111 { "==", Equal, 2, 2, -1},
112 { "!=", Diff, 2, 2, -1},
113 { ">=", Ge, 2, 2, -1},
114 { "<=", Le, 2, 2, -1},
115 { ">", Gt, 2, 1, -1},
116 { "<", Lt, 2, 1, -1},
117 { "&", And, 2, 1, -2},
118 { "|", Or, 2, 1, -2}
119 };
120
121 #define NB_FUNCTIONS 24
122 keyword_t functions[NB_FUNCTIONS] = {
123 { "sqrt", Sqr, 1, 4, 5},
124 { "pow", Pow, 2, 3, 5},
125 { "cos", Cos, 1, 3, 5},
126 { "sin", Sin, 1, 3, 5},
127 { "tan", Tan, 1, 3, 5},
128 { "acos", Acos, 1, 4, 5},
129 { "asin", Asin, 1, 4, 5},
130 { "atan", Atan, 1, 4, 5},
131 { "log", Log, 1, 3, 5},
132 { "exp", Exp, 1, 3, 5},
133 { "abs", Abs, 1, 3, 5},
134 { "floor", Floor, 1, 5, 5},
135 { "ceil", Ceil, 1, 4, 5},
136 { "sto", Store, 2, 3, 5},
137 { "rcl", Recall, 1, 3, 5},
138 { "inc", Inc, 1, 3, 5},
139 { "dec", Dec, 1, 3, 5},
140 { "disp", Disp, 0, 4, 9},
141 { "quit", Quit, 0, 4, 9},
142 { "help", Help, 0, 4, 9},
143 { "!", Not, 1, 1, 6},
144 { "cond", Cond, 3, 4, 5},
145 { "while", While, 2, 5, 5},
146 { "print", Print, 1, 5, 5}
147 };
148
149 #define NB_CONSTANTS 3
150 keyword_t constants[NB_CONSTANTS] = {
151 { "ans", Ans, 0, 3, 5},
152 { "e", E, 0, 1, 5},
153 { "pi", Pi, 0, 2, 5}
154 };
155
156 #define NB_SYMBOLS 4
157 char *symbols[NB_SYMBOLS] = {
158 "(", ")", "{", "}"
159 };
160
161 /* subparser function */
162
163 element_t *subparser (element_t **proot, char **pstr, func_t func, int nbops, int prio)
164 {
165 element_t *new = newelement (func, nbops, prio);
166 new->ops[0] = *proot;
167 new->ops[1] = parser (*pstr, pstr, new->prio);
168 if ((new->ops[1] == NULL) || ((new->ops[1] != ERROR_OP) && (new->ops[1]->prio == 9))) {
169 delelement (new->ops[1]);
170 new->ops[1] = ERROR_OP;
171 }
172 if (new->ops[1] == ERROR_OP) {
173 delelement (new);
174 *proot = NULL;
175 return ERROR_OP;
176 }
177 *proot = newelement (Val, 1, 5);
178 (*proot)->ops[0] = new;
179
180 return *proot;
181 }
182
183 /* parser function */
184
185 element_t *parser (char *str, char **next, int prio)
186 {
187 element_t *root = NULL;
188 int i;
189
190 VERBOSE (DEBUG, fprintf (stdout, "Starting parsing\n"));
191
192 /* main loop */
193 while (*str != '\0') {
194 int found = 0;
195 element_t *new = NULL;
196 VERBOSE (INFO, fprintf (stdout, "Processing: %s\n", str));
197
198 /* skip spaces and tabs */
199
200 if ((*str == ' ') || (*str == '\t')) {
201 str++;
202 continue;
203 }
204
205 /* check for open brace */
206
207 if (*str == '{') {
208 VERBOSE (DEBUG, fprintf (stdout, "start processing brace\n"));
209 if (root != NULL) {
210 delelement (root);
211 return ERROR_OP;
212 }
213 element_t **prog = NULL;
214 new = newelement (Prog, 0, 5);
215 root = new;
216 prog = &root;
217
218 do {
219 new = parser (str + 1, &str, 0);
220 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
221 delelement (new);
222 new = ERROR_OP;
223 }
224 if (new == ERROR_OP) {
225 delelement (root);
226 return ERROR_OP;
227 }
228 element_t *newprog = newelement (Prog, (*prog)->nbops + 1, 5);
229 for (i = 0; i < (*prog)->nbops; i++) {
230 newprog->ops[i] = (*prog)->ops[i];
231 (*prog)->ops[i] = NULL;
232 }
233 newprog->ops[(*prog)->nbops] = new;
234 delelement (*prog);
235 (*prog) = newprog;
236 } while (*str == ',');
237
238 if (*str != '}') {
239 delelement (root);
240 return ERROR_OP;
241 }
242 str++;
243 VERBOSE (DEBUG, fprintf (stdout, "stop processing brace\n"));
244 continue;
245 }
246
247 /* check for open bracket */
248
249 if (*str == '(') {
250 VERBOSE (DEBUG, fprintf (stdout, "start processing bracket\n"));
251 if (root) {
252 do {
253 found = 0;
254 new = parser (str + 1, &str, 0);
255 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
256 delelement (new);
257 new = ERROR_OP;
258 }
259 if ((new == NULL) || (new == ERROR_OP)) {
260 delelement (root);
261 return ERROR_OP;
262 }
263 for (i = 0; i < root->nbops; i++) {
264 if (root->ops[i] == NULL) {
265 root->ops[i] = new;
266 found = 1;
267 break;
268 }
269 }
270 if (!found) {
271 delelement (new);
272 delelement (root);
273 return ERROR_OP;
274 }
275 } while (*str == ',');
276 } else {
277 root = newelement (Val, 1, 5);
278 new = parser (str + 1, &str, 0);
279 if ((new == NULL) || ((new != ERROR_OP) && (new->prio == 9))) {
280 delelement (new);
281 new = ERROR_OP;
282 }
283 if ((new == NULL) || (new == ERROR_OP) || (*str == ',')) {
284 delelement (new);
285 delelement (root);
286 return ERROR_OP;
287 }
288 root->ops[0] = new;
289 }
290 if (*str != ')') {
291 delelement (root);
292 return ERROR_OP;
293 }
294 str++;
295 VERBOSE (DEBUG, fprintf (stdout, "stop processing bracket\n"));
296 continue;
297 }
298
299 /* check for closing bracket, closing brace or koma */
300
301 if ((*str == ')') || (*str == '}') || (*str == ',')) {
302 if (prio == -9) {
303 delelement (root);
304 return ERROR_OP;
305 }
306 if (next != NULL) {
307 *next = str;
308 }
309 return root;
310 }
311
312 /* look for operators */
313
314 for (i = 0; i < NB_OPERATORS; i++) {
315 keyword_t *operator = operators + i;
316 if (codecmp (operator->keyword, str) == 0) {
317 VERBOSE (DEBUG, fprintf (stdout, "start processing operator\n"));
318 if (root) {
319 if ((prio) && (prio > operator->prio)) {
320 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
321 *next = str;
322 return root;
323 }
324 str += operator->offset;
325 VERBOSE (INFO, fprintf (stdout, "Oper: %d\n", operator->func));
326 if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
327 delelement (root);
328 return ERROR_OP;
329 }
330 } else if (*str == '-') {
331 root = newelement (Sig, 1, 9);
332 } else {
333 return ERROR_OP;
334 }
335 found = 1;
336 VERBOSE (DEBUG, fprintf (stdout, "stop processing operator\n"));
337 break;
338 }
339 }
340 if (found) {
341 continue;
342 }
343
344 /* look for functions */
345
346 for (i = 0; i < NB_FUNCTIONS; i++) {
347 keyword_t *function = functions + i;
348 if (codecmp (function->keyword, str) == 0) {
349 VERBOSE (DEBUG, fprintf (stdout, "start processing function\n"));
350 if (root == NULL) {
351 VERBOSE (INFO, fprintf (stdout, "Func: %d\n", function->func));
352 root = newelement (function->func, function->nbops, function->prio);
353 } else {
354 delelement (root);
355 return ERROR_OP;
356 }
357 str += function->offset;
358 found = 1;
359 VERBOSE (DEBUG, fprintf (stdout, "stop processing function\n"));
360 break;
361 }
362 }
363 if (found) {
364 continue;
365 }
366
367 /* look for constant */
368
369 for (i = 0; i < NB_CONSTANTS; i++) {
370 keyword_t *constant = constants + i;
371 if (codecmp (constant->keyword, str) == 0) {
372 VERBOSE (DEBUG, fprintf (stdout, "start processing constant\n"));
373 if (root == NULL) {
374 VERBOSE (INFO, fprintf (stdout, "Const: %d\n", constant->func));
375 root = newelement (constant->func, constant->nbops, constant->prio);
376 } else {
377 delelement (root);
378 return ERROR_OP;
379 }
380 str += constant->offset;
381 found = 1;
382 VERBOSE (DEBUG, fprintf (stdout, "stop processing constant\n"));
383 break;
384 }
385 }
386 if (found) {
387 continue;
388 }
389
390 /* look for number */
391
392 if (((*str >= '0') && (*str <= '9')) ||
393 (*str == '.') || (*str == '+') || (*str == '-')) {
394 VERBOSE (DEBUG, fprintf (stdout, "start processing value\n"));
395 char *pt;
396 double value = strtod (str, &pt);
397 VERBOSE (INFO, fprintf (stdout, "Value: %f\n", value));
398 if (str != pt) {
399 if ((root == NULL) || (root->prio == 6)) {
400 new = newelement (Val, 1, 5);
401 new->value = value;
402 if (root == NULL) {
403 root = new;
404 } else {
405 for (i = 0; i < root->nbops; i++) {
406 if (root->ops[i] == NULL) {
407 root->ops[i] = new;
408 found = 1;
409 break;
410 }
411 }
412 if (!found) {
413 delelement (new);
414 delelement (root);
415 return ERROR_OP;
416 }
417 }
418 str = pt;
419 } else if ((*str == '+') || (*str == '-')) {
420 if ((prio) && (prio > 1)) {
421 VERBOSE (DEBUG, fprintf (stdout, "stop because operator priority\n"));
422 *next = str;
423 return root;
424 }
425 if (subparser (&root, &str, Add, 2, 1) == ERROR_OP) {
426 delelement (root);
427 return ERROR_OP;
428 }
429 } else {
430 delelement (root);
431 return ERROR_OP;
432 }
433 found = 1;
434 }
435 VERBOSE (DEBUG, fprintf (stdout, "stop processing value\n"));
436 }
437
438 /* error */
439
440 if (!found) {
441 delelement (root);
442 return ERROR_OP;
443 }
444
445 }
446
447 if (next != NULL) {
448 *next = str;
449 }
450
451 return root;
452 }
453
454 /* print element tree */
455
456 void print_element (element_t *root, int level)
457 {
458 char *func = NULL;
459 int i;
460
461 if ((root == NULL) || (root == ERROR_OP)) {
462 return;
463 }
464
465 for (i = 0; i < level; i++) {
466 fprintf (stdout, " ");
467 }
468
469 switch (root->func) {
470 case Val: func = "Value"; break;
471 case Sig: func = "Sign"; break;
472 case Add: func = "Addition"; break;
473 case Sub: func = "Subtraction"; break;
474 case Mul: func = "Multiplication"; break;
475 case Div: func = "Division"; break;
476 case Mod: func = "Modulo"; break;
477 case Pow: func = "Power"; break;
478 case Sqr: func = "Square Root"; break;
479 case Cos: func = "Cosine"; break;
480 case Sin: func = "Sine"; break;
481 case Tan: func = "Tangent"; break;
482 case Acos: func = "Arc Cosine"; break;
483 case Asin: func = "Arc Sine"; break;
484 case Atan: func = "Arc Tangent"; break;
485 case Log: func = "Logarithm"; break;
486 case Exp: func = "Exponantial"; break;
487 case Abs: func = "Absolute value"; break;
488 case Ceil: func = "Ceil value"; break;
489 case Floor: func = "Floor value"; break;
490 case Store: func = "Store"; break;
491 case Recall: func = "Recall"; break;
492 case Inc: func = "Increase"; break;
493 case Dec: func = "Decrease"; break;
494 case Disp: func = "Display"; break;
495 case Quit: func = "Quit"; break;
496 case Help: func = "Help"; break;
497 case Ans: func = "Ans"; break;
498 case Pi: func = "Pi"; break;
499 case E: func = "E"; break;
500 case Equal: func = "Equal"; break;
501 case Diff: func = "Different"; break;
502 case Ge: func = "Greater or equal"; break;
503 case Le: func = "Lesser or equal"; break;
504 case Gt: func = "Greater"; break;
505 case Lt: func = "Lesser"; break;
506 case And: func = "And"; break;
507 case Or: func = "Or"; break;
508 case Not: func = "Not"; break;
509 case Cond: func = "Condition"; break;
510 case While: func = "While"; break;
511 case Prog: func = "Program"; break;
512 case Print: func = "Print"; break;
513 }
514
515 fprintf (stdout, "Function: %s\n", func);
516
517 if ((root->func == Val) && (root->ops[0] == NULL)) {
518 for (i = 0; i < level; i++) {
519 fprintf (stdout, " ");
520 }
521 fprintf (stdout, "value: %f\n", root->value);
522 } else {
523 for (i = 0; i < root->nbops; i++) {
524 print_element (root->ops[i], level + 1);
525 }
526 }
527 }
528
529 /* storage functions */
530
531 double store (int index, double value)
532 {
533 if ((index > 0) && (index <= STORAGE_SIZE)) {
534 storage[index - 1] = value;
535 } else {
536 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [1, %d]\n", index, STORAGE_SIZE));
537 }
538 return value;
539 }
540
541 double recall (int index)
542 {
543 if ((index > 0) && (index <= STORAGE_SIZE)) {
544 return storage[index - 1];
545 } else {
546 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [1, %d]\n", index, STORAGE_SIZE));
547 }
548 return 0;
549 }
550
551 double increase (int index)
552 {
553 if ((index > 0) && (index <= STORAGE_SIZE)) {
554 return storage[index - 1]++;
555 } else {
556 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [1, %d]\n", index, STORAGE_SIZE));
557 }
558 return 0;
559 }
560
561 double decrease (int index)
562 {
563 if ((index > 0) && (index <= STORAGE_SIZE)) {
564 return storage[index - 1]--;
565 } else {
566 VERBOSE (WARNING, fprintf (stdout, "invalid index (%d) [1, %d]\n", index, STORAGE_SIZE));
567 }
568 return 0;
569 }
570
571 void display (void)
572 {
573 int i;
574 fprintf (stdout, "storage:");
575 for (i = 0; i < STORAGE_SIZE; i++) {
576 fprintf (stdout, " %g", storage[i]);
577 }
578 fprintf (stdout, "\n");
579 }
580
581 /* While do function */
582
583 double while_do (element_t *cond, element_t *action)
584 {
585 double ret = 0;
586 element_t *temp = NULL;
587
588 VERBOSE (DEBUG, fprintf (stdout, "starting while loop\n"));
589 while (1) {
590 VERBOSE (DEBUG, fprintf (stdout, "loop...\n"));
591
592 temp = dupelement (cond);
593 if (!evaluate_element (temp, 0)) {
594 break;
595 }
596 if (action) {
597 temp = dupelement (action);
598 ret = evaluate_element (temp, 0);
599 }
600 }
601
602 VERBOSE (DEBUG, fprintf (stdout, "ending while loop\n"));
603
604 return ret;
605 }
606
607 /* program function */
608
609 double program_do (element_t **prog, int nbcalls)
610 {
611 double ret = 0;
612 int i;
613 for (i = 0; i < nbcalls; i++) {
614 ret = evaluate_element (prog[i], 0);
615 prog[i] = NULL;
616 }
617 return ret;
618 }
619
620 /* print function */
621
622 void set_format (char *prompt, int precision)
623 {
624 char buffer[128] = {0};
625 sprintf (buffer, "%s%%.%dg\n", prompt, precision);
626 free_format ();
627 format = strdup (buffer);
628 }
629
630 void free_format ()
631 {
632 if (format) {
633 free (format);
634 format = NULL;
635 }
636 }
637
638 double print (double value)
639 {
640 fprintf (stdout, format ? format : "=> %.6g\n", value);
641 fflush (stdout);
642 return value;
643 }
644
645 /* quit function */
646
647 void quit (void)
648 {
649 fprintf (stdout, "bye\n");
650 exit (0);
651 }
652
653 /* help message */
654
655 void help (void)
656 {
657 fprintf (stdout, "calc is a simple calculator\n\n");
658 fprintf (stdout, "supported operators:");
659 fprintf (stdout, " + - * / %% ^\n");
660 fprintf (stdout, "camparison operators:");
661 fprintf (stdout, " == != >= <= > <\n");
662 fprintf (stdout, "logical operators:");
663 fprintf (stdout, " & | !\n");
664 fprintf (stdout, "mathematic functions:");
665 fprintf (stdout, " pow sqrt log exp\n");
666 fprintf (stdout, "trigonometric functions:");
667 fprintf (stdout, " cos sin tan acos asin atan\n");
668 fprintf (stdout, "supported functions:");
669 fprintf (stdout, " abs ceil floor\n");
670 fprintf (stdout, "storage functions:");
671 fprintf (stdout, " sto rcl inc dec\n");
672 fprintf (stdout, "conditional functions:");
673 fprintf (stdout, " cond while print {}\n");
674 fprintf (stdout, "miscellaneous functions:");
675 fprintf (stdout, " quit help\n");
676 fprintf (stdout, "supported constants:");
677 fprintf (stdout, " e pi\n");
678 }
679
680 /* evaluate element tree */
681
682 #define MASK_SUB 0x1
683 #define MASK_DIV 0x2
684
685 double evaluate_element (element_t *root, char mask)
686 {
687 double op0 = 0, op1 = 0;
688 char nextmask = mask;
689
690 if ((root == NULL) || (root == ERROR_OP)) {
691 VERBOSE (WARNING, fprintf (stdout, "error while evaluating\n"));
692 return 0;
693 }
694
695 /* mask to manage sub operator sub and div */
696 switch (root->func) {
697 case Add:
698 nextmask &= ~MASK_SUB;
699 nextmask &= ~MASK_DIV;
700 break;
701 case Sub:
702 nextmask |= MASK_SUB;
703 nextmask &= ~MASK_DIV;
704 break;
705 case Mul:
706 nextmask &= ~MASK_DIV;
707 break;
708 case Div:
709 nextmask |= MASK_DIV;
710 break;
711 default:
712 nextmask = mask;
713 }
714
715 switch (root->func) {
716 case Val:
717 case Sig:
718 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
719 break;
720 case Add:
721 case Sub:
722 case Mul:
723 case Div:
724 case Mod:
725 case Pow:
726 case Store:
727 case Equal:
728 case Diff:
729 case Ge:
730 case Le:
731 case Gt:
732 case Lt:
733 case And:
734 case Or:
735 if (root->ops[1]) {
736 op1 = evaluate_element (root->ops[1], nextmask);
737 } else if (root->func != Store) {
738 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[1])\n"));
739 return 0;
740 }
741 /* fallthrough */
742 case Sqr:
743 case Cos:
744 case Sin:
745 case Tan:
746 case Acos:
747 case Asin:
748 case Atan:
749 case Log:
750 case Exp:
751 case Abs:
752 case Ceil:
753 case Floor:
754 case Recall:
755 case Inc:
756 case Dec:
757 case Not:
758 case Cond:
759 if (root->ops[0]) {
760 op0 = evaluate_element (root->ops[0], 0);
761 } else {
762 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
763 return 0;
764 }
765 break;
766 case Disp:
767 case Quit:
768 case Help:
769 case Ans:
770 case Pi:
771 case E:
772 case Prog:
773 break;
774 case While:
775 if (root->ops[0] == NULL) {
776 VERBOSE (WARNING, fprintf (stdout, "error while evaluating (op[0])\n"));
777 return 0;
778 }
779 break;
780 case Print:
781 op0 = (root->ops[0]) ? evaluate_element (root->ops[0], 0) : answer;
782 break;
783 }
784
785 switch (root->func) {
786 case Val: return op0;
787 case Sig: return -op0;
788 case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
789 case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
790 case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
791 case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
792 case Mod: return fmod (op0, op1);
793 case Pow: return pow (op0, op1);
794 case Sqr: return sqrt (op0);
795 case Cos: return cos (op0);
796 case Sin: return sin (op0);
797 case Tan: return tan (op0);
798 case Acos: return acos (op0);
799 case Asin: return asin (op0);
800 case Atan: return atan (op0);
801 case Log: return log (op0);
802 case Exp: return exp (op0);
803 case Abs: return fabs (op0);
804 case Ceil: return ceil (op0);
805 case Floor: return floor (op0);
806 case Store: return store ((int)op0, (op1) ? op1 : answer);
807 case Recall: return recall ((int)op0);
808 case Inc: return increase ((int)op0);
809 case Dec: return decrease ((int)op0);
810 case Disp: display (); break;
811 case Quit: quit (); break;
812 case Help: help (); break;
813 case Ans: return answer;
814 case Pi: return M_PI;
815 case E: return M_E;
816 case Equal: return op0 == op1;
817 case Diff: return op0 != op1;
818 case Ge: return op0 >= op1;
819 case Le: return op0 <= op1;
820 case Gt: return op0 > op1;
821 case Lt: return op0 < op1;
822 case And: return (op0 != 0) && (op1 != 0);
823 case Or: return (op0 != 0) || (op1 != 0);
824 case Not: return (op0 == 0);
825 case Cond:
826 if ((op0) && (root->ops[1])) {
827 return evaluate_element (root->ops[1], 0);
828 } else if ((!op0) && (root->ops[2])) {
829 return evaluate_element (root->ops[2], 0);
830 } else {
831 return 0;
832 }
833 case While: return while_do (root->ops[0], root->ops[1]);
834 case Prog: return program_do (root->ops, root->nbops);
835 case Print: return print (op0);
836 }
837
838 return 0;
839 }
840
841 char **generate_completion_list ()
842 {
843 int i, j, l = 0;
844 char **list = (char **) calloc (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
845 if (list == NULL) {
846 VERBOSE (ERROR, fprintf (stderr, "can't allocate memory\n"));
847 exit (1);
848 }
849
850 for (i = 0; i < NB_OPERATORS; i++) {
851 list[l] = strdup ((operators + i)->keyword);
852 for (j = 0; j < (int)strlen (list[l]); j++) {
853 if (list[i][j] == '\t') {
854 list[i][j] = '\0';
855 }
856 }
857 if (list[l] != NULL) {
858 l++;
859 }
860 }
861
862 for (i = 0; i < NB_FUNCTIONS; i++) {
863 list[l] = strdup ((functions + i)->keyword);
864 if (list[l] != NULL) {
865 l++;
866 }
867 }
868
869 for (i = 0; i < NB_CONSTANTS; i++) {
870 list[l] = strdup ((constants + i)->keyword);
871 if (list[l] != NULL) {
872 l++;
873 }
874 }
875
876 for (i = 0; i < NB_SYMBOLS; i++) {
877 list[l] = strdup (symbols[i]);
878 if (list[l] != NULL) {
879 l++;
880 }
881 }
882
883 return (list);
884 }
885
886 void free_completion_list (char **list)
887 {
888 int i;
889
890 if (list) {
891 for (i = 0; i < NB_FUNCTIONS + NB_CONSTANTS; i++) {
892 if (list[i] != NULL) {
893 free (list[i]);
894 }
895 }
896 free (list);
897 }
898 }
899
900
901 /* vim: set ts=4 sw=4 et: */