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

This commit is contained in:
Arash Partow 2013-04-18 00:43:00 +10:00
parent 2a810cc9b4
commit e10cdcffcd
4 changed files with 215 additions and 77 deletions

View File

@ -1577,6 +1577,11 @@ namespace exprtk
return eof_token_;
}
inline bool finished() const
{
return (token_list_.end() == token_itr_);
}
private:
inline bool is_end(const char* itr)
@ -5610,7 +5615,7 @@ namespace exprtk
template <typename,typename> class Sequence>
static inline T process(const Sequence<Type,Allocator>& arglist)
{
if (arglist.size() > 5)
if (arglist.size() > 8)
{
if (arglist.empty())
return std::numeric_limits<T>::quiet_NaN();
@ -5632,6 +5637,9 @@ namespace exprtk
case 3 : return process_3(arglist);
case 4 : return process_4(arglist);
case 5 : return process_5(arglist);
case 6 : return process_6(arglist);
case 7 : return process_7(arglist);
case 8 : return process_8(arglist);
default : return std::numeric_limits<T>::quiet_NaN();
}
}
@ -5676,6 +5684,42 @@ namespace exprtk
value(arglist[3]);
return value(arglist[4]);
}
template <typename Sequence>
static inline T process_6(const Sequence& arglist)
{
value(arglist[0]);
value(arglist[1]);
value(arglist[2]);
value(arglist[3]);
value(arglist[4]);
return value(arglist[5]);
}
template <typename Sequence>
static inline T process_7(const Sequence& arglist)
{
value(arglist[0]);
value(arglist[1]);
value(arglist[2]);
value(arglist[3]);
value(arglist[4]);
value(arglist[5]);
return value(arglist[6]);
}
template <typename Sequence>
static inline T process_8(const Sequence& arglist)
{
value(arglist[0]);
value(arglist[1]);
value(arglist[2]);
value(arglist[3]);
value(arglist[4]);
value(arglist[5]);
value(arglist[6]);
return value(arglist[7]);
}
};
template <typename T>
@ -9472,7 +9516,7 @@ namespace exprtk
lexer_.begin();
next_token();
expression_node_ptr e = parse_expression();
expression_node_ptr e = parse_corpus();
if ((0 != e) && (token_t::e_eof == current_token_.type))
{
@ -9739,6 +9783,43 @@ namespace exprtk
current_token_ = lexer_.next_token();
}
inline expression_node_ptr parse_corpus()
{
std::deque<expression_node_ptr> arg_list;
expression_node_ptr result = error_node();
scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
do
{
expression_node_ptr arg = parse_expression();
if (0 == arg)
return error_node();
else
arg_list.push_back(arg);
if (!token_is(token_t::e_eof))
{
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR07 - Expected ';' at end of sub-expression."));
return error_node();
}
}
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);
sdd.delete_ptr = (0 == result);
return result;
}
static const precedence_level default_precedence = e_level00;
struct state_t
@ -10060,7 +10141,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR07 - Expecting argument list for function: '" + function_name + "'"));
"ERR08 - Expecting argument list for function: '" + function_name + "'"));
return error_node();
}
@ -10072,7 +10153,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR08 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
"ERR09 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
return error_node();
}
else if (i < static_cast<int>(NumberofParameters - 1))
@ -10082,7 +10163,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR09 - Invalid number of arguments for function: '" + function_name + "'"));
"ERR10 - Invalid number of arguments for function: '" + function_name + "'"));
return error_node();
}
}
@ -10093,7 +10174,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR10 - Invalid number of arguments for function: '" + function_name + "'"));
"ERR11 - Invalid number of arguments for function: '" + function_name + "'"));
return error_node();
}
else
@ -10112,7 +10193,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR11 - Expecting '()' to proceed: '" + function_name + "'"));
"ERR12 - Expecting '()' to proceed: '" + function_name + "'"));
return error_node();
}
else
@ -10129,7 +10210,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR12 - No entries found for base operation: " + operation_name));
"ERR13 - No entries found for base operation: " + operation_name));
return error_node();
}
@ -10152,7 +10233,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR13 - Impossible argument count for base function: " + operation_name));
"ERR14 - Impossible argument count for base function: " + operation_name));
return error_node();
}
@ -10173,7 +10254,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR14 - Invalid parameter count for function: " + operation_name));
"ERR15 - Invalid parameter count for function: " + operation_name));
return error_node();
}
@ -10193,7 +10274,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR15 - Failed to parse condition for if-statement"));
"ERR16 - Failed to parse condition for if-statement"));
return error_node();
}
else if (!token_is(token_t::e_comma))
@ -10203,7 +10284,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR16 - Failed to parse consequent for if-statement"));
"ERR17 - Failed to parse consequent for if-statement"));
return error_node();
}
else if (!token_is(token_t::e_comma))
@ -10213,7 +10294,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR17 - Failed to parse alternative for if-statement"));
"ERR18 - Failed to parse alternative for if-statement"));
return error_node();
}
else if (!token_is(token_t::e_rbracket))
@ -10235,23 +10316,20 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR18 - Failed to parse condition for while-loop"));
"ERR19 - Failed to parse condition for while-loop"));
return error_node();
}
else if (!token_is(token_t::e_rbracket))
return error_node();
else if (!token_is(token_t::e_lcrlbracket))
return error_node();
else if (0 == (branch = parse_expression()))
if (0 == (branch = parse_multi_sequence("while-loop")))
{
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR19 - Failed to parse branch for while-loop"));
"ERR20 - Failed to parse body of while-loop"));
return error_node();
}
else if (!token_is(token_t::e_rcrlbracket))
return error_node();
expression_node_ptr result;
if (0 == (result = expression_generator_.while_loop(condition,branch)))
@ -10259,7 +10337,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR20 - Failed to parse branch for while-loop"));
"ERR21 - Failed to synthesize while-loop"));
return error_node();
}
else
@ -10281,7 +10359,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR21 - Expected '{' for call to switch statement."));
"ERR22 - Expected '{' for call to switch statement."));
return error_node();
}
@ -10301,7 +10379,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR22 - Expected ':' for case of switch statement."));
"ERR23 - Expected ':' for case of switch statement."));
return error_node();
}
@ -10314,7 +10392,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR23 - Expected ';' at end of case for switch statement."));
"ERR24 - Expected ';' at end of case for switch statement."));
return error_node();
}
@ -10329,7 +10407,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR24 - Expected ':' for default of switch statement."));
"ERR25 - Expected ':' for default of switch statement."));
return error_node();
}
@ -10340,7 +10418,7 @@ namespace exprtk
{
set_error(make_error(parser_error::e_syntax,
current_token_,
"ERR25 - Expected ';' at end of default for switch statement."));
"ERR26 - Expected ';' at end of default for switch statement."));
return error_node();
}
@ -10354,7 +10432,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR26 - Expected '}' at end of switch statement."));
"ERR27 - Expected '}' at end of switch statement."));
return error_node();
}
@ -10372,20 +10450,24 @@ namespace exprtk
details::operator_type opt_type = details::e_default;
const std::string symbol = current_token_.value;
if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
if (details::imatch(symbol,"~"))
{
next_token();
return parse_multi_sequence();
}
else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg;
else if (details::imatch(symbol,"min" )) opt_type = details::e_min;
else if (details::imatch(symbol,"max" )) opt_type = details::e_max;
else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor;
else if (details::imatch(symbol,"~" )) opt_type = details::e_multi;
else
{
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR26 - Unsupported vararg function: " + symbol));
"ERR28 - Unsupported vararg function: " + symbol));
return error_node();
}
@ -10397,7 +10479,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR28 - Expected '(' for call to vararg function: " + symbol));
"ERR29 - Expected '(' for call to vararg function: " + symbol));
return error_node();
}
@ -10415,7 +10497,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR29 - Expected ',' for call to vararg function: " + symbol));
"ERR30 - Expected ',' for call to vararg function: " + symbol));
return error_node();
}
}
@ -10426,6 +10508,64 @@ namespace exprtk
return result;
}
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 seperator = token_t::e_eof;
if (!token_is(token_t::e_lcrlbracket))
{
if (token_is(token_t::e_lbracket))
{
close_bracket = token_t::e_rbracket;
seperator = token_t::e_comma;
}
else
{
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR31 - Expected '"+ details::to_str(close_bracket) + "' for call to multi-sequence" +
((!source.empty()) ? std::string(" section of " + source): "")));
return error_node();
}
}
std::deque<expression_node_ptr> arg_list;
expression_node_ptr result = error_node();
scoped_deq_delete<expression_node_t> sdd(*this,arg_list);
for (;;)
{
expression_node_ptr arg = parse_expression();
if (0 == arg)
return error_node();
else
arg_list.push_back(arg);
if (token_is(close_bracket))
break;
else if (!token_is(seperator))
{
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR32 - 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);
sdd.delete_ptr = (0 == result);
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;
@ -10441,7 +10581,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR30 - Expected '(' for call to vararg function: " + vararg_function_name));
"ERR33 - Expected '(' for call to vararg function: " + vararg_function_name));
return error_node();
}
@ -10459,7 +10599,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR31 - Expected ',' for call to vararg function: " + vararg_function_name));
"ERR34 - Expected ',' for call to vararg function: " + vararg_function_name));
return error_node();
}
}
@ -10520,7 +10660,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_token,
current_token_,
"ERR32 - Invalid special function[1]: " + current_token_.value));
"ERR35 - Invalid special function[1]: " + current_token_.value));
return error_node();
}
@ -10531,7 +10671,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_token,
current_token_,
"ERR33 - Invalid special function[2]: " + current_token_.value));
"ERR36 - Invalid special function[2]: " + current_token_.value));
return error_node();
}
@ -10623,7 +10763,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR34 - Invalid number of parameters for function: " + symbol));
"ERR37 - Invalid number of parameters for function: " + symbol));
return error_node();
}
}
@ -10635,7 +10775,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR35 - Failed to generate node for function: '" + symbol + "'"));
"ERR38 - Failed to generate node for function: '" + symbol + "'"));
return error_node();
}
}
@ -10655,7 +10795,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR36 - Failed to generate node for vararg function: '" + symbol + "'"));
"ERR39 - Failed to generate node for vararg function: '" + symbol + "'"));
return error_node();
}
}
@ -10664,7 +10804,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR37 - Undefined variable or function: '" + symbol + "'"));
"ERR40 - Undefined variable or function: '" + symbol + "'"));
return error_node();
}
}
@ -10713,7 +10853,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_symtab,
current_token_,
"ERR38 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
"ERR41 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token_.value));
return error_node();
}
}
@ -10788,7 +10928,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR39 - Premature end of expression.[1]"));
"ERR42 - Premature end of expression.[1]"));
return error_node();
}
else
@ -10796,7 +10936,7 @@ namespace exprtk
set_error(
make_error(parser_error::e_syntax,
current_token_,
"ERR40 - Premature end of expression.[2]"));
"ERR43 - Premature end of expression.[2]"));
return error_node();
}
}

