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

This commit is contained in:
Arash Partow 2015-08-12 06:28:07 +10:00
parent 3f228b3f86
commit 16a0e6b5ee
3 changed files with 2086 additions and 835 deletions

1522
exprtk.hpp

File diff suppressed because it is too large Load Diff

View File

@ -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?'; "

View File

@ -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