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