C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
ebf3f14ca6
commit
e105e6278c
754
exprtk.hpp
754
exprtk.hpp
File diff suppressed because it is too large
Load Diff
|
@ -4617,6 +4617,11 @@ struct gen_func2 : public exprtk::igeneric_function<T>
|
||||||
{
|
{
|
||||||
return T(0);
|
return T(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline T operator()(const std::size_t&, parameter_list_t params)
|
||||||
|
{
|
||||||
|
return this->operator()(params);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -4670,6 +4675,11 @@ struct inc_func : public exprtk::igeneric_function<T>
|
||||||
|
|
||||||
return T(0);
|
return T(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline T operator()(const std::size_t&, parameter_list_t params)
|
||||||
|
{
|
||||||
|
return this->operator()(params);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -4700,6 +4710,14 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function<T>
|
||||||
|
|
||||||
return T(0);
|
return T(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline T operator()(const std::size_t& param_seq_index, std::string& result, parameter_list_t params)
|
||||||
|
{
|
||||||
|
if (1 == param_seq_index)
|
||||||
|
return this->operator()(result,params);
|
||||||
|
else
|
||||||
|
return T(0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -4849,7 +4867,7 @@ inline bool run_test18()
|
||||||
|
|
||||||
if (!parser.compile(expression_list[i],expression))
|
if (!parser.compile(expression_list[i],expression))
|
||||||
{
|
{
|
||||||
printf("run_test18() - GenFunc Error: %s Expression: %s\n",
|
printf("run_test18() - GenFunc Error: %s Expression: %s [2]\n",
|
||||||
parser.error().c_str(),
|
parser.error().c_str(),
|
||||||
expression_list[i].c_str());
|
expression_list[i].c_str());
|
||||||
|
|
||||||
|
@ -4925,7 +4943,18 @@ inline bool run_test18()
|
||||||
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);",
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(2w / 3, 'abc123',s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z);",
|
||||||
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);",
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo('abc123', s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3);",
|
||||||
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');",
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');",
|
||||||
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:3]+s0[4:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');"
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(s0[2:3]+s0[4:5],v0, v1 + v2, v0[2], x, 2x + y, z,2w / 3, 'abc123');",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);",
|
||||||
|
"var z := 3; var w[3] := { 1/3, 1/5, 1/7 }; foo(v0,v1 + v2, v0[2], x, 2x + y, z, 2w / 3, 'abc123',s0[2:5]);"
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||||
|
@ -4942,6 +4971,14 @@ inline bool run_test18()
|
||||||
"SSVVTTTTV",
|
"SSVVTTTTV",
|
||||||
"SVVTTTTVS",
|
"SVVTTTTVS",
|
||||||
"SVVTTTTVS",
|
"SVVTTTTVS",
|
||||||
|
"V*T*VS*" ,
|
||||||
|
"V*TTTTVSS",
|
||||||
|
"VVT*VSS" ,
|
||||||
|
"VVTTTTVS*",
|
||||||
|
"TTTTTTT|STSTSTS|V*T*VS*" ,
|
||||||
|
"TTTTTTT|STSTSTS|V*TTTTVSS",
|
||||||
|
"TTTTTTT|STSTSTS|VVT*VSS" ,
|
||||||
|
"TTTTTTT|STSTSTS|VVTTTTVS*"
|
||||||
};
|
};
|
||||||
|
|
||||||
bool failure = false;
|
bool failure = false;
|
||||||
|
@ -4958,7 +4995,7 @@ inline bool run_test18()
|
||||||
|
|
||||||
if (!parser.compile(expression_list[i],expression))
|
if (!parser.compile(expression_list[i],expression))
|
||||||
{
|
{
|
||||||
printf("run_test18() - GenFunc2 Error: %s Expression: %s Parameter Sequence: %s\n",
|
printf("run_test18() - GenFunc2 Error: %s Expression: %s Parameter Sequence: %s [3]\n",
|
||||||
parser.error().c_str(),
|
parser.error().c_str(),
|
||||||
expression_list[i].c_str(),
|
expression_list[i].c_str(),
|
||||||
parameter_type_list[i].c_str());
|
parameter_type_list[i].c_str());
|
||||||
|
@ -5049,7 +5086,7 @@ inline bool run_test18()
|
||||||
|
|
||||||
if (!parser.compile(expression_list[i],expression))
|
if (!parser.compile(expression_list[i],expression))
|
||||||
{
|
{
|
||||||
printf("run_test18() - IncFunc Error: %s Expression: %s Parameter Sequence: %s\n",
|
printf("run_test18() - IncFunc Error: %s Expression: %s Parameter Sequence: %s [4]\n",
|
||||||
parser.error().c_str(),
|
parser.error().c_str(),
|
||||||
expression_list[i].c_str(),
|
expression_list[i].c_str(),
|
||||||
parameter_type_list[i].c_str());
|
parameter_type_list[i].c_str());
|
||||||
|
@ -5141,12 +5178,29 @@ inline bool run_test18()
|
||||||
" s4 := s0 + remspc_uc(s1); "
|
" s4 := s0 + remspc_uc(s1); "
|
||||||
" remspc_uc(s0 + s1) == remspc_uc(s0) + remspc_uc(s1);";
|
" remspc_uc(s0 + s1) == remspc_uc(s0) + remspc_uc(s1);";
|
||||||
|
|
||||||
|
std::string parameter_type_list[] =
|
||||||
|
{
|
||||||
|
"VVVTTT|S",
|
||||||
|
"VVTTTV|S",
|
||||||
|
"VTTTVV|S",
|
||||||
|
"TTTVVV|S",
|
||||||
|
"TTVVVT|S",
|
||||||
|
"TVVVTT|S"
|
||||||
|
};
|
||||||
|
|
||||||
|
std::size_t parameter_type_list_size = sizeof(parameter_type_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < parameter_type_list_size; ++i)
|
||||||
|
{
|
||||||
expression_t expression;
|
expression_t expression;
|
||||||
|
|
||||||
expression.register_symbol_table(symbol_table);
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
parser_t parser;
|
parser_t parser;
|
||||||
|
|
||||||
|
rsauc.parameter_sequence = parameter_type_list[i];
|
||||||
|
|
||||||
if (!parser.compile(program,expression))
|
if (!parser.compile(program,expression))
|
||||||
{
|
{
|
||||||
printf("Error: %s\tExpression: %s\n",
|
printf("Error: %s\tExpression: %s\n",
|
||||||
|
@ -5206,6 +5260,7 @@ inline bool run_test18()
|
||||||
program.c_str());
|
program.c_str());
|
||||||
failure = true;
|
failure = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (failure)
|
if (failure)
|
||||||
return false;
|
return false;
|
||||||
|
|
180
readme.txt
180
readme.txt
|
@ -1253,16 +1253,37 @@ Compile-time type checking of input parameters can be requested by
|
||||||
passing a string to the constructor of the igeneric_function that
|
passing a string to the constructor of the igeneric_function that
|
||||||
represents the required sequence of parameter types. When no parameter
|
represents the required sequence of parameter types. When no parameter
|
||||||
sequence is provided, it is implied the function can accept a variable
|
sequence is provided, it is implied the function can accept a variable
|
||||||
number of parameters comprised of any of the fundemental types. The
|
number of parameters comprised of any of the fundamental types.
|
||||||
following example demonstrates how this can be achieved:
|
|
||||||
|
Each fundamental type has an associated character. The following is a
|
||||||
|
listing of said characters and their meanings:
|
||||||
|
|
||||||
|
(1) T - Scalar
|
||||||
|
(2) V - Vector
|
||||||
|
(3) S - String
|
||||||
|
(4) ? - Any type (Scalar, Vector or String)
|
||||||
|
(5) * - Wildcard operator
|
||||||
|
(6) | - Parameter sequence delimiter
|
||||||
|
|
||||||
|
|
||||||
|
No other characters other than the six denoted above may be included
|
||||||
|
in the parameter sequence definition. If any such invalid characters
|
||||||
|
do exist, registration of the associated generic function to a symbol
|
||||||
|
table ('add_function' method) will fail. If the parameter sequence is
|
||||||
|
modified resulting in it becoming invalid after having been added to
|
||||||
|
the symbol table but before the compilation step, a compilation error
|
||||||
|
will be incurred.
|
||||||
|
|
||||||
|
The following example demonstrates a simple generic function
|
||||||
|
implementation with a user specified parameter sequence:
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct too : public exprtk::igeneric_function<T>
|
struct moo : public exprtk::igeneric_function<T>
|
||||||
{
|
{
|
||||||
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
||||||
parameter_list_t;
|
parameter_list_t;
|
||||||
|
|
||||||
too()
|
moo()
|
||||||
: exprtk::igeneric_function<T>("SVTT")
|
: exprtk::igeneric_function<T>("SVTT")
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -1273,45 +1294,13 @@ following example demonstrates how this can be achieved:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
In the example above the custom generic function 'too' expects
|
In the example above the generic function 'moo' expects exactly four
|
||||||
exactly four parameters in the following sequence:
|
|
||||||
|
|
||||||
(a) String
|
|
||||||
(b) Vector
|
|
||||||
(c) Scalar
|
|
||||||
(d) Scalar
|
|
||||||
|
|
||||||
|
|
||||||
One further refinement to the type checking facility is the
|
|
||||||
possibility of a variable number of trailing common types which can be
|
|
||||||
accomplished by using a wildcard '*' at the end of the sequence
|
|
||||||
definition.
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct too : public exprtk::igeneric_function<T>
|
|
||||||
{
|
|
||||||
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
|
||||||
parameter_list_t;
|
|
||||||
|
|
||||||
too()
|
|
||||||
: exprtk::igeneric_function<T>("SVTTV*")
|
|
||||||
{}
|
|
||||||
|
|
||||||
inline T operator()(parameter_list_t parameters)
|
|
||||||
{
|
|
||||||
...
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
In the example above the generic function 'too' expects at least five
|
|
||||||
parameters in the following sequence:
|
parameters in the following sequence:
|
||||||
|
|
||||||
(a) String
|
(1) String
|
||||||
(b) Vector
|
(2) Vector
|
||||||
(c) Scalar
|
(3) Scalar
|
||||||
(d) Scalar
|
(4) Scalar
|
||||||
(e) One or more Vectors
|
|
||||||
|
|
||||||
|
|
||||||
(4) igeneric_function II
|
(4) igeneric_function II
|
||||||
|
@ -1326,7 +1315,7 @@ situations such as concatenation and equality operations.
|
||||||
|
|
||||||
|
|
||||||
The following example defines an generic function named 'toupper' with
|
The following example defines an generic function named 'toupper' with
|
||||||
the string return type function operator being explicitly overriden:
|
the string return type function operator being explicitly overridden:
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct toupper : public exprtk::igeneric_function<T>
|
struct toupper : public exprtk::igeneric_function<T>
|
||||||
|
@ -1357,9 +1346,13 @@ In the example above the generic function 'toupper' expects only one
|
||||||
input parameter of type string, as noted by the parameter sequence
|
input parameter of type string, as noted by the parameter sequence
|
||||||
string passed during the constructor. When executed, the function will
|
string passed during the constructor. When executed, the function will
|
||||||
return as a result a copy of the input string converted to uppercase
|
return as a result a copy of the input string converted to uppercase
|
||||||
form.
|
form. An example expression using the toupper function registered as
|
||||||
|
the symbol 'toupper' is as follows:
|
||||||
|
|
||||||
When adding a string type returning generic function to a symbol
|
"'ABCDEF' == toupper('aBc') + toupper('DeF')"
|
||||||
|
|
||||||
|
|
||||||
|
Note: When adding a string type returning generic function to a symbol
|
||||||
table, the 'add_function' is invoked with an extra parameter
|
table, the 'add_function' is invoked with an extra parameter
|
||||||
(e_ft_strfunc) that denotes the function should be treated as a string
|
(e_ft_strfunc) that denotes the function should be treated as a string
|
||||||
returning function type. The following example demonstrates how this
|
returning function type. The following example demonstrates how this
|
||||||
|
@ -1374,6 +1367,99 @@ is done:
|
||||||
symbol_table_t::e_ft_strfunc);
|
symbol_table_t::e_ft_strfunc);
|
||||||
|
|
||||||
|
|
||||||
|
Note: There are two further refinements to the type checking facility
|
||||||
|
are the possibilities of a variable number of common types which can
|
||||||
|
be accomplished by using a wildcard '*' and a special 'any type' which
|
||||||
|
is done using the '?' character. It should be noted that the wildcard
|
||||||
|
operator is associated with the previous type in the sequence and
|
||||||
|
implies one or more of that type.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct zoo : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
||||||
|
parameter_list_t;
|
||||||
|
|
||||||
|
zoo()
|
||||||
|
: exprtk::igeneric_function<T>("SVT*V?")
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t parameters)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
In the example above the generic function 'zoo' expects at least five
|
||||||
|
parameters in the following sequence:
|
||||||
|
|
||||||
|
(1) String
|
||||||
|
(2) Vector
|
||||||
|
(3) One or more Scalars
|
||||||
|
(4) Vector
|
||||||
|
(5) Any type (one type of either a scalar, vector or string)
|
||||||
|
|
||||||
|
|
||||||
|
A final piece of type checking functionality is available for the
|
||||||
|
scenarios where a single function name is intended to be used for
|
||||||
|
multiple distinct parameter sequences. Two specific overrides of the
|
||||||
|
function operator are provided one for standard generic functions and
|
||||||
|
one for string returning functions. The overrides are as follows:
|
||||||
|
|
||||||
|
// f(psi,i_0,i_1,....,i_N) --> Scalar
|
||||||
|
inline T operator()(const std::size_t& ps_index,
|
||||||
|
parameter_list_t parameters)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// f(psi,i_0,i_1,....,i_N) --> String
|
||||||
|
inline T operator()(const std::size_t& ps_index,
|
||||||
|
std::string& result,
|
||||||
|
parameter_list_t parameters)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
When the function operator is invoked the 'ps_index' parameter will
|
||||||
|
have as its value the index of the parameter sequence that matches the
|
||||||
|
specific invocation. This way complex and time consuming type checking
|
||||||
|
conditions need not be executed in the function itself but rather a
|
||||||
|
simple and efficient dispatch to a specific implementation for that
|
||||||
|
particular parameter sequence can be performed.
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct roo : public exprtk::igeneric_function<T>
|
||||||
|
{
|
||||||
|
typedef typename exprtk::igeneric_function<T>::parameter_list_t
|
||||||
|
parameter_list_t;
|
||||||
|
|
||||||
|
moo()
|
||||||
|
: exprtk::igeneric_function<T>("SVTT|SS|TTV|S?V*S")
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(parameter_list_t parameters)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
In the above example there are four distinct parameter sequences that
|
||||||
|
can be processed by the generic function 'roo'. Any other parameter
|
||||||
|
sequences will cause a compilation error. The valid four sequences are
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
Sequence-0 Sequence-1 Sequence-2 Sequence-3
|
||||||
|
'SVTT' 'SS' 'TTV' 'S?V*S'
|
||||||
|
(1) String (1) String (1) Scalar (1) String
|
||||||
|
(2) Vector (2) String (2) Scalar (2) Any Type
|
||||||
|
(3) Scalar (3) Vector (3) One or more Vectors
|
||||||
|
(4) Scalar (4) String
|
||||||
|
|
||||||
|
|
||||||
(5) function_compositor
|
(5) function_compositor
|
||||||
The function compositor interface allows a user to define a function
|
The function compositor interface allows a user to define a function
|
||||||
using ExprTk syntax. The functions are limited to returning a single
|
using ExprTk syntax. The functions are limited to returning a single
|
||||||
|
@ -1745,7 +1831,7 @@ into account when using Exprtk:
|
||||||
(28) Every valid ExprTk statement is a "value returning" expression.
|
(28) Every valid ExprTk statement is a "value returning" expression.
|
||||||
Unlike some languages that limit the types of expressions that
|
Unlike some languages that limit the types of expressions that
|
||||||
can be performed in certain situations, in ExprTk any valid
|
can be performed in certain situations, in ExprTk any valid
|
||||||
expression can be used in any "value consuming" context. Eg:
|
expression can be used in any "value consuming" context. eg:
|
||||||
|
|
||||||
var y := 3;
|
var y := 3;
|
||||||
for (var x := switch
|
for (var x := switch
|
||||||
|
@ -2045,7 +2131,9 @@ files:
|
||||||
+-------------------------------------------------------------+
|
+-------------------------------------------------------------+
|
||||||
|09 - Variable Definition Statement |
|
|09 - Variable Definition Statement |
|
||||||
| |
|
| |
|
||||||
| [var] ---> [symbol] -+-> [:=] ---> [expression] -+-> [;] |
|
| [var] ---> [symbol] -+-> [:=] -+-> [expression] -+-> [;] |
|
||||||
|
| | | | |
|
||||||
|
| | +-----> [{}] -->--+ |
|
||||||
| | | |
|
| | | |
|
||||||
| +------------->-------------+ |
|
| +------------->-------------+ |
|
||||||
| |
|
| |
|
||||||
|
|
Loading…
Reference in New Issue