C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
37324fc51b
commit
f14ec583ae
579
exprtk.hpp
579
exprtk.hpp
|
@ -228,8 +228,8 @@ namespace exprtk
|
|||
static const std::string reserved_words[] =
|
||||
{
|
||||
"and", "default", "case", "false", "for", "if", "ilike", "in", "like",
|
||||
"nand", "nor", "not", "null", "or", "shl", "shr", "switch", "true",
|
||||
"while", "xnor", "xor", "&", "|"
|
||||
"nand", "nor", "not", "null", "or", "repeat", "shl", "shr", "switch",
|
||||
"true", "until", "while", "xnor", "xor", "&", "|"
|
||||
};
|
||||
|
||||
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",
|
||||
"hypot", "if", "ilike", "in", "inrange", "like", "log", "log10", "log2",
|
||||
"logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "nand", "nor",
|
||||
"not", "not_equal", "null", "or", "pow", "rad2deg", "root", "round", "roundn",
|
||||
"sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "switch", "tan",
|
||||
"tanh", "true", "trunc", "while", "xnor", "xor", "&", "|"
|
||||
"not", "not_equal", "null", "or", "pow", "rad2deg", "repeat", "root", "round",
|
||||
"roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "switch",
|
||||
"tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor", "&", "|"
|
||||
};
|
||||
|
||||
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
|
||||
should provide enough information to make the right choice.
|
||||
*/
|
||||
//typedef T Type
|
||||
//typedef const T Type
|
||||
//typedef T Type;
|
||||
//typedef const T Type;
|
||||
typedef const T& Type;
|
||||
typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
|
||||
typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
|
||||
|
@ -1314,39 +1314,17 @@ namespace exprtk
|
|||
|
||||
enum token_type
|
||||
{
|
||||
e_none = 0,
|
||||
e_error = 1,
|
||||
e_err_symbol = 2,
|
||||
e_err_number = 3,
|
||||
e_err_string = 4,
|
||||
e_err_sfunc = 5,
|
||||
e_eof = 6,
|
||||
e_number = 7,
|
||||
e_symbol = 8,
|
||||
e_string = 9,
|
||||
e_assign = 10,
|
||||
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 = ':'
|
||||
e_none = 0, e_error = 1, e_err_symbol = 2,
|
||||
e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
|
||||
e_eof = 6, e_number = 7, e_symbol = 8,
|
||||
e_string = 9, e_assign = 10, 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()
|
||||
|
@ -1423,7 +1401,7 @@ namespace exprtk
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline std::string to_str(token_type t) const
|
||||
static inline std::string to_str(token_type t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
|
@ -1561,6 +1539,16 @@ namespace exprtk
|
|||
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)
|
||||
{
|
||||
if (index < token_list_.size())
|
||||
|
@ -3002,29 +2990,29 @@ namespace exprtk
|
|||
e_none , e_null , e_constant , e_unary ,
|
||||
e_binary , e_binary_ext , e_trinary , e_quaternary ,
|
||||
e_quinary , e_senary , e_vararg , e_conditional ,
|
||||
e_while , e_switch , e_variable , e_stringvar ,
|
||||
e_stringconst , e_function , e_vafunction , e_add ,
|
||||
e_sub , e_mul , e_div , e_mod ,
|
||||
e_pow , e_lt , e_lte , e_gt ,
|
||||
e_gte , e_eq , e_ne , e_and ,
|
||||
e_nand , e_or , e_nor , e_xor ,
|
||||
e_xnor , e_in , e_like , e_ilike ,
|
||||
e_inranges , e_ipow , e_ipowinv , e_abs ,
|
||||
e_acos , e_asin , e_atan , e_ceil ,
|
||||
e_cos , e_cosh , e_exp , e_floor ,
|
||||
e_log , e_log10 , e_log2 , e_log1p ,
|
||||
e_neg , e_pos , e_round , e_sin ,
|
||||
e_sinh , e_sqrt , e_tan , e_tanh ,
|
||||
e_cot , e_sec , e_csc , e_r2d ,
|
||||
e_d2r , e_d2g , e_g2d , e_notl ,
|
||||
e_sgn , e_erf , e_erfc , e_frac ,
|
||||
e_trunc , e_uvouv , e_vov , e_cov ,
|
||||
e_voc , e_vob , e_bov , e_cob ,
|
||||
e_boc , e_vovov , e_vovoc , e_vocov ,
|
||||
e_covov , e_covoc , e_vovovov , e_vovovoc ,
|
||||
e_vovocov , e_vocovov , e_covovov , e_covocov ,
|
||||
e_vocovoc , e_covovoc , e_vococov , e_sf3ext ,
|
||||
e_sf4ext
|
||||
e_while , e_repeat , e_switch , e_variable ,
|
||||
e_stringvar , e_stringconst , e_function , e_vafunction ,
|
||||
e_add , e_sub , e_mul , e_div ,
|
||||
e_mod , e_pow , e_lt , e_lte ,
|
||||
e_gt , e_gte , e_eq , e_ne ,
|
||||
e_and , e_nand , e_or , e_nor ,
|
||||
e_xor , e_xnor , e_in , e_like ,
|
||||
e_ilike , e_inranges , e_ipow , e_ipowinv ,
|
||||
e_abs , e_acos , e_asin , e_atan ,
|
||||
e_ceil , e_cos , e_cosh , e_exp ,
|
||||
e_floor , e_log , e_log10 , e_log2 ,
|
||||
e_log1p , e_neg , e_pos , e_round ,
|
||||
e_sin , e_sinh , e_sqrt , e_tan ,
|
||||
e_tanh , e_cot , e_sec , e_csc ,
|
||||
e_r2d , e_d2r , e_d2g , e_g2d ,
|
||||
e_notl , e_sgn , e_erf , e_erfc ,
|
||||
e_frac , e_trunc , e_uvouv , e_vov ,
|
||||
e_cov , e_voc , e_vob , e_bov ,
|
||||
e_cob , e_boc , e_vovov , e_vovoc ,
|
||||
e_vocov , e_covov , e_covoc , e_vovovov ,
|
||||
e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
|
||||
e_covocov , e_vocovoc , e_covovoc , e_vococov ,
|
||||
e_sf3ext , e_sf4ext
|
||||
};
|
||||
|
||||
typedef T value_type;
|
||||
|
@ -3762,8 +3750,7 @@ namespace exprtk
|
|||
|
||||
typedef expression_node<T>* expression_ptr;
|
||||
|
||||
while_loop_node(expression_ptr test,
|
||||
expression_ptr branch)
|
||||
while_loop_node(expression_ptr test, expression_ptr branch)
|
||||
: test_(test),
|
||||
branch_(branch),
|
||||
test_deletable_(!is_variable_node(test_)),
|
||||
|
@ -3799,6 +3786,50 @@ namespace exprtk
|
|||
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>
|
||||
class switch_node : public expression_node<T>
|
||||
{
|
||||
|
@ -4369,12 +4400,13 @@ namespace exprtk
|
|||
assignment_node(const operator_type& operation,
|
||||
expression_ptr branch0,
|
||||
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
|
||||
{
|
||||
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);
|
||||
if (var_node_ptr)
|
||||
|
@ -4386,6 +4418,10 @@ namespace exprtk
|
|||
}
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool is_lefthand_variable_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -9341,6 +9377,8 @@ namespace exprtk
|
|||
typedef details::senary_node <T> senary_node_t;
|
||||
typedef details::conditional_node<T> conditional_node_t;
|
||||
typedef details::while_loop_node <T> while_loop_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
|
||||
typedef details::stringvar_node <T> stringvar_node_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, cref_t,const_t,const_t, cref_t> vococov_t;
|
||||
|
||||
struct range_pack;
|
||||
|
||||
public:
|
||||
|
||||
enum precompilation_step
|
||||
|
@ -9847,12 +9887,7 @@ namespace exprtk
|
|||
}
|
||||
while (!lexer_.finished());
|
||||
|
||||
if (arg_list.empty())
|
||||
return error_node();
|
||||
else if (arg_list.size() == 1)
|
||||
result = arg_list[0];
|
||||
else
|
||||
result = expression_generator_.vararg_function(details::e_multi,arg_list);
|
||||
result = simplify(arg_list);
|
||||
|
||||
sdd.delete_ptr = (0 == result);
|
||||
return result;
|
||||
|
@ -10382,6 +10417,88 @@ namespace exprtk
|
|||
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()
|
||||
{
|
||||
std::vector<expression_node_ptr> arg_list;
|
||||
|
@ -10397,7 +10514,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR22 - Expected '{' for call to switch statement."));
|
||||
"ERR26 - Expected '{' for call to switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10417,7 +10534,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR23 - Expected ':' for case of switch statement."));
|
||||
"ERR27 - Expected ':' for case of switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10430,7 +10547,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR24 - Expected ';' at end of case for switch statement."));
|
||||
"ERR28 - Expected ';' at end of case for switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10445,7 +10562,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR25 - Expected ':' for default of switch statement."));
|
||||
"ERR29 - Expected ':' for default of switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10456,7 +10573,7 @@ namespace exprtk
|
|||
{
|
||||
set_error(make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR26 - Expected ';' at end of default for switch statement."));
|
||||
"ERR30 - Expected ';' at end of default for switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10470,7 +10587,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR27 - Expected '}' at end of switch statement."));
|
||||
"ERR31 - Expected '}' at end of switch statement."));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10505,7 +10622,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR28 - Unsupported vararg function: " + symbol));
|
||||
"ERR32 - Unsupported vararg function: " + symbol));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10517,7 +10634,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR29 - Expected '(' for call to vararg function: " + symbol));
|
||||
"ERR33 - Expected '(' for call to vararg function: " + symbol));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10535,7 +10652,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR30 - Expected ',' for call to vararg function: " + symbol));
|
||||
"ERR34 - Expected ',' for call to vararg function: " + symbol));
|
||||
return error_node();
|
||||
}
|
||||
}
|
||||
|
@ -10546,6 +10663,35 @@ namespace exprtk
|
|||
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 = "")
|
||||
{
|
||||
token_t::token_type close_bracket = token_t::e_rcrlbracket;
|
||||
|
@ -10563,7 +10709,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
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): "")));
|
||||
return error_node();
|
||||
}
|
||||
|
@ -10583,27 +10729,202 @@ namespace exprtk
|
|||
arg_list.push_back(arg);
|
||||
if (token_is(close_bracket))
|
||||
break;
|
||||
else if (!token_is(seperator))
|
||||
|
||||
bool is_next_close = peek_token_is(close_bracket);
|
||||
|
||||
if (!token_is(seperator) && is_next_close)
|
||||
{
|
||||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_list.empty())
|
||||
return error_node();
|
||||
else if (arg_list.size() == 1)
|
||||
result = arg_list[0];
|
||||
else
|
||||
result = expression_generator_.vararg_function(details::e_multi,arg_list);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<bool,expression_node_ptr> n0_e;
|
||||
std::pair<bool,expression_node_ptr> n1_e;
|
||||
std::pair<bool,std::size_t > n0_c;
|
||||
std::pair<bool,std::size_t > n1_c;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
|
||||
{
|
||||
std::vector<expression_node_ptr> arg_list;
|
||||
|
@ -10619,7 +10940,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -10637,7 +10958,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -10698,7 +11019,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_token,
|
||||
current_token_,
|
||||
"ERR35 - Invalid special function[1]: " + current_token_.value));
|
||||
"ERR44 - Invalid special function[1]: " + current_token_.value));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10709,7 +11030,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_token,
|
||||
current_token_,
|
||||
"ERR36 - Invalid special function[2]: " + current_token_.value));
|
||||
"ERR45 - Invalid special function[2]: " + current_token_.value));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10752,19 +11073,9 @@ namespace exprtk
|
|||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
// Are we dealing with a string variable?
|
||||
variable = symbol_table_.get_stringvar(symbol);
|
||||
if (variable)
|
||||
if (symbol_table_.is_stringvar(symbol))
|
||||
{
|
||||
if (symbol_name_caching_)
|
||||
{
|
||||
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;
|
||||
return parse_string();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10801,7 +11112,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR37 - Invalid number of parameters for function: " + symbol));
|
||||
"ERR46 - Invalid number of parameters for function: " + symbol));
|
||||
return error_node();
|
||||
}
|
||||
}
|
||||
|
@ -10813,7 +11124,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR38 - Failed to generate node for function: '" + symbol + "'"));
|
||||
"ERR47 - Failed to generate node for function: '" + symbol + "'"));
|
||||
return error_node();
|
||||
}
|
||||
}
|
||||
|
@ -10833,7 +11144,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR39 - Failed to generate node for vararg function: '" + symbol + "'"));
|
||||
"ERR48 - Failed to generate node for vararg function: '" + symbol + "'"));
|
||||
return error_node();
|
||||
}
|
||||
}
|
||||
|
@ -10880,7 +11191,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_symtab,
|
||||
current_token_,
|
||||
"ERR40 - Failed to create variable: '" + symbol + "'"));
|
||||
"ERR49 - Failed to create variable: '" + symbol + "'"));
|
||||
|
||||
return error_node();
|
||||
}
|
||||
|
@ -10889,7 +11200,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR41 - Undefined variable or function: '" + symbol + "'"));
|
||||
"ERR50 - Undefined variable or function: '" + symbol + "'"));
|
||||
return error_node();
|
||||
}
|
||||
|
||||
|
@ -10897,6 +11208,7 @@ namespace exprtk
|
|||
{
|
||||
static const std::string symbol_if = "if";
|
||||
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_null = "null";
|
||||
|
||||
|
@ -10916,6 +11228,10 @@ namespace exprtk
|
|||
{
|
||||
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))
|
||||
{
|
||||
return parse_switch_statement();
|
||||
|
@ -10937,7 +11253,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_symtab,
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -11012,7 +11328,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR42 - Premature end of expression.[1]"));
|
||||
"ERR52 - Premature end of expression.[1]"));
|
||||
return error_node();
|
||||
}
|
||||
else
|
||||
|
@ -11020,7 +11336,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token_,
|
||||
"ERR43 - Premature end of expression.[2]"));
|
||||
"ERR53 - Premature end of expression.[2]"));
|
||||
return error_node();
|
||||
}
|
||||
}
|
||||
|
@ -11035,6 +11351,11 @@ namespace exprtk
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool peek_token_is(const typename token_t::token_type& ttype)
|
||||
{
|
||||
return (lexer_.peek_next_token().type == ttype);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
class expression_generator
|
||||
{
|
||||
|
@ -11641,6 +11962,30 @@ namespace exprtk
|
|||
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,typename> class Sequence>
|
||||
inline expression_node_ptr const_optimize_switch(Sequence<expression_node_ptr,Allocator>& arglist)
|
||||
|
|
|
@ -50,11 +50,10 @@ void newton_sqrt()
|
|||
" ~{ "
|
||||
" z := 100; "
|
||||
" y := x / 2; "
|
||||
" while ((z := (z - 1)) > 0) "
|
||||
" { "
|
||||
" repeat "
|
||||
" 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");
|
||||
|
|
|
@ -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)] : {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);
|
||||
|
@ -3737,6 +3745,27 @@ inline bool run_test19()
|
|||
"fibonacci_impl3(x,0,1,0)",
|
||||
"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();
|
||||
symbol_table.add_constants();
|
||||
|
@ -3745,13 +3774,16 @@ inline bool run_test19()
|
|||
std::string expression_str1 = "fibonacci1(x)";
|
||||
std::string expression_str2 = "fibonacci2(x)";
|
||||
std::string expression_str3 = "fibonacci3(x)";
|
||||
std::string expression_str4 = "fibonacci4(x)";
|
||||
|
||||
expression_t expression1;
|
||||
expression_t expression2;
|
||||
expression_t expression3;
|
||||
expression_t expression4;
|
||||
expression1.register_symbol_table(symbol_table);
|
||||
expression2.register_symbol_table(symbol_table);
|
||||
expression3.register_symbol_table(symbol_table);
|
||||
expression4.register_symbol_table(symbol_table);
|
||||
|
||||
exprtk::parser<T> parser;
|
||||
|
||||
|
@ -3779,6 +3811,14 @@ inline bool run_test19()
|
|||
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;
|
||||
|
||||
const std::size_t fibonacci_list[] =
|
||||
|
@ -3800,28 +3840,43 @@ inline bool run_test19()
|
|||
T result1 = expression1.value();
|
||||
T result2 = expression2.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 "
|
||||
"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>(fibonacci_list[i]),
|
||||
expression_str1.c_str(),
|
||||
static_cast<unsigned int>(result1),
|
||||
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;
|
||||
}
|
||||
|
||||
if (fibonacci_list[i] != expression1.value())
|
||||
{
|
||||
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>(fibonacci_list[i]),
|
||||
expression_str1.c_str(),
|
||||
static_cast<unsigned int>(result1),
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -3923,7 +3978,7 @@ struct my_usr : public exprtk::parser<T>::unknown_symbol_resolver
|
|||
error_message = "";
|
||||
return true;
|
||||
}
|
||||
else if (unknown_symbol[0] == 'w')
|
||||
else if (unknown_symbol[0] == 'c')
|
||||
{
|
||||
st = usr_t::e_constant_type;
|
||||
default_value = next_value();
|
||||
|
@ -3966,13 +4021,13 @@ inline bool run_test20()
|
|||
musr.next_value(true);
|
||||
parser.enable_unknown_symbol_resolver(&musr);
|
||||
|
||||
std::string expr_str = "v01+w02+v03+w04+v05+w06+v07+w08+v09+w10+"
|
||||
"v11+w12+v13+w14+v15+w16+v17+w18+v19+w20+"
|
||||
"v21+w22+v23+w24+v25+w26+v27+w28+v29+w30";
|
||||
std::string expr_str = "v01+c02+v03+c04+v05+c06+v07+c08+v09+c10+"
|
||||
"v11+c12+v13+c14+v15+c16+v17+c18+v19+c20+"
|
||||
"v21+c22+v23+c24+v25+c26+v27+c28+v29+c30 ";
|
||||
|
||||
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(),
|
||||
expr_str.c_str());
|
||||
return false;
|
||||
|
|
82
readme.txt
82
readme.txt
|
@ -10,7 +10,7 @@ very easily extendible.
|
|||
|
||||
|
||||
[01 - CAPABILITIES]
|
||||
The ExprTk evaluator supports the following fundamental mathematical
|
||||
The ExprTk evaluator supports the following fundamental arithmetic
|
||||
operations, functions and processes:
|
||||
|
||||
(0) Basic operators: +, -, *, /, %, ^
|
||||
|
@ -114,7 +114,7 @@ include path (e.g: /usr/include/).
|
|||
|
||||
[08 - BUILT-IN OPERATIONS & FUNCTIONS]
|
||||
|
||||
(0) Basic Operators
|
||||
(0) Arithmetic Operators
|
||||
+-----------+--------------------------------------------------------+
|
||||
| OPERATOR | DEFINITION |
|
||||
+-----------+--------------------------------------------------------+
|
||||
|
@ -158,14 +158,14 @@ include path (e.g: /usr/include/).
|
|||
| true | True state or any value other than zero (typically 1). |
|
||||
+-----------+--------------------------------------------------------+
|
||||
| false | False state, value of zero. |
|
||||
+-----------|--------------------------------------------------------+
|
||||
+-----------+--------------------------------------------------------+
|
||||
| and | Logical AND, True only if x and y are both true. |
|
||||
| | (eg: x and y) |
|
||||
+-----------+--------------------------------------------------------+
|
||||
| mand | Multi-input logical AND, True only if all inputs are |
|
||||
| | true. Left to right short-circuiting of expressions. |
|
||||
| | (eg: mand(x > y,z < w,u or v,w and x)) |
|
||||
+-----------|--------------------------------------------------------+
|
||||
+-----------+--------------------------------------------------------+
|
||||
| mor | Multi-input logical OR, True if at least one of the |
|
||||
| | inputs are true. Left to right short-circuiting of |
|
||||
| | 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 |
|
||||
| | 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 |
|
||||
| | circuiting optimisation. (eg: (x & y) == (y and x)) |
|
||||
+-----------|--------------------------------------------------------+
|
||||
+-----------+--------------------------------------------------------+
|
||||
| | | Similar to OR but with left to right expression short |
|
||||
| | circuiting optimisation. (eg: (x | y) == (y or x)) |
|
||||
+-----------+--------------------------------------------------------+
|
||||
|
@ -276,13 +260,6 @@ include path (e.g: /usr/include/).
|
|||
+-----------+--------------------------------------------------------+
|
||||
| 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
|
||||
+-----------+--------------------------------------------------------+
|
||||
|
@ -342,6 +319,55 @@ include path (e.g: /usr/include/).
|
|||
| | (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]
|
||||
|
|
Loading…
Reference in New Issue