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

This commit is contained in:
Arash Partow 2015-04-19 16:38:54 +10:00
parent 6b98239580
commit ba6f782220
2 changed files with 162 additions and 23 deletions

View File

@ -2118,6 +2118,13 @@ namespace exprtk
} }
} }
inline std::string substr(const std::size_t& begin, const std::size_t& end)
{
const char* begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
const char* end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
return std::string(begin_itr,end_itr);
}
private: private:
inline bool is_end(const char* itr) inline bool is_end(const char* itr)
@ -16584,6 +16591,7 @@ namespace exprtk
: parsing_return_stmt(false), : parsing_return_stmt(false),
parsing_break_stmt (false), parsing_break_stmt (false),
return_stmt_present(false), return_stmt_present(false),
side_effect_present(false),
scope_depth(0) scope_depth(0)
{} {}
@ -16592,12 +16600,14 @@ namespace exprtk
parsing_return_stmt = false; parsing_return_stmt = false;
parsing_break_stmt = false; parsing_break_stmt = false;
return_stmt_present = false; return_stmt_present = false;
side_effect_present = false;
scope_depth = 0; scope_depth = 0;
} }
bool parsing_return_stmt; bool parsing_return_stmt;
bool parsing_break_stmt; bool parsing_break_stmt;
bool return_stmt_present; bool return_stmt_present;
bool side_effect_present;
std::size_t scope_depth; std::size_t scope_depth;
}; };
@ -17547,12 +17557,21 @@ namespace exprtk
inline expression_node_ptr parse_corpus() inline expression_node_ptr parse_corpus()
{ {
std::vector<expression_node_ptr> arg_list; std::vector<expression_node_ptr> arg_list;
std::vector<bool> side_effect_list;
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
scoped_vec_delete<expression_node_t> sdd(*this,arg_list); scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
lexer::token begin_token;
lexer::token end_token;
for (;;) for (;;)
{ {
state_.side_effect_present = false;
begin_token = current_token();
expression_node_ptr arg = parse_expression(); expression_node_ptr arg = parse_expression();
if (0 == arg) if (0 == arg)
@ -17568,8 +17587,26 @@ namespace exprtk
return error_node(); return error_node();
} }
else else
{
arg_list.push_back(arg); arg_list.push_back(arg);
side_effect_list.push_back(state_.side_effect_present);
end_token = current_token();
std::string sub_expr = construct_subexpr(begin_token,end_token);
exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
static_cast<int>(arg_list.size() - 1),
sub_expr.c_str()));
exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
static_cast<int>(arg_list.size() - 1),
state_.side_effect_present ? "true" : "false"));
exprtk_debug(("-------------------------------------------------\n"));
}
if (lexer_.finished()) if (lexer_.finished())
break; break;
else if (token_is(token_t::e_eof,false)) else if (token_is(token_t::e_eof,false))
@ -17581,13 +17618,25 @@ namespace exprtk
} }
} }
result = simplify(arg_list); result = simplify(arg_list,side_effect_list);
sdd.delete_ptr = (0 == result); sdd.delete_ptr = (0 == result);
return result; return result;
} }
std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
{
std::string result = lexer_.substr(begin_token.position,end_token.position);
for (std::size_t i = 0; i < result.size(); ++i)
{
if (details::is_whitespace(result[i])) result[i] = ' ';
}
return result;
}
static const precedence_level default_precedence = e_level00; static const precedence_level default_precedence = e_level00;
struct state_t struct state_t
@ -17978,6 +18027,22 @@ namespace exprtk
bool& b; bool& b;
}; };
struct scoped_bool_or_restorer
{
scoped_bool_or_restorer(bool& bb)
: b(bb),
original_value_(bb)
{}
~scoped_bool_or_restorer()
{
b = b || original_value_;
}
bool& b;
bool original_value_;
};
inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
{ {
expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
@ -18106,7 +18171,11 @@ namespace exprtk
inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
{ {
expression_node_ptr result = expression_generator_.function(function); expression_node_ptr result = expression_generator_.function(function);
state_.side_effect_present = function->has_side_effects;
next_token(); next_token();
if ( if (
token_is(token_t::e_lbracket) && token_is(token_t::e_lbracket) &&
!token_is(token_t::e_rbracket) !token_is(token_t::e_rbracket)
@ -18699,6 +18768,8 @@ namespace exprtk
next_token(); next_token();
std::vector<expression_node_ptr> arg_list; std::vector<expression_node_ptr> arg_list;
std::vector<bool> side_effect_list;
scoped_vec_delete<expression_node_t> sdd(*this,arg_list); scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
brkcnt_list_.push_front(false); brkcnt_list_.push_front(false);
@ -18714,14 +18785,21 @@ namespace exprtk
scope_handler sh(*this); scope_handler sh(*this);
scoped_bool_or_restorer sbr(state_.side_effect_present);
for (;;) for (;;)
{ {
state_.side_effect_present = false;
expression_node_ptr arg = parse_expression(); expression_node_ptr arg = parse_expression();
if (0 == arg) if (0 == arg)
return error_node(); return error_node();
else else
{
arg_list.push_back(arg); arg_list.push_back(arg);
side_effect_list.push_back(state_.side_effect_present);
}
if (details::imatch(current_token_.value,"until")) if (details::imatch(current_token_.value,"until"))
{ {
@ -18749,7 +18827,7 @@ namespace exprtk
} }
} }
branch = simplify(arg_list); branch = simplify(arg_list,side_effect_list);
if ((sdd.delete_ptr = (0 == branch))) if ((sdd.delete_ptr = (0 == branch)))
{ {
@ -18929,7 +19007,11 @@ namespace exprtk
result = false; result = false;
} }
else else
{
exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
state_.side_effect_present = true;
}
} }
} }
} }
@ -19434,16 +19516,18 @@ namespace exprtk
} }
} }
template <typename Allocator, template <typename Allocator1,
typename Allocator2,
template <typename,typename> class Sequence> template <typename,typename> class Sequence>
inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list) inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
Sequence<bool,Allocator2>& side_effect_list)
{ {
if (expression_list.empty()) if (expression_list.empty())
return error_node(); return error_node();
else if (1 == expression_list.size()) else if (1 == expression_list.size())
return expression_list[0]; return expression_list[0];
Sequence<expression_node_ptr,Allocator> tmp_expression_list; Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
{ {
@ -19451,7 +19535,8 @@ namespace exprtk
continue; continue;
else if ( else if (
is_constant_node(expression_list[i]) || is_constant_node(expression_list[i]) ||
is_null_node (expression_list[i]) is_null_node (expression_list[i]) ||
!side_effect_list[i]
) )
{ {
free_node(node_allocator_,expression_list[i]); free_node(node_allocator_,expression_list[i]);
@ -19464,6 +19549,16 @@ namespace exprtk
tmp_expression_list.push_back(expression_list.back()); tmp_expression_list.push_back(expression_list.back());
expression_list.swap(tmp_expression_list); expression_list.swap(tmp_expression_list);
if ((expression_list.size() > 1) || side_effect_list.back())
state_.side_effect_present = true;
if (tmp_expression_list.size() > expression_list.size())
{
exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
static_cast<int>(tmp_expression_list.size()),
static_cast<int>(expression_list .size())));
}
if (1 == expression_list.size()) if (1 == expression_list.size())
return expression_list[0]; return expression_list[0];
else else
@ -19499,20 +19594,29 @@ namespace exprtk
} }
std::vector<expression_node_ptr> arg_list; std::vector<expression_node_ptr> arg_list;
std::vector<bool> side_effect_list;
expression_node_ptr result = error_node(); expression_node_ptr result = error_node();
scoped_vec_delete<expression_node_t> sdd(*this,arg_list); scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
scope_handler sh(*this); scope_handler sh(*this);
scoped_bool_or_restorer sbr(state_.side_effect_present);
for (;;) for (;;)
{ {
state_.side_effect_present = false;
expression_node_ptr arg = parse_expression(); expression_node_ptr arg = parse_expression();
if (0 == arg) if (0 == arg)
return error_node(); return error_node();
else else
{
arg_list.push_back(arg); arg_list.push_back(arg);
side_effect_list.push_back(state_.side_effect_present);
}
if (token_is(close_bracket)) if (token_is(close_bracket))
break; break;
@ -19533,7 +19637,7 @@ namespace exprtk
break; break;
} }
result = simplify(arg_list); result = simplify(arg_list,side_effect_list);
sdd.delete_ptr = (0 == result); sdd.delete_ptr = (0 == result);
return result; return result;
@ -20715,6 +20819,8 @@ namespace exprtk
exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
nse.name.c_str(), nse.name.c_str(),
static_cast<int>(nse.size))); static_cast<int>(nse.size)));
state_.side_effect_present = true;
} }
lodge_symbol(vec_name,e_st_local_vector); lodge_symbol(vec_name,e_st_local_vector);
@ -20789,6 +20895,8 @@ namespace exprtk
str_node = nse.str_node; str_node = nse.str_node;
exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str())); exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
state_.side_effect_present = true;
} }
lodge_symbol(str_name,e_st_local_string); lodge_symbol(str_name,e_st_local_string);
@ -20973,6 +21081,8 @@ namespace exprtk
var_node = nse.var_node; var_node = nse.var_node;
exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
state_.side_effect_present = true;
} }
lodge_symbol(var_name,e_st_local_variable); lodge_symbol(var_name,e_st_local_variable);
@ -21057,6 +21167,8 @@ namespace exprtk
} }
exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
state_.side_effect_present = true;
} }
lodge_symbol(var_name,e_st_local_variable); lodge_symbol(var_name,e_st_local_variable);
@ -21259,12 +21371,14 @@ namespace exprtk
variable_node_ptr v0 = variable_node_ptr(0); variable_node_ptr v0 = variable_node_ptr(0);
variable_node_ptr v1 = variable_node_ptr(0); variable_node_ptr v1 = variable_node_ptr(0);
expression_node_ptr result = error_node();
if ( if (
(0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
(0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
) )
{ {
expression_node_ptr result = node_allocator_.allocate<details::swap_node<T> >(v0,v1); result = node_allocator_.allocate<details::swap_node<T> >(v0,v1);
if (variable0_generated) if (variable0_generated)
{ {
@ -21275,11 +21389,13 @@ namespace exprtk
{ {
free_node(node_allocator_,variable1); free_node(node_allocator_,variable1);
} }
return result;
} }
else else
return node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1); result = node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1);
state_.side_effect_present = true;
return result;
} }
inline expression_node_ptr parse_return_statement() inline expression_node_ptr parse_return_statement()
@ -23635,6 +23751,8 @@ namespace exprtk
result = node_allocator_->allocate<literal_node_t>(v); result = node_allocator_->allocate<literal_node_t>(v);
} }
parser_->state_.side_effect_present = true;
return result; return result;
} }
@ -23674,7 +23792,10 @@ namespace exprtk
return node_allocator_->allocate<literal_node_t>(v); return node_allocator_->allocate<literal_node_t>(v);
} }
else if (genfunc_node_ptr->init_branches()) else if (genfunc_node_ptr->init_branches())
{
parser_->state_.side_effect_present = true;
return result; return result;
}
else else
{ {
details::free_node(*node_allocator_,result); details::free_node(*node_allocator_,result);
@ -23719,7 +23840,10 @@ namespace exprtk
return node_allocator_->allocate<literal_node_t>(v); return node_allocator_->allocate<literal_node_t>(v);
} }
else if (strfunc_node_ptr->init_branches()) else if (strfunc_node_ptr->init_branches())
{
parser_->state_.side_effect_present = true;
return result; return result;
}
else else
{ {
details::free_node(*node_allocator_,result); details::free_node(*node_allocator_,result);
@ -23744,7 +23868,10 @@ namespace exprtk
alloc_type* return_node_ptr = static_cast<alloc_type*>(result); alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
if (return_node_ptr->init_branches()) if (return_node_ptr->init_branches())
{
parser_->state_.side_effect_present = true;
return result; return result;
}
else else
{ {
details::free_node(*node_allocator_,result); details::free_node(*node_allocator_,result);
@ -23798,13 +23925,14 @@ namespace exprtk
result = error_node(); result = error_node();
} }
else
{
exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
parser_->state_.side_effect_present = true;
result = nse.var_node; result = nse.var_node;
} }
} }
}
else else
result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,(*vector_base)[0]); result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,(*vector_base)[0]);
@ -23845,6 +23973,8 @@ namespace exprtk
void lodge_assignment(symbol_type cst, expression_node_ptr node) void lodge_assignment(symbol_type cst, expression_node_ptr node)
{ {
parser_->state_.side_effect_present = true;
if (!parser_->dec_.collect_assignments()) if (!parser_->dec_.collect_assignments())
return; return;
@ -24167,6 +24297,8 @@ namespace exprtk
const bool v1_is_str = details::is_generally_string_node(branch[1]); const bool v1_is_str = details::is_generally_string_node(branch[1]);
#endif #endif
expression_node_ptr result = error_node();
if (v0_is_ivar && v1_is_ivar) if (v0_is_ivar && v1_is_ivar)
{ {
typedef details::variable_node<T>* variable_node_ptr; typedef details::variable_node<T>* variable_node_ptr;
@ -24179,19 +24311,19 @@ namespace exprtk
(0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
) )
{ {
return node_allocator_->allocate<details::swap_node<T> >(v0,v1); result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
} }
else else
return node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
} }
else if (v0_is_ivec && v1_is_ivec) else if (v0_is_ivec && v1_is_ivec)
{ {
return node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
} }
#ifndef exprtk_disable_string_capabilities #ifndef exprtk_disable_string_capabilities
else if (v0_is_str && v1_is_str) else if (v0_is_str && v1_is_str)
{ {
return node_allocator_->allocate<details::swap_string_node<T> >(branch[0],branch[1]); result = node_allocator_->allocate<details::swap_string_node<T> >(branch[0],branch[1]);
} }
#endif #endif
else else
@ -24200,6 +24332,10 @@ namespace exprtk
return error_node(); return error_node();
} }
parser_->state_.side_effect_present = true;
return result;
} }
#ifndef exprtk_disable_sc_andor #ifndef exprtk_disable_sc_andor
@ -30173,7 +30309,9 @@ namespace exprtk
return node_allocator_->allocate<literal_node_t>(v); return node_allocator_->allocate<literal_node_t>(v);
} }
else
parser_->state_.side_effect_present = true;
return expression_point; return expression_point;
} }

View File

@ -44,7 +44,8 @@ arithmetic operations, functions and processes:
(09) String (09) String
processing: in, like, ilike, concatenation processing: in, like, ilike, concatenation
(10) Optimisations: constant-folding and simple strength reduction (10) Optimisations: constant-folding, simple strength reduction and
dead code elimination
(11) Calculus: numerical integration and differentiation (11) Calculus: numerical integration and differentiation