C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
3f228b3f86
commit
16a0e6b5ee
1524
exprtk.hpp
1524
exprtk.hpp
File diff suppressed because it is too large
Load Diff
339
exprtk_test.cpp
339
exprtk_test.cpp
|
@ -32,7 +32,7 @@
|
||||||
typedef double numeric_type;
|
typedef double numeric_type;
|
||||||
typedef std::pair<std::string,numeric_type> test_t;
|
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
|
// Note: Each of following tests must compile down
|
||||||
// to a single literal node.
|
// 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)
|
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>
|
template <typename T>
|
||||||
inline bool not_equal_impl(const T& t1,
|
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)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
bool result = true;
|
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;
|
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); 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 < 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)) 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>);
|
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\\\\\\'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>);
|
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
|
||||||
|
|
||||||
|
{
|
||||||
const std::size_t rounds = 50;
|
const std::size_t rounds = 50;
|
||||||
|
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
@ -2294,13 +2331,13 @@ inline bool run_test02()
|
||||||
T r3 = T(3);
|
T r3 = T(3);
|
||||||
|
|
||||||
exprtk::symbol_table<T> symbol_table;
|
exprtk::symbol_table<T> symbol_table;
|
||||||
symbol_table.add_stringvar("a" ,str_a);
|
symbol_table.add_stringvar("a", str_a);
|
||||||
symbol_table.add_stringvar("b" ,str_b);
|
symbol_table.add_stringvar("b", str_b);
|
||||||
symbol_table.add_stringvar("c" ,str_c);
|
symbol_table.add_stringvar("c", str_c);
|
||||||
symbol_table.add_variable ("r0", r0);
|
symbol_table.add_variable("r0", r0);
|
||||||
symbol_table.add_variable ("r1", r1);
|
symbol_table.add_variable("r1", r1);
|
||||||
symbol_table.add_variable ("r2", r2);
|
symbol_table.add_variable("r2", r2);
|
||||||
symbol_table.add_variable ("r3", r3);
|
symbol_table.add_variable("r3", r3);
|
||||||
|
|
||||||
exprtk::expression<T> expression;
|
exprtk::expression<T> expression;
|
||||||
expression.register_symbol_table(symbol_table);
|
expression.register_symbol_table(symbol_table);
|
||||||
|
@ -2308,7 +2345,7 @@ inline bool run_test02()
|
||||||
{
|
{
|
||||||
exprtk::parser<T> parser;
|
exprtk::parser<T> parser;
|
||||||
|
|
||||||
if (!parser.compile(test.expr,expression))
|
if (!parser.compile(test.expr, expression))
|
||||||
{
|
{
|
||||||
printf("run_test02() - Error: %s Expression: %s\n",
|
printf("run_test02() - Error: %s Expression: %s\n",
|
||||||
parser.error().c_str(),
|
parser.error().c_str(),
|
||||||
|
@ -2325,7 +2362,7 @@ inline bool run_test02()
|
||||||
|
|
||||||
T expr_result = expression.value();
|
T expr_result = expression.value();
|
||||||
|
|
||||||
if (not_equal(expr_result,test.result))
|
if (not_equal(expr_result, test.result))
|
||||||
{
|
{
|
||||||
printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t"
|
printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\t"
|
||||||
"a='%s'\tb='%s'\tc='%s'\n",
|
"a='%s'\tb='%s'\tc='%s'\n",
|
||||||
|
@ -2346,6 +2383,7 @@ inline bool run_test02()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string s0;
|
std::string s0;
|
||||||
|
@ -2492,6 +2530,117 @@ inline bool run_test03()
|
||||||
expression.value();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2977,9 +3126,16 @@ 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>
|
template <typename T>
|
||||||
inline bool run_test09()
|
inline bool run_test09()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
static const std::size_t rounds = 1000;
|
static const std::size_t rounds = 1000;
|
||||||
for (std::size_t i = 0; i < rounds; ++i)
|
for (std::size_t i = 0; i < rounds; ++i)
|
||||||
{
|
{
|
||||||
|
@ -3067,6 +3223,53 @@ inline bool run_test09()
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3081,12 +3284,10 @@ inline bool run_test10()
|
||||||
T xx = T(3.3);
|
T xx = T(3.3);
|
||||||
T yy = T(4.4);
|
T yy = T(4.4);
|
||||||
|
|
||||||
std::string i = "A String";
|
std::string i_s = "A String";
|
||||||
std::string j = "Another String";
|
std::string j_s = "Another String";
|
||||||
std::string ii = "A String";
|
std::string ii_s = "A String";
|
||||||
std::string jj = "Another String";
|
std::string jj_s = "Another String";
|
||||||
|
|
||||||
exprtk::symbol_table<T> symbol_table;
|
|
||||||
|
|
||||||
struct test
|
struct test
|
||||||
{
|
{
|
||||||
|
@ -3111,14 +3312,17 @@ inline bool run_test10()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
static const std::size_t rounds = 10;
|
static const std::size_t rounds = 10;
|
||||||
|
|
||||||
|
exprtk::symbol_table<T> symbol_table;
|
||||||
|
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
symbol_table.add_variable("x", x);
|
symbol_table.add_variable("x", x);
|
||||||
symbol_table.add_variable("y", y);
|
symbol_table.add_variable("y", y);
|
||||||
symbol_table.add_variable("xx",xx);
|
symbol_table.add_variable("xx", xx);
|
||||||
symbol_table.add_variable("yy",yy);
|
symbol_table.add_variable("yy", yy);
|
||||||
|
|
||||||
if (!symbol_table.symbol_exists("x"))
|
if (!symbol_table.symbol_exists("x"))
|
||||||
{
|
{
|
||||||
|
@ -3140,22 +3344,22 @@ inline bool run_test10()
|
||||||
printf("run_test10() - Symbol 'yy' does not exist!\n");
|
printf("run_test10() - Symbol 'yy' does not exist!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!test::variable(symbol_table,"x",x))
|
else if (!test::variable(symbol_table, "x", x))
|
||||||
{
|
{
|
||||||
printf("run_test10() - Symbol 'x' value failure!\n");
|
printf("run_test10() - Symbol 'x' value failure!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!test::variable(symbol_table,"y",y))
|
else if (!test::variable(symbol_table, "y", y))
|
||||||
{
|
{
|
||||||
printf("run_test10() - Symbol 'y' value failure!\n");
|
printf("run_test10() - Symbol 'y' value failure!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!test::variable(symbol_table,"xx",xx))
|
else if (!test::variable(symbol_table, "xx", xx))
|
||||||
{
|
{
|
||||||
printf("run_test10() - Symbol 'xx' value failure!\n");
|
printf("run_test10() - Symbol 'xx' value failure!\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (!test::variable(symbol_table,"yy",yy))
|
else if (!test::variable(symbol_table, "yy", yy))
|
||||||
{
|
{
|
||||||
printf("run_test10() - Symbol 'yy' value failure!\n");
|
printf("run_test10() - Symbol 'yy' value failure!\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -3187,8 +3391,8 @@ inline bool run_test10()
|
||||||
{
|
{
|
||||||
myfunc<T> mf;
|
myfunc<T> mf;
|
||||||
|
|
||||||
symbol_table.add_function("f",mf);
|
symbol_table.add_function("f", mf);
|
||||||
symbol_table.add_function("f1",mf);
|
symbol_table.add_function("f1", mf);
|
||||||
|
|
||||||
if (!symbol_table.symbol_exists("f"))
|
if (!symbol_table.symbol_exists("f"))
|
||||||
{
|
{
|
||||||
|
@ -3215,11 +3419,11 @@ inline bool run_test10()
|
||||||
|
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
symbol_table.add_stringvar("i",i);
|
symbol_table.add_stringvar("i", i_s);
|
||||||
symbol_table.add_stringvar("j",j);
|
symbol_table.add_stringvar("j", j_s);
|
||||||
|
|
||||||
symbol_table.add_stringvar("ii",ii);
|
symbol_table.add_stringvar("ii", ii_s);
|
||||||
symbol_table.add_stringvar("jj",jj);
|
symbol_table.add_stringvar("jj", jj_s);
|
||||||
|
|
||||||
if (!symbol_table.symbol_exists("i"))
|
if (!symbol_table.symbol_exists("i"))
|
||||||
{
|
{
|
||||||
|
@ -3241,22 +3445,22 @@ inline bool run_test10()
|
||||||
printf("run_test10() - String 'jj' does not exist!\n");
|
printf("run_test10() - String 'jj' does not exist!\n");
|
||||||
return false;
|
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");
|
printf("run_test10() - String 'i' value failure!\n");
|
||||||
return false;
|
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");
|
printf("run_test10() - String 'j' value failure!\n");
|
||||||
return false;
|
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");
|
printf("run_test10() - String 'ii' value failure!\n");
|
||||||
return false;
|
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");
|
printf("run_test10() - String 'jj' value failure!\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -3287,17 +3491,17 @@ inline bool run_test10()
|
||||||
{
|
{
|
||||||
symbol_table.add_variable("x", x);
|
symbol_table.add_variable("x", x);
|
||||||
symbol_table.add_variable("y", y);
|
symbol_table.add_variable("y", y);
|
||||||
symbol_table.add_variable("xx",xx);
|
symbol_table.add_variable("xx", xx);
|
||||||
symbol_table.add_variable("yy",yy);
|
symbol_table.add_variable("yy", yy);
|
||||||
|
|
||||||
std::vector<std::string> expected_var_list;
|
std::vector<std::string> expected_var_list;
|
||||||
|
|
||||||
expected_var_list.push_back( "x");
|
expected_var_list.push_back("x");
|
||||||
expected_var_list.push_back( "y");
|
expected_var_list.push_back("y");
|
||||||
expected_var_list.push_back("xx");
|
expected_var_list.push_back("xx");
|
||||||
expected_var_list.push_back("yy");
|
expected_var_list.push_back("yy");
|
||||||
|
|
||||||
std::deque<std::pair<std::string,T> > variable_list;
|
std::deque<std::pair<std::string, T> > variable_list;
|
||||||
|
|
||||||
symbol_table.get_variable_list(variable_list);
|
symbol_table.get_variable_list(variable_list);
|
||||||
|
|
||||||
|
@ -3332,13 +3536,13 @@ inline bool run_test10()
|
||||||
{
|
{
|
||||||
symbol_table.add_variable("x", x);
|
symbol_table.add_variable("x", x);
|
||||||
symbol_table.add_variable("y", y);
|
symbol_table.add_variable("y", y);
|
||||||
symbol_table.add_variable("xx",xx);
|
symbol_table.add_variable("xx", xx);
|
||||||
symbol_table.add_variable("yy",yy);
|
symbol_table.add_variable("yy", yy);
|
||||||
|
|
||||||
std::vector<std::string> expected_var_list;
|
std::vector<std::string> expected_var_list;
|
||||||
|
|
||||||
expected_var_list.push_back( "x");
|
expected_var_list.push_back("x");
|
||||||
expected_var_list.push_back( "y");
|
expected_var_list.push_back("y");
|
||||||
expected_var_list.push_back("xx");
|
expected_var_list.push_back("xx");
|
||||||
expected_var_list.push_back("yy");
|
expected_var_list.push_back("yy");
|
||||||
|
|
||||||
|
@ -3375,19 +3579,19 @@ inline bool run_test10()
|
||||||
|
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
symbol_table.add_stringvar( "i", i);
|
symbol_table.add_stringvar("i", i_s);
|
||||||
symbol_table.add_stringvar( "j", j);
|
symbol_table.add_stringvar("j", j_s);
|
||||||
symbol_table.add_stringvar("ii",ii);
|
symbol_table.add_stringvar("ii", ii_s);
|
||||||
symbol_table.add_stringvar("jj",jj);
|
symbol_table.add_stringvar("jj", jj_s);
|
||||||
|
|
||||||
std::vector<std::string> expected_var_list;
|
std::vector<std::string> expected_var_list;
|
||||||
|
|
||||||
expected_var_list.push_back( "i");
|
expected_var_list.push_back("i");
|
||||||
expected_var_list.push_back( "j");
|
expected_var_list.push_back("j");
|
||||||
expected_var_list.push_back("ii");
|
expected_var_list.push_back("ii");
|
||||||
expected_var_list.push_back("jj");
|
expected_var_list.push_back("jj");
|
||||||
|
|
||||||
std::deque<std::pair<std::string,std::string> > stringvar_list;
|
std::deque<std::pair<std::string, std::string> > stringvar_list;
|
||||||
|
|
||||||
symbol_table.get_stringvar_list(stringvar_list);
|
symbol_table.get_stringvar_list(stringvar_list);
|
||||||
|
|
||||||
|
@ -3420,15 +3624,15 @@ inline bool run_test10()
|
||||||
|
|
||||||
for (std::size_t r = 0; r < rounds; ++r)
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
{
|
{
|
||||||
symbol_table.add_stringvar( "i", i);
|
symbol_table.add_stringvar("i", i_s);
|
||||||
symbol_table.add_stringvar( "j", j);
|
symbol_table.add_stringvar("j", j_s);
|
||||||
symbol_table.add_stringvar("ii",ii);
|
symbol_table.add_stringvar("ii", ii_s);
|
||||||
symbol_table.add_stringvar("jj",jj);
|
symbol_table.add_stringvar("jj", jj_s);
|
||||||
|
|
||||||
std::vector<std::string> expected_var_list;
|
std::vector<std::string> expected_var_list;
|
||||||
|
|
||||||
expected_var_list.push_back( "i");
|
expected_var_list.push_back("i");
|
||||||
expected_var_list.push_back( "j");
|
expected_var_list.push_back("j");
|
||||||
expected_var_list.push_back("ii");
|
expected_var_list.push_back("ii");
|
||||||
expected_var_list.push_back("jj");
|
expected_var_list.push_back("jj");
|
||||||
|
|
||||||
|
@ -3468,6 +3672,7 @@ inline bool run_test10()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
T x0 = T(0);
|
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];"
|
"2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; return [i * 8];"
|
||||||
"i += 1; i += 2; i += 3; } else i; }",
|
"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} })",
|
"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) { ~{break[i]; continue; i += i} })",
|
||||||
"0 == (for (var i := 0; i < 10; i += 1) { ~{continue; break[7]; 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()
|
va_func()
|
||||||
{
|
{
|
||||||
exprtk::enable_zero_parameters(*this);
|
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)
|
inline T operator()(const std::vector<T>& arglist)
|
||||||
|
@ -5084,12 +5294,13 @@ struct inc_func : public exprtk::igeneric_function<T>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct rem_space_and_uppercase : public exprtk::igeneric_function<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> igenfunc_t;
|
||||||
typedef typename exprtk::igeneric_function<T>::parameter_list_t parameter_list_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;
|
typedef typename generic_type::string_view string_t;
|
||||||
|
|
||||||
rem_space_and_uppercase()
|
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)
|
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)
|
for (std::size_t i = 0; i < string.size(); ++i)
|
||||||
{
|
{
|
||||||
if (' ' != (c = string[i]))
|
if (' ' != (c = string[i]))
|
||||||
result += std::toupper(c);
|
result += static_cast<char>(std::toupper(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
return T(0);
|
return T(0);
|
||||||
|
@ -5613,7 +5824,7 @@ inline bool run_test18()
|
||||||
symbol_table.add_stringvar("s3", s3);
|
symbol_table.add_stringvar("s3", s3);
|
||||||
symbol_table.add_stringvar("s4", s4);
|
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 '; "
|
std::string program = " s0 := 'How now '; "
|
||||||
" s1 := 'brown cow?'; "
|
" 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
|
ExprTk supports three fundamental types which can be used freely in
|
||||||
expressions. The types are as follows:
|
expressions. The types are as follows:
|
||||||
|
|
||||||
1. Scalar
|
(1) Scalar
|
||||||
2. Vector
|
(2) Vector
|
||||||
3. String
|
(3) String
|
||||||
|
|
||||||
|
|
||||||
(1) Scalar Type
|
(1) Scalar Type
|
||||||
|
@ -706,7 +706,7 @@ current values assigned to the variables will be used.
|
||||||
expression.value(); // 3.7 * -9 + 3
|
expression.value(); // 3.7 * -9 + 3
|
||||||
|
|
||||||
// 'x * -9 + 3' for x in range of [0,100) in steps of 0.0001
|
// '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
|
expression.value(); // x * -9 + 3
|
||||||
}
|
}
|
||||||
|
@ -860,7 +860,10 @@ handle:
|
||||||
(i) '*' '=' ---> '*=' (multiplication assignment)
|
(i) '*' '=' ---> '*=' (multiplication assignment)
|
||||||
(j) '/' '=' ---> '/=' (division assignment)
|
(j) '/' '=' ---> '/=' (division assignment)
|
||||||
(k) '%' '=' ---> '%=' (modulo 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:
|
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
|
attempt at computing the average between x and y will be transformed
|
||||||
as follows:
|
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
|
There may be situations where the above transformation will cause
|
||||||
numerical overflows and that the original form of the expression is
|
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:
|
There are five types of function interface:
|
||||||
|
|
||||||
(1) ifunction
|
+---+----------------------+-------------+
|
||||||
(2) ivararg_function
|
| # | Name | Return Type |
|
||||||
(3) igeneric_function
|
+---+----------------------+-------------+
|
||||||
(4) igeneric_function II
|
| 1 | ifunction | Scalar |
|
||||||
(5) function_compositor
|
| 2 | ivararg_function | Scalar |
|
||||||
|
| 3 | igeneric_function | Scalar |
|
||||||
|
| 4 | igeneric_function II | String |
|
||||||
|
| 5 | function_compositor | Scalar |
|
||||||
|
+---+----------------------+-------------+
|
||||||
|
|
||||||
|
|
||||||
(1) ifunction
|
(1) ifunction
|
||||||
|
@ -1446,17 +1453,21 @@ the string return type function operator being explicitly overridden:
|
||||||
typedef typename generic_t::string_view string_t;
|
typedef typename generic_t::string_view string_t;
|
||||||
|
|
||||||
toupper()
|
toupper()
|
||||||
: exprtk::igeneric_function<T>("S")
|
: exprtk::igeneric_function<T>("S",igenfunct_t::e_rtrn_string)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline T operator()(std::string& result,
|
inline T operator()(std::string& result,
|
||||||
parameter_list_t parameters)
|
parameter_list_t parameters)
|
||||||
{
|
{
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
|
string_t string(params[0]);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < string.size(); ++i)
|
for (std::size_t i = 0; i < string.size(); ++i)
|
||||||
{
|
{
|
||||||
result += std::toupper(string[i]);
|
result += std::toupper(string[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return T(0);
|
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
|
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. Furthermore a second parameter
|
||||||
return as a result a copy of the input string converted to uppercase
|
is passed to the constructor indicating that it should be treated as a
|
||||||
form. An example expression using the toupper function registered as
|
string returning function - by default it is assumed to be a scalar
|
||||||
the symbol 'toupper' is as follows:
|
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')"
|
"'ABCDEF' == toupper('aBc') + toupper('DeF')"
|
||||||
|
|
||||||
|
|
||||||
Note: When adding a string type returning generic function to a symbol
|
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. The example below demonstrates
|
||||||
(e_ft_strfunc) that denotes the function should be treated as a string
|
how this can be done:
|
||||||
returning function type. The following example demonstrates how this
|
|
||||||
is done:
|
|
||||||
|
|
||||||
toupper<T> tu;
|
toupper<T> tu;
|
||||||
|
|
||||||
exprtk::symbol_table<T> symbol_table;
|
exprtk::symbol_table<T> symbol_table;
|
||||||
|
|
||||||
symbol_table.add_function("toupper",
|
symbol_table.add_function("toupper",tu);
|
||||||
tu,
|
|
||||||
symbol_table_t::e_ft_strfunc);
|
|
||||||
|
|
||||||
|
|
||||||
Note: Two further refinements to the type checking facility are the
|
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)
|
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)
|
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
|
completed, the caller can then obtain a list of symbols and their
|
||||||
associated types from the DEC.
|
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
|
The following example demonstrates usage of the DEC in determining the
|
||||||
dependents of the given expression:
|
dependents of the given expression:
|
||||||
|
|
||||||
|
@ -1766,9 +1785,15 @@ dependents of the given expression:
|
||||||
std::string expression_string =
|
std::string expression_string =
|
||||||
"z := abs(x + sin(2 * pi / y))";
|
"z := abs(x + sin(2 * pi / y))";
|
||||||
|
|
||||||
|
T x,y,z;
|
||||||
|
|
||||||
parser_t parser;
|
parser_t parser;
|
||||||
symbol_table_t symbol_table;
|
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_t expression;
|
||||||
expression.register_symbol_table(symbol_table);
|
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
|
(std::string) and the associated type of the symbol as denoted by the
|
||||||
cases in the switch statement.
|
cases in the switch statement.
|
||||||
|
|
||||||
|
@ -1866,6 +1891,9 @@ grammar. The features fall into one of the following three categories:
|
||||||
(1) Base Functions
|
(1) Base Functions
|
||||||
(2) Control Flow Structures
|
(2) Control Flow Structures
|
||||||
(3) Logical Operators
|
(3) Logical Operators
|
||||||
|
(4) Arithmetic Operators
|
||||||
|
(5) Inequality Operators
|
||||||
|
(6) Assignment Operators
|
||||||
|
|
||||||
|
|
||||||
(1) Base Functions
|
(1) Base Functions
|
||||||
|
@ -1967,13 +1995,13 @@ flow structure:
|
||||||
" } ";
|
" } ";
|
||||||
|
|
||||||
parser.settings()
|
parser.settings()
|
||||||
.disable_all_control_structures(settings_t::e_ctrl_for_loop);
|
.disable_control_structure(settings_t::e_ctrl_for_loop);
|
||||||
|
|
||||||
parser
|
parser
|
||||||
.compile(program,expression); // failure
|
.compile(program,expression); // failure
|
||||||
|
|
||||||
parser.settings()
|
parser.settings()
|
||||||
.enable_all_control_structures(settings_t::e_ctrl_for_loop);
|
.enable_control_structure(settings_t::e_ctrl_for_loop);
|
||||||
|
|
||||||
parser
|
parser
|
||||||
.compile(program,expression); // success
|
.compile(program,expression); // success
|
||||||
|
@ -2009,18 +2037,158 @@ example demonstrates the disabling of the 'and' logical operator:
|
||||||
expression_t expression;
|
expression_t expression;
|
||||||
|
|
||||||
parser.settings()
|
parser.settings()
|
||||||
.disable_base_function(settings_t::e_logic_and);
|
.disable_logic_operation(settings_t::e_logic_and);
|
||||||
|
|
||||||
parser
|
parser
|
||||||
.compile("1 or not(0 and 1)",expression); // failure
|
.compile("1 or not(0 and 1)",expression); // failure
|
||||||
|
|
||||||
parser.settings()
|
parser.settings()
|
||||||
.enable_base_function(settings_t::e_logic_and);
|
.enable_logic_operation(settings_t::e_logic_and);
|
||||||
|
|
||||||
parser
|
parser
|
||||||
.compile("1 or not(0 and 1)",expression); // success
|
.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
|
Note: In the event of a base function being disabled, one can redefine
|
||||||
the base function using the standard custom function definition
|
the base function using the standard custom function definition
|
||||||
process. In the following example the 'sin' function is disabled then
|
process. In the following example the 'sin' function is disabled then
|
||||||
|
@ -2161,7 +2329,7 @@ following example:
|
||||||
if (!parser.compile(expression_string,expression))
|
if (!parser.compile(expression_string,expression))
|
||||||
{
|
{
|
||||||
printf("Error: %s\n", parser.error().c_str());
|
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());
|
error.diagnostic.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2214,7 +2382,7 @@ demonstrated by the following example:
|
||||||
error.column_no);
|
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
|
When building ExprTk there are a number of defines that will enable or
|
||||||
disable certain features and capabilities. The defines can either be
|
disable certain features and capabilities. The defines can either be
|
||||||
part of a compiler command line switch or scoped around the include to
|
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
|
(1) exprtk_enable_debugging
|
||||||
This define will enable printing of debug information to stdout during
|
This define will enable printing of debug information to stdout during
|
||||||
|
|
Loading…
Reference in New Issue