C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
37324fc51b
commit
f14ec583ae
635
exprtk.hpp
635
exprtk.hpp
|
@ -228,8 +228,8 @@ namespace exprtk
|
||||||
static const std::string reserved_words[] =
|
static const std::string reserved_words[] =
|
||||||
{
|
{
|
||||||
"and", "default", "case", "false", "for", "if", "ilike", "in", "like",
|
"and", "default", "case", "false", "for", "if", "ilike", "in", "like",
|
||||||
"nand", "nor", "not", "null", "or", "shl", "shr", "switch", "true",
|
"nand", "nor", "not", "null", "or", "repeat", "shl", "shr", "switch",
|
||||||
"while", "xnor", "xor", "&", "|"
|
"true", "until", "while", "xnor", "xor", "&", "|"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
|
static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
|
||||||
|
@ -241,9 +241,9 @@ namespace exprtk
|
||||||
"equal", "erf", "erfc", "exp", "false", "floor", "for", "frac", "grad2deg",
|
"equal", "erf", "erfc", "exp", "false", "floor", "for", "frac", "grad2deg",
|
||||||
"hypot", "if", "ilike", "in", "inrange", "like", "log", "log10", "log2",
|
"hypot", "if", "ilike", "in", "inrange", "like", "log", "log10", "log2",
|
||||||
"logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "nand", "nor",
|
"logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "nand", "nor",
|
||||||
"not", "not_equal", "null", "or", "pow", "rad2deg", "root", "round", "roundn",
|
"not", "not_equal", "null", "or", "pow", "rad2deg", "repeat", "root", "round",
|
||||||
"sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "switch", "tan",
|
"roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "switch",
|
||||||
"tanh", "true", "trunc", "while", "xnor", "xor", "&", "|"
|
"tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor", "&", "|"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
|
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
|
||||||
|
@ -1296,8 +1296,8 @@ namespace exprtk
|
||||||
based on the compiler and target architecture. The benchmark
|
based on the compiler and target architecture. The benchmark
|
||||||
should provide enough information to make the right choice.
|
should provide enough information to make the right choice.
|
||||||
*/
|
*/
|
||||||
//typedef T Type
|
//typedef T Type;
|
||||||
//typedef const T Type
|
//typedef const T Type;
|
||||||
typedef const T& Type;
|
typedef const T& Type;
|
||||||
typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
|
typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
|
||||||
typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
|
typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
|
||||||
|
@ -1314,39 +1314,17 @@ namespace exprtk
|
||||||
|
|
||||||
enum token_type
|
enum token_type
|
||||||
{
|
{
|
||||||
e_none = 0,
|
e_none = 0, e_error = 1, e_err_symbol = 2,
|
||||||
e_error = 1,
|
e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
|
||||||
e_err_symbol = 2,
|
e_eof = 6, e_number = 7, e_symbol = 8,
|
||||||
e_err_number = 3,
|
e_string = 9, e_assign = 10, e_shr = 11,
|
||||||
e_err_string = 4,
|
e_shl = 12, e_lte = 13, e_ne = 14,
|
||||||
e_err_sfunc = 5,
|
e_gte = 15, e_lt = '<', e_gt = '>',
|
||||||
e_eof = 6,
|
e_eq = '=', e_rbracket = ')', e_lbracket = '(',
|
||||||
e_number = 7,
|
e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
|
||||||
e_symbol = 8,
|
e_lcrlbracket = '{', e_comma = ',', e_add = '+',
|
||||||
e_string = 9,
|
e_sub = '-', e_div = '/', e_mul = '*',
|
||||||
e_assign = 10,
|
e_mod = '%', e_pow = '^', e_colon = ':'
|
||||||
e_shr = 11,
|
|
||||||
e_shl = 12,
|
|
||||||
e_lte = 13,
|
|
||||||
e_ne = 14,
|
|
||||||
e_gte = 15,
|
|
||||||
e_lt = '<',
|
|
||||||
e_gt = '>',
|
|
||||||
e_eq = '=',
|
|
||||||
e_rbracket = ')',
|
|
||||||
e_lbracket = '(',
|
|
||||||
e_rsqrbracket = ']',
|
|
||||||
e_lsqrbracket = '[',
|
|
||||||
e_rcrlbracket = '}',
|
|
||||||
e_lcrlbracket = '{',
|
|
||||||
e_comma = ',',
|
|
||||||
e_add = '+',
|
|
||||||
e_sub = '-',
|
|
||||||
e_div = '/',
|
|
||||||
e_mul = '*',
|
|
||||||
e_mod = '%',
|
|
||||||
e_pow = '^',
|
|
||||||
e_colon = ':'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
token()
|
token()
|
||||||
|
@ -1423,7 +1401,7 @@ namespace exprtk
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string to_str(token_type t) const
|
static inline std::string to_str(token_type t)
|
||||||
{
|
{
|
||||||
switch (t)
|
switch (t)
|
||||||
{
|
{
|
||||||
|
@ -1561,6 +1539,16 @@ namespace exprtk
|
||||||
return eof_token_;
|
return eof_token_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline token_t& peek_next_token()
|
||||||
|
{
|
||||||
|
if (token_list_.end() != token_itr_)
|
||||||
|
{
|
||||||
|
return *token_itr_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return eof_token_;
|
||||||
|
}
|
||||||
|
|
||||||
inline token_t& operator[](const std::size_t& index)
|
inline token_t& operator[](const std::size_t& index)
|
||||||
{
|
{
|
||||||
if (index < token_list_.size())
|
if (index < token_list_.size())
|
||||||
|
@ -3002,29 +2990,29 @@ namespace exprtk
|
||||||
e_none , e_null , e_constant , e_unary ,
|
e_none , e_null , e_constant , e_unary ,
|
||||||
e_binary , e_binary_ext , e_trinary , e_quaternary ,
|
e_binary , e_binary_ext , e_trinary , e_quaternary ,
|
||||||
e_quinary , e_senary , e_vararg , e_conditional ,
|
e_quinary , e_senary , e_vararg , e_conditional ,
|
||||||
e_while , e_switch , e_variable , e_stringvar ,
|
e_while , e_repeat , e_switch , e_variable ,
|
||||||
e_stringconst , e_function , e_vafunction , e_add ,
|
e_stringvar , e_stringconst , e_function , e_vafunction ,
|
||||||
e_sub , e_mul , e_div , e_mod ,
|
e_add , e_sub , e_mul , e_div ,
|
||||||
e_pow , e_lt , e_lte , e_gt ,
|
e_mod , e_pow , e_lt , e_lte ,
|
||||||
e_gte , e_eq , e_ne , e_and ,
|
e_gt , e_gte , e_eq , e_ne ,
|
||||||
e_nand , e_or , e_nor , e_xor ,
|
e_and , e_nand , e_or , e_nor ,
|
||||||
e_xnor , e_in , e_like , e_ilike ,
|
e_xor , e_xnor , e_in , e_like ,
|
||||||
e_inranges , e_ipow , e_ipowinv , e_abs ,
|
e_ilike , e_inranges , e_ipow , e_ipowinv ,
|
||||||
e_acos , e_asin , e_atan , e_ceil ,
|
e_abs , e_acos , e_asin , e_atan ,
|
||||||
e_cos , e_cosh , e_exp , e_floor ,
|
e_ceil , e_cos , e_cosh , e_exp ,
|
||||||
e_log , e_log10 , e_log2 , e_log1p ,
|
e_floor , e_log , e_log10 , e_log2 ,
|
||||||
e_neg , e_pos , e_round , e_sin ,
|
e_log1p , e_neg , e_pos , e_round ,
|
||||||
e_sinh , e_sqrt , e_tan , e_tanh ,
|
e_sin , e_sinh , e_sqrt , e_tan ,
|
||||||
e_cot , e_sec , e_csc , e_r2d ,
|
e_tanh , e_cot , e_sec , e_csc ,
|
||||||
e_d2r , e_d2g , e_g2d , e_notl ,
|
e_r2d , e_d2r , e_d2g , e_g2d ,
|
||||||
e_sgn , e_erf , e_erfc , e_frac ,
|
e_notl , e_sgn , e_erf , e_erfc ,
|
||||||
e_trunc , e_uvouv , e_vov , e_cov ,
|
e_frac , e_trunc , e_uvouv , e_vov ,
|
||||||
e_voc , e_vob , e_bov , e_cob ,
|
e_cov , e_voc , e_vob , e_bov ,
|
||||||
e_boc , e_vovov , e_vovoc , e_vocov ,
|
e_cob , e_boc , e_vovov , e_vovoc ,
|
||||||
e_covov , e_covoc , e_vovovov , e_vovovoc ,
|
e_vocov , e_covov , e_covoc , e_vovovov ,
|
||||||
e_vovocov , e_vocovov , e_covovov , e_covocov ,
|
e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
|
||||||
e_vocovoc , e_covovoc , e_vococov , e_sf3ext ,
|
e_covocov , e_vocovoc , e_covovoc , e_vococov ,
|
||||||
e_sf4ext
|
e_sf3ext , e_sf4ext
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef T value_type;
|
typedef T value_type;
|
||||||
|
@ -3586,9 +3574,9 @@ namespace exprtk
|
||||||
const T arg3 = branch_[3].first->value();
|
const T arg3 = branch_[3].first->value();
|
||||||
switch (operation_)
|
switch (operation_)
|
||||||
{
|
{
|
||||||
case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
|
case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
|
||||||
case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
|
case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
|
||||||
default : return std::numeric_limits<T>::quiet_NaN();
|
default : return std::numeric_limits<T>::quiet_NaN();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3762,8 +3750,7 @@ namespace exprtk
|
||||||
|
|
||||||
typedef expression_node<T>* expression_ptr;
|
typedef expression_node<T>* expression_ptr;
|
||||||
|
|
||||||
while_loop_node(expression_ptr test,
|
while_loop_node(expression_ptr test, expression_ptr branch)
|
||||||
expression_ptr branch)
|
|
||||||
: test_(test),
|
: test_(test),
|
||||||
branch_(branch),
|
branch_(branch),
|
||||||
test_deletable_(!is_variable_node(test_)),
|
test_deletable_(!is_variable_node(test_)),
|
||||||
|
@ -3799,6 +3786,50 @@ namespace exprtk
|
||||||
bool branch_deletable_;
|
bool branch_deletable_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class repeat_until_loop_node : public expression_node<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef expression_node<T>* expression_ptr;
|
||||||
|
|
||||||
|
repeat_until_loop_node(expression_ptr test, expression_ptr branch)
|
||||||
|
: test_(test),
|
||||||
|
branch_(branch),
|
||||||
|
test_deletable_(!is_variable_node(test_)),
|
||||||
|
branch_deletable_(!is_variable_node(branch_))
|
||||||
|
{}
|
||||||
|
|
||||||
|
~repeat_until_loop_node()
|
||||||
|
{
|
||||||
|
if (test_ && test_deletable_) delete test_;
|
||||||
|
if (branch_ && branch_deletable_) delete branch_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline T value() const
|
||||||
|
{
|
||||||
|
T result = T(0);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result = branch_->value();
|
||||||
|
}
|
||||||
|
while (is_false(test_));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline typename expression_node<T>::node_type type() const
|
||||||
|
{
|
||||||
|
return expression_node<T>::e_repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
expression_ptr test_;
|
||||||
|
expression_ptr branch_;
|
||||||
|
bool test_deletable_;
|
||||||
|
bool branch_deletable_;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class switch_node : public expression_node<T>
|
class switch_node : public expression_node<T>
|
||||||
{
|
{
|
||||||
|
@ -4369,12 +4400,13 @@ namespace exprtk
|
||||||
assignment_node(const operator_type& operation,
|
assignment_node(const operator_type& operation,
|
||||||
expression_ptr branch0,
|
expression_ptr branch0,
|
||||||
expression_ptr branch1)
|
expression_ptr branch1)
|
||||||
: binary_node<T>(operation,branch0,branch1)
|
: binary_node<T>(operation,branch0,branch1),
|
||||||
|
is_lefthand_variable_(is_variable_node(binary_node<T>::branch_[0].first))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline T value() const
|
inline T value() const
|
||||||
{
|
{
|
||||||
if (is_variable_node(binary_node<T>::branch_[0].first))
|
if (is_lefthand_variable_)
|
||||||
{
|
{
|
||||||
variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
|
variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
|
||||||
if (var_node_ptr)
|
if (var_node_ptr)
|
||||||
|
@ -4386,6 +4418,10 @@ namespace exprtk
|
||||||
}
|
}
|
||||||
return std::numeric_limits<T>::quiet_NaN();
|
return std::numeric_limits<T>::quiet_NaN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool is_lefthand_variable_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -9324,32 +9360,34 @@ namespace exprtk
|
||||||
|
|
||||||
struct state_t;
|
struct state_t;
|
||||||
|
|
||||||
typedef const T& cref_t;
|
typedef const T& cref_t;
|
||||||
typedef const T const_t;
|
typedef const T const_t;
|
||||||
typedef ifunction <T> F;
|
typedef ifunction <T> F;
|
||||||
typedef ivararg_function <T> VAF;
|
typedef ivararg_function <T> VAF;
|
||||||
typedef ifunction <T> ifunction_t;
|
typedef ifunction <T> ifunction_t;
|
||||||
typedef ivararg_function <T> ivararg_function_t;
|
typedef ivararg_function <T> ivararg_function_t;
|
||||||
typedef details::expression_node <T> expression_node_t;
|
typedef details::expression_node <T> expression_node_t;
|
||||||
typedef details::literal_node <T> literal_node_t;
|
typedef details::literal_node <T> literal_node_t;
|
||||||
typedef details::string_literal_node<T> string_literal_node_t;
|
typedef details::string_literal_node<T> string_literal_node_t;
|
||||||
typedef details::unary_node <T> unary_node_t;
|
typedef details::unary_node <T> unary_node_t;
|
||||||
typedef details::binary_node <T> binary_node_t;
|
typedef details::binary_node <T> binary_node_t;
|
||||||
typedef details::trinary_node <T> trinary_node_t;
|
typedef details::trinary_node <T> trinary_node_t;
|
||||||
typedef details::quaternary_node <T> quaternary_node_t;
|
typedef details::quaternary_node <T> quaternary_node_t;
|
||||||
typedef details::quinary_node <T> quinary_node_t;
|
typedef details::quinary_node <T> quinary_node_t;
|
||||||
typedef details::senary_node <T> senary_node_t;
|
typedef details::senary_node <T> senary_node_t;
|
||||||
typedef details::conditional_node<T> conditional_node_t;
|
typedef details::conditional_node<T> conditional_node_t;
|
||||||
typedef details::while_loop_node <T> while_loop_node_t;
|
typedef details::while_loop_node <T> while_loop_node_t;
|
||||||
typedef details::variable_node <T> variable_node_t;
|
typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
|
||||||
|
typedef details::switch_node<T> switch_node_t;
|
||||||
|
typedef details::variable_node <T> variable_node_t;
|
||||||
#ifndef exprtk_disable_string_capabilities
|
#ifndef exprtk_disable_string_capabilities
|
||||||
typedef details::stringvar_node <T> stringvar_node_t;
|
typedef details::stringvar_node <T> stringvar_node_t;
|
||||||
#endif
|
#endif
|
||||||
typedef details::assignment_node <T> assignment_node_t;
|
typedef details::assignment_node <T> assignment_node_t;
|
||||||
typedef details::scand_node <T> scand_node_t;
|
typedef details::scand_node <T> scand_node_t;
|
||||||
typedef details::scor_node <T> scor_node_t;
|
typedef details::scor_node <T> scor_node_t;
|
||||||
typedef lexer::token token_t;
|
typedef lexer::token token_t;
|
||||||
typedef expression_node_t* expression_node_ptr;
|
typedef expression_node_t* expression_node_ptr;
|
||||||
|
|
||||||
typedef typename details::functor_t<T> functor_t;
|
typedef typename details::functor_t<T> functor_t;
|
||||||
typedef typename functor_t::qfunc_t quaternary_functor_t;
|
typedef typename functor_t::qfunc_t quaternary_functor_t;
|
||||||
|
@ -9387,6 +9425,8 @@ namespace exprtk
|
||||||
typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
|
typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
|
||||||
typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
|
typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
|
||||||
|
|
||||||
|
struct range_pack;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum precompilation_step
|
enum precompilation_step
|
||||||
|
@ -9847,12 +9887,7 @@ namespace exprtk
|
||||||
}
|
}
|
||||||
while (!lexer_.finished());
|
while (!lexer_.finished());
|
||||||
|
|
||||||
if (arg_list.empty())
|
result = simplify(arg_list);
|
||||||
return error_node();
|
|
||||||
else if (arg_list.size() == 1)
|
|
||||||
result = arg_list[0];
|
|
||||||
else
|
|
||||||
result = expression_generator_.vararg_function(details::e_multi,arg_list);
|
|
||||||
|
|
||||||
sdd.delete_ptr = (0 == result);
|
sdd.delete_ptr = (0 == result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -10382,6 +10417,88 @@ namespace exprtk
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expression_node_ptr parse_repeat_until_loop()
|
||||||
|
{
|
||||||
|
// Parse: [repeat][{][expression][}][until][(][test expr][)]
|
||||||
|
expression_node_ptr condition = error_node();
|
||||||
|
expression_node_ptr branch = error_node();
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
std::deque<expression_node_ptr> arg_list;
|
||||||
|
scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
|
||||||
|
|
||||||
|
{
|
||||||
|
token_t::token_type seperator = token_t::e_eof;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
expression_node_ptr arg = parse_expression();
|
||||||
|
if (0 == arg)
|
||||||
|
return error_node();
|
||||||
|
else
|
||||||
|
arg_list.push_back(arg);
|
||||||
|
|
||||||
|
if (details::imatch(current_token_.value,"until"))
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!token_is(seperator))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR22 - Expected '" + token_t::to_str(seperator) +"' for body of repeat until loop"));
|
||||||
|
return error_node();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details::imatch(current_token_.value,"until"))
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
branch = simplify(arg_list);
|
||||||
|
|
||||||
|
sdd.delete_ptr = (0 == branch);
|
||||||
|
|
||||||
|
if (0 == branch)
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR23 - Failed to parse body of repeat until loop."));
|
||||||
|
return error_node();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token_is(token_t::e_lbracket))
|
||||||
|
return error_node();
|
||||||
|
else if (0 == (condition = parse_expression()))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR24 - Failed to parse condition for repeat until loop."));
|
||||||
|
return error_node();
|
||||||
|
}
|
||||||
|
else if (!token_is(token_t::e_rbracket))
|
||||||
|
return error_node();
|
||||||
|
|
||||||
|
expression_node_ptr result;
|
||||||
|
if (0 == (result = expression_generator_.repeat_until_loop(condition,branch)))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR25 - Failed to synthesize repeat until loop."));
|
||||||
|
return error_node();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline expression_node_ptr parse_switch_statement()
|
inline expression_node_ptr parse_switch_statement()
|
||||||
{
|
{
|
||||||
std::vector<expression_node_ptr> arg_list;
|
std::vector<expression_node_ptr> arg_list;
|
||||||
|
@ -10397,11 +10514,11 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR22 - Expected '{' for call to switch statement."));
|
"ERR26 - Expected '{' for call to switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
for ( ; ; )
|
||||||
{
|
{
|
||||||
if (!details::imatch("case",current_token_.value))
|
if (!details::imatch("case",current_token_.value))
|
||||||
return error_node();
|
return error_node();
|
||||||
|
@ -10417,7 +10534,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR23 - Expected ':' for case of switch statement."));
|
"ERR27 - Expected ':' for case of switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10430,7 +10547,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR24 - Expected ';' at end of case for switch statement."));
|
"ERR28 - Expected ';' at end of case for switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10445,7 +10562,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR25 - Expected ':' for default of switch statement."));
|
"ERR29 - Expected ':' for default of switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10456,7 +10573,7 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
set_error(make_error(parser_error::e_syntax,
|
set_error(make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR26 - Expected ';' at end of default for switch statement."));
|
"ERR30 - Expected ';' at end of default for switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10470,7 +10587,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR27 - Expected '}' at end of switch statement."));
|
"ERR31 - Expected '}' at end of switch statement."));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10505,7 +10622,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR28 - Unsupported vararg function: " + symbol));
|
"ERR32 - Unsupported vararg function: " + symbol));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10517,7 +10634,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR29 - Expected '(' for call to vararg function: " + symbol));
|
"ERR33 - Expected '(' for call to vararg function: " + symbol));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10535,7 +10652,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR30 - Expected ',' for call to vararg function: " + symbol));
|
"ERR34 - Expected ',' for call to vararg function: " + symbol));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10546,6 +10663,35 @@ namespace exprtk
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Allocator,
|
||||||
|
template <typename,typename> class Sequence>
|
||||||
|
inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator>& expression_list)
|
||||||
|
{
|
||||||
|
if (expression_list.empty())
|
||||||
|
return error_node();
|
||||||
|
if (expression_list.size() == 1)
|
||||||
|
return expression_list[0];
|
||||||
|
|
||||||
|
Sequence<expression_node_ptr,Allocator> tmp_expression_list;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
|
||||||
|
{
|
||||||
|
if (is_variable_node(expression_list[i]))
|
||||||
|
continue;
|
||||||
|
else if (is_constant_node(expression_list[i]))
|
||||||
|
{
|
||||||
|
free_node(node_allocator_,expression_list[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp_expression_list.push_back(expression_list[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_expression_list.push_back(expression_list.back());
|
||||||
|
expression_list.swap(tmp_expression_list);
|
||||||
|
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 = "")
|
||||||
{
|
{
|
||||||
token_t::token_type close_bracket = token_t::e_rcrlbracket;
|
token_t::token_type close_bracket = token_t::e_rcrlbracket;
|
||||||
|
@ -10563,7 +10709,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR31 - Expected '"+ details::to_str(close_bracket) + "' for call to multi-sequence" +
|
"ERR35 - Expected '"+ details::to_str(close_bracket) + "' for call to multi-sequence" +
|
||||||
((!source.empty()) ? std::string(" section of " + source): "")));
|
((!source.empty()) ? std::string(" section of " + source): "")));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -10583,24 +10729,199 @@ namespace exprtk
|
||||||
arg_list.push_back(arg);
|
arg_list.push_back(arg);
|
||||||
if (token_is(close_bracket))
|
if (token_is(close_bracket))
|
||||||
break;
|
break;
|
||||||
else if (!token_is(seperator))
|
|
||||||
|
bool is_next_close = peek_token_is(close_bracket);
|
||||||
|
|
||||||
|
if (!token_is(seperator) && is_next_close)
|
||||||
{
|
{
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR32 - Expected '"+ details::to_str(seperator) +"' for call to multi-sequence section of " + source));
|
"ERR36 - Expected '"+ details::to_str(seperator) +"' for call to multi-sequence section of " + source));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (token_is(close_bracket))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = simplify(arg_list);
|
||||||
|
|
||||||
|
sdd.delete_ptr = (0 == result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range_pack
|
||||||
|
{
|
||||||
|
range_pack()
|
||||||
|
: n0_e(std::make_pair(false,expression_node_ptr(0))),
|
||||||
|
n1_e(std::make_pair(false,expression_node_ptr(0))),
|
||||||
|
n0_c(std::make_pair(false,0)),
|
||||||
|
n1_c(std::make_pair(false,0))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
n0_e = std::make_pair(false,expression_node_ptr(0));
|
||||||
|
n1_e = std::make_pair(false,expression_node_ptr(0));
|
||||||
|
n0_c = std::make_pair(false,0);
|
||||||
|
n1_c = std::make_pair(false,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free()
|
||||||
|
{
|
||||||
|
if (n0_e.first && n0_e.second)
|
||||||
|
{
|
||||||
|
n0_e.first = false;
|
||||||
|
delete n0_e.second;
|
||||||
|
}
|
||||||
|
if (n1_e.first && n1_e.second)
|
||||||
|
{
|
||||||
|
n1_e.first = false;
|
||||||
|
delete n1_e.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_list.empty())
|
std::pair<bool,expression_node_ptr> n0_e;
|
||||||
return error_node();
|
std::pair<bool,expression_node_ptr> n1_e;
|
||||||
else if (arg_list.size() == 1)
|
std::pair<bool,std::size_t > n0_c;
|
||||||
result = arg_list[0];
|
std::pair<bool,std::size_t > n1_c;
|
||||||
else
|
};
|
||||||
result = expression_generator_.vararg_function(details::e_multi,arg_list);
|
|
||||||
|
|
||||||
sdd.delete_ptr = (0 == result);
|
inline bool parse_range(range_pack& rp)
|
||||||
|
{
|
||||||
|
//Examples of valid ranges:
|
||||||
|
// 1. [1:5] -> 1..5
|
||||||
|
// 2. [ :5] -> 0..5
|
||||||
|
// 3. [1: ] -> 1..end
|
||||||
|
// 4. [x:y] -> x..y where x <= y
|
||||||
|
// 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
|
||||||
|
// 6. [ :y] -> 0..y where 0 <= y
|
||||||
|
// 7. [x: ] -> x..end where x <= end
|
||||||
|
|
||||||
|
rp.clear();
|
||||||
|
|
||||||
|
if (!token_is(token_t::e_lsqrbracket))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR37 - Expected '[' for start of range."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token_is(token_t::e_colon))
|
||||||
|
{
|
||||||
|
rp.n0_c.first = true;
|
||||||
|
rp.n0_c.second = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expression_node_ptr r0 = parse_expression();
|
||||||
|
|
||||||
|
if (0 == r0)
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR38 - Failed parse begin section of range."));
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (is_constant_node(r0))
|
||||||
|
{
|
||||||
|
rp.n0_c.first = true;
|
||||||
|
rp.n0_c.second = static_cast<std::size_t>(r0->value());
|
||||||
|
free_node(node_allocator_,r0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rp.n0_e.first = true;
|
||||||
|
rp.n0_e.second = r0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token_is(token_t::e_colon))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR39 - Expected ':' for break in range."));
|
||||||
|
rp.free();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token_is(token_t::e_rsqrbracket))
|
||||||
|
{
|
||||||
|
rp.n1_c.first = true;
|
||||||
|
rp.n1_c.second = std::numeric_limits<std::size_t>::max();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expression_node_ptr r1 = parse_expression();
|
||||||
|
|
||||||
|
if (0 == r1)
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR40 - Failed parse end section of range."));
|
||||||
|
rp.free();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (is_constant_node(r1))
|
||||||
|
{
|
||||||
|
rp.n1_c.first = true;
|
||||||
|
rp.n1_c.second = static_cast<std::size_t>(r1->value());
|
||||||
|
free_node(node_allocator_,r1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rp.n1_e.first = true;
|
||||||
|
rp.n1_e.second = r1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token_is(token_t::e_rsqrbracket))
|
||||||
|
{
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_syntax,
|
||||||
|
current_token_,
|
||||||
|
"ERR41 - Expected ']' for start of range."));
|
||||||
|
rp.free();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline expression_node_ptr parse_string()
|
||||||
|
{
|
||||||
|
const std::string symbol = current_token_.value;
|
||||||
|
expression_node_ptr result = symbol_table_.get_stringvar(symbol);
|
||||||
|
|
||||||
|
if (symbol_name_caching_)
|
||||||
|
{
|
||||||
|
symbol_name_cache_.push_back(symbol);
|
||||||
|
}
|
||||||
|
if (symbol_table_.is_constant_node(symbol))
|
||||||
|
{
|
||||||
|
result = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(result)->str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peek_token_is(token_t::e_lsqrbracket))
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
range_pack rp;
|
||||||
|
if (!parse_range(rp))
|
||||||
|
{
|
||||||
|
free_node(node_allocator_,result);
|
||||||
|
return error_node();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
next_token();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10619,7 +10940,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR33 - Expected '(' for call to vararg function: " + vararg_function_name));
|
"ERR42 - Expected '(' for call to vararg function: " + vararg_function_name));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10637,7 +10958,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR34 - Expected ',' for call to vararg function: " + vararg_function_name));
|
"ERR43 - Expected ',' for call to vararg function: " + vararg_function_name));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10698,7 +11019,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_token,
|
make_error(parser_error::e_token,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR35 - Invalid special function[1]: " + current_token_.value));
|
"ERR44 - Invalid special function[1]: " + current_token_.value));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10709,7 +11030,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_token,
|
make_error(parser_error::e_token,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR36 - Invalid special function[2]: " + current_token_.value));
|
"ERR45 - Invalid special function[2]: " + current_token_.value));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10752,19 +11073,9 @@ namespace exprtk
|
||||||
|
|
||||||
#ifndef exprtk_disable_string_capabilities
|
#ifndef exprtk_disable_string_capabilities
|
||||||
// Are we dealing with a string variable?
|
// Are we dealing with a string variable?
|
||||||
variable = symbol_table_.get_stringvar(symbol);
|
if (symbol_table_.is_stringvar(symbol))
|
||||||
if (variable)
|
|
||||||
{
|
{
|
||||||
if (symbol_name_caching_)
|
return parse_string();
|
||||||
{
|
|
||||||
symbol_name_cache_.push_back(symbol);
|
|
||||||
}
|
|
||||||
if (symbol_table_.is_constant_node(symbol))
|
|
||||||
{
|
|
||||||
variable = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(variable)->str());
|
|
||||||
}
|
|
||||||
next_token();
|
|
||||||
return variable;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -10801,7 +11112,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR37 - Invalid number of parameters for function: " + symbol));
|
"ERR46 - Invalid number of parameters for function: " + symbol));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10813,7 +11124,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR38 - Failed to generate node for function: '" + symbol + "'"));
|
"ERR47 - Failed to generate node for function: '" + symbol + "'"));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10833,7 +11144,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR39 - Failed to generate node for vararg function: '" + symbol + "'"));
|
"ERR48 - Failed to generate node for vararg function: '" + symbol + "'"));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10880,7 +11191,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_symtab,
|
make_error(parser_error::e_symtab,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR40 - Failed to create variable: '" + symbol + "'"));
|
"ERR49 - Failed to create variable: '" + symbol + "'"));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -10889,7 +11200,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR41 - Undefined variable or function: '" + symbol + "'"));
|
"ERR50 - Undefined variable or function: '" + symbol + "'"));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10897,6 +11208,7 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
static const std::string symbol_if = "if";
|
static const std::string symbol_if = "if";
|
||||||
static const std::string symbol_while = "while";
|
static const std::string symbol_while = "while";
|
||||||
|
static const std::string symbol_repeat = "repeat";
|
||||||
static const std::string symbol_switch = "switch";
|
static const std::string symbol_switch = "switch";
|
||||||
static const std::string symbol_null = "null";
|
static const std::string symbol_null = "null";
|
||||||
|
|
||||||
|
@ -10916,6 +11228,10 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
return parse_while_loop();
|
return parse_while_loop();
|
||||||
}
|
}
|
||||||
|
else if (details::imatch(current_token_.value,symbol_repeat))
|
||||||
|
{
|
||||||
|
return parse_repeat_until_loop();
|
||||||
|
}
|
||||||
else if (details::imatch(current_token_.value,symbol_switch))
|
else if (details::imatch(current_token_.value,symbol_switch))
|
||||||
{
|
{
|
||||||
return parse_switch_statement();
|
return parse_switch_statement();
|
||||||
|
@ -10937,7 +11253,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_symtab,
|
make_error(parser_error::e_symtab,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR41 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
|
"ERR51 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11012,7 +11328,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR42 - Premature end of expression.[1]"));
|
"ERR52 - Premature end of expression.[1]"));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -11020,7 +11336,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token_,
|
current_token_,
|
||||||
"ERR43 - Premature end of expression.[2]"));
|
"ERR53 - Premature end of expression.[2]"));
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11035,6 +11351,11 @@ namespace exprtk
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool peek_token_is(const typename token_t::token_type& ttype)
|
||||||
|
{
|
||||||
|
return (lexer_.peek_next_token().type == ttype);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class expression_generator
|
class expression_generator
|
||||||
{
|
{
|
||||||
|
@ -11641,6 +11962,30 @@ namespace exprtk
|
||||||
return node_allocator_->allocate<while_loop_node_t>(condition,branch);
|
return node_allocator_->allocate<while_loop_node_t>(condition,branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline expression_node_ptr repeat_until_loop(expression_node_ptr condition,
|
||||||
|
expression_node_ptr branch) const
|
||||||
|
{
|
||||||
|
if (details::is_constant_node(condition))
|
||||||
|
{
|
||||||
|
if (details::is_true(condition) && details::is_constant_node(branch))
|
||||||
|
{
|
||||||
|
free_node(*node_allocator_,condition);
|
||||||
|
return branch;
|
||||||
|
}
|
||||||
|
expression_node_ptr result = error_node();
|
||||||
|
free_node(*node_allocator_,condition);
|
||||||
|
free_node(*node_allocator_,branch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (details::is_null_node(condition))
|
||||||
|
{
|
||||||
|
free_node(*node_allocator_,condition);
|
||||||
|
return branch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Allocator,
|
template <typename Allocator,
|
||||||
template <typename,typename> class Sequence>
|
template <typename,typename> class Sequence>
|
||||||
inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arglist)
|
inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arglist)
|
||||||
|
|
|
@ -50,11 +50,10 @@ void newton_sqrt()
|
||||||
" ~{ "
|
" ~{ "
|
||||||
" z := 100; "
|
" z := 100; "
|
||||||
" y := x / 2; "
|
" y := x / 2; "
|
||||||
" while ((z := (z - 1)) > 0) "
|
" repeat "
|
||||||
" { "
|
|
||||||
" if (equal(y * y,x), z := 0, 0);"
|
" if (equal(y * y,x), z := 0, 0);"
|
||||||
" y := (1 / 2) * (y + (x / y)) "
|
" y := (1 / 2) * (y + (x / y)); "
|
||||||
" } "
|
" until ((z := (z - 1)) <= 0) "
|
||||||
" }; "
|
" }; "
|
||||||
"} ",
|
"} ",
|
||||||
"x","y","z");
|
"x","y","z");
|
||||||
|
|
|
@ -968,7 +968,15 @@ static const test_t test_list[] =
|
||||||
test_t("switch { case {1 <= 2} : switch { case {1 <= 2} : 1; default: 1.12345; }; default: 1.12345; }",1.0),
|
test_t("switch { case {1 <= 2} : switch { case {1 <= 2} : 1; default: 1.12345; }; default: 1.12345; }",1.0),
|
||||||
test_t("switch { case [(1 <= 2)] : {1}; default: 1.12345; }",1.0),
|
test_t("switch { case [(1 <= 2)] : {1}; default: 1.12345; }",1.0),
|
||||||
test_t("switch { case ([1 > 2]) : [0]; case ([1 <= 2]) : 1; default: 1.12345; }",1.0),
|
test_t("switch { case ([1 > 2]) : [0]; case ([1 <= 2]) : 1; default: 1.12345; }",1.0),
|
||||||
test_t("switch { case {(1 <= 2)} : switch { case ({1 <= 2}) : 1; default: 1.12345; }; default: 1.12345; }",1.0)
|
test_t("switch { case {(1 <= 2)} : switch { case ({1 <= 2}) : 1; default: 1.12345; }; default: 1.12345; }",1.0),
|
||||||
|
test_t("repeat 1.1 + 2.2 until (1 < 2)",3.3),
|
||||||
|
test_t("repeat (1.1 + 2.2) until (1 < 2)",3.3),
|
||||||
|
test_t("repeat 1.1 + 2.2; until (1 < 2)",3.3),
|
||||||
|
test_t("repeat (1.1 + 2.2); until (1 < 2)",3.3),
|
||||||
|
test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2 until (1 < 2)",3.3),
|
||||||
|
test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2) until (1 < 2)",3.3),
|
||||||
|
test_t("repeat 1.1234; 1 < 2; 1.1 + 2.2; until (1 < 2)",3.3),
|
||||||
|
test_t("repeat 1.1234; 1 < 2; (1.1 + 2.2); until (1 < 2)",3.3)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_t);
|
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_t);
|
||||||
|
@ -3737,6 +3745,27 @@ inline bool run_test19()
|
||||||
"fibonacci_impl3(x,0,1,0)",
|
"fibonacci_impl3(x,0,1,0)",
|
||||||
"x");
|
"x");
|
||||||
|
|
||||||
|
compositor
|
||||||
|
.add("fibonacci_impl4",
|
||||||
|
"switch "
|
||||||
|
"{ "
|
||||||
|
" case x == 0 : 0; "
|
||||||
|
" case x == 1 : 1; "
|
||||||
|
" default : repeat "
|
||||||
|
" w := z; "
|
||||||
|
" z := z + y; "
|
||||||
|
" y := w; "
|
||||||
|
" x := x - 1; "
|
||||||
|
" z "
|
||||||
|
" until (x <= 1);"
|
||||||
|
"} ",
|
||||||
|
"x","y","z","w");
|
||||||
|
|
||||||
|
compositor
|
||||||
|
.add("fibonacci4",
|
||||||
|
"fibonacci_impl4(x,0,1,0)",
|
||||||
|
"x");
|
||||||
|
|
||||||
|
|
||||||
exprtk::symbol_table<T>& symbol_table = compositor.symbol_table();
|
exprtk::symbol_table<T>& symbol_table = compositor.symbol_table();
|
||||||
symbol_table.add_constants();
|
symbol_table.add_constants();
|
||||||
|
@ -3745,13 +3774,16 @@ inline bool run_test19()
|
||||||
std::string expression_str1 = "fibonacci1(x)";
|
std::string expression_str1 = "fibonacci1(x)";
|
||||||
std::string expression_str2 = "fibonacci2(x)";
|
std::string expression_str2 = "fibonacci2(x)";
|
||||||
std::string expression_str3 = "fibonacci3(x)";
|
std::string expression_str3 = "fibonacci3(x)";
|
||||||
|
std::string expression_str4 = "fibonacci4(x)";
|
||||||
|
|
||||||
expression_t expression1;
|
expression_t expression1;
|
||||||
expression_t expression2;
|
expression_t expression2;
|
||||||
expression_t expression3;
|
expression_t expression3;
|
||||||
|
expression_t expression4;
|
||||||
expression1.register_symbol_table(symbol_table);
|
expression1.register_symbol_table(symbol_table);
|
||||||
expression2.register_symbol_table(symbol_table);
|
expression2.register_symbol_table(symbol_table);
|
||||||
expression3.register_symbol_table(symbol_table);
|
expression3.register_symbol_table(symbol_table);
|
||||||
|
expression4.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
exprtk::parser<T> parser;
|
exprtk::parser<T> parser;
|
||||||
|
|
||||||
|
@ -3779,18 +3811,26 @@ inline bool run_test19()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parser.compile(expression_str4,expression4))
|
||||||
|
{
|
||||||
|
printf("run_test19() - Error: %s Expression4: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expression_str4.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool failure = false;
|
bool failure = false;
|
||||||
|
|
||||||
const std::size_t fibonacci_list[] =
|
const std::size_t fibonacci_list[] =
|
||||||
{
|
{
|
||||||
0, 1, 1, 2,
|
0, 1, 1, 2,
|
||||||
3, 5, 8, 13,
|
3, 5, 8, 13,
|
||||||
21, 34, 55, 89,
|
21, 34, 55, 89,
|
||||||
144, 233, 377, 610,
|
144, 233, 377, 610,
|
||||||
987, 1597, 2584, 4181,
|
987, 1597, 2584, 4181,
|
||||||
6765, 10946, 17711, 28657,
|
6765, 10946, 17711, 28657,
|
||||||
46368, 75025, 121393, 196418,
|
46368, 75025, 121393, 196418,
|
||||||
317811, 514229, 832040, 1346269
|
317811, 514229, 832040, 1346269
|
||||||
};
|
};
|
||||||
const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t);
|
const std::size_t fibonacci_list_size = sizeof(fibonacci_list) / sizeof(std::size_t);
|
||||||
|
|
||||||
|
@ -3800,28 +3840,43 @@ inline bool run_test19()
|
||||||
T result1 = expression1.value();
|
T result1 = expression1.value();
|
||||||
T result2 = expression2.value();
|
T result2 = expression2.value();
|
||||||
T result3 = expression3.value();
|
T result3 = expression3.value();
|
||||||
|
T result4 = expression4.value();
|
||||||
|
|
||||||
if ((result1 != result2) || (result1 != result3))
|
if (
|
||||||
|
(result1 != result2) ||
|
||||||
|
(result1 != result3) ||
|
||||||
|
(result1 != result4)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
printf("run_test19() - Error in evaluation! (3) Results don't match! fibonacci(%d) = %d "
|
printf("run_test19() - Error in evaluation! (3) Results don't match! fibonacci(%d) = %d "
|
||||||
"Expression1: %s Expression2: %s Expression3: %s\n",
|
"Expression1: %s = %d Expression2: %s = %d Expression3: %s = %d Expression4: %s = %d\n",
|
||||||
static_cast<unsigned int>(i),
|
static_cast<unsigned int>(i),
|
||||||
static_cast<unsigned int>(fibonacci_list[i]),
|
static_cast<unsigned int>(fibonacci_list[i]),
|
||||||
expression_str1.c_str(),
|
expression_str1.c_str(),
|
||||||
|
static_cast<unsigned int>(result1),
|
||||||
expression_str2.c_str(),
|
expression_str2.c_str(),
|
||||||
expression_str3.c_str());
|
static_cast<unsigned int>(result2),
|
||||||
|
expression_str3.c_str(),
|
||||||
|
static_cast<unsigned int>(result3),
|
||||||
|
expression_str4.c_str(),
|
||||||
|
static_cast<unsigned int>(result4));
|
||||||
failure = true;
|
failure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fibonacci_list[i] != expression1.value())
|
if (fibonacci_list[i] != expression1.value())
|
||||||
{
|
{
|
||||||
printf("run_test19() - Error in evaluation! (4) fibonacci(%d) = %d "
|
printf("run_test19() - Error in evaluation! (4) fibonacci(%d) = %d "
|
||||||
"Expression1: %s Expression2: %s Expression3: %s\n",
|
"Expression1: %s = %d Expression2: %s = %d Expression3: %s = %d Expression4: %s = %d\n",
|
||||||
static_cast<unsigned int>(i),
|
static_cast<unsigned int>(i),
|
||||||
static_cast<unsigned int>(fibonacci_list[i]),
|
static_cast<unsigned int>(fibonacci_list[i]),
|
||||||
expression_str1.c_str(),
|
expression_str1.c_str(),
|
||||||
|
static_cast<unsigned int>(result1),
|
||||||
expression_str2.c_str(),
|
expression_str2.c_str(),
|
||||||
expression_str3.c_str());
|
static_cast<unsigned int>(result2),
|
||||||
|
expression_str3.c_str(),
|
||||||
|
static_cast<unsigned int>(result3),
|
||||||
|
expression_str4.c_str(),
|
||||||
|
static_cast<unsigned int>(result4));
|
||||||
failure = true;
|
failure = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3923,7 +3978,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
|
||||||
error_message = "";
|
error_message = "";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (unknown_symbol[0] == 'w')
|
else if (unknown_symbol[0] == 'c')
|
||||||
{
|
{
|
||||||
st = usr_t::e_constant_type;
|
st = usr_t::e_constant_type;
|
||||||
default_value = next_value();
|
default_value = next_value();
|
||||||
|
@ -3966,13 +4021,13 @@ inline bool run_test20()
|
||||||
musr.next_value(true);
|
musr.next_value(true);
|
||||||
parser.enable_unknown_symbol_resolver(&musr);
|
parser.enable_unknown_symbol_resolver(&musr);
|
||||||
|
|
||||||
std::string expr_str = "v01+w02+v03+w04+v05+w06+v07+w08+v09+w10+"
|
std::string expr_str = "v01+c02+v03+c04+v05+c06+v07+c08+v09+c10+"
|
||||||
"v11+w12+v13+w14+v15+w16+v17+w18+v19+w20+"
|
"v11+c12+v13+c14+v15+c16+v17+c18+v19+c20+"
|
||||||
"v21+w22+v23+w24+v25+w26+v27+w28+v29+w30";
|
"v21+c22+v23+c24+v25+c26+v27+c28+v29+c30 ";
|
||||||
|
|
||||||
if (!parser.compile(expr_str,expression))
|
if (!parser.compile(expr_str,expression))
|
||||||
{
|
{
|
||||||
printf("run_test18() - Error: %s Expression: %s\n",
|
printf("run_test20() - Error: %s Expression: %s\n",
|
||||||
parser.error().c_str(),
|
parser.error().c_str(),
|
||||||
expr_str.c_str());
|
expr_str.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
|
88
readme.txt
88
readme.txt
|
@ -10,7 +10,7 @@ very easily extendible.
|
||||||
|
|
||||||
|
|
||||||
[01 - CAPABILITIES]
|
[01 - CAPABILITIES]
|
||||||
The ExprTk evaluator supports the following fundamental mathematical
|
The ExprTk evaluator supports the following fundamental arithmetic
|
||||||
operations, functions and processes:
|
operations, functions and processes:
|
||||||
|
|
||||||
(0) Basic operators: +, -, *, /, %, ^
|
(0) Basic operators: +, -, *, /, %, ^
|
||||||
|
@ -114,7 +114,7 @@ include path (e.g: /usr/include/).
|
||||||
|
|
||||||
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
|
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
|
||||||
|
|
||||||
(0) Basic Operators
|
(0) Arithmetic Operators
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| OPERATOR | DEFINITION |
|
| OPERATOR | DEFINITION |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
@ -158,14 +158,14 @@ include path (e.g: /usr/include/).
|
||||||
| true | True state or any value other than zero (typically 1). |
|
| true | True state or any value other than zero (typically 1). |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| false | False state, value of zero. |
|
| false | False state, value of zero. |
|
||||||
+-----------|--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| and | Logical AND, True only if x and y are both true. |
|
| and | Logical AND, True only if x and y are both true. |
|
||||||
| | (eg: x and y) |
|
| | (eg: x and y) |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| mand | Multi-input logical AND, True only if all inputs are |
|
| mand | Multi-input logical AND, True only if all inputs are |
|
||||||
| | true. Left to right short-circuiting of expressions. |
|
| | true. Left to right short-circuiting of expressions. |
|
||||||
| | (eg: mand(x > y,z < w,u or v,w and x)) |
|
| | (eg: mand(x > y,z < w,u or v,w and x)) |
|
||||||
+-----------|--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| mor | Multi-input logical OR, True if at least one of the |
|
| mor | Multi-input logical OR, True if at least one of the |
|
||||||
| | inputs are true. Left to right short-circuiting of |
|
| | inputs are true. Left to right short-circuiting of |
|
||||||
| | expressions. (eg: mand(x > y,z < w,u or v,w and x)) |
|
| | expressions. (eg: mand(x > y,z < w,u or v,w and x)) |
|
||||||
|
@ -187,25 +187,9 @@ include path (e.g: /usr/include/).
|
||||||
| xnor | Logical XNOR, True iff the biconditional of x and y is |
|
| xnor | Logical XNOR, True iff the biconditional of x and y is |
|
||||||
| | satisfied. (eg: x xnor y) |
|
| | satisfied. (eg: x xnor y) |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| if | If x is true then return y else return z. |
|
|
||||||
| | (eg: if(x, y, z) or if((x + 1) > 2y, z + 1, w / v)) |
|
|
||||||
+-----------+--------------------------------------------------------+
|
|
||||||
| switch | The first true case condition that is encountered will |
|
|
||||||
| | determine the result of the switch. If none of the case|
|
|
||||||
| | conditions hold true, the default action is assumed as |
|
|
||||||
| | the final return value. This is sometimes also known as|
|
|
||||||
| | a multi-way branch mechanism. |
|
|
||||||
| | eg: |
|
|
||||||
| | switch |
|
|
||||||
| | { |
|
|
||||||
| | case x > (y+z) : 2*x/abs(y-z); |
|
|
||||||
| | case x < 3 : sin(x + y) |
|
|
||||||
| | default : 1 + x; |
|
|
||||||
| | } |
|
|
||||||
+-----------|--------------------------------------------------------+
|
|
||||||
| & | Similar to AND but with left to right expression short |
|
| & | Similar to AND but with left to right expression short |
|
||||||
| | circuiting optimisation. (eg: (x & y) == (y and x)) |
|
| | circuiting optimisation. (eg: (x & y) == (y and x)) |
|
||||||
+-----------|--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| | | Similar to OR but with left to right expression short |
|
| | | Similar to OR but with left to right expression short |
|
||||||
| | circuiting optimisation. (eg: (x | y) == (y or x)) |
|
| | circuiting optimisation. (eg: (x | y) == (y or x)) |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
@ -217,7 +201,7 @@ include path (e.g: /usr/include/).
|
||||||
| abs | Absolute value of x. |
|
| abs | Absolute value of x. |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| avg | Average of all the inputs. |
|
| avg | Average of all the inputs. |
|
||||||
| | (eg: avg(x,y,z,w,u,v) == (x+y+z+w+u+v)/6) |
|
| | (eg: avg(x,y,z,w,u,v) == (x + y + z + w + u + v) / 6) |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| ceil | Smallest integer that is greater than or equal to x. |
|
| ceil | Smallest integer that is greater than or equal to x. |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
@ -255,7 +239,7 @@ include path (e.g: /usr/include/).
|
||||||
| min | Smallest value of all the inputs. (eg: min(x,y,z,w,u)) |
|
| min | Smallest value of all the inputs. (eg: min(x,y,z,w,u)) |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| mul | Product of all the inputs. |
|
| mul | Product of all the inputs. |
|
||||||
| | (eg: mul(x,y,z,w,u,v,t) == (x*y*z*w*u*v*t)) |
|
| | (eg: mul(x,y,z,w,u,v,t) == (x * y * z * w * u * v * t))|
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| nequal | Not-equal test between x and y using normalized epsilon|
|
| nequal | Not-equal test between x and y using normalized epsilon|
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
@ -272,17 +256,10 @@ include path (e.g: /usr/include/).
|
||||||
| sqrt | Square root of x, where x > 0 |
|
| sqrt | Square root of x, where x > 0 |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| sum | Sum of all the inputs. |
|
| sum | Sum of all the inputs. |
|
||||||
| | (eg: sum(x,y,z,w,u,v,t) == (x+y+z+w+u+v+t)) |
|
| | (eg: sum(x,y,z,w,u,v,t) == (x + y + z + w + u + v + t))|
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| trunc | Integer portion of x |
|
| trunc | Integer portion of x |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
| ~ | Evaluate each sub-expression, then return as the result|
|
|
||||||
| | the value of the last sub-expression. This is sometimes|
|
|
||||||
| | known as multiple sequence point evaluation. |
|
|
||||||
| | eg: |
|
|
||||||
| | ~(i:=x+1, j:=y/z, k:=sin(w/u)) == (sin(w/u))) |
|
|
||||||
| | ~{i:=x+1; j:=y/z; k:=sin(w/u)} == (sin(w/u))) |
|
|
||||||
+-----------+--------------------------------------------------------+
|
|
||||||
|
|
||||||
(4) Trigonometry Functions
|
(4) Trigonometry Functions
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
@ -342,6 +319,55 @@ include path (e.g: /usr/include/).
|
||||||
| | (eg: x ilike y or 'a1B2c3D4e5F6g7H' like 'a?d*h') |
|
| | (eg: x ilike y or 'a1B2c3D4e5F6g7H' like 'a?d*h') |
|
||||||
+-----------+--------------------------------------------------------+
|
+-----------+--------------------------------------------------------+
|
||||||
|
|
||||||
|
(6) Control Structures
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| STRUCTURE | DEFINITION |
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| if | If x is true then return y else return z. |
|
||||||
|
| | (eg: if(x, y, z) or if((x + 1) > 2y, z + 1, w / v)) |
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| switch | The first true case condition that is encountered will |
|
||||||
|
| | determine the result of the switch. If none of the case|
|
||||||
|
| | conditions hold true, the default action is assumed as |
|
||||||
|
| | the final return value. This is sometimes also known as|
|
||||||
|
| | a multi-way branch mechanism. |
|
||||||
|
| | eg: |
|
||||||
|
| | switch |
|
||||||
|
| | { |
|
||||||
|
| | case x > (y + z) : 2 * x / abs(y - z); |
|
||||||
|
| | case x < 3 : sin(x + y) |
|
||||||
|
| | default : 1 + x; |
|
||||||
|
| | } |
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| while | The structure will repeatedly evaluate the internal |
|
||||||
|
| | statement(s) 'while' the condition is true. The final |
|
||||||
|
| | statement in the final iteration will be used as the |
|
||||||
|
| | return value of the loop. |
|
||||||
|
| | eg: |
|
||||||
|
| | while ((x := (x - 1)) > 0) |
|
||||||
|
| | { |
|
||||||
|
| | y := x + z; |
|
||||||
|
| | w := z + y; |
|
||||||
|
| | } |
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| repeat/ | The structure will repeatedly evaluate the internal |
|
||||||
|
| until | statement(s) 'until' the condition is true. The final |
|
||||||
|
| | statement in the final iteration will be used as the |
|
||||||
|
| | return value of the loop. |
|
||||||
|
| | eg: |
|
||||||
|
| | repeat |
|
||||||
|
| | y := x + z; |
|
||||||
|
| | w := z + y; |
|
||||||
|
| | until ((x := (x - 1)) <= 0) |
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
| ~ | Evaluate each sub-expression, then return as the result|
|
||||||
|
| | the value of the last sub-expression. This is sometimes|
|
||||||
|
| | known as multiple sequence point evaluation. |
|
||||||
|
| | eg: |
|
||||||
|
| | ~(i := x + 1, j := y / z, k := sin(w/u)) == (sin(w/u)))|
|
||||||
|
| | ~{i := x + 1; j := y / z; k := sin(w/u)} == (sin(w/u)))|
|
||||||
|
+-----------+--------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[09 - SPECIAL FUNCTIONS]
|
[09 - SPECIAL FUNCTIONS]
|
||||||
|
|
Loading…
Reference in New Issue