View File

@ -33,21 +33,19 @@ void fibonacci()
compositor
.add("fibonacci_impl",
"switch "
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : "
" while (~(x := (x - 1)) > 0)"
" {~ "
" ( "
" w := z, "
" z := z + y, "
" y := w, "
" z "
" ) "
" }; "
"} ",
"switch "
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : "
" while ((x := (x - 1)) > 0)"
" { "
" w := z; "
" z := z + y; "
" y := w; "
" z "
" }; "
"} ",
"x","y","z","w");
compositor

View File

@ -3578,7 +3578,7 @@ inline bool run_test19()
"{ "
" switch "
" { "
" case y == 1 : ~(y := 0,true); "
" case y == 1 : ~(y := 0, true);"
" case (x % y) == 0 : ~(y := 0,false);"
" default : y := y - 1; "
" } "
@ -3718,20 +3718,18 @@ inline bool run_test19()
compositor
.add("fibonacci_impl3",
"switch "
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : while (~(x := (x - 1)) > 0)"
" {~ "
" ( "
" w := z, "
" z := z + y, "
" y := w, "
" z "
" ) "
" }; "
"} ",
"switch "
"{ "
" case x == 0 : 0; "
" case x == 1 : 1; "
" default : while ((x := (x - 1)) > 0)"
" { "
" w := z; "
" z := z + y; "
" y := w; "
" z "
" }; "
"} ",
"x","y","z","w");
compositor

View File

@ -277,9 +277,11 @@ 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 known as |
| | multiple sequence point evaluation. |
| | (eg: ~(x+1,y/z,abs(y^3),sin(w/u)) == (sin(w/u))) |
| | 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
@ -467,7 +469,7 @@ correctly optimize such expressions for a given architecture.
compile time: exprtk_disable_string_capabilities
(16) Composited functions can call themselves or any other functions
that have been previously defined.
that have been defined prior to their own definition.
(17) Expressions may contain any of the following comment styles:
1. // .... \n