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]);
!details::is_variable_node (branch[0]) &&
!details::is_vector_elem_node(branch[0]) && if (details::is_string_node(branch[0]))
!details::is_vector_node (branch[0]) return !b1_is_genstring;
) || else
is_generally_string_node(branch[1]) return (
); !details::is_variable_node (branch[0]) &&
!details::is_vector_elem_node(branch[0]) &&
!details::is_vector_node (branch[0])
)
|| 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))
@ -20935,7 +20962,7 @@ namespace exprtk
alloc_type* genfunc_node_ptr = static_cast<alloc_type*>(result); alloc_type* genfunc_node_ptr = static_cast<alloc_type*>(result);
if ( if (
!arg_list.empty() && !arg_list.empty() &&
!gf->has_side_effects && !gf->has_side_effects &&
is_constant_foldable(arg_list) is_constant_foldable(arg_list)
) )
@ -20971,7 +20998,7 @@ namespace exprtk
alloc_type* genfunc_node_ptr = static_cast<alloc_type*>(result); alloc_type* genfunc_node_ptr = static_cast<alloc_type*>(result);
if ( if (
!arg_list.empty() && !arg_list.empty() &&
!gf->has_side_effects && !gf->has_side_effects &&
is_constant_foldable(arg_list) is_constant_foldable(arg_list)
) )
@ -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

@ -130,16 +130,16 @@ static const test_t test_list[] =
test_t("-7.7",-7.7), test_t("-7.7",-7.7),
test_t("-8.8",-8.8), test_t("-8.8",-8.8),
test_t("-9.9",-9.9), test_t("-9.9",-9.9),
test_t("0.0e+0",+0.0e+0), test_t("0.0e+0" ,+0.0e+0),
test_t("1.1e+1",+1.1e+1), test_t("1.1e+1" ,+1.1e+1),
test_t("2.2e+2",+2.2e+2), test_t("2.2e+2" ,+2.2e+2),
test_t("3.3e+3",+3.3e+3), test_t("3.3e+3" ,+3.3e+3),
test_t("4.4e+4",+4.4e+4), test_t("4.4e+4" ,+4.4e+4),
test_t("5.5e+5",+5.5e+5), test_t("5.5e+5" ,+5.5e+5),
test_t("6.6e+6",+6.6e+6), test_t("6.6e+6" ,+6.6e+6),
test_t("7.7e+7",+7.7e+7), test_t("7.7e+7" ,+7.7e+7),
test_t("8.8e+8",+8.8e+8), test_t("8.8e+8" ,+8.8e+8),
test_t("9.9e+9",+9.9e+9), test_t("9.9e+9" ,+9.9e+9),
test_t("-0.0e+0",-0.0e+0), test_t("-0.0e+0",-0.0e+0),
test_t("-1.1e+1",-1.1e+1), test_t("-1.1e+1",-1.1e+1),
test_t("-2.2e+2",-2.2e+2), test_t("-2.2e+2",-2.2e+2),
@ -150,16 +150,16 @@ static const test_t test_list[] =
test_t("-7.7e+7",-7.7e+7), test_t("-7.7e+7",-7.7e+7),
test_t("-8.8e+8",-8.8e+8), test_t("-8.8e+8",-8.8e+8),
test_t("-9.9e+9",-9.9e+9), test_t("-9.9e+9",-9.9e+9),
test_t("0.0E+0",+0.0E+0), test_t("0.0E+0" ,+0.0E+0),
test_t("1.1E+1",+1.1E+1), test_t("1.1E+1" ,+1.1E+1),
test_t("2.2E+2",+2.2E+2), test_t("2.2E+2" ,+2.2E+2),
test_t("3.3E+3",+3.3E+3), test_t("3.3E+3" ,+3.3E+3),
test_t("4.4E+4",+4.4E+4), test_t("4.4E+4" ,+4.4E+4),
test_t("5.5E+5",+5.5E+5), test_t("5.5E+5" ,+5.5E+5),
test_t("6.6E+6",+6.6E+6), test_t("6.6E+6" ,+6.6E+6),
test_t("7.7E+7",+7.7E+7), test_t("7.7E+7" ,+7.7E+7),
test_t("8.8E+8",+8.8E+8), test_t("8.8E+8" ,+8.8E+8),
test_t("9.9E+9",+9.9E+9), test_t("9.9E+9" ,+9.9E+9),
test_t("-0.0E+0",-0.0E+0), test_t("-0.0E+0",-0.0E+0),
test_t("-1.1E+1",-1.1E+1), test_t("-1.1E+1",-1.1E+1),
test_t("-2.2E+2",-2.2E+2), test_t("-2.2E+2",-2.2E+2),
@ -200,16 +200,16 @@ static const test_t test_list[] =
test_t("(7.7)",7.7), test_t("(7.7)",7.7),
test_t("(8.8)",8.8), test_t("(8.8)",8.8),
test_t("(9.9)",9.9), test_t("(9.9)",9.9),
test_t("(+0)",0.0), test_t("(+0)" ,0.0),
test_t("(+1)",1.0), test_t("(+1)" ,1.0),
test_t("(+2)",2.0), test_t("(+2)" ,2.0),
test_t("(+3)",3.0), test_t("(+3)" ,3.0),
test_t("(+4)",4.0), test_t("(+4)" ,4.0),
test_t("(+5)",5.0), test_t("(+5)" ,5.0),
test_t("(+6)",6.0), test_t("(+6)" ,6.0),
test_t("(+7)",7.0), test_t("(+7)" ,7.0),
test_t("(+8)",8.0), test_t("(+8)" ,8.0),
test_t("(+9)",9.0), test_t("(+9)" ,9.0),
test_t("(+0.0)",0.0), test_t("(+0.0)",0.0),
test_t("(+1.0)",1.0), test_t("(+1.0)",1.0),
test_t("(+2.0)",2.0), test_t("(+2.0)",2.0),
@ -230,16 +230,16 @@ static const test_t test_list[] =
test_t("(+7.7)",7.7), test_t("(+7.7)",7.7),
test_t("(+8.8)",8.8), test_t("(+8.8)",8.8),
test_t("(+9.9)",9.9), test_t("(+9.9)",9.9),
test_t("(-0)",-0.0), test_t("(-0)" ,-0.0),
test_t("(-1)",-1.0), test_t("(-1)" ,-1.0),
test_t("(-2)",-2.0), test_t("(-2)" ,-2.0),
test_t("(-3)",-3.0), test_t("(-3)" ,-3.0),
test_t("(-4)",-4.0), test_t("(-4)" ,-4.0),
test_t("(-5)",-5.0), test_t("(-5)" ,-5.0),
test_t("(-6)",-6.0), test_t("(-6)" ,-6.0),
test_t("(-7)",-7.0), test_t("(-7)" ,-7.0),
test_t("(-8)",-8.0), test_t("(-8)" ,-8.0),
test_t("(-9)",-9.0), test_t("(-9)" ,-9.0),
test_t("(-0.0)",-0.0), test_t("(-0.0)",-0.0),
test_t("(-1.0)",-1.0), test_t("(-1.0)",-1.0),
test_t("(-2.0)",-2.0), test_t("(-2.0)",-2.0),
@ -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: |