C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
diff --git a/exprtk.hpp b/exprtk.hpp index 535f203..d7964cf 100644 --- a/exprtk.hpp +++ b/exprtk.hpp
@@ -3736,6 +3736,10 @@ : v_(*reinterpret_cast<value_t*>(ts.data)) {} + scalar_view(const type_store_t& ts) + : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) + {} + value_t& operator()() { return v_; @@ -17566,7 +17570,7 @@ lexer::token begin_token; lexer::token end_token; - for (;;) + for ( ; ; ) { state_.side_effect_present = false; @@ -18787,7 +18791,7 @@ scoped_bool_or_restorer sbr(state_.side_effect_present); - for (;;) + for ( ; ; ) { state_.side_effect_present = false; @@ -19529,10 +19533,27 @@ Sequence<expression_node_ptr,Allocator1> tmp_expression_list; + bool return_node_present = false; + for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) { if (is_variable_node(expression_list[i])) continue; + else if (is_return_node(expression_list[i])) + { + tmp_expression_list.push_back(expression_list[i]); + + // Remove all subexpressions after first encountered return node. + + for (std::size_t j = i + 1; j < (expression_list.size() - 1); ++j) + { + free_node(node_allocator_,expression_list[j]); + } + + return_node_present = true; + + break; + } else if ( is_constant_node(expression_list[i]) || is_null_node (expression_list[i]) || @@ -19546,12 +19567,20 @@ tmp_expression_list.push_back(expression_list[i]); } - tmp_expression_list.push_back(expression_list.back()); - expression_list.swap(tmp_expression_list); - - if ((expression_list.size() > 1) || side_effect_list.back()) + if ( + return_node_present || + side_effect_list.back() || + (expression_list.size() > 1) + ) state_.side_effect_present = true; + if (!return_node_present) + { + tmp_expression_list.push_back(expression_list.back()); + } + + expression_list.swap(tmp_expression_list); + if (tmp_expression_list.size() > expression_list.size()) { exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", @@ -19604,7 +19633,7 @@ scoped_bool_or_restorer sbr(state_.side_effect_present); - for (;;) + for ( ; ; ) { state_.side_effect_present = false; @@ -20697,7 +20726,7 @@ } else if (!token_is(token_t::e_rcrlbracket)) { - for (;;) + for ( ; ; ) { expression_node_ptr initialiser = parse_expression();
diff --git a/exprtk_test.cpp b/exprtk_test.cpp index fd35c25..bd43bf2 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp
@@ -6621,6 +6621,21 @@ } template <typename T> +inline bool result_equal(const exprtk::results_context<T>& results, const T& value) +{ + typedef exprtk::results_context<T> results_context_t; + typedef typename results_context_t::type_store_t type_t; + typedef typename type_t::scalar_view scalar_t; + + if (1 != results.count()) + return false; + else if (type_t::e_scalar != results[0].type) + return false; + else + return (value == scalar_t(results[0])()); +} + +template <typename T> inline bool run_test21() { typedef exprtk::symbol_table<T> symbol_table_t; @@ -6703,7 +6718,7 @@ std::string pattern = results_to_string<T>(expression.results()); - if (result_list[i] != results_to_string<T>(expression.results())) + if (result_list[i] != pattern) { printf("run_test21() - Invalid return results [1] Expected %s Got: %s Expression: %s\n", result_list[i].c_str(), @@ -6711,6 +6726,83 @@ expression_list[i].c_str()); failure = true; + continue; + } + } + + if (failure) + return false; + } + + { + static const std::string expression_list[] = + { + "x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1];", + "x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7;", + "x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7;", + "x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7;", + "x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7;", + "x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7;", + "return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7;", + "~{x := 1; x + 1; x + 2; x + 3; x + 5; x + 7; return [x + 1]}", + "~{x := 1; x + 1; x + 2; x + 3; x + 5; return [x + 1]; x := 7}", + "~{x := 1; x + 1; x + 2; x + 3; return [x + 1]; x + 5; x := 7}", + "~{x := 1; x + 1; x + 2; return [x + 1]; x + 3; x + 5; x := 7}", + "~{x := 1; x + 1; return [x + 1]; x + 2; x + 3; x + 5; x := 7}", + "~{x := 1; return [x + 1]; x + 1; x + 2; x + 3; x + 5; x := 7}", + "~{return [x + 1]; x := 1; x + 1; x + 2; x + 3; x + 5; x := 7}" + }; + + static const std::string result_list[] = + { + "T", "T", "T", "T", "T", "T", "T", + "T", "T", "T", "T", "T", "T", "T", + }; + + static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); + + bool failure = false; + + for (std::size_t i = 0; i < expression_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(expression_list[i],expression)) + { + printf("run_test21() - Error: %s Expression: %s [2]\n", + parser.error().c_str(), + expression_list[i].c_str()); + + failure = true; + continue; + } + + expression.value(); + + std::string pattern = results_to_string<T>(expression.results()); + + if (result_list[i] != pattern) + { + printf("run_test21() - Invalid return results [2] Expected %s Got: %s Expression: %s\n", + result_list[i].c_str(), + pattern.c_str(), + expression_list[i].c_str()); + + failure = true; + continue; + } + else if (!result_equal(expression.results(), x + T(1))) + { + printf("run_test21() - Invalid return results [2] Expected %s Got: %s Expression: %s\n", + result_list[i].c_str(), + pattern.c_str(), + expression_list[i].c_str()); + + failure = true; + continue; } }