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