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

This commit is contained in:
Arash Partow 2013-04-27 13:55:23 +10:00
parent 37324fc51b
commit f14ec583ae
4 changed files with 624 additions and 199 deletions

View File

@ -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)

View File

@ -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");

View File

@ -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;

View File

@ -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]