C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2014-12-29 05:43:32 +11:00
parent e0bbb336dd
commit c8657e95a2
3 changed files with 475 additions and 198 deletions

View File

@ -2393,7 +2393,7 @@ namespace exprtk
private: private:
token_list_t token_list_; token_list_t token_list_;
token_list_itr_t token_itr_; token_list_itr_t token_itr_;
token_list_itr_t store_token_itr_; token_list_itr_t store_token_itr_;
token_t eof_token_; token_t eof_token_;
@ -2436,7 +2436,7 @@ namespace exprtk
inline std::size_t process(generator& g) inline std::size_t process(generator& g)
{ {
if (!g.token_list_.empty()) if (g.token_list_.size() >= stride_)
{ {
for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
{ {
@ -2561,6 +2561,8 @@ namespace exprtk
{ {
if (g.token_list_.empty()) if (g.token_list_.empty())
return 0; return 0;
else if (g.token_list_.size() < stride_)
return 0;
std::size_t changes = 0; std::size_t changes = 0;
@ -4380,9 +4382,11 @@ namespace exprtk
typedef range_data_type<T> range_data_type_t; typedef range_data_type<T> range_data_type_t;
virtual std::string str() const = 0; virtual std::string str () const = 0;
virtual const char* base() const = 0; virtual const char* base() const = 0;
virtual std::size_t size() const = 0;
}; };
template <typename T> template <typename T>
@ -4428,6 +4432,11 @@ namespace exprtk
return value_.data(); return value_.data();
} }
std::size_t size() const
{
return value_.size();
}
range_t& range_ref() range_t& range_ref()
{ {
return rp_; return rp_;
@ -5383,9 +5392,9 @@ namespace exprtk
expression_ptr incrementor, expression_ptr incrementor,
expression_ptr loop_body) expression_ptr loop_body)
: initialiser_(initialiser), : initialiser_(initialiser),
condition_ (condition), condition_ (condition ),
incrementor_(incrementor), incrementor_(incrementor),
loop_body_ (loop_body), loop_body_ (loop_body ),
initialiser_deletable_(branch_deletable(initialiser_)), initialiser_deletable_(branch_deletable(initialiser_)),
condition_deletable_ (branch_deletable(condition_ )), condition_deletable_ (branch_deletable(condition_ )),
incrementor_deletable_(branch_deletable(incrementor_)), incrementor_deletable_(branch_deletable(incrementor_)),
@ -6247,26 +6256,31 @@ namespace exprtk
return std::numeric_limits<T>::quiet_NaN(); return std::numeric_limits<T>::quiet_NaN();
} }
inline std::string str() const std::string str() const
{ {
return ref(); return ref();
} }
inline virtual std::string& ref() const char* base() const
{
return (*value_).data();
}
std::size_t size() const
{
return ref().size();
}
std::string& ref()
{ {
return (*value_); return (*value_);
} }
inline virtual const std::string& ref() const const std::string& ref() const
{ {
return (*value_); return (*value_);
} }
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_stringvar;
}
range_t& range_ref() range_t& range_ref()
{ {
return rp_; return rp_;
@ -6277,9 +6291,9 @@ namespace exprtk
return rp_; return rp_;
} }
const char* base() const inline typename expression_node<T>::node_type type() const
{ {
return (*value_).data(); return expression_node<T>::e_stringvar;
} }
private: private:
@ -6327,6 +6341,16 @@ namespace exprtk
return (*value_); return (*value_);
} }
const char* base() const
{
return (*value_).data();
}
std::size_t size() const
{
return ref().size();
}
inline range_t range() const inline range_t range() const
{ {
return rp_; return rp_;
@ -6357,11 +6381,6 @@ namespace exprtk
return expression_node<T>::e_stringvarrng; return expression_node<T>::e_stringvarrng;
} }
const char* base() const
{
return (*value_).data();
}
private: private:
std::string* value_; std::string* value_;
@ -6395,22 +6414,32 @@ namespace exprtk
return std::numeric_limits<T>::quiet_NaN(); return std::numeric_limits<T>::quiet_NaN();
} }
inline std::string str() const std::string str() const
{ {
return value_; return value_;
} }
inline range_t range() const const char* base() const
{
return value_.data();
}
std::size_t size() const
{
return value_.size();
}
range_t range() const
{ {
return rp_; return rp_;
} }
inline virtual range_t& range_ref() range_t& range_ref()
{ {
return rp_; return rp_;
} }
inline virtual const range_t& range_ref() const const range_t& range_ref() const
{ {
return rp_; return rp_;
} }
@ -6420,11 +6449,6 @@ namespace exprtk
return expression_node<T>::e_cstringvarrng; return expression_node<T>::e_cstringvarrng;
} }
const char* base() const
{
return value_.data();
}
private: private:
const_string_range_node<T>& operator=(const const_string_range_node<T>&); const_string_range_node<T>& operator=(const const_string_range_node<T>&);
@ -6500,7 +6524,7 @@ namespace exprtk
range_t& range = str_range_ptr_->range_ref(); range_t& range = str_range_ptr_->range_ref();
const std::size_t base_str_size = str_base_ptr_->str().size(); const std::size_t base_str_size = str_base_ptr_->size();
if ( if (
range (str_r0,str_r1,base_str_size) && range (str_r0,str_r1,base_str_size) &&
@ -6529,6 +6553,11 @@ namespace exprtk
return value_.data(); return value_.data();
} }
std::size_t size() const
{
return value_.size();
}
range_t& range_ref() range_t& range_ref()
{ {
return range_; return range_;
@ -6634,8 +6663,8 @@ namespace exprtk
range_t& range1 = str1_range_ptr_->range_ref(); range_t& range1 = str1_range_ptr_->range_ref();
if ( if (
range0(str0_r0,str0_r1,str0_base_ptr_->str().size()) && range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->str().size()) range1(str1_r0,str1_r1,str1_base_ptr_->size())
) )
{ {
const std::size_t size0 = (str0_r1 - str0_r0) + 1; const std::size_t size0 = (str0_r1 - str0_r0) + 1;
@ -6662,6 +6691,11 @@ namespace exprtk
return value_.data(); return value_.data();
} }
std::size_t size() const
{
return value_.size();
}
range_t& range_ref() range_t& range_ref()
{ {
return range_; return range_;
@ -6745,6 +6779,11 @@ namespace exprtk
return str0_node_ptr_->base(); return str0_node_ptr_->base();
} }
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref() range_t& range_ref()
{ {
return str0_node_ptr_->range_ref(); return str0_node_ptr_->range_ref();
@ -6837,7 +6876,7 @@ namespace exprtk
if (str_base_ptr_) if (str_base_ptr_)
{ {
branch_->value(); branch_->value();
result = T(str_base_ptr_->str().size()); result = T(str_base_ptr_->size());
} }
return result; return result;
@ -6854,6 +6893,266 @@ namespace exprtk
bool branch_deletable_; bool branch_deletable_;
str_base_ptr str_base_ptr_; str_base_ptr str_base_ptr_;
}; };
struct asn_assignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.assign(data,size); }
};
struct asn_addassignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.append(data,size); }
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str1_range_ptr_(0)
{
if (is_string_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[1].first->value();
std::size_t r0 = 0;
std::size_t r1 = 0;
range_t& range = (*str1_range_ptr_);
if (range(r0,r1,str1_base_ptr_->size()))
{
AssignmentProcess::execute(str0_node_ptr_->ref(),
str1_base_ptr_->base() + r0,
(r1 - r0) + 1);
binary_node<T>::branch_[0].first->value();
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str1_range_ptr_;
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_range_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_range_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str0_range_ptr_(0),
str1_range_ptr_(0)
{
if (is_string_range_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
if (0 == range_ptr)
return;
str0_range_ptr_ = &(range_ptr->range_ref());
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str0_range_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[0].first->value();
binary_node<T>::branch_[1].first->value();
std::size_t s0_r0 = 0;
std::size_t s0_r1 = 0;
std::size_t s1_r0 = 0;
std::size_t s1_r1 = 0;
range_t& range0 = (*str0_range_ptr_);
range_t& range1 = (*str1_range_ptr_);
if (
range0(s0_r0,s0_r1,str0_base_ptr_->size()) &&
range1(s1_r0,s1_r1,str1_base_ptr_->size())
)
{
std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;
std::copy(str1_base_ptr_->base() + s1_r0,
str1_base_ptr_->base() + s1_r0 + size,
const_cast<char*>(base() + s0_r0));
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
std::size_t size() const
{
return str0_node_ptr_->size();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str0_range_ptr_;
range_ptr str1_range_ptr_;
};
#endif #endif
template <typename T, std::size_t N> template <typename T, std::size_t N>
@ -7388,128 +7687,6 @@ namespace exprtk
variable_node<T>* var_node_ptr_; variable_node<T>* var_node_ptr_;
}; };
struct asn_assignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.assign(data,size); }
};
struct asn_addassignment
{
static inline void execute(std::string& s, const char* data, const std::size_t size)
{ s.append(data,size); }
};
template <typename T, typename AssignmentProcess = asn_assignment>
class assignment_string_node : public binary_node <T>,
public string_base_node<T>,
public range_interface <T>
{
public:
typedef expression_node <T>* expression_ptr;
typedef stringvar_node <T>* strvar_node_ptr;
typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t;
typedef range_t* range_ptr;
typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr;
typedef typename range_t::cached_range_t cached_range_t;
assignment_string_node(const operator_type& opr,
expression_ptr branch0,
expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1),
str0_base_ptr_ (0),
str1_base_ptr_ (0),
str0_node_ptr_ (0),
str1_range_ptr_(0)
{
if (is_string_node(binary_node<T>::branch_[0].first))
{
str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
}
if (is_generally_string_node(binary_node<T>::branch_[1].first))
{
str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
if (0 == str1_base_ptr_)
return;
irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
if (0 == range_ptr)
return;
str1_range_ptr_ = &(range_ptr->range_ref());
}
}
inline T value() const
{
if (
str0_base_ptr_ &&
str1_base_ptr_ &&
str0_node_ptr_ &&
str1_range_ptr_
)
{
binary_node<T>::branch_[1].first->value();
std::size_t r0 = 0;
std::size_t r1 = 0;
range_t& range = (*str1_range_ptr_);
if (range(r0,r1,str1_base_ptr_->str().size()))
{
AssignmentProcess::execute(str0_node_ptr_->ref(),
str1_base_ptr_->str().data() + r0,
(r1 - r0) + 1);
binary_node<T>::branch_[0].first->value();
}
}
return std::numeric_limits<T>::quiet_NaN();
}
std::string str() const
{
return str0_node_ptr_->str();
}
const char* base() const
{
return str0_node_ptr_->base();
}
range_t& range_ref()
{
return str0_node_ptr_->range_ref();
}
const range_t& range_ref() const
{
return str0_node_ptr_->range_ref();
}
inline typename expression_node<T>::node_type type() const
{
return expression_node<T>::e_strass;
}
private:
str_base_ptr str0_base_ptr_;
str_base_ptr str1_base_ptr_;
strvar_node_ptr str0_node_ptr_;
range_ptr str1_range_ptr_;
};
template <typename T> template <typename T>
class assignment_vec_elem_node : public binary_node<T> class assignment_vec_elem_node : public binary_node<T>
{ {
@ -9153,7 +9330,7 @@ namespace exprtk
if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
return false; return false;
ts.size = sbn->str().size(); ts.size = sbn->size();
ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base())); ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base()));
ts.type = type_store_t::e_string; ts.type = type_store_t::e_string;
@ -9328,7 +9505,8 @@ namespace exprtk
{ {
typedef typename StringFunction::parameter_list_t parameter_list_t; typedef typename StringFunction::parameter_list_t parameter_list_t;
result = (*gen_function_t::function_)(ret_string_,parameter_list_t(gen_function_t::typestore_list_)); result = (*gen_function_t::function_)(ret_string_,
parameter_list_t(gen_function_t::typestore_list_));
range_.n1_c.second = ret_string_.size() - 1; range_.n1_c.second = ret_string_.size() - 1;
range_.cache.second = range_.n1_c.second; range_.cache.second = range_.n1_c.second;
@ -9355,6 +9533,11 @@ namespace exprtk
return ret_string_.data(); return ret_string_.data();
} }
std::size_t size() const
{
return ret_string_.size();
}
range_t& range_ref() range_t& range_ref()
{ {
return range_; return range_;
@ -9396,7 +9579,8 @@ namespace exprtk
{ {
typedef typename GenericFunction::parameter_list_t parameter_list_t; typedef typename GenericFunction::parameter_list_t parameter_list_t;
return (*gen_function_t::function_)(param_seq_index_,parameter_list_t(gen_function_t::typestore_list_)); return (*gen_function_t::function_)(param_seq_index_,
parameter_list_t(gen_function_t::typestore_list_));
} }
} }
@ -9462,27 +9646,27 @@ namespace exprtk
std::size_t param_seq_index_; std::size_t param_seq_index_;
}; };
#define exprtk_define_unary_op(OpName) \ #define exprtk_define_unary_op(OpName) \
template <typename T> \ template <typename T> \
struct OpName##_op \ struct OpName##_op \
{ \ { \
typedef typename functor_t<T>::Type Type; \ typedef typename functor_t<T>::Type Type; \
\ \
static inline T process(Type v) \ static inline T process(Type v) \
{ \ { \
return numeric:: OpName (v); \ return numeric:: OpName (v); \
} \ } \
\ \
static inline typename expression_node<T>::node_type type()\ static inline typename expression_node<T>::node_type type() \
{ \ { \
return expression_node<T>::e_##OpName; \ return expression_node<T>::e_##OpName; \
} \ } \
\ \
static inline details::operator_type operation() \ static inline details::operator_type operation() \
{ \ { \
return details::e_##OpName; \ return details::e_##OpName; \
} \ } \
}; \ }; \
exprtk_define_unary_op(abs ) exprtk_define_unary_op(abs )
exprtk_define_unary_op(acos ) exprtk_define_unary_op(acos )
@ -10373,6 +10557,7 @@ namespace exprtk
static inline T process(const ivector_ptr v) static inline T process(const ivector_ptr v)
{ {
vector_holder<T>& vec = v->vec()->ref(); vector_holder<T>& vec = v->vec()->ref();
T result = T(0); T result = T(0);
for (std::size_t i = 0; i < vec.size(); ++i) for (std::size_t i = 0; i < vec.size(); ++i)
@ -10392,6 +10577,7 @@ namespace exprtk
static inline T process(const ivector_ptr v) static inline T process(const ivector_ptr v)
{ {
vector_holder<T>& vec = v->vec()->ref(); vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]); T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i) for (std::size_t i = 1; i < vec.size(); ++i)
@ -10411,6 +10597,7 @@ namespace exprtk
static inline T process(const ivector_ptr v) static inline T process(const ivector_ptr v)
{ {
vector_holder<T>& vec = v->vec()->ref(); vector_holder<T>& vec = v->vec()->ref();
T result = T(0); T result = T(0);
for (std::size_t i = 0; i < vec.size(); ++i) for (std::size_t i = 0; i < vec.size(); ++i)
@ -10430,6 +10617,7 @@ namespace exprtk
static inline T process(const ivector_ptr v) static inline T process(const ivector_ptr v)
{ {
vector_holder<T>& vec = v->vec()->ref(); vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]); T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i) for (std::size_t i = 1; i < vec.size(); ++i)
@ -10452,6 +10640,7 @@ namespace exprtk
static inline T process(const ivector_ptr v) static inline T process(const ivector_ptr v)
{ {
vector_holder<T>& vec = v->vec()->ref(); vector_holder<T>& vec = v->vec()->ref();
T result = (*vec[0]); T result = (*vec[0]);
for (std::size_t i = 1; i < vec.size(); ++i) for (std::size_t i = 1; i < vec.size(); ++i)
@ -12290,12 +12479,12 @@ namespace exprtk
{ {
public: public:
typedef expression_node <T>* expression_ptr; typedef expression_node <T>* expression_ptr;
typedef string_base_node<T>* str_base_ptr; typedef string_base_node<T>* str_base_ptr;
typedef range_pack <T> range_t; typedef range_pack <T> range_t;
typedef range_t* range_ptr; typedef range_t* range_ptr;
typedef range_interface<T> irange_t; typedef range_interface<T> irange_t;
typedef irange_t* irange_ptr; typedef irange_t* irange_ptr;
str_sogens_node(const operator_type& opr, str_sogens_node(const operator_type& opr,
expression_ptr branch0, expression_ptr branch0,
@ -12359,8 +12548,8 @@ namespace exprtk
range_t& range1 = (*str1_range_ptr_); range_t& range1 = (*str1_range_ptr_);
if ( if (
range0(str0_r0,str0_r1,str0_base_ptr_->str().size()) && range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
range1(str1_r0,str1_r1,str1_base_ptr_->str().size()) range1(str1_r0,str1_r1,str1_base_ptr_->size())
) )
{ {
return Operation::process( return Operation::process(
@ -14883,9 +15072,10 @@ namespace exprtk
typedef details::const_string_range_node<T> const_string_range_node_t; typedef details::const_string_range_node<T> const_string_range_node_t;
typedef details::generic_string_range_node<T> generic_string_range_node_t; typedef details::generic_string_range_node<T> generic_string_range_node_t;
typedef details::string_concat_node <T> string_concat_node_t; typedef details::string_concat_node <T> string_concat_node_t;
typedef details::assignment_string_node<T> assignment_string_node_t;
typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
#endif #endif
typedef details::assignment_node<T> assignment_node_t; typedef details::assignment_node<T> assignment_node_t;
typedef details::assignment_string_node <T> assignment_string_node_t;
typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t; typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t;
typedef details::assignment_vec_node <T> assignment_vec_node_t; typedef details::assignment_vec_node <T> assignment_vec_node_t;
typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t; typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
@ -15051,7 +15241,7 @@ namespace exprtk
for (std::size_t j = 0; j < element_.size(); ++j) for (std::size_t j = 0; j < element_.size(); ++j)
{ {
if ( if (
(element_[j].name == se.name ) && (element_[j].name == se.name ) &&
(element_[j].depth <= se.depth) && (element_[j].depth <= se.depth) &&
(element_[j].index == se.index) && (element_[j].index == se.index) &&
(element_[j].size == se.size ) (element_[j].size == se.size )
@ -16780,6 +16970,7 @@ namespace exprtk
make_error(parser_error::e_syntax, make_error(parser_error::e_syntax,
current_token_, current_token_,
"ERR38 - Expected '?' after condition of ternary if-statement")); "ERR38 - Expected '?' after condition of ternary if-statement"));
result = false; result = false;
} }
else if (0 == (consequent = parse_expression())) else if (0 == (consequent = parse_expression()))
@ -16788,6 +16979,7 @@ namespace exprtk
make_error(parser_error::e_syntax, make_error(parser_error::e_syntax,
current_token_, current_token_,
"ERR39 - Failed to parse consequent for if-statement")); "ERR39 - Failed to parse consequent for if-statement"));
result = false; result = false;
} }
else if (!token_is(token_t::e_colon)) else if (!token_is(token_t::e_colon))
@ -16796,6 +16988,7 @@ namespace exprtk
make_error(parser_error::e_syntax, make_error(parser_error::e_syntax,
current_token_, current_token_,
"ERR40 - Expected ':' between ternary if-statement consequent and alternative")); "ERR40 - Expected ':' between ternary if-statement consequent and alternative"));
result = false; result = false;
} }
else if (0 == (alternative = parse_expression())) else if (0 == (alternative = parse_expression()))
@ -16804,6 +16997,7 @@ namespace exprtk
make_error(parser_error::e_syntax, make_error(parser_error::e_syntax,
current_token_, current_token_,
"ERR41 - Failed to parse alternative for if-statement")); "ERR41 - Failed to parse alternative for if-statement"));
result = false; result = false;
} }
@ -17944,7 +18138,7 @@ namespace exprtk
{ {
free_node(node_allocator_,result); free_node(node_allocator_,result);
return expression_generator_(T(const_str_node->str().size())); return expression_generator_(T(const_str_node->size()));
} }
else else
return node_allocator_.allocate<details::stringvar_size_node<T> > return node_allocator_.allocate<details::stringvar_size_node<T> >
@ -21760,6 +21954,12 @@ namespace exprtk
return synthesize_expression<assignment_string_node_t,2>(operation,branch); return synthesize_expression<assignment_string_node_t,2>(operation,branch);
} }
else if (details::is_string_range_node(branch[0]))
{
lodge_assignment(e_st_string,branch[0]);
return synthesize_expression<assignment_string_range_node_t,2>(operation,branch);
}
else if (details::is_vector_node(branch[0])) else if (details::is_vector_node(branch[0]))
{ {
lodge_assignment(e_st_vector,branch[0]); lodge_assignment(e_st_vector,branch[0]);

View File

@ -2121,7 +2121,7 @@ inline bool run_test02()
test_ab<T>("('abc' + b[r0:r2]) == 'abc234567' ","abc","0123456789" ,T(1.0)), test_ab<T>("('abc' + b[r0:r2]) == 'abc234567' ","abc","0123456789" ,T(1.0)),
test_ab<T>("(a[r0:r0] + b[r3:r3]) == 'c3' ","abc","0123456789" ,T(1.0)), test_ab<T>("(a[r0:r0] + b[r3:r3]) == 'c3' ","abc","0123456789" ,T(1.0)),
test_ab<T>("(a[r3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), test_ab<T>("(a[r3:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)),
test_ab<T>("('abc' + b[:r2]) == 'abc01234567' ","abc","0123456789" ,T(1.0)), test_ab<T>("('abc' + b[:r2]) == 'abc01234567' ","abc","0123456789" ,T(1.0)),
test_ab<T>("a[0:r0] + '123' == 'abc' + b[0:r0] ","abcXYZ", "123XYZ", T(1.0)), test_ab<T>("a[0:r0] + '123' == 'abc' + b[0:r0] ","abcXYZ", "123XYZ", T(1.0)),
test_ab<T>("a[ :r0] + '123' == 'abc' + b[ :r0] ","abcXYZ", "123XYZ", T(1.0)), test_ab<T>("a[ :r0] + '123' == 'abc' + b[ :r0] ","abcXYZ", "123XYZ", T(1.0)),
test_ab<T>("a[r3: ] + '123' == 'abc' + b[r3: ]","XYZabc", "XYZ123", T(1.0)), test_ab<T>("a[r3: ] + '123' == 'abc' + b[r3: ]","XYZabc", "XYZ123", T(1.0)),
@ -2170,7 +2170,74 @@ inline bool run_test02()
test_ab<T>("(a + b)[0:5][] == 6 ","abc","123" ,T(1.0)), test_ab<T>("(a + b)[0:5][] == 6 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][] == 4 ","abc","123" ,T(1.0)), test_ab<T>("(a + b)[0:5][1:4][] == 4 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][1:2][] == 2 ","abc","123" ,T(1.0)), test_ab<T>("(a + b)[0:5][1:4][1:2][] == 2 ","abc","123" ,T(1.0)),
test_ab<T>("(a + b)[0:5][1:4][1:2][0:0][] == 1 ","abc","123" ,T(1.0)) test_ab<T>("(a + b)[0:5][1:4][1:2][0:0][] == 1 ","abc","123" ,T(1.0)),
test_ab<T>("(a[ : ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0: ] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[ :9] := b); (a == 'ABCDEFGHIJ');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:7] := b); (a == '012ABCDE89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:8] := b); (a == '01ABCDEFG9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:9] := b); (a == '0ABCDEFGHI');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0:0] := b); (a == 'A123456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:1] := b); (a == '0A23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:2] := b); (a == '01A3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:3] := b); (a == '012A456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[4:4] := b); (a == '0123A56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[5:5] := b); (a == '01234A6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[6:6] := b); (a == '012345A789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[7:7] := b); (a == '0123456A89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[8:8] := b); (a == '01234567A9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[9:9] := b); (a == '012345678A');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[0:1] := b); (a == 'AB23456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[1:2] := b); (a == '0AB3456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[2:3] := b); (a == '01AB456789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[3:4] := b); (a == '012AB56789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[4:5] := b); (a == '0123AB6789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[5:6] := b); (a == '01234AB789');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[6:7] := b); (a == '012345AB89');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[7:8] := b); (a == '0123456AB9');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[8:9] := b); (a == '01234567AB');", "0123456789","ABCDEFGHIJ" ,T(1.0)),
test_ab<T>("(a[ : ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0: ] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[ :9] := b[3:b[] - 3]); (a == 'ABCDEFGHIJ');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:7] := b[3:b[] - 3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:8] := b[3:b[] - 3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:9] := b[3:b[] - 3]); (a == '0ABCDEFGHI');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:0] := b[3:b[] - 3]); (a == 'A123456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:1] := b[3:b[] - 3]); (a == '0A23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:2] := b[3:b[] - 3]); (a == '01A3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:3] := b[3:b[] - 3]); (a == '012A456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[4:4] := b[3:b[] - 3]); (a == '0123A56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[5:5] := b[3:b[] - 3]); (a == '01234A6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[6:6] := b[3:b[] - 3]); (a == '012345A789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[7:7] := b[3:b[] - 3]); (a == '0123456A89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[8:8] := b[3:b[] - 3]); (a == '01234567A9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[9:9] := b[3:b[] - 3]); (a == '012345678A');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:1] := b[3:b[] - 3]); (a == 'AB23456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[1:2] := b[3:b[] - 3]); (a == '0AB3456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[2:3] := b[3:b[] - 3]); (a == '01AB456789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[3:4] := b[3:b[] - 3]); (a == '012AB56789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[4:5] := b[3:b[] - 3]); (a == '0123AB6789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[5:6] := b[3:b[] - 3]); (a == '01234AB789');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[6:7] := b[3:b[] - 3]); (a == '012345AB89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[7:8] := b[3:b[] - 3]); (a == '0123456AB9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[8:9] := b[3:b[] - 3]); (a == '01234567AB');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'A123456789');", "0123456789","A" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'AB23456789');", "0123456789","AB" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABC3456789');", "0123456789","ABC" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCD456789');", "0123456789","ABCD" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDE56789');", "0123456789","ABCDE" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEF6789');", "0123456789","ABCDEF" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFG789');", "0123456789","ABCDEFG" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFGH89');", "0123456789","ABCDEFGH" ,T(1.0)),
test_ab<T>("(a[0:9] := b); (a == 'ABCDEFGHI9');", "0123456789","ABCDEFGHI" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012A456789');", "0123456789","A" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012AB56789');", "0123456789","AB" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABC6789');", "0123456789","ABC" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCD789');", "0123456789","ABCD" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCDE89');", "0123456789","ABCDE" ,T(1.0)),
test_ab<T>("(a[3:9] := b); (a == '012ABCDEF9');", "0123456789","ABCDEF" ,T(1.0)),
test_ab<T>("(a[r1 / r0:r2] := b[3:b[] - r3]); (a == '012ABCDE89');", "0123456789","xyzABCDEFGHIJxyz",T(1.0)),
test_ab<T>("(a[r0:r2 + 1] := b[r3:b[] - r3]); (a == '01ABCDEFG9');", "0123456789","xyzABCDEFGHIJxyz",T(1.0))
}; };
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>); static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);

