C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
3f228b3f86
commit
16a0e6b5ee
1522
exprtk.hpp
1522
exprtk.hpp
File diff suppressed because it is too large
Load Diff
277
exprtk_test.cpp
277
exprtk_test.cpp
|
@ -32,7 +32,7 @@
|
|||
typedef double numeric_type;
|
||||
typedef std::pair<std::string,numeric_type> test_t;
|
||||
|
||||
static const test_t test_list[] =
|
||||
static const test_t global_test_list[] =
|
||||
{
|
||||
// Note: Each of following tests must compile down
|
||||
// to a single literal node.
|
||||
|
@ -1061,7 +1061,7 @@ static const test_t test_list[] =
|
|||
test_t("if (1 > 2) { 1+2; 3;} else if (1 > 2) {1+2; 4;} == null",1.0)
|
||||
};
|
||||
|
||||
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_t);
|
||||
static const std::size_t global_test_list_size = sizeof(global_test_list) / sizeof(test_t);
|
||||
|
||||
template <typename T>
|
||||
inline bool not_equal_impl(const T& t1,
|
||||
|
@ -1165,9 +1165,9 @@ inline bool run_test00()
|
|||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
bool result = true;
|
||||
for (std::size_t i = 0; i < test_list_size; ++i)
|
||||
for (std::size_t i = 0; i < global_test_list_size; ++i)
|
||||
{
|
||||
if (!test_expression<T>(test_list[i].first,T(test_list[i].second)))
|
||||
if (!test_expression<T>(global_test_list[i].first,T(global_test_list[i].second)))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
@ -1576,7 +1576,14 @@ inline bool run_test01()
|
|||
test_xy<T>("for(var i := 0; (i < 10) and (i != y); i+=2) { x += i; }; x;" ,T(1),T(20),T(21)),
|
||||
test_xy<T>("for(var i := 0; (i < 10) and (i != y);) { x += i; i+=2; }; x;",T(1),T(20),T(21)),
|
||||
test_xy<T>("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) x += i; else break; }; x;" ,T(0),T(10),T(15)),
|
||||
test_xy<T>("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) continue; else x += i; }; x;" ,T(0),T(10),T(30))
|
||||
test_xy<T>("for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) continue; else x += i; }; x;" ,T(0),T(10),T(30)),
|
||||
test_xy<T>("var a := 2; (0 * a) == 0",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (0 / a) == 0",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (a * 0) == 0",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (a / 1) == a",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (0 + a) == a",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (a + 0) == a",T(0),T(0),T(1)),
|
||||
test_xy<T>("var a := 2; (1 * a) == a",T(0),T(0),T(1))
|
||||
};
|
||||
|
||||
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_xy<T>);
|
||||
|
@ -2270,12 +2277,42 @@ inline bool run_test02()
|
|||
test_ab<T>("'a\\'\\\\b' == a" ,"a'\\b","",T(1.0)),
|
||||
test_ab<T>("'a\\\\\\'b' == a" ,"a\\'b","",T(1.0)),
|
||||
test_ab<T>("'a\\'\\\\\\\\b' == a" ,"a'\\\\b","",T(1.0)),
|
||||
test_ab<T>("'a\\0x30\\'\\0x31\\\\\\0x32b' == a" ,"a0'1\\2b","",T(1.0))
|
||||
test_ab<T>("'a\\0x30\\'\\0x31\\\\\\0x32b' == a" ,"a0'1\\2b","",T(1.0)),
|
||||
|
||||
test_ab<T>("var x := 3; x > 2 and 'abc' like '*bc'" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and 'abc' ilike '*Bc'" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and 'abc' in '123abc123'","","",T(1.0)),
|
||||
|
||||
test_ab<T>("var x := 3; var s := 'abc'; x > 2 and s like '*bc'" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; var s := 'abc'; x > 2 and s ilike '*Bc'" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; var s := 'abc'; x > 2 and s in '123abc123'","","",T(1.0)),
|
||||
|
||||
test_ab<T>("var x := 3; var s := 'abc'; var t := '*bc'; x > 2 and s like t" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; var s := 'abc'; var t := '*Bc'; x > 2 and s ilike t" ,"","",T(1.0)),
|
||||
test_ab<T>("var x := 3; var s := 'abc'; var t := '123abc123'; x > 2 and s in t","","",T(1.0)),
|
||||
|
||||
test_ab<T>("var x := 3; x > 2 and a like '*bc'" ,"abc","",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and a ilike '*Bc'" ,"abc","",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and a in '123abc123'","abc","",T(1.0)),
|
||||
|
||||
test_ab<T>("var x := 3; x > 2 and a like b ","abc","*bc",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and a ilike b","abc","*Bc",T(1.0)),
|
||||
test_ab<T>("var x := 3; x > 2 and a in b ","abc","123abc123",T(1.0)),
|
||||
|
||||
test_ab<T>("a[] > 2 and a like '*bc'" ,"abc","",T(1.0)),
|
||||
test_ab<T>("a[] > 2 and a ilike '*Bc'" ,"abc","",T(1.0)),
|
||||
test_ab<T>("a[] > 2 and a in '123abc123'","abc","",T(1.0)),
|
||||
|
||||
test_ab<T>("a[] > 2 and a like b ","abc","*bc",T(1.0)),
|
||||
test_ab<T>("a[] > 2 and a ilike b","abc","*Bc",T(1.0)),
|
||||
test_ab<T>("a[] > 2 and a in b ","abc","123abc123",T(1.0))
|
||||
};
|
||||
|
||||
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
|
||||
|
||||
{
|
||||
const std::size_t rounds = 50;
|
||||
|
||||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
bool result = true;
|
||||
|
@ -2346,6 +2383,7 @@ inline bool run_test02()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::string s0;
|
||||
|
@ -2492,6 +2530,117 @@ inline bool run_test03()
|
|||
expression.value();
|
||||
}
|
||||
|
||||
{
|
||||
static const std::string invalid_expr[] =
|
||||
{
|
||||
"x y",
|
||||
"x y z",
|
||||
"x y z w",
|
||||
"x 1",
|
||||
"x 1 2",
|
||||
"x 1 2 3",
|
||||
"x 'abc'",
|
||||
"x 1 'abc'",
|
||||
"x 'abc' 1",
|
||||
"1 2",
|
||||
"1 2 3",
|
||||
"1 2 3 4",
|
||||
"'abc' 'xyz'",
|
||||
"'abc' 1",
|
||||
"1 'abc'",
|
||||
"x sin(1)",
|
||||
"s 'abc'",
|
||||
"s x",
|
||||
"s y",
|
||||
"s 1",
|
||||
"s 1 x",
|
||||
"s 1 y",
|
||||
"s x 1",
|
||||
"s y 1",
|
||||
"x s ",
|
||||
"y s ",
|
||||
"1 s ",
|
||||
"1 s x",
|
||||
"1 s y",
|
||||
"x s 1",
|
||||
"y s 1",
|
||||
"v 'abc'",
|
||||
"v x ",
|
||||
"v y ",
|
||||
"v s ",
|
||||
"v 1 ",
|
||||
"v 1 x",
|
||||
"v 1 y",
|
||||
"v 1 s",
|
||||
"v x 1",
|
||||
"v y 1",
|
||||
"v s 1",
|
||||
"x v ",
|
||||
"y v ",
|
||||
"1 v ",
|
||||
"1 v x",
|
||||
"1 v y",
|
||||
"x v 1",
|
||||
"y v 1"
|
||||
};
|
||||
|
||||
const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string);
|
||||
|
||||
{
|
||||
for (std::size_t i = 0; i < invalid_expr_size; ++i)
|
||||
{
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
|
||||
exprtk::expression<T> expression;
|
||||
|
||||
T x = T(0);
|
||||
std::string s;
|
||||
std::vector<T> v(10, T(1.234));
|
||||
|
||||
symbol_table.add_variable ("x",x);
|
||||
symbol_table.add_stringvar("s",s);
|
||||
symbol_table.add_vector ("v",v);
|
||||
|
||||
exprtk::parser<T> parser;
|
||||
|
||||
if (parser.compile(invalid_expr[i],expression))
|
||||
{
|
||||
printf("run_test03() - Error: [1] Invalid expression compiled successfuly. Expression: %s\n",
|
||||
invalid_expr[i].c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
T x = T(0);
|
||||
std::string s;
|
||||
std::vector<T> v(10, T(1.234));
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
|
||||
symbol_table.add_variable ("x",x);
|
||||
symbol_table.add_stringvar("s",s);
|
||||
symbol_table.add_vector ("v",v);
|
||||
|
||||
exprtk::parser<T> parser;
|
||||
|
||||
for (std::size_t i = 0; i < invalid_expr_size; ++i)
|
||||
{
|
||||
exprtk::expression<T> expression;
|
||||
|
||||
if (parser.compile(invalid_expr[i],expression))
|
||||
{
|
||||
printf("run_test03() - Error: [2] Invalid expression compiled successfuly. Expression: %s\n",
|
||||
invalid_expr[i].c_str());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2977,8 +3126,15 @@ struct myfunc : public exprtk::ifunction<T>
|
|||
}
|
||||
};
|
||||
|
||||
double foo1(double v0) { return v0; }
|
||||
double foo2(double v0, double v1) { return v0 + v1; }
|
||||
double foo3(double v0, double v1, double v2) { return v0 + v1 + v2; }
|
||||
double foo4(double v0, double v1, double v2, double v3) { return v0 + v1 + v2 + v3; }
|
||||
double foo5(double v0, double v1, double v2, double v3, double v4) { return v0 + v1 + v2 + v3 + v4; }
|
||||
|
||||
template <typename T>
|
||||
inline bool run_test09()
|
||||
{
|
||||
{
|
||||
static const std::size_t rounds = 1000;
|
||||
for (std::size_t i = 0; i < rounds; ++i)
|
||||
|
@ -3067,6 +3223,53 @@ inline bool run_test09()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
|
||||
bool result = true;
|
||||
|
||||
const std::string expression_list[] =
|
||||
{
|
||||
"foo1(1) == 1",
|
||||
"foo2(1,2) == (1 + 2)",
|
||||
"foo3(1,2,3) == (1 + 2 + 3)",
|
||||
"foo4(1,2,3,4) == (1 + 2 + 3 + 4)",
|
||||
"foo5(1,2,3,4,5) == (1 + 2 + 3 + 4 + 5)"
|
||||
};
|
||||
|
||||
const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
|
||||
symbol_table.add_function("foo1",foo1);
|
||||
symbol_table.add_function("foo2",foo2);
|
||||
symbol_table.add_function("foo3",foo3);
|
||||
symbol_table.add_function("foo4",foo4);
|
||||
symbol_table.add_function("foo5",foo5);
|
||||
|
||||
for (std::size_t i = 0; i < expression_list_size; ++i)
|
||||
{
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
exprtk::parser<T> parser;
|
||||
|
||||
if (!parser.compile(expression_list[i],expression))
|
||||
{
|
||||
printf("run_test09() - Error: %s Expression: %s\n",
|
||||
parser.error().c_str(),
|
||||
expression_list[i].c_str());
|
||||
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3081,12 +3284,10 @@ inline bool run_test10()
|
|||
T xx = T(3.3);
|
||||
T yy = T(4.4);
|
||||
|
||||
std::string i = "A String";
|
||||
std::string j = "Another String";
|
||||
std::string ii = "A String";
|
||||
std::string jj = "Another String";
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
std::string i_s = "A String";
|
||||
std::string j_s = "Another String";
|
||||
std::string ii_s = "A String";
|
||||
std::string jj_s = "Another String";
|
||||
|
||||
struct test
|
||||
{
|
||||
|
@ -3111,8 +3312,11 @@ inline bool run_test10()
|
|||
}
|
||||
};
|
||||
|
||||
{
|
||||
static const std::size_t rounds = 10;
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
|
||||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
symbol_table.add_variable("x", x);
|
||||
|
@ -3215,11 +3419,11 @@ inline bool run_test10()
|
|||
|
||||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
symbol_table.add_stringvar("i",i);
|
||||
symbol_table.add_stringvar("j",j);
|
||||
symbol_table.add_stringvar("i", i_s);
|
||||
symbol_table.add_stringvar("j", j_s);
|
||||
|
||||
symbol_table.add_stringvar("ii",ii);
|
||||
symbol_table.add_stringvar("jj",jj);
|
||||
symbol_table.add_stringvar("ii", ii_s);
|
||||
symbol_table.add_stringvar("jj", jj_s);
|
||||
|
||||
if (!symbol_table.symbol_exists("i"))
|
||||
{
|
||||
|
@ -3241,22 +3445,22 @@ inline bool run_test10()
|
|||
printf("run_test10() - String 'jj' does not exist!\n");
|
||||
return false;
|
||||
}
|
||||
else if (!test::string(symbol_table,"i",i))
|
||||
else if (!test::string(symbol_table, "i", i_s))
|
||||
{
|
||||
printf("run_test10() - String 'i' value failure!\n");
|
||||
return false;
|
||||
}
|
||||
else if (!test::string(symbol_table,"j",j))
|
||||
else if (!test::string(symbol_table, "j", j_s))
|
||||
{
|
||||
printf("run_test10() - String 'j' value failure!\n");
|
||||
return false;
|
||||
}
|
||||
else if (!test::string(symbol_table,"ii",ii))
|
||||
else if (!test::string(symbol_table, "ii", ii_s))
|
||||
{
|
||||
printf("run_test10() - String 'ii' value failure!\n");
|
||||
return false;
|
||||
}
|
||||
else if (!test::string(symbol_table,"jj",jj))
|
||||
else if (!test::string(symbol_table, "jj", jj_s))
|
||||
{
|
||||
printf("run_test10() - String 'jj' value failure!\n");
|
||||
return false;
|
||||
|
@ -3375,10 +3579,10 @@ inline bool run_test10()
|
|||
|
||||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
symbol_table.add_stringvar( "i", i);
|
||||
symbol_table.add_stringvar( "j", j);
|
||||
symbol_table.add_stringvar("ii",ii);
|
||||
symbol_table.add_stringvar("jj",jj);
|
||||
symbol_table.add_stringvar("i", i_s);
|
||||
symbol_table.add_stringvar("j", j_s);
|
||||
symbol_table.add_stringvar("ii", ii_s);
|
||||
symbol_table.add_stringvar("jj", jj_s);
|
||||
|
||||
std::vector<std::string> expected_var_list;
|
||||
|
||||
|
@ -3420,10 +3624,10 @@ inline bool run_test10()
|
|||
|
||||
for (std::size_t r = 0; r < rounds; ++r)
|
||||
{
|
||||
symbol_table.add_stringvar( "i", i);
|
||||
symbol_table.add_stringvar( "j", j);
|
||||
symbol_table.add_stringvar("ii",ii);
|
||||
symbol_table.add_stringvar("jj",jj);
|
||||
symbol_table.add_stringvar("i", i_s);
|
||||
symbol_table.add_stringvar("j", j_s);
|
||||
symbol_table.add_stringvar("ii", ii_s);
|
||||
symbol_table.add_stringvar("jj", jj_s);
|
||||
|
||||
std::vector<std::string> expected_var_list;
|
||||
|
||||
|
@ -3468,6 +3672,7 @@ inline bool run_test10()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
T x0 = T(0);
|
||||
|
@ -3977,6 +4182,9 @@ inline bool run_test10()
|
|||
"2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; return [i * 8];"
|
||||
"i += 1; i += 2; i += 3; } else i; }",
|
||||
|
||||
"var x[10] := [-1]; var y[10] := [-1]; for (var i := 0; i < 10; i += 1) { x[i] := i; "
|
||||
"y[i] := 2 * x[i]; }; (sum(x) == 45) and (sum(y) == (2 * sum(x)));"
|
||||
|
||||
"7 == (for (var i := 0; i < 10; i += 1) { ~{break[7]; continue; i += i} })",
|
||||
"0 == (for (var i := 0; i < 10; i += 1) { ~{break[i]; continue; i += i} })",
|
||||
"0 == (for (var i := 0; i < 10; i += 1) { ~{continue; break[7]; i += i} })",
|
||||
|
@ -4932,6 +5140,8 @@ struct va_func : public exprtk::ivararg_function<T>
|
|||
va_func()
|
||||
{
|
||||
exprtk::enable_zero_parameters(*this);
|
||||
exprtk::set_min_num_args(*this, 0);
|
||||
exprtk::set_max_num_args(*this, 20);
|
||||
}
|
||||
|
||||
inline T operator()(const std::vector<T>& arglist)
|
||||
|
@ -5084,12 +5294,13 @@ struct inc_func : public exprtk::igeneric_function<T>
|
|||
template <typename T>
|
||||
struct rem_space_and_uppercase : public exprtk::igeneric_function<T>
|
||||
{
|
||||
typedef typename exprtk::igeneric_function<T>::generic_type generic_type;
|
||||
typedef typename exprtk::igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
typedef typename exprtk::igeneric_function<T> igenfunc_t;
|
||||
typedef typename igenfunc_t::generic_type generic_type;
|
||||
typedef typename igenfunc_t::parameter_list_t parameter_list_t;
|
||||
typedef typename generic_type::string_view string_t;
|
||||
|
||||
rem_space_and_uppercase()
|
||||
: exprtk::igeneric_function<T>("S")
|
||||
: igenfunc_t("S",igenfunc_t::e_rtrn_string)
|
||||
{}
|
||||
|
||||
inline T operator()(std::string& result, parameter_list_t params)
|
||||
|
@ -5104,7 +5315,7 @@ struct rem_space_and_uppercase : public exprtk::igeneric_function<T>
|
|||
for (std::size_t i = 0; i < string.size(); ++i)
|
||||
{
|
||||
if (' ' != (c = string[i]))
|
||||
result += std::toupper(c);
|
||||
result += static_cast<char>(std::toupper(c));
|
||||
}
|
||||
|
||||
return T(0);
|
||||
|
@ -5613,7 +5824,7 @@ inline bool run_test18()
|
|||
symbol_table.add_stringvar("s3", s3);
|
||||
symbol_table.add_stringvar("s4", s4);
|
||||
|
||||
symbol_table.add_function("remspc_uc",rsauc,symbol_table_t::e_ft_strfunc);
|
||||
symbol_table.add_function("remspc_uc",rsauc);
|
||||
|
||||
std::string program = " s0 := 'How now '; "
|
||||
" s1 := 'brown cow?'; "
|
||||
|
|
242
readme.txt
242
readme.txt
|
@ -610,9 +610,9 @@ appropriate may represent any of one the following:
|
|||
ExprTk supports three fundamental types which can be used freely in
|
||||
expressions. The types are as follows:
|
||||
|
||||
1. Scalar
|
||||
2. Vector
|
||||
3. String
|
||||
(1) Scalar
|
||||
(2) Vector
|
||||
(3) String
|
||||
|
||||
|
||||
(1) Scalar Type
|
||||
|
@ -706,7 +706,7 @@ current values assigned to the variables will be used.
|
|||
expression.value(); // 3.7 * -9 + 3
|
||||
|
||||
// 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001
|
||||
for (x = 0; x < 100; x += 0.0001)
|
||||
for (x = 0.0; x < 100.0; x += 0.0001)
|
||||
{
|
||||
expression.value(); // x * -9 + 3
|
||||
}
|
||||
|
@ -860,7 +860,10 @@ handle:
|
|||
(i) '*' '=' ---> '*=' (multiplication assignment)
|
||||
(j) '/' '=' ---> '/=' (division assignment)
|
||||
(k) '%' '=' ---> '%=' (modulo assignment)
|
||||
(l) '<=' '>' ---> '<=>' (swap)
|
||||
(l) '+' '-' ---> '-' (subtraction)
|
||||
(m) '-' '+' ---> '-' (subtraction)
|
||||
(n) '-' '-' ---> '+' (addition)
|
||||
(o) '<=' '>' ---> '<=>' (swap)
|
||||
|
||||
|
||||
An example of the transformation that takes place is as follows:
|
||||
|
@ -926,7 +929,7 @@ In the following example the given expression which represents an
|
|||
attempt at computing the average between x and y will be transformed
|
||||
as follows:
|
||||
|
||||
(x * 0.5) + (y * 0.5) ---> 0.5 * (x + y)
|
||||
(0.5 * x) + (y * 0.5) ---> 0.5 * (x + y)
|
||||
|
||||
There may be situations where the above transformation will cause
|
||||
numerical overflows and that the original form of the expression is
|
||||
|
@ -1216,11 +1219,15 @@ embedded into the expression.
|
|||
|
||||
There are five types of function interface:
|
||||
|
||||
(1) ifunction
|
||||
(2) ivararg_function
|
||||
(3) igeneric_function
|
||||
(4) igeneric_function II
|
||||
(5) function_compositor
|
||||
+---+----------------------+-------------+
|
||||
| # | Name | Return Type |
|
||||
+---+----------------------+-------------+
|
||||
| 1 | ifunction | Scalar |
|
||||
| 2 | ivararg_function | Scalar |
|
||||
| 3 | igeneric_function | Scalar |
|
||||
| 4 | igeneric_function II | String |
|
||||
| 5 | function_compositor | Scalar |
|
||||
+---+----------------------+-------------+
|
||||
|
||||
|
||||
(1) ifunction
|
||||
|
@ -1446,17 +1453,21 @@ the string return type function operator being explicitly overridden:
|
|||
typedef typename generic_t::string_view string_t;
|
||||
|
||||
toupper()
|
||||
: exprtk::igeneric_function<T>("S")
|
||||
: exprtk::igeneric_function<T>("S",igenfunct_t::e_rtrn_string)
|
||||
{}
|
||||
|
||||
inline T operator()(std::string& result,
|
||||
parameter_list_t parameters)
|
||||
{
|
||||
result.clear();
|
||||
|
||||
string_t string(params[0]);
|
||||
|
||||
for (std::size_t i = 0; i < string.size(); ++i)
|
||||
{
|
||||
result += std::toupper(string[i]);
|
||||
}
|
||||
|
||||
return T(0);
|
||||
}
|
||||
};
|
||||
|
@ -1464,27 +1475,27 @@ the string return type function operator being explicitly overridden:
|
|||
|
||||
In the example above the generic function 'toupper' expects only one
|
||||
input parameter of type string, as noted by the parameter sequence
|
||||
string passed during the constructor. When executed, the function will
|
||||
return as a result a copy of the input string converted to uppercase
|
||||
form. An example expression using the toupper function registered as
|
||||
the symbol 'toupper' is as follows:
|
||||
string passed during the constructor. Furthermore a second parameter
|
||||
is passed to the constructor indicating that it should be treated as a
|
||||
string returning function - by default it is assumed to be a scalar
|
||||
returning function.
|
||||
|
||||
When executed, the function will return as a result a copy of the
|
||||
input string converted to uppercase form. An example expression using
|
||||
the toupper function registered as the symbol 'toupper' is as follows:
|
||||
|
||||
"'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
|
||||
(e_ft_strfunc) that denotes the function should be treated as a string
|
||||
returning function type. The following example demonstrates how this
|
||||
is done:
|
||||
table the 'add_function' is invoked. The example below demonstrates
|
||||
how this can be done:
|
||||
|
||||
toupper<T> tu;
|
||||
|
||||
exprtk::symbol_table<T> symbol_table;
|
||||
|
||||
symbol_table.add_function("toupper",
|
||||
tu,
|
||||
symbol_table_t::e_ft_strfunc);
|
||||
symbol_table.add_function("toupper",tu);
|
||||
|
||||
|
||||
Note: Two further refinements to the type checking facility are the
|
||||
|
@ -1689,7 +1700,7 @@ the function can be disabled.
|
|||
{
|
||||
foo() : exprtk::ifunction<T>(3)
|
||||
{
|
||||
disable_has_side_effects(*this);
|
||||
exprtk::disable_has_side_effects(*this);
|
||||
}
|
||||
|
||||
T operator()(const T& v1, const T& v2, const T& v3)
|
||||
|
@ -1757,6 +1768,14 @@ parsing phase. Once the compilation process has successfully
|
|||
completed, the caller can then obtain a list of symbols and their
|
||||
associated types from the DEC.
|
||||
|
||||
The kinds of questions one can ask regarding the dependent entities
|
||||
within an expression are as follows:
|
||||
|
||||
* What user defined or local variables, vectors or strings are used?
|
||||
* What functions or custom user functions are used?
|
||||
* Which variables, vectors or strings have values assigned to them?
|
||||
|
||||
|
||||
The following example demonstrates usage of the DEC in determining the
|
||||
dependents of the given expression:
|
||||
|
||||
|
@ -1766,9 +1785,15 @@ dependents of the given expression:
|
|||
std::string expression_string =
|
||||
"z := abs(x + sin(2 * pi / y))";
|
||||
|
||||
T x,y,z;
|
||||
|
||||
parser_t parser;
|
||||
symbol_table_t symbol_table;
|
||||
|
||||
symbol_table.add_variable("x",x);
|
||||
symbol_table.add_variable("y",y);
|
||||
symbol_table.add_variable("z",z);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
|
@ -1799,7 +1824,7 @@ dependents of the given expression:
|
|||
}
|
||||
|
||||
|
||||
Note: The 'symbol_t' type is a pair comprising of the symbol name
|
||||
Note: The 'symbol_t' type is a std::pair comprising of the symbol name
|
||||
(std::string) and the associated type of the symbol as denoted by the
|
||||
cases in the switch statement.
|
||||
|
||||
|
@ -1866,6 +1891,9 @@ grammar. The features fall into one of the following three categories:
|
|||
(1) Base Functions
|
||||
(2) Control Flow Structures
|
||||
(3) Logical Operators
|
||||
(4) Arithmetic Operators
|
||||
(5) Inequality Operators
|
||||
(6) Assignment Operators
|
||||
|
||||
|
||||
(1) Base Functions
|
||||
|
@ -1967,13 +1995,13 @@ flow structure:
|
|||
" } ";
|
||||
|
||||
parser.settings()
|
||||
.disable_all_control_structures(settings_t::e_ctrl_for_loop);
|
||||
.disable_control_structure(settings_t::e_ctrl_for_loop);
|
||||
|
||||
parser
|
||||
.compile(program,expression); // failure
|
||||
|
||||
parser.settings()
|
||||
.enable_all_control_structures(settings_t::e_ctrl_for_loop);
|
||||
.enable_control_structure(settings_t::e_ctrl_for_loop);
|
||||
|
||||
parser
|
||||
.compile(program,expression); // success
|
||||
|
@ -2009,18 +2037,158 @@ example demonstrates the disabling of the 'and' logical operator:
|
|||
expression_t expression;
|
||||
|
||||
parser.settings()
|
||||
.disable_base_function(settings_t::e_logic_and);
|
||||
.disable_logic_operation(settings_t::e_logic_and);
|
||||
|
||||
parser
|
||||
.compile("1 or not(0 and 1)",expression); // failure
|
||||
|
||||
parser.settings()
|
||||
.enable_base_function(settings_t::e_logic_and);
|
||||
.enable_logic_operation(settings_t::e_logic_and);
|
||||
|
||||
parser
|
||||
.compile("1 or not(0 and 1)",expression); // success
|
||||
|
||||
|
||||
(4) Arithmetic Operators
|
||||
The list of available arithmetic operators is as follows:
|
||||
|
||||
+, -, *, /, %, ^
|
||||
|
||||
|
||||
The above mentioned arithmetic operators can be either enabled or
|
||||
disabled 'all' at once, as is demonstrated below:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
|
||||
parser.settings().disable_all_arithmetic_ops();
|
||||
|
||||
parser
|
||||
.compile("1 + 2 / 3",expression); // compilation failure
|
||||
|
||||
parser.settings().enable_all_arithmetic_ops();
|
||||
|
||||
parser
|
||||
.compile("1 + 2 / 3",expression); // compilation success
|
||||
|
||||
|
||||
One can also enable or disable specific arithmetic operators. The following
|
||||
example demonstrates the disabling of the addition '+' arithmetic operator:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
|
||||
parser.settings()
|
||||
.disable_arithmetic_operation(settings_t::e_arith_add);
|
||||
|
||||
parser
|
||||
.compile("1 + 2 / 3",expression); // failure
|
||||
|
||||
parser.settings()
|
||||
.enable_arithmetic_operation(settings_t::e_arith_add);
|
||||
|
||||
parser
|
||||
.compile("1 + 2 / 3",expression); // success
|
||||
|
||||
|
||||
(5) Inequality Operators
|
||||
The list of available inequality operators is as follows:
|
||||
|
||||
<, <=, >, >=, ==, =, != <>
|
||||
|
||||
|
||||
The above mentioned inequality operators can be either enabled or
|
||||
disabled 'all' at once, as is demonstrated below:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
|
||||
parser.settings().disable_all_inequality_ops();
|
||||
|
||||
parser
|
||||
.compile("1 < 3",expression); // compilation failure
|
||||
|
||||
parser.settings().enable_all_inequality_ops();
|
||||
|
||||
parser
|
||||
.compile("1 < 3",expression); // compilation success
|
||||
|
||||
|
||||
One can also enable or disable specific inequality operators. The following
|
||||
example demonstrates the disabling of the less-than '<' inequality operator:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
|
||||
parser.settings()
|
||||
.disable_inequality_operation(settings_t::e_ineq_lt);
|
||||
|
||||
parser
|
||||
.compile("1 < 3",expression); // failure
|
||||
|
||||
parser.settings()
|
||||
.enable_inequality_operation(settings_t::e_ineq_lt);
|
||||
|
||||
parser
|
||||
.compile("1 < 3",expression); // success
|
||||
|
||||
|
||||
(6) Assignment Operators
|
||||
The list of available assignment operators is as follows:
|
||||
|
||||
:=, +=, -=, *=, /=, %=
|
||||
|
||||
|
||||
The above mentioned assignment operators can be either enabled or
|
||||
disabled 'all' at once, as is demonstrated below:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
symbol_table_t symbol_table;
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser.settings().disable_all_assignment_ops();
|
||||
|
||||
parser
|
||||
.compile("x := 3",expression); // compilation failure
|
||||
|
||||
parser.settings().enable_all_assignment_ops();
|
||||
|
||||
parser
|
||||
.compile("x := 3",expression); // compilation success
|
||||
|
||||
|
||||
One can also enable or disable specific assignment operators. The following
|
||||
example demonstrates the disabling of the '+=' addition assignment operator:
|
||||
|
||||
parser_t parser;
|
||||
expression_t expression;
|
||||
symbol_table_t symbol_table;
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser.settings()
|
||||
.disable_assignment_operation(settings_t::e_assign_addass);
|
||||
|
||||
parser
|
||||
.compile("x += 3",expression); // failure
|
||||
|
||||
parser.settings()
|
||||
.enable_assignment_operation(settings_t::e_assign_addass);
|
||||
|
||||
parser
|
||||
.compile("x += 3",expression); // success
|
||||
|
||||
|
||||
Note: In the event of a base function being disabled, one can redefine
|
||||
the base function using the standard custom function definition
|
||||
process. In the following example the 'sin' function is disabled then
|
||||
|
@ -2161,7 +2329,7 @@ following example:
|
|||
if (!parser.compile(expression_string,expression))
|
||||
{
|
||||
printf("Error: %s\n", parser.error().c_str());
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2189,7 +2357,7 @@ in the event of a failed compilation.
|
|||
error.diagnostic.c_str());
|
||||
}
|
||||
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2214,7 +2382,7 @@ demonstrated by the following example:
|
|||
error.column_no);
|
||||
}
|
||||
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2530,7 +2698,15 @@ int main()
|
|||
When building ExprTk there are a number of defines that will enable or
|
||||
disable certain features and capabilities. The defines can either be
|
||||
part of a compiler command line switch or scoped around the include to
|
||||
the ExprTk header.
|
||||
the ExprTk header. The defines are as follows:
|
||||
|
||||
(1) exprtk_enable_debugging
|
||||
(2) exprtk_disable_comments
|
||||
(3) exprtk_disable_break_continue
|
||||
(4) exprtk_disable_sc_andor
|
||||
(5) exprtk_disable_enhanced_features
|
||||
(6) exprtk_disable_string_capabilities
|
||||
|
||||
|
||||
(1) exprtk_enable_debugging
|
||||
This define will enable printing of debug information to stdout during
|
||||
|
|
Loading…
Reference in New Issue