C++ Mathematical Expression Toolkit (ExprTk) release
Loading...
Searching...
No Matches
exprtk_repl.cpp
Go to the documentation of this file.
1/*
2 **************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * ExprTk REPL (Read Evaluate Print Loop) Interface *
6 * Author: Arash Partow (1999-2025) *
7 * URL: https://www.partow.net/programming/exprtk/index.html *
8 * *
9 * Copyright notice: *
10 * Free use of the Mathematical Expression Toolkit Library is *
11 * permitted under the guidelines and in accordance with the *
12 * most current version of the MIT License. *
13 * https://www.opensource.org/licenses/MIT *
14 * SPDX-License-Identifier: MIT *
15 * *
16 **************************************************************
17*/
18
19
20#include <algorithm>
21#include <cstdio>
22#include <deque>
23#include <fstream>
24#include <iostream>
25#include <numeric>
26#include <string>
27
28#include "exprtk.hpp"
29
30
31template <typename T>
32struct putch : public exprtk::ifunction<T>
33{
34 using exprtk::ifunction<T>::operator();
35
36 putch() : exprtk::ifunction<T>(1) {}
37
38 inline T operator()(const T& v)
39 {
40 printf("%c",static_cast<int>(v));
41 return T(0);
42 }
43};
44
45template <typename T>
46struct putint : public exprtk::ifunction<T>
47{
48 using exprtk::ifunction<T>::operator();
49
50 putint() : exprtk::ifunction<T>(1) {}
51
52 inline T operator()(const T& v)
53 {
54 printf("%d",static_cast<int>(v));
55 return T(0);
56 }
57};
58
59template <typename T>
60struct rnd_01 : public exprtk::ifunction<T>
61{
62 using exprtk::ifunction<T>::operator();
63
65 { ::srand(static_cast<unsigned int>(time(NULL))); }
66
67 inline T operator()()
68 {
69 // Note: Do not use this in production
70 // Result is in the interval [0,1)
71 return T(::rand() / T(RAND_MAX + 1.0));
72 }
73};
74
76{
78 {
79 printf("Runtime vector access violation\n"
80 "base: %p end: %p access: %p typesize: %d\n",
81 context.base_ptr ,
82 context.end_ptr ,
83 context.access_ptr ,
84 static_cast<unsigned int>(context.type_size));
85
86 throw std::runtime_error("Runtime vector access violation.");
87 return false;
88 }
89};
90
91template <typename T>
93{
94public:
95
104
105 typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
106 typedef std::vector<symbol_t> symbol_list_t;
107
109 : persist_symbol_table_ (false)
110 , symbol_dump_ (false)
111 , assignment_dump_ (false)
112 , display_total_time_ (false)
114 , enable_usr_ (false)
115 , disable_local_vardef_ (false)
117 , batch_runs_cnt_ (0 )
119 #ifdef exprtk_enable_repl_variables
120 , s0_("abcdefghijk")
121 , s1_("abcdefghijk0123456789")
122 , s2_("012345678901234567890123456789")
123 , v0_({ 1, 1, 1 })
124 , v1_({ 2, 2, 2, 2, 2})
125 , v2_({ 3, 3, 3, 3, 3, 3, 3})
126 , v3_({ 4, 4, 4, 4, 4, 4, 4, 4})
127 , vv_(exprtk::make_vector_view(v2_,v2_.size()))
128 #endif
129 {
130 symbol_table_.add_constants();
131
132 symbol_table_.add_function("putch" , putch_ );
133 symbol_table_.add_function("putint" , putint_ );
134 symbol_table_.add_function("rnd_01" , rnd_01_ );
135 symbol_table_.add_package (fileio_package_ );
136 symbol_table_.add_package (vecops_package_ );
137 symbol_table_.add_package (io_package_ );
138
139 symbol_table_.add_function("poly01", poly01_);
140 symbol_table_.add_function("poly02", poly02_);
141 symbol_table_.add_function("poly03", poly03_);
142 symbol_table_.add_function("poly04", poly04_);
143 symbol_table_.add_function("poly05", poly05_);
144 symbol_table_.add_function("poly06", poly06_);
145 symbol_table_.add_function("poly07", poly07_);
146 symbol_table_.add_function("poly08", poly08_);
147 symbol_table_.add_function("poly09", poly09_);
148 symbol_table_.add_function("poly10", poly10_);
149 symbol_table_.add_function("poly11", poly11_);
150 symbol_table_.add_function("poly12", poly12_);
151
152 #ifdef exprtk_enable_repl_variables
153 symbol_table_.add_stringvar("s0", s0_);
154 symbol_table_.add_stringvar("s1", s1_);
155 symbol_table_.add_stringvar("s2", s2_);
156 symbol_table_.add_vector ("v0", v0_);
157 symbol_table_.add_vector ("v1", v1_);
158 symbol_table_.add_vector ("v2", v2_);
159 symbol_table_.add_vector ("v3", v3_);
160
161 vv_ = exprtk::make_vector_view(v2_,v2_.size());
162 symbol_table_.add_vector ("vv", vv_);
163 #endif
164
165 compositor_.add_auxiliary_symtab(symbol_table_);
166
173
180
189
191 }
192
197
199 {
201 }
202
204 {
205 return symbol_dump_;
206 }
207
209 {
210 return assignment_dump_;
211 }
212
214 {
215 return display_total_time_;
216 }
217
222
224 {
225 return enable_usr_;
226 }
227
229 {
231 }
232
237
239 {
241 {
242 symbol_table_.clear_variables();
243 symbol_table_.add_constants ();
245 }
246 }
247
248 void process(std::string program)
249 {
250 program = trim_whitespace(program);
251
252 if (program.empty())
253 return;
254
256
257 expression_t expression;
260
261 exprtk::timer compile_timer;
262 compile_timer.start();
263
264 if (enable_usr_)
265 parser_.enable_unknown_symbol_resolver();
266 else
267 parser_.disable_unknown_symbol_resolver();
268
270 parser_.settings().disable_local_vardef();
271 else
272 parser_.settings().enable_local_vardef();
273
275 parser_.settings().disable_commutative_check();
276 else
277 parser_.settings().enable_commutative_check();
278
279 parser_.dec().collect_variables() = symbol_dump_;
280 parser_.dec().collect_functions() = symbol_dump_;
281
282 parser_.dec().collect_assignments() = assignment_dump_;
283
284 parser_.register_vector_access_runtime_check(vector_access_rtc_);
285
286 if (!parser_.compile(program,expression))
287 {
288 printf("Error: %s\tExpression:%c%s\n",
289 parser_.error().c_str(),
290 ((std::string::npos != program.find_first_of('\n')) ? '\n' : ' '),
291 ((program.size() < 200) ? program.c_str() : "....."));
292
293 for (std::size_t i = 0; i < parser_.error_count(); ++i)
294 {
295 error_t error = parser_.get_error(i);
296
297 printf("Err No.: %02d Pos: %02d Type: [%14s] Msg: %s\n",
298 static_cast<unsigned int>(i),
299 static_cast<unsigned int>(error.token.position),
300 exprtk::parser_error::to_str(error.mode).c_str(),
301 error.diagnostic.c_str());
302
303 if (
304 (0 == i) &&
306 )
307 {
308 printf("Error (line: %d column: %d)\n",
309 static_cast<unsigned int>(error.line_no),
310 static_cast<unsigned int>(error.column_no));
311
312 printf("%s \n",error.error_line.c_str());
313 printf("%s^\n",std::string(error.column_no,'~').c_str());
314 }
315 }
316
317 return;
318 }
319
320 compile_timer.stop();
321
323 {
324 printf("\nCompile time: %6.3fms\n",compile_timer.time() * 1000.0);
325 }
326
327 if (batch_runs_cnt_)
328 {
329 std::vector<double> timings(batch_runs_cnt_,0.0);
330
331 exprtk::timer total_timer;
332 exprtk::timer timer;
333
334 T result = T(0);
335
336 total_timer.start();
337
338 for (std::size_t i = 0; i < batch_runs_cnt_; ++i)
339 {
340 timer.start();
341
342 result = expression.value();
343
344 timer.stop();
345
346 timings[i] = timer.time() * 1000.0;
347 }
348
349 total_timer.stop();
350
351 printf("\nResult: %15.9f\n",result);
352
353 std::sort(timings.begin(),timings.end());
354
355 printf("\nRuns: %4d Time min: %7.3fms max: %7.3fms avg: %7.3fms tot: %7.3fms 90%%:%7.3fms\n",
356 static_cast<unsigned int>(batch_runs_cnt_),
357 timings.front(),
358 timings.back (),
359 std::accumulate(timings.begin(),timings.end(),0.0) / timings.size(),
360 total_timer.time() * 1000.0,
361 timings[static_cast<int>(timings.size() * 0.90)]);
362
363 return;
364 }
365
366 exprtk::timer timer;
367 timer.start();
368
369 const T result = expression.value();
370
371 timer.stop();
372
373 if (expression.results().count())
374 {
375 print_results(expression.results());
376 }
377
378 printf("\nResult: %15.9f\n",result);
379
381 {
382 printf("\nTotal time: %6.3fms\n",timer.time() * 1000.0);
383 }
384
385 if (symbol_dump_)
386 {
387 symbol_list_t symbol_list;
388
389 parser_.dec().symbols(symbol_list);
390
391 printf("------ Symbols ------\n");
392 perform_symbol_dump(symbol_list);
393 printf("---------------------\n");
394 }
395
397 {
398 symbol_list_t assignment_list;
399
400 parser_.dec().assignment_symbols(assignment_list);
401
402 printf("---- Assignments ----\n");
403 perform_symbol_dump(assignment_list);
404 printf("---------------------\n");
405 }
406 }
407
408 void process_from_file(const std::string& file_name)
409 {
410 if (file_name.empty())
411 return;
412
413 std::ifstream stream(file_name.c_str());
414
415 if (!stream)
416 {
417 printf("ERROR: Failed to open file: %s\n\n",file_name.c_str());
418 return;
419 }
420
421 std::string program(
422 (std::istreambuf_iterator<char>(stream)),
423 (std::istreambuf_iterator<char>())
424 );
425
426 process_function_definition(program,false);
427 }
428
429 void process_directive(std::string expression)
430 {
431 expression = trim_whitespace(expression);
432
433 if ('$' != expression[0])
434 return;
435 else if ("$enable_cache" == expression)
436 persist_symbol_table() = true;
437 else if ("$disable_cache" == expression)
438 persist_symbol_table() = false;
439 else if ("$enable_symbol_dump" == expression)
440 symbol_dump() = true;
441 else if ("$disable_symbol_dump" == expression)
442 symbol_dump() = false;
443 else if ("$enable_assignment_dump" == expression)
444 assignment_dump() = true;
445 else if ("$disable_assignment_dump" == expression)
446 assignment_dump() = false;
447 else if ("$enable_timer" == expression)
448 display_total_time() = true;
449 else if ("$enable_compile_timer" == expression)
451 else if ("$disable_timer" == expression)
452 display_total_time() = false;
453 else if ("$disable_compile_timer" == expression)
455 else if ("$enable_usr" == expression)
456 enable_usr() = true;
457 else if ("$disable_usr" == expression)
458 enable_usr() = false;
459 else if ("$enable_local_vardef" == expression)
460 disable_local_vardef() = false;
461 else if ("$disable_local_vardef" == expression)
462 disable_local_vardef() = true;
463 else if ("$enable_commutative_check" == expression)
465 else if ("$disable_commutative_check" == expression)
467 else if ("$list_vars" == expression)
468 list_symbols();
469 else if ("$clear_functions" == expression)
471 else if ((0 == expression.find("$batch_run ")) && (expression.size() >= 12))
472 process_batch_run(expression.substr(11,expression.size() - 11));
473 else if ((0 == expression.find("$load ")) && (expression.size() > 7))
474 process_from_file(expression.substr(6,expression.size() - 6));
475 else if ((0 == expression.find("$disable arithmetic ")) && (expression.size() >= 21))
476 process_disable_arithmetic(expression.substr(20,expression.size() - 20));
477 else if ((0 == expression.find("$disable assignment ")) && (expression.size() >= 21))
478 process_disable_assignment(expression.substr(20,expression.size() - 20));
479 else if ((0 == expression.find("$disable inequality ")) && (expression.size() >= 21))
480 process_disable_inequality(expression.substr(20,expression.size() - 20));
481 else if ((0 == expression.find("$enable arithmetic ")) && (expression.size() >= 20))
482 process_enable_arithmetic(expression.substr(19,expression.size() - 19));
483 else if ((0 == expression.find("$enable assignment ")) && (expression.size() >= 20))
484 process_enable_assignment(expression.substr(19,expression.size() - 19));
485 else if ((0 == expression.find("$enable inequality ")) && (expression.size() >= 20))
486 process_enable_inequality(expression.substr(19,expression.size() - 19));
487 else if ("$begin" == expression)
489 else if (0 == expression.find("$function"))
490 process_function_definition(expression);
491 else
492 printf("\nERROR - Invalid directive: %s\n",expression.c_str());
493 }
494
495private:
496
498 {
499 typedef exprtk::results_context<T> results_context_t;
500 typedef typename results_context_t::type_store_t type_t;
501 typedef typename type_t::scalar_view scalar_t;
502 typedef typename type_t::vector_view vector_t;
503 typedef typename type_t::string_view string_t;
504
506
507 printf("%s\n",std::string(10,'-').c_str());
508 printf("Return Results (#%d)\n",static_cast<int>(results.count()));
509
510 for (std::size_t i = 0; i < results.count(); ++i)
511 {
512 printf("[%02d] ",static_cast<int>(i));
513
514 type_t t = results[i];
515
516 switch (t.type)
517 {
518 case type_t::e_scalar : printf("Scalar\t");
519 exprtk::rtl::io::details::print_type("%10.5f",scalar_t(t)(),num_type);
520 break;
521
522 case type_t::e_vector : {
523 printf("Vector\t");
524 vector_t vector(t);
525
526 for (std::size_t x = 0; x < vector.size(); ++x)
527 {
528 exprtk::rtl::io::details::print_type("%10.5f",vector[x],num_type);
529
530 if ((x + 1) < vector.size())
531 printf(" ");
532 }
533 }
534 break;
535
536 case type_t::e_string : printf("String\t");
537 printf("%s",to_str(string_t(t)).c_str());
538 break;
539
540 default : continue;
541 }
542
543 printf("\n");
544 }
545
546 printf("%s\n",std::string(10,'-').c_str());
547 }
548
549 void perform_symbol_dump(const symbol_list_t& variable_list) const
550 {
551 for (std::size_t i = 0; i < variable_list.size(); ++i)
552 {
553 const symbol_t& symbol = variable_list[i];
554
555 switch (symbol.second)
556 {
557 case parser_t::e_st_variable : printf("[%02d] Variable %s\n",
558 static_cast<int>(i),symbol.first.c_str());
559 break;
560
561 case parser_t::e_st_vector : printf("[%02d] Vector %s\n",
562 static_cast<int>(i),symbol.first.c_str());
563 break;
564
565 case parser_t::e_st_string : printf("[%02d] String %s\n",
566 static_cast<int>(i),symbol.first.c_str());
567 break;
568
569 case parser_t::e_st_function : printf("[%02d] Function %s\n",
570 static_cast<int>(i),symbol.first.c_str());
571 break;
572
574 : printf("[%02d] LocalVar %s\n",
575 static_cast<int>(i),symbol.first.c_str());
576 break;
577
579 : printf("[%02d] LocalVec %s\n",
580 static_cast<int>(i),symbol.first.c_str());
581 break;
582
584 : printf("[%02d] LocalStr %s\n",
585 static_cast<int>(i),symbol.first.c_str());
586 break;
587
588 default : break;
589 }
590 }
591 }
592
593 void process_batch_run(const std::string& batch_runs_cnt)
594 {
595 batch_runs_cnt_ = atoi(batch_runs_cnt.c_str());
596 }
597
599 {
600 std::string program;
601
602 for ( ; ; )
603 {
604 std::string line;
605
606 std::cout << ">> ";
607 std::getline(std::cin,line);
608
609 line = trim_whitespace(line);
610
611 if (line.empty())
612 continue;
613 else if ("$end" == line)
614 break;
615 else
616 program += (line + "\n");
617 }
618
619 process(program);
620 }
621
622 struct function_definition
623 {
624 std::string name;
625 std::string body;
626 std::vector<std::string> var_list;
627
628 void clear()
629 {
630 name .clear();
631 body .clear();
632 var_list.clear();
633 }
634 };
635
637 {
638 e_parse_unknown = 0,
639 e_parse_success = 1,
640 e_parse_partial = 2,
641 e_parse_lexfail = 4,
643 };
644
645 struct parse_function_definition_impl : public exprtk::lexer::parser_helper
646 {
648 {
649 if (!init(func_def))
650 return e_parse_lexfail;
651
652 if (!token_is(token_t::e_symbol,"function"))
653 return e_parse_notfunc;
654
656 return e_parse_partial;
657
658 fd.name = current_token().value;
659
660 next_token();
661
663 return e_parse_partial;
664
666 {
667 std::vector<std::string> var_list;
668
669 for ( ; ; )
670 {
671 // (x,y,z,....w)
673 return e_parse_partial;
674
675 var_list.push_back(current_token().value);
676
677 next_token();
678
680 break;
681
683 return e_parse_partial;
684 }
685
686 var_list.swap(fd.var_list);
687 }
688
689 const std::size_t body_begin = current_token().position;
690 std::size_t body_end = current_token().position;
691
692 int bracket_stack = 0;
693
695 return e_parse_partial;
696
697 for ( ; ; )
698 {
699 body_end = current_token().position;
700
702 bracket_stack++;
704 {
705 if (0 == --bracket_stack)
706 break;
707 }
708 else
709 {
710 if (lexer().finished())
711 return e_parse_partial;
712
713 next_token();
714 }
715 }
716
717 const std::size_t size = body_end - body_begin + 1;
718
719 fd.body = func_def.substr(body_begin,size);
720
721 const std::size_t index = body_begin + size;
722
723 if (index < func_def.size())
724 func_def = func_def.substr(index,func_def.size() - index);
725 else
726 func_def = "";
727
728 return e_parse_success;
729 }
730 };
731
733 {
735 return parser.process(func_def,cf);
736 }
737
738 std::string read_from_stdin()
739 {
740 std::string input;
741
742 for ( ; ; )
743 {
744 std::string line;
745
746 std::cout << ">> ";
747 std::getline(std::cin,line);
748
749 if (line.empty())
750 continue;
751 else if ("$end" == line)
752 break;
753 else
754 input += (line + "\n");
755 }
756
757 if (!input.empty())
758 input.erase(input.end() - 1);
759
760 return input;
761 }
762
763 void process_function_definition(const std::string& func_def_header, bool read_stdin = true)
764 {
765 std::string func_def = func_def_header;
766
767 if (read_stdin)
768 {
769 func_def += read_from_stdin();
770
771 if (!func_def.empty() && ('$' == func_def[0]))
772 func_def.erase(func_def.begin());
773 }
774
775 do
776 {
778
779 func_parse_result fp_result = parse_function_definition(func_def,fd);
780
781 if (e_parse_success == fp_result)
782 {
783 std::string vars;
784
785 for (std::size_t i = 0; i < fd.var_list.size(); ++i)
786 {
787 vars += fd.var_list[i] + ((i < fd.var_list.size() - 1) ? "," : "");
788 }
789
790 function_t f(fd.name);
791
792 for (std::size_t i = 0; i < fd.var_list.size(); ++i)
793 {
794 f.var(fd.var_list[i]);
795 }
796
797 f.expression(fd.body);
798
799 if (function_symbol_table_.get_function(fd.name))
800 {
801 function_symbol_table_.remove_function(fd.name);
802
803 for (std::size_t i = 0; i < func_def_list_.size(); ++i)
804 {
805 if (exprtk::details::imatch(fd.name, func_def_list_[i].name))
806 {
807 func_def_list_.erase(func_def_list_.begin() + i);
808
809 break;
810 }
811 }
812 }
813
814 if (!compositor_.add(f,true))
815 {
816 function_symbol_table_.remove_function(fd.name);
817
818 printf("Error - Failed to add function: %s\n",fd.name.c_str());
819
820 return;
821 }
822
823 printf("Function[%02d]\n",static_cast<int>(func_def_list_.size()));
824 printf("Name: %s \n",fd.name.c_str() );
825 printf("Vars: (%s) \n",vars.c_str() );
826 printf("------------------------------------------------------\n");
827
828 func_def_list_.push_back(fd);
829 }
830 else if (e_parse_notfunc != fp_result)
831 {
832 printf("Error - Critical parsing error - partial parse occurred\n");
833 return;
834 }
835 else
836 break;
837 }
838 while (!func_def.empty());
839
840 if (!func_def.empty())
841 {
842 process(func_def);
843 }
844 }
845
847 {
848 std::deque<std::pair<std::string,T> > variable_list;
849 symbol_table_.get_variable_list(variable_list);
850
851 std::size_t max_varname_length = 0;
852
853 for (std::size_t i = 0; i < variable_list.size(); ++i)
854 {
855 max_varname_length = std::max(max_varname_length,variable_list[i].first.size());
856 }
857
858 for (std::size_t i = 0; i < variable_list.size(); ++i)
859 {
860 int pad_length = 0;
861
862 if (max_varname_length > variable_list[i].first.size())
863 {
864 pad_length = static_cast<int>(max_varname_length - variable_list[i].first.size());
865 }
866
867 printf("%02d %s%*.*s %25.10f\n",
868 static_cast<unsigned int>(i),
869 variable_list[i].first.c_str(),
870 pad_length,
871 pad_length,
872 std::string(max_varname_length,' ').c_str(),
873 variable_list[i].second);
874 }
875 }
876
878 {
879 func_def_list_.clear();
881 }
882
883 std::string trim_whitespace(std::string s)
884 {
885 static const std::string whitespace(" \n\r\t\b\v\f");
886
887 if (!s.empty())
888 {
889 s.erase(0,s.find_first_not_of(whitespace));
890
891 if (!s.empty())
892 {
893 std::size_t index = s.find_last_not_of(whitespace);
894
895 if (std::string::npos != index)
896 s.erase(index + 1);
897 else
898 s.clear();
899 }
900 }
901
902 return s;
903 }
904
905 void process_disable_arithmetic(const std::string& arithmetic)
906 {
907 typename std::map<std::string,typename settings_store_t::settings_arithmetic_opr>::iterator itr;
908
909 if (arith_opr_.end() != (itr = arith_opr_.find(arithmetic)))
910 {
911 parser_.settings()
912 .disable_arithmetic_operation(itr->second);
913 }
914 }
915
916 void process_disable_assignment(const std::string& assignment)
917 {
918 typename std::map<std::string,typename settings_store_t::settings_assignment_opr>::iterator itr;
919
920 if (assign_opr_.end() != (itr = assign_opr_.find(assignment)))
921 {
922 parser_.settings()
923 .disable_assignment_operation(itr->second);
924 }
925 }
926
927 void process_disable_inequality(const std::string& inequality)
928 {
929 typename std::map<std::string,typename settings_store_t::settings_inequality_opr>::iterator itr;
930
931 if (inequality_opr_.end() != (itr = inequality_opr_.find(inequality)))
932 {
933 parser_.settings()
934 .disable_inequality_operation(itr->second);
935 }
936 }
937
938 void process_enable_arithmetic(const std::string& arithmetic)
939 {
940 typename std::map<std::string,typename settings_store_t::settings_arithmetic_opr>::iterator itr;
941
942 if (arith_opr_.end() != (itr = arith_opr_.find(arithmetic)))
943 {
944 parser_.settings()
945 .enable_arithmetic_operation(itr->second);
946 }
947 }
948
949 void process_enable_assignment(const std::string& assignment)
950 {
951 typename std::map<std::string,typename settings_store_t::settings_assignment_opr>::iterator itr;
952
953 if (assign_opr_.end() != (itr = assign_opr_.find(assignment)))
954 {
955 parser_.settings()
956 .enable_assignment_operation(itr->second);
957 }
958 }
959
960 void process_enable_inequality(const std::string& inequality)
961 {
962 typename std::map<std::string,typename settings_store_t::settings_inequality_opr>::iterator itr;
963
964 if (inequality_opr_.end() != (itr = inequality_opr_.find(inequality)))
965 {
966 parser_.settings()
967 .enable_inequality_operation(itr->second);
968 }
969 }
970
971
972private:
973
975 bool symbol_dump_;
976 bool assignment_dump_;
979 bool enable_usr_;
982 std::size_t batch_runs_cnt_;
983
989
991 putint <T> putint_;
992 rnd_01 <T> rnd_01_;
996
1009
1010 std::vector<function_definition> func_def_list_;
1011
1012 std::map<std::string,typename settings_store_t::settings_arithmetic_opr> arith_opr_;
1013 std::map<std::string,typename settings_store_t::settings_assignment_opr> assign_opr_;
1014 std::map<std::string,typename settings_store_t::settings_inequality_opr> inequality_opr_;
1015
1016 #ifdef exprtk_enable_repl_variables
1017 std::string s0_;
1018 std::string s1_;
1019 std::string s2_;
1020 std::vector<T> v0_;
1021 std::vector<T> v1_;
1022 std::vector<T> v2_;
1023 std::vector<T> v3_;
1025 #endif
1026};
1027
1028template <typename T>
1029void repl(int argc, char* argv[])
1030{
1031 expression_processor<T> processor;
1032
1033 if (argc > 1)
1034 {
1035 for (int i = 1; i < argc; ++i)
1036 {
1037 processor.process_from_file(argv[i]);
1038 }
1039 }
1040 else
1041 {
1042 for ( ; ; )
1043 {
1044 std::string expression;
1045
1046 std::cout << ">> ";
1047 std::getline(std::cin,expression);
1048
1049 if (expression.empty())
1050 continue;
1051 else if ("exit" == expression)
1052 break;
1053 else if ("quit" == expression)
1054 break;
1055 else if ('$' == expression[0])
1056 processor.process_directive(expression);
1057 else
1058 processor.process(expression);
1059 }
1060 }
1061}
1062
1063int main(int argc, char* argv[])
1064{
1065 repl<double>(argc,argv);
1066 return 0;
1067}
1068
1069
1070/*
1071
1072REPL commands:
1073
1074 $enable_cache/$disable_cache
1075 Enable or disable caching of variables.
1076
1077 $enable_symbol_dump/$disable_symbol_dump
1078 Enable or disable dumping of symbols found in expression during
1079 compilation process.
1080
1081 $enable_assignment_dump/$disable_assignment_dump
1082 Enable or disable dumping of symbols that undergo assignment in
1083 expression.
1084
1085 $enable_timer/$disable_timer
1086 Enable or disable expression evaluation timer.
1087
1088 $enable_compile_timer/$disable_compile_timer
1089 Enable or disable compilation timer
1090
1091 $enable_usr/$disable_usr
1092 Enable or disable unknown symbol resolver.
1093
1094 $list_vars
1095 List variables found in the global symbol table.
1096
1097 $clear_functions
1098 Clear all functions found in the global function symbol table.
1099
1100 $load <program file name>
1101 Load the file as a complete program and execute.
1102
1103 $begin/$end
1104 Pre/post-ambles for multiline expressions.
1105
1106
1107Example REPL Instructions:
1108 Step 1.1 Enter: var x := 3; var y := 4; var z := x + y; println(z / 2);
1109 Step 1.2 Enter: var x := 3; var y := 4; var z := x - y; putint(z / 2);
1110
1111
1112 Step 2.Enter the following multi-line program:
1113 --- snip ---
1114
1115$begin
1116var x := 3;
1117var y := 4;
1118var z := sin(x / pi) * cos(y * pi);
1119println(z / 2);
1120$end
1121
1122 --- snip ---
1123
1124
1125 Step 3.1 Create a new file called mandelbrot.txt
1126 Step 3.2 Copy the contents between the snip lines into the file
1127 Step 3.3 Execute: ./exprtk_repl mandelbrot.txt
1128
1129
1130 Step 4.1 Execute: ./exprtk_repl
1131 Step 4.2 Enter: $load mandelbrot.txt
1132
1133---- snip ----
1134
1135var width := 118;
1136var height := 41;
1137var imag_max := +1;
1138var imag_min := -1;
1139var real_max := +1;
1140var real_min := -2.5;
1141var x_step := (real_max - real_min) / width;
1142var y_step := (imag_max - imag_min) / height;
1143
1144for (var y := 0; y < height; y += 1)
1145{
1146 var imag := imag_min + (y_step * y);
1147
1148 for (var x := 0; x < width; x += 1)
1149 {
1150 var real := real_min + x_step * x;
1151 var z_real := real;
1152 var z_imag := imag;
1153 var plot_value := 0;
1154
1155 for (var n := 0; n < 30; n += 1)
1156 {
1157 var a := z_real^2;
1158 var b := z_imag^2;
1159
1160 plot_value := n;
1161
1162 if ((a + b) < 4)
1163 {
1164 z_imag := 2 * z_real * z_imag + imag;
1165 z_real := a - b + real;
1166 }
1167 else
1168 break;
1169 };
1170
1171 putch(61 - plot_value);
1172
1173 };
1174
1175 println()
1176}
1177
1178---- snip ----
1179
1180
1181 Step 5.1 Copy into the REPL the contents of the snippet below:
1182---- snip ----
1183$function is_prime(x)
1184{
1185 if (x == 1)
1186 return [false];
1187 else if (x == 2)
1188 return [true];
1189 else if ((x % 2) == 0)
1190 return [false];
1191
1192 var upper_bound := sqrt(x) + 1;
1193
1194 for (var i := 3; i <= upper_bound; i += 2)
1195 {
1196 if (0 == (x % i))
1197 {
1198 return[false];
1199 }
1200 };
1201
1202 return [true];
1203}
1204$end
1205
1206$begin
1207for (var i := 1; i < 50; i += 1)
1208{
1209 if (is_prime(i))
1210 {
1211 println(i);
1212 }
1213}
1214$end
1215
1216---- snip ----
1217
1218
1219 Step 6.1 Copy into the REPL the contents of the snippet below:
1220---- snip ----
1221
1222$begin
1223var s := 'abcdefghijkl';
1224for (var i := 0; i < (s[] / 2); i+= 1)
1225{
1226 var j := s[] - i - 1;
1227 s[i:i + 1] <=> s[j:j + 1];
1228};
1229
1230println(s)
1231$end
1232
1233---- snip ----
1234
1235
1236 Step 7.1 Copy into the REPL the contents of the snippet below:
1237---- snip ----
1238$begin
1239var vec[11] := { -1, -2, 3, 5, 6, -2, -1, 4, -4, 2, -1 };
1240var zero := 0;
1241var max_sum := 0;
1242var max_start := 0;
1243var max_end := 0;
1244var curr_sum := 0;
1245var curr_start := 0;
1246
1247for (var i := 0; i < vec[]; i += 1)
1248{
1249 curr_sum += vec[i];
1250
1251 if (curr_sum < zero)
1252 {
1253 curr_sum := 0;
1254 curr_start := i + 1;
1255 }
1256 else if (curr_sum > max_sum)
1257 {
1258 max_sum := curr_sum;
1259 max_start := curr_start;
1260 max_end := i;
1261 }
1262}
1263
1264println('vec: ',vec);
1265
1266println('Max sum: ', max_sum );
1267println('Start index: ', max_start);
1268println('End index: ', max_end );
1269
1270for (var i := max_start; i <= max_end; i += 1)
1271{
1272 print(vec[i],' ');
1273}
1274$end
1275
1276---- snip ----
1277
1278
1279 Step 8.1 Copy into the REPL the contents of the snippet below:
1280---- snip ----
1281
1282$function is_prime(x)
1283{
1284 if (x <= 0)
1285 return [false];
1286 else if (frac(x) != 0)
1287 return [false];
1288 else
1289 {
1290 switch
1291 {
1292 case 1 == x : return [false];
1293 case 2 == x : return [true ];
1294 default :
1295 {
1296 var prime_lut[160] :=
1297 {
1298 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
1299 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
1300 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
1301 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
1302 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
1303 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
1304 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
1305 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
1306 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
1307 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
1308 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
1309 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
1310 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
1311 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
1312 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
1313 877, 881, 883, 887, 907, 911, 919, 929, 937, 941
1314 };
1315
1316 var upper_bound := min(x - 1,trunc(sqrt(x)) + 1);
1317
1318 for (var i := 0; i < prime_lut[]; i += 1)
1319 {
1320 if (prime_lut[i] >= upper_bound)
1321 return [true];
1322 else if ((x % prime_lut[i]) == 0)
1323 return [false];
1324 };
1325
1326 var lower_bound := prime_lut[prime_lut[] - 1] + 2;
1327
1328 for (var i := lower_bound; i < upper_bound; i += 2)
1329 {
1330 if ((x % i) == 0)
1331 {
1332 return [false];
1333 }
1334 }
1335 };
1336 }
1337 };
1338
1339 return [true];
1340}
1341
1342var prime_count := 0;
1343
1344for (var i := 1; i < 10^6; i += 1)
1345{
1346 if (is_prime(i))
1347 {
1348 prime_count += 1;
1349 }
1350};
1351
1352prime_count
1353$end
1354---- snip ----
1355
1356
1357Step 9.1 Copy into the REPL the contents of the snippet below:
1358---- snip ----
1359$begin
1360var file := open('file.txt','w');
1361var s := 'Hello world...\n';
1362
1363for (var i := 0; i < 10; i += 1)
1364{
1365 write(file,s);
1366};
1367
1368close(file);
1369
1370println('~~~~~~~~~~~~~~~~~~~~~~');
1371
1372file := open('file.txt','r');
1373var i := 0;
1374
1375while (not(eof(file)))
1376{
1377 s := getline(file);
1378
1379 if (s[] > 0)
1380 {
1381 println('[',i+=1,'] - ',s);
1382 }
1383};
1384
1385close(file);
1386$end
1387---- snip ----
1388
1389
1390Step 10.1 Copy into the REPL the contents of the snippet below:
1391---- snip ----
1392$begin
1393var v0[1000] := [rnd_01];
1394var v1[1000] := [0];
1395
1396~{
1397 var file := open('data.dat','w');
1398
1399 if (not(write(file,v0)))
1400 {
1401 println('failed to write vector 0\n');
1402 return [false];
1403 };
1404
1405 close(file);
1406 };
1407
1408~{
1409 var file := open('data.dat','r');
1410
1411 if (not(read(file,v1)))
1412 {
1413 println('failed to read vector 1\n');
1414 return [false];
1415 };
1416
1417 close(file);
1418 };
1419
1420if (sum(v0 != v1) > 0)
1421 println('error: v0 != v1');
1422else
1423{
1424 println('success: v0 == v1');
1425 println('sum(v0) = ',sum(v0),' avg(v0) = ',avg(v0));
1426 println('sum(v1) = ',sum(v1),' avg(v1) = ',avg(v1));
1427}
1428$end
1429---- snip ----
1430
1431
1432Step 11.1 Copy into the REPL the contents of the snippet below:
1433---- snip ----
1434$function fibonacci(x)
1435{
1436 switch
1437 {
1438 case x == 0 : 0;
1439 case x == 1 : 1;
1440 default :
1441 {
1442 var prev := 0;
1443 var curr := 1;
1444 while ((x -= 1) > 0)
1445 {
1446 curr += (curr <=> prev);
1447 };
1448 };
1449 }
1450}
1451
1452for (var i := 0; i < 20; i += 1)
1453{
1454 println(i, ' = ', fibonacci(i));
1455};
1456
1457$end
1458---- snip ----
1459
1460*/
void print_results(const exprtk::results_context< T > &results)
exprtk::rtl::io::file::package< T > fileio_package_
exprtk::polynomial< T, 6 > poly06_
void process_enable_inequality(const std::string &inequality)
exprtk::expression< T > expression_t
exprtk::polynomial< T, 5 > poly05_
std::vector< function_definition > func_def_list_
void process_disable_inequality(const std::string &inequality)
std::map< std::string, typename settings_store_t::settings_arithmetic_opr > arith_opr_
parser_t::dependent_entity_collector::symbol_t symbol_t
exprtk::polynomial< T, 7 > poly07_
exprtk::rtl::vecops::package< T > vecops_package_
void process_enable_assignment(const std::string &assignment)
exprtk::polynomial< T, 4 > poly04_
exprtk::polynomial< T, 8 > poly08_
parser_t::settings_store settings_store_t
void perform_symbol_dump(const symbol_list_t &variable_list) const
void process_batch_run(const std::string &batch_runs_cnt)
std::vector< symbol_t > symbol_list_t
std::map< std::string, typename settings_store_t::settings_assignment_opr > assign_opr_
void process_disable_arithmetic(const std::string &arithmetic)
func_parse_result parse_function_definition(std::string &func_def, function_definition &cf)
exprtk::polynomial< T, 3 > poly03_
compositor_t::function function_t
exprtk::polynomial< T, 9 > poly09_
std::string trim_whitespace(std::string s)
exprtk::parser_error::type error_t
bool & disable_commutative_check()
exprtk::symbol_table< T > symbol_table_t
void process_disable_assignment(const std::string &assignment)
exprtk::function_compositor< T > compositor_t
exprtk::lexer::parser_helper prsrhlpr_t
std::map< std::string, typename settings_store_t::settings_inequality_opr > inequality_opr_
exprtk::polynomial< T, 2 > poly02_
exprtk::parser< T > parser_t
vector_access_rtc vector_access_rtc_
void process_function_definition(const std::string &func_def_header, bool read_stdin=true)
exprtk::polynomial< T, 12 > poly12_
symbol_table_t function_symbol_table_
exprtk::rtl::io::package< T > io_package_
exprtk::polynomial< T, 11 > poly11_
std::string read_from_stdin()
exprtk::polynomial< T, 10 > poly10_
bool & display_total_compile_time()
exprtk::polynomial< T, 1 > poly01_
void process_from_file(const std::string &file_name)
void process_directive(std::string expression)
void process(std::string program)
void process_enable_arithmetic(const std::string &arithmetic)
bool register_symbol_table(symbol_table< T > &st)
Definition exprtk.hpp:22071
const results_context_t & results() const
Definition exprtk.hpp:22102
ifunction(const std::size_t &pc)
Definition exprtk.hpp:19864
bool init(const std::string &str)
Definition exprtk.hpp:4417
const token_t & current_token() const
Definition exprtk.hpp:4458
bool token_is(const token_t::token_type &ttype, const token_advance_mode mode=e_advance)
Definition exprtk.hpp:4482
std::size_t count() const
Definition exprtk.hpp:5044
double time() const
Definition exprtk.hpp:44125
T putch(T v)
void repl(int argc, char *argv[])
bool imatch(const char_t c1, const char_t c2)
Definition exprtk.hpp:190
bool update_error(type &error, const std::string &expression)
Definition exprtk.hpp:22463
std::string to_str(error_mode mode)
Definition exprtk.hpp:22447
void print_type(const std::string &fmt, const T v, exprtk::details::numeric::details::real_type_tag)
Definition exprtk.hpp:44170
vector_view< T > make_vector_view(T *data, const std::size_t size, const std::size_t offset=0)
Definition exprtk.hpp:4783
func_parse_result process(std::string &func_def, function_definition &fd)
function & expression(const std::string &e)
Definition exprtk.hpp:43139
function & var(const std::string &v)
Definition exprtk.hpp:43145
std::size_t position
Definition exprtk.hpp:2454
std::string value
Definition exprtk.hpp:2453
T operator()(const T &v)
T operator()(const T &v)
T operator()()
bool handle_runtime_violation(violation_context &context)