View File

@ -403,13 +403,19 @@ of C++ compilers:
| | will be performed. (eg: 1.67 --> 1) | | | will be performed. (eg: 1.67 --> 1) |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| := | Assign the value of x to y. Where x is a mutable string | | := | Assign the value of x to y. Where x is a mutable string |
| | and y is either a string or a string range. eg: | | | or string range and y is either a string or a string |
| | range. eg: |
| | 1. x := y | | | 1. x := y |
| | 2. x := 'abc' | | | 2. x := 'abc' |
| | 3. x := y[:i + j] | | | 3. x := y[:i + j] |
| | 4. x := '0123456789'[2:7] | | | 4. x := '0123456789'[2:7] |
| | 5. x := '0123456789'[2i + 1:7] | | | 5. x := '0123456789'[2i + 1:7] |
| | 6. x := (y := '0123456789'[2:7]) | | | 6. x := (y := '0123456789'[2:7]) |
| | 7. x[i:j] := y |
| | 8. x[i:j] := (y + 'abcdefg'[8 / 4:5])[m:n] |
| | |
| | Note: For options 7 and 8 the shorter of the two ranges |
| | will denote the number characters that are to be copied.|
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| + | Concatenation of x and y. Where x and y are strings or | | + | Concatenation of x and y. Where x and y are strings or |
| | string ranges. eg | | | string ranges. eg |
@ -841,6 +847,7 @@ following are examples of the various transformations that can occur:
(d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y) (d) (2 / x) / (3 / y) ---> (2 / 3) / (x * y)
(e) (2 * x) * (3 * y) ---> (2 * 3) * (x * y) (e) (2 * x) * (3 * y) ---> (2 * 3) * (x * y)
Note: Note:
When using strength reduction in conjunction with expressions whose When using strength reduction in conjunction with expressions whose
inputs or sub-expressions may result in values nearing either of the inputs or sub-expressions may result in values nearing either of the
@ -1919,11 +1926,14 @@ into account when using Exprtk:
be to recompile an expression from its string form every time be to recompile an expression from its string form every time
it requires evaluating. it requires evaluating.
(24) Where appropriate the return values of method invocations from (24) It is strongly recommended that the return value of method
the parser and symbol_table should be taken into account. invocations from the parser and symbol_table types be taken
Specifically the 'compile' method of the parser and the into account. Specifically the 'compile' method of the parser
'add_xxx' set of methods of the symbol table as they denote and the 'add_xxx' set of methods of the symbol_table as they
success or failure of the invoked call. denote either the success or failure state of the invoked call.
Cointinued processing from a failed state without having first
rectified the underlying issue will in turn result in further
failures and undefined behaviours.
(25) The following are examples of compliant floating point value (25) The following are examples of compliant floating point value
representations: representations: