Orbiter 2022
Combinatorial Objects
expression_parser.cpp
Go to the documentation of this file.
1/*
2 * expression_parser.cpp
3 *
4 * Created on: Feb 14, 2021
5 * Author: betten
6 */
7
8/*
9
10 Parser - an expression parser
11
12 Author: Nick Gammon
13 http://www.gammon.com.au/
14
15(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
16distribute this software is granted provided this copyright notice appears
17in all copies. This software is provided "as is" without express or implied
18warranty, and with no claim as to its suitability for any purpose.
19
20Modified 24 October 2005 by Nick Gammon.
21
22 1. Changed use of "abs" to "fabs"
23 2. Changed inclues from math.h and time.h to fmath and ftime
24 3. Rewrote DoMin and DoMax to inline the computation because of some problems with some libraries.
25 4. Removed "using namespace std;" and put "std::" in front of std namespace names where appropriate
26 5. Removed MAKE_STRING macro and inlined the functionality where required.
27 6. Changed Evaluate function to take its argument by reference.
28
29Modified 13 January 2010 by Nick Gammon.
30
31 1. Changed getrandom to work more reliably (see page 2 of discussion thread)
32 2. Changed recognition of numbers to allow for .5 (eg. "a + .5" where there is no leading 0)
33 Also recognises -.5 (so you don't have to write -0.5)
34 3. Fixed problem where (2+3)-1 would not parse correctly (- sign directly after parentheses)
35 4. Fixed problem where changing a parameter and calling p.Evaluate again would fail because the
36 initial token type was not reset to NONE.
37
38Modified 16 February 2010 by Nick Gammon
39
40 1. Fixed bug where if you called Evaluate () twice, the original expression would not be reprocessed.
41
42Modified 27 November 2014 by Nick Gammon
43
44 1. Fixed bug where a literal number followed by EOF would throw an error.
45
46Thanks to various posters on my forum for suggestions. The relevant post is currently at:
47
48 http://www.gammon.com.au/forum/?id=4649
49
50*/
51
52/*
53
54Expression-evaluator
55--------------------
56
57Author: Nick Gammon
58-------------------
59
60
61Example usage:
62
63 Parser p ("2 + 2 * (3 * 5) + nick");
64
65 p.symbols_ ["nick"] = 42;
66
67 double v = p.Evaluate ();
68
69 double v1 = p.Evaluate ("5 + 6"); // supply new expression and evaluate it
70
71Syntax:
72
73 You can use normal algebraic syntax.
74
75 Multiply and divide has higher precedence than add and subtract.
76
77 You can use parentheses (eg. (2 + 3) * 5 )
78
79 Variables can be assigned, and tested. eg. a=24+a*2
80
81 Variables can be preloaded:
82
83 p.symbols_ ["abc"] = 42;
84 p.symbols_ ["def"] = 42;
85
86 Afterwards they can be retrieved:
87
88 x = p.symbols_ ["abc"];
89
90 There are 2 predefined symbols, "pi" and "e".
91
92 You can use the comma operator to load variables and then use them, eg.
93
94 a=42, b=a+6
95
96 You can use predefined functions, see below for examples of writing your own.
97
98 42 + sqrt (64)
99
100
101 Comparisons
102 -----------
103
104 Comparisons work by returning 1.0 if true, 0.0 if false.
105
106 Thus, 2 > 3 would return 0.0
107 3 > 2 would return 1.0
108
109 Similarly, tests for truth (eg. a && b) test whether the values are 0.0 or not.
110
111 If test
112 -------
113
114 There is a ternary function: if (truth-test, true-value, false-value)
115
116 eg. if (1 < 2, 22, 33) returns 22
117
118
119 Precedence
120 ----------
121
122 ( ) = - nested brackets, including function calls like sqrt (x), and assignment
123 * / - multiply, divide
124 + - - add and subtract
125 < <= > >= == != - comparisons
126 && || - AND and OR
127 , - comma operator
128
129 Credits:
130
131 Based in part on a simple calculator described in "The C++ Programming Language"
132 by Bjarne Stroustrup, however with considerable enhancements by me, and also based
133 on my earlier experience in writing Pascal compilers, which had a similar structure.
134
135*/
136
137
138#include "foundations.h"
139
140using namespace std;
141
142
143namespace orbiter {
144namespace layer1_foundations {
146
147
148
149typedef double (*OneArgFunction) (double arg);
150typedef const double (*TwoArgFunction) (const double arg1, const double arg2);
151typedef const double (*ThreeArgFunction) (const double arg1, const double arg2, const double arg3);
152
153// maps of function names to functions
154static std::map<std::string, OneArgFunction> OneArgumentFunctions;
155static std::map<std::string, TwoArgFunction> TwoArgumentFunctions;
156static std::map<std::string, ThreeArgFunction> ThreeArgumentFunctions;
157
158// for standard library functions
159#define STD_FUNCTION(arg) OneArgumentFunctions [#arg] = arg
160
161static int LoadOneArgumentFunctions ()
162 {
163 OneArgumentFunctions ["abs"] = fabs;
164 STD_FUNCTION (acos);
165 STD_FUNCTION (asin);
166 STD_FUNCTION (atan);
167#ifndef WIN32 // doesn't seem to exist under Visual C++ 6
168 STD_FUNCTION (atanh);
169#endif
170 STD_FUNCTION (ceil);
171 STD_FUNCTION (cos);
172 STD_FUNCTION (cosh);
173 STD_FUNCTION (exp);
174 STD_FUNCTION (exp);
175 STD_FUNCTION (floor);
176 STD_FUNCTION (log);
177 STD_FUNCTION (log10);
178 STD_FUNCTION (sin);
179 STD_FUNCTION (sinh);
180 STD_FUNCTION (sqrt);
181 STD_FUNCTION (tan);
182 STD_FUNCTION (tanh);
183
184#if 0
185 OneArgumentFunctions ["int"] = DoInt;
186 OneArgumentFunctions ["rand"] = DoRandom;
187 OneArgumentFunctions ["rand"] = DoRandom;
188 OneArgumentFunctions ["percent"] = DoPercent;
189#endif
190 return 0;
191 } // end of LoadOneArgumentFunctions
192
193static int LoadTwoArgumentFunctions ()
194 {
195#if 0
196 TwoArgumentFunctions ["min"] = DoMin;
197 TwoArgumentFunctions ["max"] = DoMax;
198 TwoArgumentFunctions ["mod"] = DoFmod;
199 TwoArgumentFunctions ["pow"] = DoPow; // x to the power y
200 TwoArgumentFunctions ["roll"] = DoRoll; // dice roll
201#endif
202 return 0;
203 } // end of LoadTwoArgumentFunctions
204
205static int LoadThreeArgumentFunctions ()
206 {
207#if 0
208 ThreeArgumentFunctions ["if"] = DoIf;
209#endif
210 return 0;
211 } // end of LoadThreeArgumentFunctions
212
213
215{
216 Lexer = NULL;
217 Tree = NULL;
218 // insert pre-defined names:
219 symbols_ ["pi"] = 3.1415926535897932385;
220 symbols_ ["e"] = 2.7182818284590452354;
221 LoadOneArgumentFunctions ();
222 LoadTwoArgumentFunctions ();
223 LoadThreeArgumentFunctions ();
224}
225
226expression_parser::~expression_parser()
227{
228 if (Lexer) {
229 FREE_OBJECT(Lexer);
230 }
231}
232
233#if 0
234double expression_parser::Function(int verbose_level, std::string &word)
235{
236 int f_v = (verbose_level >= 1);
237
239
240 // might be single-argument function (eg. abs (x) )
241 std::map<std::string, OneArgFunction>::const_iterator si;
242 si = OneArgumentFunctions.find (word);
243 if (si != OneArgumentFunctions.end ())
244 {
245 if (f_v) {
246 std::cout << "expression_parser::Primary one argument function" << std::endl;
247 }
248 double v = Expression (verbose_level, true); // get argument
249 Lexer.CheckToken (RHPAREN);
250 Lexer.GetToken (verbose_level, true); // get next one (one-token lookahead)
251 if (f_v) {
252 std::cout << "expression_parser::Primary one argument function done" << std::endl;
253 }
254 return si->second (v); // evaluate function
255 }
256
257 // might be double-argument function (eg. roll (6, 2) )
258 std::map<std::string, TwoArgFunction>::const_iterator di;
259 di = TwoArgumentFunctions.find (word);
260 if (di != TwoArgumentFunctions.end ())
261 {
262 if (f_v) {
263 std::cout << "expression_parser::Primary two argument function" << std::endl;
264 }
265 double v1 = Expression (verbose_level, true); // get argument 1 (not commalist)
266 Lexer.CheckToken (COMMA);
267 double v2 = Expression (verbose_level, true); // get argument 2 (not commalist)
268 Lexer.CheckToken (RHPAREN);
269 Lexer.GetToken (verbose_level, true); // get next one (one-token lookahead)
270 if (f_v) {
271 std::cout << "expression_parser::Primary two argument function dibe" << std::endl;
272 }
273 return di->second (v1, v2); // evaluate function
274 }
275
276 // might be double-argument function (eg. roll (6, 2) )
277 std::map<std::string, ThreeArgFunction>::const_iterator ti;
278 ti = ThreeArgumentFunctions.find (word);
279 if (ti != ThreeArgumentFunctions.end ())
280 {
281 if (f_v) {
282 std::cout << "expression_parser::Primary three argument function" << std::endl;
283 }
284 double v1 = Expression (verbose_level, true); // get argument 1 (not commalist)
285 Lexer.CheckToken (COMMA);
286 double v2 = Expression (verbose_level, true); // get argument 2 (not commalist)
287 Lexer.CheckToken (COMMA);
288 double v3 = Expression (verbose_level, true); // get argument 3 (not commalist)
289 Lexer.CheckToken (RHPAREN);
290 Lexer.GetToken (verbose_level, true); // get next one (one-token lookahead)
291 if (f_v) {
292 std::cout << "expression_parser::Primary three argument function done" << std::endl;
293 }
294 return ti->second (v1, v2, v3); // evaluate function
295 }
296
297 throw std::runtime_error ("Function '" + word + "' not implemented.");
298
299}
300#endif
301
302
303syntax_tree_node *expression_parser::Primary (int verbose_level,
304 int &f_single_literal, std::string &single_literal, int &f_has_seen_minus, const bool get)
305 {
306 int f_v = (verbose_level >= 1);
307
309
310
311 if (f_v) {
312 std::cout << "expression_parser::Primary" << std::endl;
313 }
314 f_single_literal = false;
315 f_has_seen_minus = false;
316
317 N = new syntax_tree_node;
318 N->Tree = Tree;
319 if (f_v) {
320 std::cout << "expression_parser::Primary opening node " << N->idx << std::endl;
321 }
322
323 if (get)
324 Lexer->GetToken(verbose_level); // one-token lookahead
325
326 if (Lexer->type_ == NUMBER) {
327 double v = Lexer->value_;
328 N->f_terminal = true;
329 N->T = Lexer->T;
330 Lexer->T = 0L;
331 Lexer->GetToken (verbose_level, true); // get next one (one-token lookahead)
332 if (f_v) {
333 std::cout << "expression_parser::Primary NUMBER " << v << " done" << std::endl;
334 }
335 if (f_v) {
336 N->print(std::cout);
337 }
338 return N;
339 }
340 else if (Lexer->type_ == NAME) {
341 std::string word = Lexer->word_;
342
343 N->f_terminal = true;
344 N->T = Lexer->T;
345 Lexer->T = 0L;
346
347 Lexer->GetToken (verbose_level, true);
348 if (Lexer->type_ == LHPAREN)
349 {
350 exit(1);
351 //return Function(verbose_level, word);
352 }
353
354 // not a function? must be a symbol in the symbol table
355 f_single_literal = true;
356 single_literal.assign(word);
357 //double & v = symbols_ [word]; // get REFERENCE to symbol table entry
358 // change table entry with expression? (eg. a = 22, or a = 22)
359#if 0
360 switch (Lexer.type_)
361 {
362 // maybe check for NaN or Inf here (see: isinf, isnan functions)
363 case ASSIGN: v = Expression (verbose_level, true); break;
364 case ASSIGN_ADD: v += Expression (verbose_level, true); break;
365 case ASSIGN_SUB: v -= Expression (verbose_level, true); break;
366 case ASSIGN_MUL: v *= Expression (verbose_level, true); break;
367 case ASSIGN_DIV:
368 {
369 if (f_v) {
370 std::cout << "Parser::Primary assignment" << std::endl;
371 }
372 double d = Expression (verbose_level, true);
373 if (d == 0.0)
374 throw std::runtime_error ("Divide by zero");
375 v /= d;
376 break; // change table entry with expression
377 } // end of ASSIGN_DIV
378 default: break; // do nothing for others
379 } // end of switch on type_
380#endif
381 if (f_v) {
382 std::cout << "expression_parser::Primary symbol " << word << std::endl;
383 }
384 if (f_v) {
385 N->print(std::cout);
386 }
387 return N; // and return new value
388 }
389 else if (Lexer->type_ == MINUS) {
390 // unary minus
391 if (f_v) {
392 std::cout << "expression_parser::Primary unary minus" << std::endl;
393 }
394 delete N;
395 N = Primary(verbose_level, f_single_literal, single_literal, f_has_seen_minus, true);
396 if (f_has_seen_minus) {
397 std::cout << "expression_parser::Primary double minus" << std::endl;
398 exit(1);
399 }
400 f_has_seen_minus = true;
401 return N;
402 }
403#if 0
404 else if (Lexer.type_ == NOT) {
405 // unary not
406 if (f_v) {
407 std::cout << "expression_parser::Primary unary not" << std::endl;
408 }
409 f_single_literal = true;
410 double val2 = (Primary (verbose_level, f_single_literal, single_literal, true) == 0.0) ? 1.0 : 0.0;
411 return N;
412 }
413#endif
414 else if (Lexer->type_ == LHPAREN) {
415 if (f_v) {
416 std::cout << "expression_parser::Primary left hand parenthesis, calling CommaList" << std::endl;
417 }
418 syntax_tree_node * N1 = CommaList (verbose_level, true); // inside parens, you could have commas
419 if (f_v) {
420 std::cout << "expression_parser::Primary left hand parenthesis, after CommaList" << std::endl;
421 }
422 Lexer->CheckToken (RHPAREN);
423 Lexer->GetToken (verbose_level, true); // eat the ')'
424 if (f_v) {
425 std::cout << "expression_parser::Primary left hand parenthesis done" << std::endl;
426 }
427 delete N;
428 if (f_v) {
429 N1->print(std::cout);
430 }
431 return N1;
432 }
433 else {
434 std::string remainder;
435
436 remainder.assign(Lexer->pWord_);
437 throw std::runtime_error ("Unexpected token: " + Lexer->word_ + " at " + remainder);
438 } // end of if on type
439
440 } // end of Parser::Primary
441
442#if 0
443syntax_tree_node *expression_parser::Term (int verbose_level, const bool get)
444// multiply and divide
445 {
446 int f_v = (verbose_level >= 1);
447 int f_single_literal;
448 std::string single_literal;
449 int *monomial;
450 int i;
452 int f_has_seen_minus;
453 int nb_minus_signs = 0;
454
455 if (f_v) {
456 std::cout << "expression_parser::Term" << std::endl;
457 }
458
459 if (Tree->managed_variables.size()) {
460 monomial = NEW_int(Tree->managed_variables.size());
461 int_vec_zero(monomial, Tree->managed_variables.size());
462 }
463
464 N = new syntax_tree_node;
465 N->Tree = Tree;
467 if (f_v) {
468 std::cout << "expression_parser::Term opening node " << N->idx << std::endl;
469 }
470 if (f_v) {
471 std::cout << "expression_parser::Term before Primary" << std::endl;
472 }
473 syntax_tree_node *left = Primary (verbose_level, f_single_literal, single_literal, f_has_seen_minus, get);
474 if (f_has_seen_minus) {
475 nb_minus_signs++;
476 }
477 if (f_v) {
478 std::cout << "expression_parser::Term after Primary, f_single_literal = " << f_single_literal << std::endl;
479 }
480 int f_done;
481 f_done = false;
482 if (Tree->managed_variables.size() && f_single_literal) {
483 i = Tree->identify_single_literal(single_literal);
484 if (i >= 0) {
485 monomial[i]++;
486 delete left;
487 f_done = true;
488 }
489 }
490 if (!f_done) {
491 N->nb_nodes = 1;
492 N->Nodes[0] = left;
493 if (f_v) {
494 std::cout << "expression_parser::Term first descendant of " << N->idx << " is node " << N->Nodes[0]->idx << std::endl;
495 }
496 }
497 while (true)
498 {
499 switch (Lexer.type_)
500 {
501 case MULTIPLY:
502 if (f_v) {
503 std::cout << "expression_parser::Term MULTIPLY, calling Primary" << std::endl;
504 }
505 syntax_tree_node * N2;
506 N2 = Primary (verbose_level, f_single_literal, single_literal, f_has_seen_minus, true);
507 if (f_v) {
508 std::cout << "Parser::Term MULTIPLY, after Primary, f_single_literal=" << f_single_literal << std::endl;
509 }
510 if (f_has_seen_minus) {
511 nb_minus_signs++;
512 }
513 f_done = false;
514 if (f_single_literal) {
515 std::cout << "single_literal = " << single_literal << std::endl;
516 if (Tree->managed_variables.size() && f_single_literal) {
517 i = Tree->identify_single_literal(single_literal);
518 if (i >= 0) {
519 monomial[i]++;
520 delete N2;
521 f_done = true;
522 }
523 }
524 }
525 if (!f_done) {
526 std::cout << "not a single_literal, N->nb_nodes=" << N->nb_nodes << std::endl;
527 {
528 N->Nodes[N->nb_nodes] = N2;
529 N->nb_nodes++;
530 if (ODD(nb_minus_signs)) {
531 N->f_has_minus = TRUE;
532 }
533 }
534 }
535 break;
536#if 0
537 case DIVIDE:
538 {
539 if (f_v) {
540 std::cout << "expression_parser::Term DIVIDE, calling Primary" << std::endl;
541 }
542 double d = Primary (verbose_level, f_single_literal, single_literal, true);
543 if (f_v) {
544 std::cout << "expression_parser::Term DIVIDE, after Primary" << std::endl;
545 }
546 if (d == 0.0)
547 throw std::runtime_error ("Divide by zero");
548 left /= d;
549 break;
550 }
551#endif
552 default:
553 if (Tree->managed_variables.size()) {
554 N->f_has_monomial = TRUE;
555 N->monomial = monomial;
556 }
557 if (f_v) {
558 std::cout << "expression_parser::Term before return, ";
559 N->print_without_recursion(std::cout);
560 if (N->f_has_monomial) {
561 Tree->print_monomial(std::cout, N->monomial);
562 }
563 std::cout << std::endl;
564 }
565 return N;
566 } // end of switch on type
567 } // end of loop
568 if (f_v) {
569 std::cout << "expression_parser::Term done" << std::endl;
570 }
571 } // end of Parser::Term
572#else
573syntax_tree_node *expression_parser::Term (int verbose_level, const bool get)
574// multiply and divide
575 {
576 int f_v = (verbose_level >= 1);
577 int f_single_literal;
578 std::string single_literal;
579 int *monomial;
580 int i;
582 int f_has_seen_minus;
583 int nb_minus_signs = 0;
584
585 if (f_v) {
586 std::cout << "expression_parser::Term" << std::endl;
587 }
588
589 monomial = NEW_int(Tree->managed_variables.size());
590 Int_vec_zero(monomial, Tree->managed_variables.size());
591
592 N = new syntax_tree_node;
593 N->Tree = Tree;
595 if (f_v) {
596 std::cout << "expression_parser::Term opening node " << N->idx << std::endl;
597 }
598 if (f_v) {
599 std::cout << "expression_parser::Term before Primary" << std::endl;
600 }
601 syntax_tree_node *left = Primary (verbose_level, f_single_literal, single_literal, f_has_seen_minus, get);
602 if (f_has_seen_minus) {
603 nb_minus_signs++;
604 }
605 if (f_v) {
606 std::cout << "expression_parser::Term after Primary, f_single_literal = " << f_single_literal << std::endl;
607 }
608 int f_done;
609 f_done = false;
610 if (f_single_literal) {
611 i = Tree->identify_single_literal(single_literal);
612 if (i >= 0) {
613 monomial[i]++;
614 delete left;
615 f_done = true;
616 }
617 }
618 if (!f_done) {
619 N->nb_nodes = 1;
620 N->Nodes[0] = left;
621 if (f_v) {
622 std::cout << "expression_parser::Term first descendant of " << N->idx << " is node " << N->Nodes[0]->idx << std::endl;
623 }
624 }
625 while (true)
626 {
627 switch (Lexer->type_)
628 {
629 case MULTIPLY:
630 if (f_v) {
631 std::cout << "expression_parser::Term MULTIPLY, calling Primary" << std::endl;
632 }
633 syntax_tree_node * N2;
634 N2 = Primary (verbose_level, f_single_literal, single_literal, f_has_seen_minus, true);
635 if (f_v) {
636 std::cout << "Parser::Term MULTIPLY, after Primary, f_single_literal=" << f_single_literal << std::endl;
637 }
638 if (f_has_seen_minus) {
639 nb_minus_signs++;
640 }
641 f_done = false;
642 if (f_single_literal) {
643 if (f_v) {
644 std::cout << "single_literal = " << single_literal << std::endl;
645 }
646 if (f_single_literal) {
647 i = Tree->identify_single_literal(single_literal);
648 if (i >= 0) {
649 monomial[i]++;
650 delete N2;
651 f_done = true;
652 }
653 }
654 }
655 if (!f_done) {
656 if (f_v) {
657 std::cout << "not a single_literal, N->nb_nodes=" << N->nb_nodes << std::endl;
658 }
659 {
660 N->Nodes[N->nb_nodes] = N2;
661 N->nb_nodes++;
662 if (ODD(nb_minus_signs)) {
663 N->f_has_minus = TRUE;
664 }
665 }
666 }
667 break;
668#if 0
669 case DIVIDE:
670 {
671 if (f_v) {
672 std::cout << "expression_parser::Term DIVIDE, calling Primary" << std::endl;
673 }
674 double d = Primary (verbose_level, f_single_literal, single_literal, true);
675 if (f_v) {
676 std::cout << "expression_parser::Term DIVIDE, after Primary" << std::endl;
677 }
678 if (d == 0.0)
679 throw std::runtime_error ("Divide by zero");
680 left /= d;
681 break;
682 }
683#endif
684 default:
685 N->monomial = monomial;
686 N->f_has_monomial = TRUE;
687 if (f_v) {
688 std::cout << "expression_parser::Term before return ";
689 if (N->f_has_monomial) {
690 Tree->print_monomial(std::cout, N->monomial);
691 }
692 std::cout << std::endl;
693 std::cout << "expression_parser::Term created the following node:" << endl;
694 N->print_without_recursion(std::cout);
695 std::cout << "expression_parser::Term done" << endl;
696 }
697 return N;
698 } // end of switch on type
699 } // end of loop
700 if (f_v) {
701 std::cout << "expression_parser::Term done" << std::endl;
702 }
703 } // end of Parser::Term
704
705#endif
706
707syntax_tree_node *expression_parser::AddSubtract (int verbose_level, const bool get)
708// add and subtract
709 {
710 int f_v = (verbose_level >= 1);
712
713 if (f_v) {
714 std::cout << "expression_parser::AddSubtract" << std::endl;
715 }
716 N = new syntax_tree_node;
718 N->Tree = Tree;
719 if (f_v) {
720 std::cout << "expression_parser::AddSubtract opening node " << N->idx << std::endl;
721 }
722 if (f_v) {
723 std::cout << "expression_parser::AddSubtract before Term" << std::endl;
724 }
725 syntax_tree_node *left = Term (verbose_level, get);
726 N->nb_nodes = 1;
727 N->Nodes[0] = left;
728 if (f_v) {
729 std::cout << "expression_parser::AddSubtract after Term" << std::endl;
730 }
731 while (true)
732 {
733 switch (Lexer->type_)
734 {
735 case PLUS:
736 if (f_v) {
737 std::cout << "expression_parser::AddSubtract PLUS before Term" << std::endl;
738 }
739 //syntax_tree_node *N2;
740 left = Term (verbose_level, true);
741 {
742 N->Nodes[N->nb_nodes] = left;
743 N->nb_nodes++;
744 }
745 if (f_v) {
746 std::cout << "expression_parser::AddSubtract PLUS after Term" << std::endl;
747 }
748 break;
749 case MINUS:
750 if (f_v) {
751 std::cout << "expression_parser::AddSubtract MINUS before Term" << std::endl;
752 }
753 left = Term (verbose_level, true);
754 if (f_v) {
755 std::cout << "expression_parser::AddSubtract MINUS after Term" << std::endl;
756 }
757 {
758 N->Nodes[N->nb_nodes] = left;
759 N->nb_nodes++;
760 if (f_v) {
761 std::cout << "expression_parser::AddSubtract pushing a minus" << std::endl;
762 }
763 left->push_a_minus_sign();
764 }
765 break;
766 default:
767 if (f_v) {
768 std::cout << "expression_parser::AddSubtract before return" << std::endl;
769 }
770 if (f_v) {
771 N->print_without_recursion(std::cout);
772 }
773 return N;
774 } // end of switch on type
775 } // end of loop
776 if (f_v) {
777 std::cout << "expression_parser::AddSubtract done" << std::endl;
778 }
779 } // end of Parser::AddSubtract
780
781syntax_tree_node *expression_parser::Comparison (int verbose_level, const bool get) // LT, GT, LE, EQ etc.
782 {
783 syntax_tree_node *left = AddSubtract (verbose_level, get);
784#if 0
785 while (true)
786 {
787 switch (Lexer.type_)
788 {
789 case LT: left = left < AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
790 case GT: left = left > AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
791 case LE: left = left <= AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
792 case GE: left = left >= AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
793 case EQ: left = left == AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
794 case NE: left = left != AddSubtract (verbose_level, true) ? 1.0 : 0.0; break;
795 default: return left;
796 } // end of switch on type
797 } // end of loop
798#endif
799 return left;
800 } // end of Parser::Comparison
801
802syntax_tree_node *expression_parser::Expression (int verbose_level, const bool get) // AND and OR
803 {
804 int f_v = (verbose_level >= 1);
805 //syntax_tree_node *N;
806
807 if (f_v) {
808 std::cout << "expression_parser::Expression" << std::endl;
809 }
810 if (f_v) {
811 std::cout << "expression_parser::Expression before Comparison" << std::endl;
812 }
813 syntax_tree_node *left = Comparison (verbose_level, get);
814 if (f_v) {
815 std::cout << "expression_parser::Expression after Comparison" << std::endl;
816 }
817#if 0
818 if (f_v) {
819 std::cout << "expression_parser::Expression after Comparison" << std::endl;
820 }
821 while (true)
822 {
823 switch (Lexer.type_)
824 {
825 case AND:
826 {
827 if (f_v) {
828 std::cout << "expression_parser::Expression AND before Comparison" << std::endl;
829 }
830 syntax_tree_node *N2 = Comparison (verbose_level, true); // don't want short-circuit evaluation
831 if (f_v) {
832 std::cout << "expression_parser::Expression AND after Comparison" << std::endl;
833 }
834 //left = (left != 0.0) && (d != 0.0);
835 N = new syntax_tree_node;
836 N->nb_nodes = 2;
837 N->Nodes = new syntax_tree_node [2];
838 N->Nodes[0] = *left;
839 left->null();
840 delete left;
841 }
842 break;
843 case OR:
844 {
845 if (f_v) {
846 std::cout << "expression_parser::Expression OR before Comparison" << std::endl;
847 }
848 syntax_tree_node *N2 = Comparison (verbose_level, true); // don't want short-circuit evaluation
849 if (f_v) {
850 std::cout << "expression_parser::Expression OR after Comparison" << std::endl;
851 }
852 //left = (left != 0.0) || (d != 0.0);
853 }
854 break;
855 default:
856 if (f_v) {
857 std::cout << "expression_parser::Expression before return" << std::endl;
858 }
859 return left;
860 } // end of switch on type
861 } // end of loop
862#endif
863
864 if (f_v) {
865 std::cout << "expression_parser::Expression:" << std::endl;
866 left->print_without_recursion(std::cout);
867 }
868
869
870 return left;
871 } // end of Parser::Expression
872
873syntax_tree_node *expression_parser::CommaList (int verbose_level, const bool get) // expr1, expr2
874 {
875 int f_v = (verbose_level >= 1);
876
877 if (f_v) {
878 std::cout << "expression_parser::CommaList" << std::endl;
879 }
880 if (f_v) {
881 std::cout << "expression_parser::CommaList before Expression" << std::endl;
882 }
883 syntax_tree_node *left = Expression (verbose_level, get);
884 if (f_v) {
885 std::cout << "expression_parser::CommaList after Expression" << std::endl;
886 }
887
888 if (f_v) {
889 std::cout << "expression_parser::CommaList:" << std::endl;
890 left->print_without_recursion(std::cout);
891 }
892 return left;
893#if 0
894 while (true)
895 {
896 switch (Lexer.type_)
897 {
898 case COMMA:
899 if (f_v) {
900 std::cout << "expression_parser::CommaList COMMA, before Expression" << std::endl;
901 }
902 left = Expression (verbose_level, true);
903 if (f_v) {
904 std::cout << "expression_parser::CommaList COMMA, after Expression" << std::endl;
905 }
906 break; // discard previous value
907 default:
908 if (f_v) {
909 std::cout << "expression_parser::CommaList done" << std::endl;
910 }
911 return left;
912 } // end of switch on type
913 } // end of loop
914#endif
915 } // end of Parser::CommaList
916
917void expression_parser::parse (syntax_tree *tree, std::string & program, int verbose_level)
918 {
919 int f_v = (verbose_level >= 1);
920
921 if (f_v) {
922 std::cout << "expression_parser::parse" << std::endl;
923 }
924 Lexer = NEW_OBJECT(lexer);
925 Tree = tree;
926 Lexer->program_ = program;
927 Lexer->pWord_ = Lexer->program_.c_str ();
928 Lexer->type_ = NONE;
929 if (f_v) {
930 std::cout << "expression_parser::parse before CommaList" << std::endl;
931 }
932 Tree->Root = CommaList (verbose_level, true);
933 if (f_v) {
934 std::cout << "expression_parser::parse after CommaList" << std::endl;
935 }
936 if (Lexer->type_ != END)
937 throw std::runtime_error ("Unexpected text at end of expression: " + std::string (Lexer->pWordStart_));
938 }
939
940
941}}}
942
943
syntax_tree_node * CommaList(int verbose_level, const bool get)
syntax_tree_node * AddSubtract(int verbose_level, const bool get)
syntax_tree_node * Term(int verbose_level, const bool get)
syntax_tree_node * Primary(int verbose_level, int &f_single_literal, std::string &single_literal, int &f_has_seen_minus, const bool get)
syntax_tree_node * Expression(int verbose_level, const bool get)
syntax_tree_node * Comparison(int verbose_level, const bool get)
TokenType GetToken(int verbose_level, const bool ignoreSign=false)
Definition: lexer.cpp:124
void print_monomial(std::ostream &ost, int *monomial)
Definition: syntax_tree.cpp:33
int identify_single_literal(std::string &single_literal)
Definition: syntax_tree.cpp:47
#define STD_FUNCTION(arg)
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define TRUE
Definition: foundations.h:231
#define ODD(x)
Definition: foundations.h:222
const double(* TwoArgFunction)(const double arg1, const double arg2)
const double(* ThreeArgFunction)(const double arg1, const double arg2, const double arg3)
the orbiter library for the classification of combinatorial objects