From 9fc92bd811559e943b3939acaa2246f9ded25c83 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 1 Jan 2024 00:00:00 +0000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html --- CMakeLists.txt | 4 +- include/exprtk.hpp | 1582 +++++++++++++++++++++++++------------------- license.txt | 2 +- 3 files changed, 918 insertions(+), 670 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3db5b7..e5e7224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # ****************************************************************** # * C++ Mathematical Expression Toolkit Library * # * * -# * Author: Arash Partow (1999-2022) * +# * Author: Arash Partow (1999-2023) * # * URL: https://www.partow.net/programming/exprtk/index.html * # * * # * Copyright notice: * @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.15) project( ExprTk LANGUAGES CXX - VERSION 0.0.1 + VERSION 0.0.2 DESCRIPTION "C++ Mathematical Expression Toolkit Library (ExprTk)" HOMEPAGE_URL "https://www.partow.net/programming/exprtk/index.html" ) diff --git a/include/exprtk.hpp b/include/exprtk.hpp index 4a4db54..b4530ba 100644 --- a/include/exprtk.hpp +++ b/include/exprtk.hpp @@ -2,7 +2,7 @@ ****************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Author: Arash Partow (1999-2022) * + * Author: Arash Partow (1999-2023) * * URL: https://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -298,7 +297,6 @@ namespace exprtk std::reverse(result.begin(), result.end()); - return result; } @@ -401,7 +399,7 @@ namespace exprtk { public: - build_string(const std::size_t& initial_size = 64) + explicit build_string(const std::size_t& initial_size = 64) { data_.reserve(initial_size); } @@ -605,6 +603,8 @@ namespace exprtk const typename std::iterator_traits::value_type& zero_or_more, const typename std::iterator_traits::value_type& exactly_one ) { + typedef typename std::iterator_traits::value_type type; + const Iterator null_itr(0); Iterator p_itr = pattern_begin; @@ -614,39 +614,45 @@ namespace exprtk for ( ; ; ) { - const bool pvalid = p_itr != pattern_end; - const bool dvalid = d_itr != data_end; - - if (!pvalid && !dvalid) - break; - - if (pvalid) + if (p_itr != pattern_end) { - const typename std::iterator_traits::value_type c = *(p_itr); + const type c = *(p_itr); - if (zero_or_more == c) + if ((data_end != d_itr) && (Compare::cmp(c,*(d_itr)) || (exactly_one == c))) { - np_itr = p_itr; - nd_itr = d_itr + 1; - ++p_itr; - continue; - } - else if (dvalid && ((exactly_one == c) || Compare::cmp(c,*(d_itr)))) - { - ++p_itr; ++d_itr; + ++p_itr; + continue; + } + else if (zero_or_more == c) + { + while ((pattern_end != p_itr) && (zero_or_more == *(p_itr))) + { + ++p_itr; + } + + const type d = *(p_itr); + + while ((data_end != d_itr) && !(Compare::cmp(d,*(d_itr)) || (exactly_one == d))) + { + ++d_itr; + } + + // set backtrack iterators + np_itr = p_itr - 1; + nd_itr = d_itr + 1; + continue; } } + else if (data_end == d_itr) + return true; - if ((null_itr != nd_itr) && (nd_itr <= data_end)) - { - p_itr = np_itr; - d_itr = nd_itr; - continue; - } + if ((data_end == d_itr) || (null_itr == nd_itr)) + return false; - return false; + p_itr = np_itr; + d_itr = nd_itr; } return true; @@ -774,7 +780,6 @@ namespace exprtk { struct unknown_type_tag { unknown_type_tag() {} }; struct real_type_tag { real_type_tag () {} }; - struct complex_type_tag { complex_type_tag() {} }; struct int_type_tag { int_type_tag () {} }; template @@ -788,10 +793,6 @@ namespace exprtk template <> struct number_type \ { typedef real_type_tag type; number_type() {} }; \ - #define exprtk_register_complex_type_tag(T) \ - template <> struct number_type > \ - { typedef complex_type_tag type; number_type() {} }; \ - #define exprtk_register_int_type_tag(T) \ template <> struct number_type \ { typedef int_type_tag type; number_type() {} }; \ @@ -800,10 +801,6 @@ namespace exprtk exprtk_register_real_type_tag(long double) exprtk_register_real_type_tag(float ) - exprtk_register_complex_type_tag(double ) - exprtk_register_complex_type_tag(long double) - exprtk_register_complex_type_tag(float ) - exprtk_register_int_type_tag(short ) exprtk_register_int_type_tag(int ) exprtk_register_int_type_tag(_int64_t ) @@ -2063,6 +2060,11 @@ namespace exprtk details::_uint64_t iteration_count; }; + virtual bool check() + { + return true; + } + virtual void handle_runtime_violation(const violation_context&) { throw std::runtime_error("ExprTk Loop run-time violation."); @@ -3318,7 +3320,7 @@ namespace exprtk ignore_set_.insert(symbol); } - inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) + inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) exprtk_override { bool match = false; new_token.type = lexer::token::e_mul; @@ -3373,7 +3375,7 @@ namespace exprtk : token_joiner(stride) {} - inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) + inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) exprtk_override { // ': =' --> ':=' if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) @@ -3521,7 +3523,7 @@ namespace exprtk inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, - lexer::token& t) + lexer::token& t) exprtk_override { // '[ * ]' --> '[*]' if ( @@ -3626,7 +3628,8 @@ namespace exprtk lexer::token error_token_; }; - class numeric_checker : public lexer::token_scanner + template + class numeric_checker exprtk_final : public lexer::token_scanner { public: @@ -3652,7 +3655,7 @@ namespace exprtk { if (token::e_number == t.type) { - double v; + T v; if (!exprtk::details::string_to_real(t.value,v)) { @@ -3756,7 +3759,7 @@ namespace exprtk replace_map_t replace_map_; }; - class sequence_validator : public lexer::token_scanner + class sequence_validator exprtk_final : public lexer::token_scanner { private: @@ -3928,7 +3931,7 @@ namespace exprtk std::vector > error_list_; }; - class sequence_validator_3tokens : public lexer::token_scanner + class sequence_validator_3tokens exprtk_final : public lexer::token_scanner { private: @@ -4762,12 +4765,12 @@ namespace exprtk inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) { if (size) - exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); - else exprtk_debug(("%s - addr: %p size: %d\n", s.c_str(), ptr, static_cast(size))); + else + exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); } #else inline void dump_ptr(const std::string&, const void*) {} @@ -4811,7 +4814,7 @@ namespace exprtk { if (data && destruct && (0 == ref_count)) { - dump_ptr("~control_block() data",data); + dump_ptr("~vec_data_store::control_block() data",data); delete[] data; data = reinterpret_cast(0); } @@ -5224,12 +5227,6 @@ namespace exprtk return std::not_equal_to()(0.0f,v); } - template - inline bool is_true(const std::complex& v) - { - return std::not_equal_to >()(std::complex(0),v); - } - template inline bool is_true(const expression_node* node) { @@ -5342,7 +5339,11 @@ namespace exprtk template inline bool is_constant_node(const expression_node* node) { - return node && (details::expression_node::e_constant == node->type()); + return node && + ( + details::expression_node::e_constant == node->type() || + details::expression_node::e_stringconst == node->type() + ); } template @@ -5942,16 +5943,16 @@ namespace exprtk : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) {} - vector_holder(const vds_t& vds) + explicit vector_holder(const vds_t& vds) : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) {} template - vector_holder(std::vector& vec) + explicit vector_holder(std::vector& vec) : vector_holder_base_(new(buffer)sequence_vector_impl(vec)) {} - vector_holder(exprtk::vector_view& vec) + explicit vector_holder(exprtk::vector_view& vec) : vector_holder_base_(new(buffer)vector_view_impl(vec)) {} @@ -6069,9 +6070,9 @@ namespace exprtk const bool result = details::numeric::is_nan(v); if (result) - return (equality_) ? T(1) : T(0); + return equality_ ? T(1) : T(0); else - return (equality_) ? T(0) : T(1); + return equality_ ? T(0) : T(1); } inline typename expression_node::node_type type() const exprtk_override @@ -6255,9 +6256,7 @@ namespace exprtk inline T value() const exprtk_override { assert(branch_.first); - const T arg = branch_.first->value(); - return numeric::process(operation_,arg); } @@ -6286,12 +6285,12 @@ namespace exprtk expression_node::ndb_t::collect(branch_, node_delete_list); } - std::size_t node_depth() const exprtk_override exprtk_final + std::size_t node_depth() const exprtk_final { return expression_node::ndb_t::compute_node_depth(branch_); } - protected: + private: operator_type operation_; branch_t branch_; @@ -6321,7 +6320,7 @@ namespace exprtk const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); - return numeric::process(operation_,arg0,arg1); + return numeric::process(operation_, arg0, arg1); } inline typename expression_node::node_type type() const exprtk_override @@ -6349,12 +6348,12 @@ namespace exprtk expression_node::ndb_t::template collect(branch_, node_delete_list); } - std::size_t node_depth() const exprtk_override exprtk_final + std::size_t node_depth() const exprtk_final { return expression_node::ndb_t::template compute_node_depth<2>(branch_); } - protected: + private: operator_type operation_; branch_t branch_[2]; @@ -6733,7 +6732,7 @@ namespace exprtk { if ( (0 == loop_runtime_check_) || - (++iteration_count_ <= max_loop_iterations_) + ((++iteration_count_ <= max_loop_iterations_) && loop_runtime_check_->check()) ) { return true; @@ -8169,6 +8168,8 @@ namespace exprtk typedef vector_node * vector_node_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + swap_vecvec_node(expression_ptr branch0, expression_ptr branch1) : binary_node(details::e_swap, branch0, branch1) @@ -8177,22 +8178,22 @@ namespace exprtk , vec_size_ (0) , initialised_ (false) { - if (is_ivector_node(binary_node::branch_[0].first)) + if (is_ivector_node(branch(0))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + if (0 != (vi = dynamic_cast*>(branch(0)))) { vec0_node_ptr_ = vi->vec(); vds() = vi->vds(); } } - if (is_ivector_node(binary_node::branch_[1].first)) + if (is_ivector_node(branch(1))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); } @@ -8213,11 +8214,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + binary_node::branch(0)->value(); + binary_node::branch(1)->value(); T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vec1_node_ptr_->vds().data(); @@ -8678,6 +8679,8 @@ namespace exprtk typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; + using binary_node::branch; + string_concat_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -8694,27 +8697,27 @@ namespace exprtk range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; - if (is_generally_string_node(binary_node::branch_[0].first)) + if (is_generally_string_node(branch(0))) { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_base_ptr_ = dynamic_cast(branch(0)); if (0 == str0_base_ptr_) return; - str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_range_ptr_ = dynamic_cast(branch(0)); if (0 == str0_range_ptr_) return; } - if (is_generally_string_node(binary_node::branch_[1].first)) + if (is_generally_string_node(branch(1))) { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_base_ptr_ = dynamic_cast(branch(1)); if (0 == str1_base_ptr_) return; - str1_range_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_range_ptr_ = dynamic_cast(branch(1)); if (0 == str1_range_ptr_) return; @@ -8732,11 +8735,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; @@ -8823,20 +8826,22 @@ namespace exprtk typedef stringvar_node * strvar_node_ptr; typedef string_base_node* str_base_ptr; + using binary_node::branch; + swap_string_node(expression_ptr branch0, expression_ptr branch1) : binary_node(details::e_swap, branch0, branch1), initialised_(false), str0_node_ptr_(0), str1_node_ptr_(0) { - if (is_string_node(binary_node::branch_[0].first)) + if (is_string_node(branch(0))) { - str0_node_ptr_ = static_cast(binary_node::branch_[0].first); + str0_node_ptr_ = static_cast(branch(0)); } - if (is_string_node(binary_node::branch_[1].first)) + if (is_string_node(branch(1))) { - str1_node_ptr_ = static_cast(binary_node::branch_[1].first); + str1_node_ptr_ = static_cast(branch(1)); } initialised_ = (str0_node_ptr_ && str1_node_ptr_); @@ -8848,11 +8853,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); } @@ -8909,6 +8914,8 @@ namespace exprtk typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; + using binary_node::branch; + swap_genstrings_node(expression_ptr branch0, expression_ptr branch1) : binary_node(details::e_default, branch0, branch1) @@ -8918,14 +8925,14 @@ namespace exprtk , str1_range_ptr_(0) , initialised_(false) { - if (is_generally_string_node(binary_node::branch_[0].first)) + if (is_generally_string_node(branch(0))) { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_base_ptr_ = dynamic_cast(branch(0)); if (0 == str0_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + irange_ptr range = dynamic_cast(branch(0)); if (0 == range) return; @@ -8933,14 +8940,14 @@ namespace exprtk str0_range_ptr_ = &(range->range_ref()); } - if (is_generally_string_node(binary_node::branch_[1].first)) + if (is_generally_string_node(branch(1))) { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_base_ptr_ = dynamic_cast(branch(1)); if (0 == str1_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + irange_ptr range = dynamic_cast(branch(1)); if (0 == range) return; @@ -8960,11 +8967,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; @@ -9174,6 +9181,8 @@ namespace exprtk typedef stringvar_node * strvar_node_ptr; typedef string_base_node* str_base_ptr; + using binary_node::branch; + assignment_string_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -9184,21 +9193,20 @@ namespace exprtk , str0_node_ptr_ (0) , str1_range_ptr_(0) { - if (is_string_node(binary_node::branch_[0].first)) + if (is_string_node(branch(0))) { - str0_node_ptr_ = static_cast(binary_node::branch_[0].first); - - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_node_ptr_ = static_cast(branch(0)); + str0_base_ptr_ = dynamic_cast(branch(0)); } - if (is_generally_string_node(binary_node::branch_[1].first)) + if (is_generally_string_node(branch(1))) { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_base_ptr_ = dynamic_cast(branch(1)); if (0 == str1_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + irange_ptr range = dynamic_cast(branch(1)); if (0 == range) return; @@ -9218,10 +9226,10 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[1].first->value(); + branch(1)->value(); std::size_t r0 = 0; std::size_t r1 = 0; @@ -9234,7 +9242,7 @@ namespace exprtk str1_base_ptr_->base() + r0, (r1 - r0) + 1); - binary_node::branch_[0].first->value(); + branch(0)->value(); } } @@ -9297,6 +9305,8 @@ namespace exprtk typedef string_range_node* str_rng_node_ptr; typedef string_base_node * str_base_ptr; + using binary_node::branch; + assignment_string_range_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -9308,13 +9318,11 @@ namespace exprtk , str0_range_ptr_ (0) , str1_range_ptr_ (0) { - if (is_string_range_node(binary_node::branch_[0].first)) + if (is_string_range_node(branch(0))) { - str0_rng_node_ptr_ = static_cast(binary_node::branch_[0].first); - - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); - - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + str0_rng_node_ptr_ = static_cast(branch(0)); + str0_base_ptr_ = dynamic_cast(branch(0)); + irange_ptr range = dynamic_cast(branch(0)); if (0 == range) return; @@ -9322,14 +9330,14 @@ namespace exprtk str0_range_ptr_ = &(range->range_ref()); } - if (is_generally_string_node(binary_node::branch_[1].first)) + if (is_generally_string_node(branch(1))) { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_base_ptr_ = dynamic_cast(branch(1)); if (0 == str1_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + irange_ptr range = dynamic_cast(branch(1)); if (0 == range) return; @@ -9350,11 +9358,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); std::size_t s0_r0 = 0; std::size_t s0_r1 = 0; @@ -9601,6 +9609,8 @@ namespace exprtk typedef expression_node * expression_ptr; typedef string_base_node* str_base_ptr; + using binary_node::branch; + cons_conditional_str_node(expression_ptr condition, expression_ptr consequent) : binary_node(details::e_default, consequent, condition) @@ -9616,14 +9626,14 @@ namespace exprtk range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; - if (is_generally_string_node(binary_node::branch_[0].first)) + if (is_generally_string_node(branch(0))) { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_base_ptr_ = dynamic_cast(branch(0)); if (0 == str0_base_ptr_) return; - str0_range_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_range_ptr_ = dynamic_cast(branch(0)); if (0 == str0_range_ptr_) return; @@ -10349,6 +10359,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_node(const operator_type& opr, expression_ptr branch0, @@ -10356,9 +10367,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , var_node_ptr_(0) { - if (is_variable_node(binary_node::branch_[0].first)) + if (is_variable_node(branch(0))) { - var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + var_node_ptr_ = static_cast*>(branch(0)); } } @@ -10366,11 +10377,10 @@ namespace exprtk { if (var_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& result = var_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); + result = branch(1)->value(); return result; } @@ -10389,6 +10399,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_vec_elem_node(const operator_type& opr, expression_ptr branch0, @@ -10396,9 +10407,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) { - if (is_vector_elem_node(binary_node::branch_[0].first)) + if (is_vector_elem_node(branch(0))) { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10406,11 +10417,10 @@ namespace exprtk { if (vec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& result = vec_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); + result = branch(1)->value(); return result; } @@ -10429,6 +10439,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using expression_node::branch; assignment_rebasevec_elem_node(const operator_type& opr, expression_ptr branch0, @@ -10436,9 +10447,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) { - if (is_rebasevector_elem_node(binary_node::branch_[0].first)) + if (is_rebasevector_elem_node(branch(0))) { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + rbvec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10446,11 +10457,11 @@ namespace exprtk { if (rbvec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& result = rbvec_node_ptr_->ref(); - result = binary_node::branch_[1].first->value(); + result = branch(1)->value(); return result; } @@ -10469,6 +10480,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_rebasevec_celem_node(const operator_type& opr, expression_ptr branch0, @@ -10476,9 +10488,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) { - if (is_rebasevector_celem_node(binary_node::branch_[0].first)) + if (is_rebasevector_celem_node(branch(0))) { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + rbvec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10486,11 +10498,10 @@ namespace exprtk { if (rbvec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& result = rbvec_node_ptr_->ref(); - - result = binary_node::branch_[1].first->value(); + result = branch(1)->value(); return result; } @@ -10514,15 +10525,17 @@ namespace exprtk typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + assignment_vec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) { - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec_node_ptr_ = static_cast*>(branch(0)); vds() = vec_node_ptr_->vds(); } } @@ -10531,9 +10544,9 @@ namespace exprtk { if (vec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); - const T v = binary_node::branch_[1].first->value(); + const T v = branch(1)->value(); T* vec = vds().data(); @@ -10634,6 +10647,8 @@ namespace exprtk typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + assignment_vecvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -10643,22 +10658,22 @@ namespace exprtk , initialised_(false) , src_is_ivec_(false) { - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec0_node_ptr_ = static_cast*>(branch(0)); vds() = vec0_node_ptr_->vds(); } - if (is_vector_node(binary_node::branch_[1].first)) + if (is_vector_node(branch(1))) { - vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); + vec1_node_ptr_ = static_cast*>(branch(1)); vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); } - else if (is_ivector_node(binary_node::branch_[1].first)) + else if (is_ivector_node(branch(1))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); @@ -10681,9 +10696,9 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); - binary_node::branch_[1].first->value(); + branch(1)->value(); if (src_is_ivec_) return vec0_node_ptr_->value(); @@ -10787,6 +10802,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_op_node(const operator_type& opr, expression_ptr branch0, @@ -10794,9 +10810,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , var_node_ptr_(0) { - if (is_variable_node(binary_node::branch_[0].first)) + if (is_variable_node(branch(0))) { - var_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + var_node_ptr_ = static_cast*>(branch(0)); } } @@ -10804,10 +10820,10 @@ namespace exprtk { if (var_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& v = var_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); + v = Operation::process(v,branch(1)->value()); return v; } @@ -10826,6 +10842,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_vec_elem_op_node(const operator_type& opr, expression_ptr branch0, @@ -10833,9 +10850,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) { - if (is_vector_elem_node(binary_node::branch_[0].first)) + if (is_vector_elem_node(branch(0))) { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10843,10 +10860,10 @@ namespace exprtk { if (vec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& v = vec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); + v = Operation::process(v,branch(1)->value()); return v; } @@ -10865,6 +10882,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_rebasevec_elem_op_node(const operator_type& opr, expression_ptr branch0, @@ -10872,9 +10890,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) { - if (is_rebasevector_elem_node(binary_node::branch_[0].first)) + if (is_rebasevector_elem_node(branch(0))) { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + rbvec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10882,10 +10900,10 @@ namespace exprtk { if (rbvec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); + v = Operation::process(v,branch(1)->value()); return v; } @@ -10904,6 +10922,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; assignment_rebasevec_celem_op_node(const operator_type& opr, expression_ptr branch0, @@ -10911,9 +10930,9 @@ namespace exprtk : binary_node(opr, branch0, branch1) , rbvec_node_ptr_(0) { - if (is_rebasevector_celem_node(binary_node::branch_[0].first)) + if (is_rebasevector_celem_node(branch(0))) { - rbvec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + rbvec_node_ptr_ = static_cast*>(branch(0)); } } @@ -10921,10 +10940,10 @@ namespace exprtk { if (rbvec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); T& v = rbvec_node_ptr_->ref(); - v = Operation::process(v,binary_node::branch_[1].first->value()); + v = Operation::process(v,branch(1)->value()); return v; } @@ -10948,15 +10967,17 @@ namespace exprtk typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + assignment_vec_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node(opr, branch0, branch1) , vec_node_ptr_(0) { - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec_node_ptr_ = static_cast*>(branch(0)); vds() = vec_node_ptr_->vds(); } } @@ -10965,9 +10986,9 @@ namespace exprtk { if (vec_node_ptr_) { - assert(binary_node::branch_[1].first); + assert(branch(1)); - const T v = binary_node::branch_[1].first->value(); + const T v = branch(1)->value(); T* vec = vds().data(); @@ -11073,6 +11094,8 @@ namespace exprtk typedef vector_node* vector_node_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + assignment_vecvec_op_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -11081,22 +11104,22 @@ namespace exprtk , vec1_node_ptr_(0) , initialised_(false) { - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec0_node_ptr_ = static_cast*>(binary_node::branch_[0].first); + vec0_node_ptr_ = static_cast*>(branch(0)); vds() = vec0_node_ptr_->vds(); } - if (is_vector_node(binary_node::branch_[1].first)) + if (is_vector_node(branch(1))) { - vec1_node_ptr_ = static_cast*>(binary_node::branch_[1].first); + vec1_node_ptr_ = static_cast*>(branch(1)); vec1_node_ptr_->vds() = vds(); } - else if (is_ivector_node(binary_node::branch_[1].first)) + else if (is_ivector_node(branch(1))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); vec1_node_ptr_->vds() = vds(); @@ -11114,11 +11137,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); T* vec0 = vec0_node_ptr_->vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); @@ -11231,6 +11254,8 @@ namespace exprtk typedef vector_holder* vector_holder_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + vec_binop_vecvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -11244,30 +11269,30 @@ namespace exprtk bool v0_is_ivec = false; bool v1_is_ivec = false; - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); + vec0_node_ptr_ = static_cast(branch(0)); } - else if (is_ivector_node(binary_node::branch_[0].first)) + else if (is_ivector_node(branch(0))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + if (0 != (vi = dynamic_cast*>(branch(0)))) { vec0_node_ptr_ = vi->vec(); v0_is_ivec = true; } } - if (is_vector_node(binary_node::branch_[1].first)) + if (is_vector_node(branch(1))) { - vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); + vec1_node_ptr_ = static_cast(branch(1)); } - else if (is_ivector_node(binary_node::branch_[1].first)) + else if (is_ivector_node(branch(1))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); v1_is_ivec = true; @@ -11305,11 +11330,11 @@ namespace exprtk { if (initialised_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); const T* vec0 = vec0_node_ptr_->vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); @@ -11421,6 +11446,8 @@ namespace exprtk typedef vector_holder* vector_holder_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + vec_binop_vecval_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -11431,15 +11458,15 @@ namespace exprtk { bool v0_is_ivec = false; - if (is_vector_node(binary_node::branch_[0].first)) + if (is_vector_node(branch(0))) { - vec0_node_ptr_ = static_cast(binary_node::branch_[0].first); + vec0_node_ptr_ = static_cast(branch(0)); } - else if (is_ivector_node(binary_node::branch_[0].first)) + else if (is_ivector_node(branch(0))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[0].first))) + if (0 != (vi = dynamic_cast*>(branch(0)))) { vec0_node_ptr_ = vi->vec(); v0_is_ivec = true; @@ -11468,11 +11495,11 @@ namespace exprtk { if (vec0_node_ptr_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - binary_node::branch_[0].first->value(); - const T v = binary_node::branch_[1].first->value(); + branch(0)->value(); + const T v = branch(1)->value(); const T* vec0 = vec0_node_ptr_->vds().data(); T* vec1 = vds().data(); @@ -11580,6 +11607,8 @@ namespace exprtk typedef vector_holder* vector_holder_ptr; typedef vec_data_store vds_t; + using binary_node::branch; + vec_binop_valvec_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -11590,15 +11619,15 @@ namespace exprtk { bool v1_is_ivec = false; - if (is_vector_node(binary_node::branch_[1].first)) + if (is_vector_node(branch(1))) { - vec1_node_ptr_ = static_cast(binary_node::branch_[1].first); + vec1_node_ptr_ = static_cast(branch(1)); } - else if (is_ivector_node(binary_node::branch_[1].first)) + else if (is_ivector_node(branch(1))) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(binary_node::branch_[1].first))) + if (0 != (vi = dynamic_cast*>(branch(1)))) { vec1_node_ptr_ = vi->vec(); v1_is_ivec = true; @@ -11627,11 +11656,11 @@ namespace exprtk { if (vec1_node_ptr_) { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); - const T v = binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + const T v = branch(0)->value(); + branch(1)->value(); T* vec0 = vds().data(); const T* vec1 = vec1_node_ptr_->vds().data(); @@ -11739,6 +11768,8 @@ namespace exprtk typedef vector_holder* vector_holder_ptr; typedef vec_data_store vds_t; + using expression_node::branch; + unary_vector_node(const operator_type& opr, expression_ptr branch0) : unary_node(opr, branch0) , vec0_node_ptr_(0) @@ -11747,15 +11778,15 @@ namespace exprtk { bool vec0_is_ivec = false; - if (is_vector_node(unary_node::branch_.first)) + if (is_vector_node(branch())) { - vec0_node_ptr_ = static_cast(unary_node::branch_.first); + vec0_node_ptr_ = static_cast(branch()); } - else if (is_ivector_node(unary_node::branch_.first)) + else if (is_ivector_node(branch())) { vector_interface* vi = reinterpret_cast*>(0); - if (0 != (vi = dynamic_cast*>(unary_node::branch_.first))) + if (0 != (vi = dynamic_cast*>(branch()))) { vec0_node_ptr_ = vi->vec(); vec0_is_ivec = true; @@ -11782,9 +11813,9 @@ namespace exprtk inline T value() const exprtk_override { - assert(unary_node::branch_.first); + assert(branch()); - unary_node::branch_.first->value(); + branch()->value(); if (vec0_node_ptr_) { @@ -12048,6 +12079,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; scand_node(const operator_type& opr, expression_ptr branch0, @@ -12057,14 +12089,14 @@ namespace exprtk inline T value() const exprtk_override { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); return ( std::not_equal_to() - (T(0),binary_node::branch_[0].first->value()) && + (T(0),branch(0)->value()) && std::not_equal_to() - (T(0),binary_node::branch_[1].first->value()) + (T(0),branch(1)->value()) ) ? T(1) : T(0); } }; @@ -12075,6 +12107,7 @@ namespace exprtk public: typedef expression_node* expression_ptr; + using binary_node::branch; scor_node(const operator_type& opr, expression_ptr branch0, @@ -12084,14 +12117,14 @@ namespace exprtk inline T value() const exprtk_override { - assert(binary_node::branch_[0].first); - assert(binary_node::branch_[1].first); + assert(branch(0)); + assert(branch(1)); return ( std::not_equal_to() - (T(0),binary_node::branch_[0].first->value()) || + (T(0),branch(0)->value()) || std::not_equal_to() - (T(0),binary_node::branch_[1].first->value()) + (T(0),branch(1)->value()) ) ? T(1) : T(0); } }; @@ -13518,7 +13551,7 @@ namespace exprtk case 3 : return process_3(arg_list); case 4 : return process_4(arg_list); case 5 : return process_5(arg_list); - default : return vararg_add_op::process(arg_list) / arg_list.size(); + default : return vararg_add_op::process(arg_list) / T(arg_list.size()); } } @@ -14177,8 +14210,7 @@ namespace exprtk static inline T process(const ivector_ptr v) { - const std::size_t vec_size = v->vec()->vds().size(); - + const T vec_size = T(v->vec()->vds().size()); return vec_add_op::process(v) / vec_size; } }; @@ -14959,7 +14991,7 @@ namespace exprtk private: T0oT1oT2(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -15056,7 +15088,7 @@ namespace exprtk private: T0oT1oT2oT3(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -15141,7 +15173,7 @@ namespace exprtk private: T0oT1oT2_sf3(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -15168,8 +15200,6 @@ namespace exprtk { public: - typedef typename details::functor_t functor_t; - typedef typename functor_t::tfunc_t tfunc_t; typedef T value_type; typedef T0oT1oT2_sf3ext node_type; @@ -15231,7 +15261,7 @@ namespace exprtk private: T0oT1oT2_sf3ext(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -15332,7 +15362,7 @@ namespace exprtk private: T0oT1oT2oT3_sf4(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -15346,8 +15376,6 @@ namespace exprtk { public: - typedef typename details::functor_t functor_t; - typedef typename functor_t::tfunc_t tfunc_t; typedef T value_type; typedef T0oT1oT2oT3_sf4ext node_type; @@ -15410,7 +15438,7 @@ namespace exprtk private: T0oT1oT2oT3_sf4ext(const node_type&) exprtk_delete; - node_type& operator=(const node_type&) { return (*this); } + node_type& operator=(const node_type&) exprtk_delete; T0 t0_; T1 t1_; @@ -16111,6 +16139,8 @@ namespace exprtk typedef range_interface irange_t; typedef irange_t* irange_ptr; + using binary_node::branch; + str_sogens_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) @@ -16120,14 +16150,14 @@ namespace exprtk , str0_range_ptr_(0) , str1_range_ptr_(0) { - if (is_generally_string_node(binary_node::branch_[0].first)) + if (is_generally_string_node(branch(0))) { - str0_base_ptr_ = dynamic_cast(binary_node::branch_[0].first); + str0_base_ptr_ = dynamic_cast(branch(0)); if (0 == str0_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[0].first); + irange_ptr range = dynamic_cast(branch(0)); if (0 == range) return; @@ -16135,14 +16165,14 @@ namespace exprtk str0_range_ptr_ = &(range->range_ref()); } - if (is_generally_string_node(binary_node::branch_[1].first)) + if (is_generally_string_node(branch(1))) { - str1_base_ptr_ = dynamic_cast(binary_node::branch_[1].first); + str1_base_ptr_ = dynamic_cast(branch(1)); if (0 == str1_base_ptr_) return; - irange_ptr range = dynamic_cast(binary_node::branch_[1].first); + irange_ptr range = dynamic_cast(branch(1)); if (0 == range) return; @@ -16160,8 +16190,8 @@ namespace exprtk str1_range_ptr_ ) { - binary_node::branch_[0].first->value(); - binary_node::branch_[1].first->value(); + branch(0)->value(); + branch(1)->value(); std::size_t str0_r0 = 0; std::size_t str0_r1 = 0; @@ -17281,22 +17311,29 @@ namespace exprtk { public: - typedef T (*ff00_functor)(); - typedef T (*ff01_functor)(T); - typedef T (*ff02_functor)(T, T); - typedef T (*ff03_functor)(T, T, T); - typedef T (*ff04_functor)(T, T, T, T); - typedef T (*ff05_functor)(T, T, T, T, T); - typedef T (*ff06_functor)(T, T, T, T, T, T); - typedef T (*ff07_functor)(T, T, T, T, T, T, T); - typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); - typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); - typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); - typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); - typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); + enum symtab_mutability_type + { + e_unknown = 0, + e_mutable = 1, + e_immutable = 2 + }; + + typedef T (*ff00_functor)(); + typedef T (*ff01_functor)(T); + typedef T (*ff02_functor)(T, T); + typedef T (*ff03_functor)(T, T, T); + typedef T (*ff04_functor)(T, T, T, T); + typedef T (*ff05_functor)(T, T, T, T, T); + typedef T (*ff06_functor)(T, T, T, T, T, T); + typedef T (*ff07_functor)(T, T, T, T, T, T, T); + typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); + typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); + typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); + typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); + typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); protected: @@ -17938,11 +17975,13 @@ namespace exprtk control_block() : ref_count(1) , data_(st_data::create()) + , mutability_(e_mutable) {} explicit control_block(st_data* data) : ref_count(1) , data_(data) + , mutability_(e_mutable) {} ~control_block() @@ -17978,21 +18017,29 @@ namespace exprtk } } + void set_mutability(const symtab_mutability_type mutability) + { + mutability_ = mutability; + } + std::size_t ref_count; st_data* data_; + symtab_mutability_type mutability_; }; public: - symbol_table() + symbol_table(const symtab_mutability_type mutability = e_mutable) : control_block_(control_block::create()) { + control_block_->set_mutability(mutability); clear(); } ~symbol_table() { - control_block::destroy(control_block_,this); + exprtk::details::dump_ptr("~symbol_table", this); + control_block::destroy(control_block_, this); } symbol_table(const symbol_table& st) @@ -18019,6 +18066,11 @@ namespace exprtk return (this == &st) || (control_block_ == st.control_block_); } + inline symtab_mutability_type mutability() const + { + return valid() ? control_block_->mutability_ : e_unknown; + } + inline void clear_variables(const bool delete_node = true) { local_data().variable_store.clear(delete_node); @@ -19092,6 +19144,7 @@ namespace exprtk inline expression& release() { + exprtk::details::dump_ptr("expression::release", this); control_block::destroy(control_block_); return (*this); @@ -19127,6 +19180,14 @@ namespace exprtk inline void register_symbol_table(symbol_table& st) { + for (std::size_t i = 0; i < symbol_table_list_.size(); ++i) + { + if (&st == &symbol_table_list_[i]) + { + return; + } + } + symbol_table_list_.push_back(st); } @@ -19894,6 +19955,130 @@ namespace exprtk parser_t& parser_; }; + template + struct halfopen_range_policy + { + static inline bool is_within(const T_& v, const T_& begin, const T_& end) + { + assert(begin <= end); + return (begin <= v) && (v < end); + } + + static inline bool is_less(const T_& v, const T_& begin) + { + return (v < begin); + } + + static inline bool is_greater(const T_& v, const T_& end) + { + return (end <= v); + } + + static inline bool end_inclusive() + { + return false; + } + }; + + template + struct closed_range_policy + { + static inline bool is_within(const T_& v, const T_& begin, const T_& end) + { + assert(begin <= end); + return (begin <= v) && (v <= end); + } + + static inline bool is_less(const T_& v, const T_& begin) + { + return (v < begin); + } + + static inline bool is_greater(const T_& v, const T_& end) + { + return (end < v); + } + + static inline bool end_inclusive() + { + return true; + } + }; + + template > + class interval_container_t + { + public: + + typedef IntervalPointType interval_point_t; + typedef std::pair interval_t; + typedef std::map interval_map_t; + typedef typename interval_map_t::const_iterator interval_map_citr_t; + + std::size_t size() const + { + return interval_map_.size(); + } + + void reset() + { + interval_map_.clear(); + } + + bool in_interval(const interval_point_t point, interval_t& interval) const + { + interval_map_citr_t itr = RangePolicy::end_inclusive() ? + interval_map_.lower_bound(point): + interval_map_.upper_bound(point); + + for (; itr != interval_map_.end(); ++itr) + { + const interval_point_t& begin = itr->second.first; + const interval_point_t& end = itr->second.second; + + if (RangePolicy::is_within(point, begin, end)) + { + interval = interval_t(begin,end); + return true; + } + else if (RangePolicy::is_greater(point, end)) + { + break; + } + } + + return false; + } + + bool in_interval(const interval_point_t point) const + { + interval_t interval; + return in_interval(point,interval); + } + + bool add_interval(const interval_point_t begin, const interval_point_t end) + { + if ((end <= begin) || in_interval(begin) || in_interval(end)) + { + return false; + } + + interval_map_[end] = std::make_pair(begin, end); + + return true; + } + + bool add_interval(const interval_t interval) + { + return add_interval(interval.first, interval.second); + } + + private: + + interval_map_t interval_map_; + }; + class stack_limit_handler { public: @@ -19948,6 +20133,41 @@ namespace exprtk typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; + struct variable_context + { + variable_context() + : symbol_table(0) + , variable(0) + {} + + const symbol_table_t* symbol_table; + variable_ptr variable; + }; + + struct vector_context + { + vector_context() + : symbol_table(0) + , vector_holder(0) + {} + + const symbol_table_t* symbol_table; + vector_holder_ptr vector_holder; + }; + + #ifndef exprtk_disable_string_capabilities + struct string_context + { + string_context() + : symbol_table(0) + , str_var(0) + {} + + const symbol_table_t* symbol_table; + stringvar_ptr str_var; + }; + #endif + inline bool empty() const { return symtab_list_.empty(); @@ -19988,6 +20208,31 @@ namespace exprtk return false; } + inline variable_context get_variable_context(const std::string& variable_name) const + { + variable_context result; + if (!valid_symbol(variable_name)) + return result; + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + { + continue; + } + + result.variable = local_data(i) + .variable_store.get(variable_name); + if (result.variable) + { + result.symbol_table = &symtab_list_[i]; + break; + } + } + + return result; + } + inline variable_ptr get_variable(const std::string& variable_name) const { if (!valid_symbol(variable_name)) @@ -20028,6 +20273,32 @@ namespace exprtk } #ifndef exprtk_disable_string_capabilities + inline string_context get_string_context(const std::string& string_name) const + { + string_context result; + + if (!valid_symbol(string_name)) + return result; + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + { + continue; + } + + result.str_var = local_data(i).stringvar_store.get(string_name); + + if (result.str_var) + { + result.symbol_table = &symtab_list_[i]; + break; + } + } + + return result; + } + inline stringvar_ptr get_stringvar(const std::string& string_name) const { if (!valid_symbol(string_name)) @@ -20155,6 +20426,31 @@ namespace exprtk return result; } + inline vector_context get_vector_context(const std::string& vector_name) const + { + vector_context result; + if (!valid_symbol(vector_name)) + return result; + + for (std::size_t i = 0; i < symtab_list_.size(); ++i) + { + if (!symtab_list_[i].valid()) + { + continue; + } + + result.vector_holder = local_data(i).vector_store.get(vector_name); + + if (result.vector_holder) + { + result.symbol_table = &symtab_list_[i]; + break; + } + } + + return result; + } + inline vector_holder_ptr get_vector(const std::string& vector_name) const { if (!valid_symbol(vector_name)) @@ -21540,7 +21836,7 @@ namespace exprtk if (helper_assembly_.error_token_scanner) { lexer::helper::bracket_checker* bracket_checker_ptr = 0; - lexer::helper::numeric_checker* numeric_checker_ptr = 0; + lexer::helper::numeric_checker* numeric_checker_ptr = 0; lexer::helper::sequence_validator* sequence_validator_ptr = 0; lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; @@ -21552,7 +21848,7 @@ namespace exprtk "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", exprtk_error_location)); } - else if (0 != (numeric_checker_ptr = dynamic_cast(helper_assembly_.error_token_scanner))) + else if (0 != (numeric_checker_ptr = dynamic_cast*>(helper_assembly_.error_token_scanner))) { for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) { @@ -23204,6 +23500,12 @@ namespace exprtk return parse_base_operation(); } + void handle_brkcnt_scope_exit() + { + assert(!brkcnt_list_.empty()); + brkcnt_list_.pop_front(); + } + inline expression_node_ptr parse_while_loop() { // Parse: [while][(][test expr][)][{][expression][}] @@ -23252,7 +23554,7 @@ namespace exprtk { scoped_inc_dec sid(state_.parsing_loop_stmt_count); - if (0 == (branch = parse_multi_sequence("while-loop"))) + if (0 == (branch = parse_multi_sequence("while-loop", true))) { set_error( make_error(parser_error::e_syntax, @@ -23274,18 +23576,18 @@ namespace exprtk } } + handle_brkcnt_scope_exit(); + if (!result) { free_node(node_allocator_, branch ); free_node(node_allocator_, condition ); free_node(node_allocator_, result_node); - brkcnt_list_.pop_front(); - return error_node(); } - else - return result_node; + + return result_node; } inline expression_node_ptr parse_repeat_until_loop() @@ -23364,8 +23666,6 @@ namespace exprtk if (sdd.delete_ptr) { - brkcnt_list_.pop_front(); - set_error( make_error(parser_error::e_syntax, current_token(), @@ -23378,8 +23678,6 @@ namespace exprtk if (!token_is(token_t::e_lbracket)) { - brkcnt_list_.pop_front(); - set_error( make_error(parser_error::e_syntax, current_token(), @@ -23387,13 +23685,10 @@ namespace exprtk exprtk_error_location)); free_node(node_allocator_,branch); - return error_node(); } else if (0 == (condition = parse_expression())) { - brkcnt_list_.pop_front(); - set_error( make_error(parser_error::e_syntax, current_token(), @@ -23401,7 +23696,6 @@ namespace exprtk exprtk_error_location)); free_node(node_allocator_,branch); - return error_node(); } else if (!token_is(token_t::e_rbracket)) @@ -23415,8 +23709,6 @@ namespace exprtk free_node(node_allocator_, branch ); free_node(node_allocator_, condition); - brkcnt_list_.pop_front(); - return error_node(); } @@ -23435,15 +23727,12 @@ namespace exprtk free_node(node_allocator_,condition); - brkcnt_list_.pop_front(); - return error_node(); } - else - { - brkcnt_list_.pop_front(); - return result; - } + + handle_brkcnt_scope_exit(); + + return result; } inline expression_node_ptr parse_for_loop() @@ -23635,7 +23924,7 @@ namespace exprtk scoped_inc_dec sid(state_.parsing_loop_stmt_count); - if (0 == (loop_body = parse_multi_sequence("for-loop"))) + if (0 == (loop_body = parse_multi_sequence("for-loop", true))) { set_error( make_error(parser_error::e_syntax, @@ -23658,26 +23947,18 @@ namespace exprtk free_node(node_allocator_, condition ); free_node(node_allocator_, incrementor); free_node(node_allocator_, loop_body ); - - if (!brkcnt_list_.empty()) - { - brkcnt_list_.pop_front(); - } - return error_node(); } - else - { - expression_node_ptr result_node = - expression_generator_.for_loop(initialiser, - condition, - incrementor, - loop_body, - brkcnt_list_.front()); - brkcnt_list_.pop_front(); - return result_node; - } + expression_node_ptr result_node = + expression_generator_.for_loop(initialiser, + condition, + incrementor, + loop_body, + brkcnt_list_.front()); + handle_brkcnt_scope_exit(); + + return result_node; } inline expression_node_ptr parse_switch_statement() @@ -23987,7 +24268,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR096 - Unsupported vararg function: " + symbol, + "ERR096 - Unsupported built-in vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -24010,6 +24291,18 @@ namespace exprtk return error_node(); } + if (token_is(token_t::e_rbracket)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR098 - vararg function: " + symbol + + " requires at least one input parameter", + exprtk_error_location)); + + return error_node(); + } + for ( ; ; ) { expression_node_ptr arg = parse_expression(); @@ -24026,7 +24319,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR098 - Expected ',' for call to vararg function: " + symbol, + "ERR099 - Expected ',' for call to vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -24047,7 +24340,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR099 - Expected '[' as start of string range definition", + "ERR100 - Expected '[' as start of string range definition", exprtk_error_location)); free_node(node_allocator_,expression); @@ -24075,7 +24368,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR100 - Failed to generate string range node", + "ERR101 - Failed to generate string range node", exprtk_error_location)); free_node(node_allocator_,expression); @@ -24195,15 +24488,18 @@ namespace exprtk return expression_generator_.vararg_function(details::e_multi,expression_list); } - inline expression_node_ptr parse_multi_sequence(const std::string& source = "") + inline expression_node_ptr parse_multi_sequence(const std::string& source = "", + const bool enforce_crlbrackets = false) { + token_t::token_type open_bracket = token_t::e_lcrlbracket; token_t::token_type close_bracket = token_t::e_rcrlbracket; token_t::token_type seperator = token_t::e_eof; - if (!token_is(token_t::e_lcrlbracket)) + if (!token_is(open_bracket)) { - if (token_is(token_t::e_lbracket)) + if (!enforce_crlbrackets && token_is(token_t::e_lbracket)) { + open_bracket = token_t::e_lbracket; close_bracket = token_t::e_rbracket; seperator = token_t::e_comma; } @@ -24212,14 +24508,14 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR101 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + + "ERR102 - Expected '" + token_t::to_str(open_bracket) + "' for call to multi-sequence" + ((!source.empty()) ? std::string(" section of " + source): ""), exprtk_error_location)); return error_node(); } } - else if (token_is(token_t::e_rcrlbracket)) + else if (token_is(close_bracket)) { return node_allocator_.allocate >(); } @@ -24259,7 +24555,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR102 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, + "ERR103 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, exprtk_error_location)); return error_node(); @@ -24269,7 +24565,7 @@ namespace exprtk break; } - result = simplify(arg_list,side_effect_list,source.empty()); + result = simplify(arg_list, side_effect_list, source.empty()); sdd.delete_ptr = (0 == result); return result; @@ -24293,7 +24589,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR103 - Expected '[' for start of range", + "ERR104 - Expected '[' for start of range", exprtk_error_location)); return false; @@ -24314,7 +24610,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR104 - Failed parse begin section of range", + "ERR105 - Failed parse begin section of range", exprtk_error_location)); return false; @@ -24337,7 +24633,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR105 - Range lower bound less than zero! Constraint: r0 >= 0", + "ERR106 - Range lower bound less than zero! Constraint: r0 >= 0", exprtk_error_location)); return false; @@ -24354,7 +24650,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR106 - Expected ':' for break in range", + "ERR107 - Expected ':' for break in range", exprtk_error_location)); rp.free(); @@ -24377,7 +24673,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR107 - Failed parse end section of range", + "ERR108 - Failed parse end section of range", exprtk_error_location)); rp.free(); @@ -24402,7 +24698,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR108 - Range upper bound less than zero! Constraint: r1 >= 0", + "ERR109 - Range upper bound less than zero! Constraint: r1 >= 0", exprtk_error_location)); rp.free(); @@ -24421,7 +24717,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR109 - Expected ']' for start of range", + "ERR110 - Expected ']' for start of range", exprtk_error_location)); rp.free(); @@ -24449,7 +24745,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR110 - Invalid range, Constraint: r0 <= r1", + "ERR111 - Invalid range, Constraint: r0 <= r1", exprtk_error_location)); return false; @@ -24485,24 +24781,36 @@ namespace exprtk } else { - if (!symtab_store_.is_conststr_stringvar(symbol)) + typedef typename symtab_store::string_context str_ctxt_t; + str_ctxt_t str_ctx = symtab_store_.get_string_context(symbol); + + if ((0 == str_ctx.str_var) || !symtab_store_.is_conststr_stringvar(symbol)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR111 - Unknown string symbol", + "ERR112 - Unknown string symbol", exprtk_error_location)); return error_node(); } - result = symtab_store_.get_stringvar(symbol); + assert(str_ctx.str_var != 0); + assert(str_ctx.symbol_table != 0); + + result = str_ctx.str_var; if (symtab_store_.is_constant_string(symbol)) { const_str_node = static_cast(result); result = expression_generator_(const_str_node->str()); } + else if (symbol_table_t::e_immutable == str_ctx.symbol_table->mutability()) + { + lodge_immutable_symbol( + current_token(), + make_memory_range(str_ctx.str_var->base(), str_ctx.str_var->size())); + } lodge_symbol(symbol, e_st_string); } @@ -24605,7 +24913,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR112 - Overflow in range for string: '" + const_str + "'[" + + "ERR113 - Overflow in range for string: '" + const_str + "'[" + (rp.n0_c.first ? details::to_str(static_cast(rp.n0_c.second)) : "?") + ":" + (rp.n1_c.first ? details::to_str(static_cast(rp.n1_c.second)) : "?") + "]", exprtk_error_location)); @@ -24646,20 +24954,37 @@ namespace exprtk (scope_element::e_vector != se.type) ) { - if (0 == (vec = symtab_store_.get_vector(symbol))) + typedef typename symtab_store::vector_context vec_ctxt_t; + vec_ctxt_t vec_ctx = symtab_store_.get_vector_context(symbol); + + if (0 == vec_ctx.vector_holder) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR113 - Symbol '" + symbol+ " not a vector", + "ERR114 - Symbol '" + symbol+ " not a vector", exprtk_error_location)); return error_node(); } + + assert(0 != vec_ctx.vector_holder); + assert(0 != vec_ctx.symbol_table ); + + vec = vec_ctx.vector_holder; + + if (symbol_table_t::e_immutable == vec_ctx.symbol_table->mutability()) + { + lodge_immutable_symbol( + current_token(), + make_memory_range(vec->data(), vec->size())); + } } else vec = se.vec_node; + assert(0 != vec); + expression_node_ptr index_expr = error_node(); next_token(); @@ -24677,7 +25002,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR114 - Failed to parse index for vector: '" + symbol + "'", + "ERR115 - Failed to parse index for vector: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -24687,7 +25012,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR115 - Expected ']' for index of vector: '" + symbol + "'", + "ERR116 - Expected ']' for index of vector: '" + symbol + "'", exprtk_error_location)); free_node(node_allocator_,index_expr); @@ -24706,7 +25031,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR116 - Index of " + details::to_str(index) + " out of range for " + "ERR117 - Index of " + details::to_str(index) + " out of range for " "vector '" + symbol + "' of size " + details::to_str(vec_size), exprtk_error_location)); @@ -24738,7 +25063,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR117 - Zero parameter call to vararg function: " + "ERR118 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -24763,7 +25088,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR118 - Expected ',' for call to vararg function: " + "ERR119 - Expected ',' for call to vararg function: " + vararg_function_name, exprtk_error_location)); @@ -24777,7 +25102,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR119 - Zero parameter call to vararg function: " + "ERR120 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -24789,7 +25114,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR120 - Invalid number of parameters to call to vararg function: " + "ERR121 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require at least " + details::to_str(static_cast(vararg_function->min_num_args())) + " parameters", exprtk_error_location)); @@ -24801,7 +25126,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR121 - Invalid number of parameters to call to vararg function: " + "ERR122 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require no more than " + details::to_str(static_cast(vararg_function->max_num_args())) + " parameters", exprtk_error_location)); @@ -24879,7 +25204,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR122 - Failed parameter type check for function '" + function_name_ + "', " + "ERR123 - Failed parameter type check for function '" + function_name_ + "', " "Expected '" + function_definition_list_[0].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -24901,7 +25226,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR123 - Failed parameter type check for function '" + function_name_ + "', " + "ERR124 - Failed parameter type check for function '" + function_name_ + "', " "Best match: '" + function_definition_list_[max_diff_index].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -25043,7 +25368,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR124 - Invalid parameter sequence of '" + param_seq_list[i] + + "ERR125 - Invalid parameter sequence of '" + param_seq_list[i] + "' for function: " + function_name_, exprtk_error_location)); return; @@ -25059,7 +25384,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR125 - Function '" + function_name_ + "' has a parameter sequence conflict between " + + "ERR126 - Function '" + function_name_ + "' has a parameter sequence conflict between " + "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + "pseq_idx[" + details::to_str(i) + "] " + "param seq: " + param_seq_list[i], @@ -25091,14 +25416,18 @@ namespace exprtk std::string param_type_list; - type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); + type_checker tc( + (*this), + function_name, + function->parameter_sequence, + type_checker::e_string); if (tc.invalid()) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR126 - Type checker instantiation failure for generic function: " + function_name, + "ERR127 - Type checker instantiation failure for generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -25116,7 +25445,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR127 - Zero parameter call to generic function: " + "ERR128 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -25148,7 +25477,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR128 - Expected ',' for call to generic function: " + function_name, + "ERR129 - Expected ',' for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -25165,7 +25494,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR129 - Zero parameter call to generic function: " + "ERR130 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -25182,7 +25511,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR130 - Invalid input parameter sequence for call to generic function: " + function_name, + "ERR131 - Invalid input parameter sequence for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -25220,7 +25549,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR131 - Zero parameter call to generic function: " + "ERR132 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -25252,7 +25581,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR132 - Expected ',' for call to string function: " + function_name, + "ERR133 - Expected ',' for call to string function: " + function_name, exprtk_error_location)); return false; @@ -25299,7 +25628,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR133 - Invalid input parameter sequence for call to string function: " + function_name, + "ERR134 - Invalid input parameter sequence for call to string function: " + function_name, exprtk_error_location)); return error_node(); @@ -25351,7 +25680,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR134 - Invalid input parameter sequence for call to overloaded function: " + function_name, + "ERR135 - Invalid input parameter sequence for call to overloaded function: " + function_name, exprtk_error_location)); return error_node(); @@ -25382,7 +25711,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR135 - Invalid return type for call to overloaded function: " + function_name, + "ERR136 - Invalid return type for call to overloaded function: " + function_name, exprtk_error_location)); } @@ -25410,7 +25739,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR136 - Expected '(' for special function '" + sf_name + "'", + "ERR137 - Expected '(' for special function '" + sf_name + "'", exprtk_error_location)); return error_node(); @@ -25431,7 +25760,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR137 - Expected ',' before next parameter of special function '" + sf_name + "'", + "ERR138 - Expected ',' before next parameter of special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -25444,7 +25773,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR138 - Invalid number of parameters for special function '" + sf_name + "'", + "ERR139 - Invalid number of parameters for special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -25471,7 +25800,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR139 - Invalid special function[1]: " + sf_name, + "ERR140 - Invalid special function[1]: " + sf_name, exprtk_error_location)); return error_node(); @@ -25485,7 +25814,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR140 - Invalid special function[2]: " + sf_name, + "ERR141 - Invalid special function[2]: " + sf_name, exprtk_error_location)); return error_node(); @@ -25517,7 +25846,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR141 - Invoking 'break' within a break call is not allowed", + "ERR142 - Invoking 'break' within a break call is not allowed", exprtk_error_location)); return error_node(); @@ -25527,7 +25856,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR142 - Invalid use of 'break', allowed only in the scope of a loop", + "ERR143 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); @@ -25550,7 +25879,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR143 - Failed to parse return expression for 'break' statement", + "ERR144 - Failed to parse return expression for 'break' statement", exprtk_error_location)); return error_node(); @@ -25560,7 +25889,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR144 - Expected ']' at the completion of break's return expression", + "ERR145 - Expected ']' at the completion of break's return expression", exprtk_error_location)); free_node(node_allocator_,return_expr); @@ -25578,7 +25907,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR145 - Invalid use of 'break', allowed only in the scope of a loop", + "ERR146 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); } @@ -25592,7 +25921,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR146 - Invalid use of 'continue', allowed only in the scope of a loop", + "ERR147 - Invalid use of 'continue', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); @@ -25618,7 +25947,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR147 - Expected '[' as part of vector size definition", + "ERR148 - Expected '[' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -25628,7 +25957,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR148 - Failed to determine size of vector '" + vec_name + "'", + "ERR149 - Failed to determine size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -25640,7 +25969,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR149 - Expected a literal number as size of vector '" + vec_name + "'", + "ERR150 - Expected a literal number as size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -25662,7 +25991,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR150 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + + "ERR151 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + details::to_str(details::numeric::to_int32(vector_size)), exprtk_error_location)); @@ -25682,7 +26011,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR151 - Expected ']' as part of vector size definition", + "ERR152 - Expected ']' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -25694,7 +26023,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR152 - Expected ':=' as part of vector definition", + "ERR153 - Expected ':=' as part of vector definition", exprtk_error_location)); return error_node(); @@ -25708,7 +26037,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR153 - Failed to parse single vector initialiser", + "ERR154 - Failed to parse single vector initialiser", exprtk_error_location)); return error_node(); @@ -25721,7 +26050,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR154 - Expected ']' to close single value vector initialiser", + "ERR155 - Expected ']' to close single value vector initialiser", exprtk_error_location)); return error_node(); @@ -25768,7 +26097,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR155 - Expected '{' as part of vector initialiser list", + "ERR156 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -25788,7 +26117,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR156 - Expected '{' as part of vector initialiser list", + "ERR157 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -25806,7 +26135,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR157 - Expected ',' between vector initialisers", + "ERR158 - Expected ',' between vector initialisers", exprtk_error_location)); return error_node(); @@ -25828,19 +26157,19 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR158 - Expected ';' at end of vector definition", + "ERR159 - Expected ';' at end of vector definition", exprtk_error_location)); return error_node(); } } - if (vec_initilizer_list.size() > vector_size) + if (T(vec_initilizer_list.size()) > vector_size) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR159 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", + "ERR160 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -25860,7 +26189,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR160 - Illegal redefinition of local vector: '" + vec_name + "'", + "ERR161 - Illegal redefinition of local vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -25894,7 +26223,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR161 - Failed to add new local vector '" + vec_name + "' to SEM", + "ERR162 - Failed to add new local vector '" + vec_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -25953,7 +26282,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR162 - Illegal redefinition of local variable: '" + str_name + "'", + "ERR163 - Illegal redefinition of local variable: '" + str_name + "'", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -25985,7 +26314,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR163 - Failed to add new local string variable '" + str_name + "' to SEM", + "ERR164 - Failed to add new local string variable '" + str_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -26031,7 +26360,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR164 - Illegal variable definition", + "ERR165 - Illegal variable definition", exprtk_error_location)); return error_node(); @@ -26052,7 +26381,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR165 - Expected a symbol for variable definition", + "ERR166 - Expected a symbol for variable definition", exprtk_error_location)); return error_node(); @@ -26062,7 +26391,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR166 - Illegal redefinition of reserved keyword: '" + var_name + "'", + "ERR167 - Illegal redefinition of reserved keyword: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -26072,7 +26401,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR167 - Illegal redefinition of variable '" + var_name + "'", + "ERR168 - Illegal redefinition of variable '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -26082,7 +26411,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR168 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR169 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -26102,7 +26431,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR169 - Failed to parse initialisation expression", + "ERR170 - Failed to parse initialisation expression", exprtk_error_location)); return error_node(); @@ -26120,7 +26449,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR170 - Expected ';' after variable definition", + "ERR171 - Expected ';' after variable definition", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -26148,7 +26477,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR171 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR172 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -26180,7 +26509,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR172 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR173 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -26217,7 +26546,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR173 - Expected a '{}' for uninitialised var definition", + "ERR174 - Expected a '{}' for uninitialised var definition", exprtk_error_location)); return error_node(); @@ -26227,7 +26556,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR174 - Expected ';' after uninitialised variable definition", + "ERR175 - Expected ';' after uninitialised variable definition", exprtk_error_location)); return error_node(); @@ -26244,7 +26573,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR175 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR176 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -26274,7 +26603,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR176 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR177 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -26307,7 +26636,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR177 - Expected '(' at start of swap statement", + "ERR178 - Expected '(' at start of swap statement", exprtk_error_location)); return error_node(); @@ -26326,7 +26655,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR178 - Expected a symbol for variable or vector element definition", + "ERR179 - Expected a symbol for variable or vector element definition", exprtk_error_location)); return error_node(); @@ -26338,7 +26667,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR179 - First parameter to swap is an invalid vector element: '" + var0_name + "'", + "ERR180 - First parameter to swap is an invalid vector element: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -26371,7 +26700,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR180 - First parameter to swap is an invalid variable: '" + var0_name + "'", + "ERR181 - First parameter to swap is an invalid variable: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -26385,7 +26714,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR181 - Expected ',' between parameters to swap", + "ERR182 - Expected ',' between parameters to swap", exprtk_error_location)); if (variable0_generated) @@ -26403,7 +26732,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR182 - Expected a symbol for variable or vector element definition", + "ERR183 - Expected a symbol for variable or vector element definition", exprtk_error_location)); if (variable0_generated) @@ -26420,7 +26749,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR183 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", + "ERR184 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -26458,7 +26787,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR184 - Second parameter to swap is an invalid variable: '" + var1_name + "'", + "ERR185 - Second parameter to swap is an invalid variable: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -26477,7 +26806,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR185 - Expected ')' at end of swap statement", + "ERR186 - Expected ')' at end of swap statement", exprtk_error_location)); if (variable0_generated) @@ -26534,7 +26863,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR186 - Return call within a return call is not allowed", + "ERR187 - Return call within a return call is not allowed", exprtk_error_location)); return error_node(); @@ -26558,7 +26887,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR187 - Expected '[' at start of return statement", + "ERR188 - Expected '[' at start of return statement", exprtk_error_location)); return error_node(); @@ -26581,7 +26910,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR188 - Expected ',' between values during call to return", + "ERR189 - Expected ',' between values during call to return", exprtk_error_location)); return error_node(); @@ -26593,7 +26922,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR189 - Zero parameter return statement not allowed", + "ERR190 - Zero parameter return statement not allowed", exprtk_error_location)); return error_node(); @@ -26608,7 +26937,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR190 - Invalid ']' found during return call", + "ERR191 - Invalid ']' found during return call", exprtk_error_location)); return error_node(); @@ -26661,7 +26990,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR191 - Invalid sequence of variable '"+ symbol + "' and bracket", + "ERR192 - Invalid sequence of variable '" + symbol + "' and bracket", exprtk_error_location)); return false; @@ -26709,7 +27038,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR192 - Invalid sequence of brackets", + "ERR193 - Invalid sequence of brackets", exprtk_error_location)); return false; @@ -26725,27 +27054,65 @@ namespace exprtk return true; } + typedef typename interval_container_t::interval_t interval_t; + typedef interval_container_t immutable_memory_map_t; + typedef std::map immutable_symtok_map_t; + + inline interval_t make_memory_range(const T& t) + { + const T* begin = reinterpret_cast(&t); + const T* end = begin + 1; + return interval_t(begin, end); + } + + inline interval_t make_memory_range(const T* begin, const std::size_t size) + { + return interval_t(begin, begin + size); + } + + inline interval_t make_memory_range(details::char_cptr begin, const std::size_t size) + { + return interval_t(begin, begin + size); + } + + void lodge_immutable_symbol(const lexer::token& token, const interval_t interval) + { + immutable_memory_map_.add_interval(interval); + immutable_symtok_map_[interval] = token; + } + inline expression_node_ptr parse_symtab_symbol() { const std::string symbol = current_token().value; // Are we dealing with a variable or a special constant? - expression_node_ptr variable = symtab_store_.get_variable(symbol); + typedef typename symtab_store::variable_context var_ctxt_t; + var_ctxt_t var_ctx = symtab_store_.get_variable_context(symbol); - if (variable) + if (var_ctx.variable) { + assert(var_ctx.symbol_table); + + expression_node_ptr result_variable = var_ctx.variable; + if (symtab_store_.is_constant_node(symbol)) { - variable = expression_generator_(variable->value()); + result_variable = expression_generator_(var_ctx.variable->value()); + } + else if (symbol_table_t::e_immutable == var_ctx.symbol_table->mutability()) + { + lodge_immutable_symbol(current_token(), make_memory_range(var_ctx.variable->ref())); + result_variable = var_ctx.variable; } if (!post_variable_process(symbol)) return error_node(); lodge_symbol(symbol, e_st_variable); + next_token(); - return variable; + return result_variable; } // Are we dealing with a locally defined variable, vector or string? @@ -26806,7 +27173,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR193 - Failed to generate node for function: '" + symbol + "'", + "ERR194 - Failed to generate node for function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -26832,7 +27199,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR194 - Failed to generate node for vararg function: '" + symbol + "'", + "ERR195 - Failed to generate node for vararg function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -26858,7 +27225,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR195 - Failed to generate node for generic function: '" + symbol + "'", + "ERR196 - Failed to generate node for generic function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -26885,7 +27252,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR196 - Failed to generate node for string function: '" + symbol + "'", + "ERR197 - Failed to generate node for string function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -26911,7 +27278,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR197 - Failed to generate node for overload function: '" + symbol + "'", + "ERR198 - Failed to generate node for overload function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -26937,7 +27304,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR198 - Invalid use of reserved symbol '" + symbol + "'", + "ERR199 - Invalid use of reserved symbol '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -27000,7 +27367,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR199 - Failed to create variable: '" + symbol + "'" + + "ERR200 - Failed to create variable: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); @@ -27020,7 +27387,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR200 - Failed to resolve symbol: '" + symbol + "'" + + "ERR201 - Failed to resolve symbol: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); } @@ -27032,7 +27399,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR201 - Undefined symbol: '" + symbol + "'", + "ERR202 - Undefined symbol: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -27146,7 +27513,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR202 - Variable or function detected, yet symbol-table is invalid, Symbol: " + symbol, + "ERR203 - Variable or function detected, yet symbol-table is invalid, Symbol: " + symbol, exprtk_error_location)); return error_node(); @@ -27177,7 +27544,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR203 - Failed generate node for scalar: '" + current_token().value + "'", + "ERR204 - Failed generate node for scalar: '" + current_token().value + "'", exprtk_error_location)); return error_node(); @@ -27191,7 +27558,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR204 - Failed to convert '" + current_token().value + "' to a number", + "ERR205 - Failed to convert '" + current_token().value + "' to a number", exprtk_error_location)); return error_node(); @@ -27218,7 +27585,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR205 - Expected ')' instead of: '" + current_token().value + "'", + "ERR206 - Expected ')' instead of: '" + current_token().value + "'", exprtk_error_location)); details::free_node(node_allocator_,branch); @@ -27243,7 +27610,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR206 - Expected ']' instead of: '" + current_token().value + "'", + "ERR207 - Expected ']' instead of: '" + current_token().value + "'", exprtk_error_location)); details::free_node(node_allocator_,branch); @@ -27268,7 +27635,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR207 - Expected '}' instead of: '" + current_token().value + "'", + "ERR208 - Expected '}' instead of: '" + current_token().value + "'", exprtk_error_location)); details::free_node(node_allocator_,branch); @@ -27317,7 +27684,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR208 - Premature end of expression[1]", + "ERR209 - Premature end of expression[1]", exprtk_error_location)); return error_node(); @@ -27327,7 +27694,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR209 - Premature end of expression[2]", + "ERR210 - Premature end of expression[2]", exprtk_error_location)); return error_node(); @@ -29616,43 +29983,105 @@ namespace exprtk } } + const void* base_ptr(expression_node_ptr node) + { + if (node) + { + switch(node->type()) + { + case details::expression_node::e_variable: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_vecelem: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_rbvecelem: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_rbveccelem: + return reinterpret_cast(&static_cast(node)->ref()); + + case details::expression_node::e_vector: + return reinterpret_cast(static_cast(node)->vec_holder().data()); + + #ifndef exprtk_disable_string_capabilities + case details::expression_node::e_stringvar: + return reinterpret_cast((static_cast(node)->base())); + + case details::expression_node::e_stringvarrng: + return reinterpret_cast((static_cast(node)->base())); + #endif + default : return reinterpret_cast(0); + } + } + + return reinterpret_cast(0); + } + + bool assign_immutable_symbol(expression_node_ptr node) + { + interval_t interval; + const void* baseptr_addr = base_ptr(node); + + exprtk_debug(("assign_immutable_symbol - base ptr addr: %p\n", baseptr_addr)); + + if (parser_->immutable_memory_map_.in_interval(baseptr_addr,interval)) + { + typename immutable_symtok_map_t::iterator itr = parser_->immutable_symtok_map_.find(interval); + + if (parser_->immutable_symtok_map_.end() != itr) + { + token_t& token = itr->second; + parser_->set_error( + parser_error::make_error(parser_error::e_parser, + token, + "ERR211 - Symbol '" + token.value + "' cannot be assigned-to as it is immutable.", + exprtk_error_location)); + } + else + parser_->set_synthesis_error("Unable to assign symbol is immutable."); + + return true; + } + + return false; + } + inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { - if (details::is_variable_node(branch[0])) + if (assign_immutable_symbol(branch[0])) + { + return error_node(); + } + else if (details::is_variable_node(branch[0])) { lodge_assignment(e_st_variable,branch[0]); - return synthesize_expression(operation,branch); } else if (details::is_vector_elem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); - return synthesize_expression(operation, branch); } else if (details::is_rebasevector_elem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); - return synthesize_expression(operation, branch); } else if (details::is_rebasevector_celem_node(branch[0])) { lodge_assignment(e_st_vecelem,branch[0]); - return synthesize_expression(operation, branch); } #ifndef exprtk_disable_string_capabilities else if (details::is_string_node(branch[0])) { lodge_assignment(e_st_string,branch[0]); - return synthesize_expression(operation, branch); } else if (details::is_string_range_node(branch[0])) { lodge_assignment(e_st_string,branch[0]); - return synthesize_expression(operation, branch); } #endif @@ -29676,6 +30105,11 @@ namespace exprtk inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) { + if (assign_immutable_symbol(branch[0])) + { + return error_node(); + } + if (details::is_variable_node(branch[0])) { lodge_assignment(e_st_variable,branch[0]); @@ -36995,6 +37429,9 @@ namespace exprtk std::string synthesis_error_; scope_element_manager sem_; + immutable_memory_map_t immutable_memory_map_; + immutable_symtok_map_t immutable_symtok_map_; + lexer::helper::helper_assembly helper_assembly_; lexer::helper::commutative_inserter commutative_inserter_; @@ -37002,7 +37439,7 @@ namespace exprtk lexer::helper::operator_joiner operator_joiner_3_; lexer::helper::symbol_replacer symbol_replacer_; lexer::helper::bracket_checker bracket_checker_; - lexer::helper::numeric_checker numeric_checker_; + lexer::helper::numeric_checker numeric_checker_; lexer::helper::sequence_validator sequence_validator_; lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; @@ -38541,202 +38978,7 @@ namespace exprtk std::vector auxiliary_symtab_list_; }; // class function_compositor - template - inline bool pgo_primer() - { - static const std::string expression_list[] = - { - "(y + x)", - "2 * (y + x)", - "(2 * y + 2 * x)", - "(y + x / y) * (x - y / x)", - "x / ((x + y) * (x - y)) / y", - "1 - ((x * y) + (y / x)) - 3", - "sin(2 * x) + cos(pi / y)", - "1 - sin(2 * x) + cos(pi / y)", - "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", - "(x^2 / sin(2 * pi / y)) -x / 2", - "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", - "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", - "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", - "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", - "(yy + xx)", - "2 * (yy + xx)", - "(2 * yy + 2 * xx)", - "(yy + xx / yy) * (xx - yy / xx)", - "xx / ((xx + yy) * (xx - yy)) / yy", - "1 - ((xx * yy) + (yy / xx)) - 3", - "sin(2 * xx) + cos(pi / yy)", - "1 - sin(2 * xx) + cos(pi / yy)", - "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", - "(xx^2 / sin(2 * pi / yy)) -xx / 2", - "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", - "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", - "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", - "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", - "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", - "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", - "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", - "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", - "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", - "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", - "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", - "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", - "2 + (x * (y / 3))", "x + (2 * (3 / y))", - "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", - "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", - "x + ((2 * 3) / y)", "(((x + y) * z) / w)", - "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", - "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", - "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", - "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", - "((x + (2 * 3)) / y)", - "(xx + yy) * zz", "xx + (yy * zz)", - "(xx + yy) * 7", "xx + (yy * 7)", - "(xx + 7) * yy", "xx + (7 * yy)", - "(7 + xx) * yy", "7 + (xx * yy)", - "(2 + x) * 3", "2 + (x * 3)", - "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", - "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", - "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", - "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", - "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", - "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", - "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", - "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", - "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", - "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", - "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", - "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", - "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", - "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", - "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", - "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", - "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", - "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", - "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", - "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", - "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", - "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", - "((xx + (2 * 3)) / yy)" - }; - - static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); - - T x = T(0); - T y = T(0); - T z = T(0); - T w = T(0); - T xx = T(0); - T yy = T(0); - T zz = T(0); - T ww = T(0); - - exprtk::symbol_table symbol_table; - symbol_table.add_constants(); - symbol_table.add_variable( "x", x); - symbol_table.add_variable( "y", y); - symbol_table.add_variable( "z", z); - symbol_table.add_variable( "w", w); - symbol_table.add_variable("xx",xx); - symbol_table.add_variable("yy",yy); - symbol_table.add_variable("zz",zz); - symbol_table.add_variable("ww",ww); - - typedef typename std::deque > expr_list_t; - expr_list_t expr_list; - - const std::size_t rounds = 50; - - { - for (std::size_t r = 0; r < rounds; ++r) - { - expr_list.clear(); - exprtk::parser parser; - - for (std::size_t i = 0; i < expression_list_size; ++i) - { - exprtk::expression expression; - expression.register_symbol_table(symbol_table); - - if (!parser.compile(expression_list[i],expression)) - { - return false; - } - - expr_list.push_back(expression); - } - } - } - - struct execute - { - static inline T process(T& x, T& y, expression& expression) - { - static const T lower_bound = T(-20); - static const T upper_bound = T(+20); - static const T delta = T(0.1); - - T total = T(0); - - for (x = lower_bound; x <= upper_bound; x += delta) - { - for (y = lower_bound; y <= upper_bound; y += delta) - { - total += expression.value(); - } - } - - return total; - } - }; - - for (std::size_t i = 0; i < expr_list.size(); ++i) - { - execute::process( x, y, expr_list[i]); - execute::process(xx, yy, expr_list[i]); - } - - { - for (std::size_t i = 0; i < 10000; ++i) - { - const T v = T(123.456 + i); - - if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T(1))))) - return false; - - #define else_stmt(N) \ - else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp::result(v),details::numeric::pow(v,T(N))))) \ - return false; \ - - else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5) - else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9) - else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13) - else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17) - else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21) - else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25) - else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29) - else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33) - else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37) - else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41) - else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45) - else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49) - else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53) - else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57) - else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61) - } - } - - return true; - } -} +} // namespace exprtk #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) # ifndef NOMINMAX @@ -39012,6 +39254,9 @@ namespace exprtk { namespace rtl { namespace io { namespace file { namespace details { + using ::exprtk::details::char_ptr; + using ::exprtk::details::char_cptr; + enum file_mode { e_error = 0, @@ -39120,11 +39365,11 @@ namespace exprtk switch (mode) { case e_write : reinterpret_cast(stream_ptr)-> - write(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); + write(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); break; case e_rdwrt : reinterpret_cast(stream_ptr)-> - write(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); + write(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); break; default : return false; @@ -39139,11 +39384,11 @@ namespace exprtk switch (mode) { case e_read : reinterpret_cast(stream_ptr)-> - read(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); + read(reinterpret_cast(view.begin() + offset), amount * sizeof(typename View::value_t)); break; case e_rdwrt : reinterpret_cast(stream_ptr)-> - read(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); + read(reinterpret_cast(view.begin() + offset) , amount * sizeof(typename View::value_t)); break; default : return false; @@ -39207,12 +39452,11 @@ namespace exprtk template file_descriptor* make_handle(T v) { + const std::size_t fd_size = sizeof(details::file_descriptor*); details::file_descriptor* fd = reinterpret_cast(0); - const std::size_t fd_size = sizeof(details::file_descriptor*); - - std::memcpy(reinterpret_cast(&fd), - reinterpret_cast(&v), + std::memcpy(reinterpret_cast(&fd), + reinterpret_cast(&v ), fd_size); return fd; } @@ -39253,18 +39497,18 @@ namespace exprtk inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) { - std::string file_name = to_str(string_t(parameters[0])); - std::string access; + const std::string file_name = to_str(string_t(parameters[0])); if (file_name.empty()) return T(0); - if (0 == ps_index) - access = "r"; - else if (0 == string_t(parameters[1]).size()) + if ((1 == ps_index) && (0 == string_t(parameters[1]).size())) + { return T(0); - else - access = to_str(string_t(parameters[1])); + } + + const std::string access = + (0 == ps_index) ? "r" : to_str(string_t(parameters[1])); details::file_descriptor* fd = new details::file_descriptor(file_name,access); @@ -40685,18 +40929,22 @@ namespace exprtk { namespace information { - static const char* library = "Mathematical Expression Toolkit"; - static const char* version = "2.7182818284590452353602874713526" - "624977572470936999595749669676277" - "240766303535475945713821785251664" - "274274663919320030599218174135966"; - static const char* date = "20220101"; + using ::exprtk::details::char_cptr; + + static char_cptr library = "Mathematical Expression Toolkit"; + static char_cptr version = "2.71828182845904523536028747135266" + "2497757247093699959574966967627724" + "0766303535475945713821785251664274" + "2746639193200305992181741359662904"; + static char_cptr date = "20230101"; + static char_cptr min_cpp = "199711L"; static inline std::string data() { static const std::string info_str = std::string(library) + std::string(" v") + std::string(version) + - std::string(" (") + date + std::string(")"); + std::string(" (") + date + std::string(")") + + std::string(" (") + min_cpp + std::string(")"); return info_str; } diff --git a/license.txt b/license.txt index 3ab7965..9422473 100644 --- a/license.txt +++ b/license.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 1999-2022 Arash Partow +Copyright (c) 1999-2023 Arash Partow Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the