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