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