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

This commit is contained in:
Arash Partow 2014-12-10 01:42:42 +11:00
parent 6385bd7c90
commit 5631cc5b8e
3 changed files with 215 additions and 63 deletions

View File

@ -4033,7 +4033,10 @@ namespace exprtk
{ {
if (0 != node) if (0 != node)
{ {
if (is_variable_node(node) && !force_delete) if (
(is_variable_node(node) || is_string_node(node)) ||
force_delete
)
return; return;
node_allocator.free(node); node_allocator.free(node);
@ -6407,9 +6410,11 @@ 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();
if ( if (
range (str_r0,str_r1,str_base_ptr_->str().size()) && range (str_r0,str_r1,base_str_size) &&
base_range_(r0,r1) base_range_( r0, r1,base_str_size)
) )
{ {
const std::size_t size = (r1 - r0) + 1; const std::size_t size = (r1 - r0) + 1;
@ -7293,7 +7298,19 @@ namespace exprtk
variable_node<T>* var_node_ptr_; variable_node<T>* var_node_ptr_;
}; };
template <typename T> 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>, class assignment_string_node : public binary_node <T>,
public string_base_node<T>, public string_base_node<T>,
public range_interface <T> public range_interface <T>
@ -7359,7 +7376,9 @@ namespace exprtk
if (range(r0,r1,str1_base_ptr_->str().size())) if (range(r0,r1,str1_base_ptr_->str().size()))
{ {
str0_node_ptr_->ref().assign(str1_base_ptr_->str().data() + r0, (r1 - r0) + 1); AssignmentProcess::execute(str0_node_ptr_->ref(),
str1_base_ptr_->str().data() + r0,
(r1 - r0) + 1);
binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[0].first->value();
} }
@ -19627,6 +19646,7 @@ namespace exprtk
(details::e_like == operation) || (details::e_like == operation) ||
(details::e_ilike == operation) || (details::e_ilike == operation) ||
(details::e_assign == operation) || (details::e_assign == operation) ||
(details::e_addass == operation) ||
(details::e_swap == operation) ; (details::e_swap == operation) ;
} }
#else #else
@ -19836,15 +19856,22 @@ namespace exprtk
inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
{ {
return is_assignment_operation(operation) && if (is_assignment_operation(operation))
( {
( const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
if (details::is_string_node(branch[0]))
return !b1_is_genstring;
else
return (
!details::is_variable_node (branch[0]) && !details::is_variable_node (branch[0]) &&
!details::is_vector_elem_node(branch[0]) && !details::is_vector_elem_node(branch[0]) &&
!details::is_vector_node (branch[0]) !details::is_vector_node (branch[0])
) || )
is_generally_string_node(branch[1]) || b1_is_genstring;
); }
else
return false;
} }
inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
@ -20170,8 +20197,8 @@ namespace exprtk
#endif #endif
} }
inline expression_node_ptr repeat_until_loop(expression_node_ptr condition, inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
expression_node_ptr branch, expression_node_ptr& branch,
const bool brkcont = false) const const bool brkcont = false) const
{ {
if (!brkcont && details::is_constant_node(condition)) if (!brkcont && details::is_constant_node(condition))
@ -20204,10 +20231,10 @@ namespace exprtk
#endif #endif
} }
inline expression_node_ptr for_loop(expression_node_ptr initialiser, inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
expression_node_ptr condition, expression_node_ptr& condition,
expression_node_ptr incrementor, expression_node_ptr& incrementor,
expression_node_ptr loop_body, expression_node_ptr& loop_body,
bool brkcont = false) const bool brkcont = false) const
{ {
if (!brkcont && details::is_constant_node(condition)) if (!brkcont && details::is_constant_node(condition))
@ -21169,6 +21196,15 @@ namespace exprtk
} }
} }
} }
else if (
(details::e_addass == operation) &&
details::is_string_node(branch[0])
)
{
typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
return synthesize_expression<addass_t,2>(operation,branch);
}
else else
{ {
parser_->set_synthesis_error("Invalid assignment operation[2]"); parser_->set_synthesis_error("Invalid assignment operation[2]");
@ -28917,6 +28953,89 @@ namespace exprtk
return true; return true;
} }
namespace helper
{
namespace details
{
template <typename T>
struct print_impl
{
typedef typename igeneric_function<T>::generic_type generic_type;
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
typedef typename generic_type::scalar_view scalar_t;
typedef typename generic_type::vector_view vector_t;
typedef typename generic_type::string_view string_t;
static void process(const std::string& scalar_format, parameter_list_t parameters)
{
for (std::size_t i = 0; i < parameters.size(); ++i)
{
generic_type& gt = parameters[i];
switch (gt.type)
{
case generic_type::e_scalar : printf(scalar_format.c_str(),scalar_t(gt)());
break;
case generic_type::e_vector : {
vector_t vector(gt);
for (std::size_t x = 0; x < vector.size(); ++x)
{
printf(scalar_format.c_str(),vector[x]);
if ((x + 1) < vector.size())
printf(" ");
}
}
break;
case generic_type::e_string : printf("%s",to_str(string_t(gt)).c_str());
break;
default : continue;
}
}
}
};
}
template <typename T>
struct print : public exprtk::igeneric_function<T>
{
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
print(const std::string& scalar_format = "%10.5f")
: scalar_format_(scalar_format)
{}
inline T operator()(parameter_list_t parameters)
{
details::print_impl<T>::process(scalar_format_,parameters);
return T(0);
}
std::string scalar_format_;
};
template <typename T>
struct println : public exprtk::igeneric_function<T>
{
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
println(const std::string& scalar_format = "%10.5f")
: scalar_format_(scalar_format)
{}
inline T operator()(parameter_list_t parameters)
{
details::print_impl<T>::process(scalar_format_,parameters);
printf("\n");
return T(0);
}
std::string scalar_format_;
};
}
} }
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)

View File

@ -2086,7 +2086,33 @@ inline bool run_test02()
test_ab<T>("(a[r0:r0] + b[r3:r0+1]) == 'c3' ","abc","0123456789" ,T(1.0)), test_ab<T>("(a[r0:r0] + b[r3:r0+1]) == 'c3' ","abc","0123456789" ,T(1.0)),
test_ab<T>("(a[r0+1:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)), test_ab<T>("(a[r0+1:] + b) == 'defghij0123' ","abcdefghij","0123",T(1.0)),
test_ab<T>("a[r0+1: ] + '123' == 'abc' + b[r0+1: ]","XYZabc", "XYZ123", T(1.0)), test_ab<T>("a[r0+1: ] + '123' == 'abc' + b[r0+1: ]","XYZabc", "XYZ123", T(1.0)),
test_ab<T>("a[r0+1:a[] - 1] + '123' == 'abc' + b[r0+1:b[] - 1]","XYZabc", "XYZ123", T(1.0)) test_ab<T>("a[r0+1:a[] - 1] + '123' == 'abc' + b[r0+1:b[] - 1]","XYZabc", "XYZ123", T(1.0)),
test_ab<T>("(a + b)[ :13] == 'abcdefghij0123' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[ 6: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[ 2:3r1-1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a[2:7] + b[2:7]) == 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a[2:7] + b[2:7])[3:8] == 'fgh234' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[r0 - 2: r1 + r2] == 'abcdefghij0123' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[r0*r3:] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[3r0: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[2r3: ] == 'ghij0123456789' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a + b)[2:3r1 - 1] == 'cdefghij01234567' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a[r0:7] + b[r0:r2])== 'cdefgh234567' ", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a[r1 / r3:7] + b[r0:r2])[3:r2 + 1] == 'fgh234'", "abcdefghij", "0123456789" ,T(1.0)),
test_ab<T>("(a += b) == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += '123') == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b[3:5]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)),
test_ab<T>("(a += 'XXX123XXX'[3:5]) == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b)[:] == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += '123')[:] == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b[3:5])[:] == 'abc123' ", "abc","XXX123XXX" ,T(1.0)),
test_ab<T>("(a += 'XXX123XXX'[3:5])[:] == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b[r1/2:r1-1]) == 'abc123' ", "abc","XXX123XXX" ,T(1.0)),
test_ab<T>("(a += 'XXX123XXX'[r0+1:r1-1]) == 'abc123' ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b)[] == 6 ", "abc","123" ,T(1.0)),
test_ab<T>("(a += '123')[] == 6 ", "abc","123" ,T(1.0)),
test_ab<T>("(a += b[3:5])[] == 6 ", "abc","XXX123XXX" ,T(1.0)),
test_ab<T>("(a += b[r0+1:r1-1])[] == 6 ", "abc","XXX123XXX" ,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

@ -419,6 +419,13 @@ of C++ compilers:
| | 6. 'abc' + '1234567' | | | 6. 'abc' + '1234567' |
| | 7. (x + 'a1B2c3D4' + y)[i:2j] | | | 7. (x + 'a1B2c3D4' + y)[i:2j] |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| += | Append to x the value of y. Where x is a mutable string |
| | and y is either a string or a string range. eg: |
| | 1. x += y |
| | 2. x += 'abc' |
| | 3. x += y[:i + j] + 'abc' |
| | 4. x += '0123456789'[2:7] |
+----------+---------------------------------------------------------+
| [] | The string size operator returns the size of the string | | [] | The string size operator returns the size of the string |
| | being actioned. | | | being actioned. |
| | eg: | | | eg: |