Skip to content

Commit 398de25

Browse files
committed
Updates to ExprTk
1 parent e019d4d commit 398de25

File tree

2 files changed

+217
-33
lines changed

2 files changed

+217
-33
lines changed

exprtk/exprtk.hpp

Lines changed: 136 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3788,6 +3788,91 @@ namespace exprtk
37883788
std::vector<std::pair<lexer::token,lexer::token> > error_list_;
37893789
};
37903790

3791+
class sequence_validator_3tokens : public lexer::token_scanner
3792+
{
3793+
private:
3794+
3795+
typedef lexer::token::token_type token_t;
3796+
typedef std::pair<token_t,std::pair<token_t,token_t>> token_triplet_t;
3797+
typedef std::set<token_triplet_t> set_t;
3798+
3799+
public:
3800+
3801+
using lexer::token_scanner::operator();
3802+
3803+
sequence_validator_3tokens()
3804+
: lexer::token_scanner(3)
3805+
{
3806+
add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number);
3807+
add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string);
3808+
add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
3809+
3810+
add_invalid(lexer::token::e_add ,lexer::token::e_add , lexer::token::e_add);
3811+
add_invalid(lexer::token::e_sub ,lexer::token::e_sub , lexer::token::e_sub);
3812+
add_invalid(lexer::token::e_div ,lexer::token::e_div , lexer::token::e_div);
3813+
add_invalid(lexer::token::e_mul ,lexer::token::e_mul , lexer::token::e_mul);
3814+
add_invalid(lexer::token::e_mod ,lexer::token::e_mod , lexer::token::e_mod);
3815+
add_invalid(lexer::token::e_pow ,lexer::token::e_pow , lexer::token::e_pow);
3816+
3817+
add_invalid(lexer::token::e_add ,lexer::token::e_sub , lexer::token::e_add);
3818+
add_invalid(lexer::token::e_sub ,lexer::token::e_add , lexer::token::e_sub);
3819+
add_invalid(lexer::token::e_div ,lexer::token::e_mul , lexer::token::e_div);
3820+
add_invalid(lexer::token::e_mul ,lexer::token::e_div , lexer::token::e_mul);
3821+
add_invalid(lexer::token::e_mod ,lexer::token::e_pow , lexer::token::e_mod);
3822+
add_invalid(lexer::token::e_pow ,lexer::token::e_mod , lexer::token::e_pow);
3823+
}
3824+
3825+
bool result()
3826+
{
3827+
return error_list_.empty();
3828+
}
3829+
3830+
bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3831+
{
3832+
const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3833+
3834+
if (invalid_comb_.find(p) != invalid_comb_.end())
3835+
{
3836+
error_list_.push_back(std::make_pair(t0,t1));
3837+
}
3838+
3839+
return true;
3840+
}
3841+
3842+
std::size_t error_count() const
3843+
{
3844+
return error_list_.size();
3845+
}
3846+
3847+
std::pair<lexer::token,lexer::token> error(const std::size_t index)
3848+
{
3849+
if (index < error_list_.size())
3850+
{
3851+
return error_list_[index];
3852+
}
3853+
else
3854+
{
3855+
static const lexer::token error_token;
3856+
return std::make_pair(error_token,error_token);
3857+
}
3858+
}
3859+
3860+
void clear_errors()
3861+
{
3862+
error_list_.clear();
3863+
}
3864+
3865+
private:
3866+
3867+
void add_invalid(token_t t0, token_t t1, token_t t2)
3868+
{
3869+
invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3870+
}
3871+
3872+
set_t invalid_comb_;
3873+
std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3874+
};
3875+
37913876
struct helper_assembly
37923877
{
37933878
inline bool register_scanner(lexer::token_scanner* scanner)
@@ -19908,7 +19993,8 @@ namespace exprtk
1990819993

1990919994
if (settings_.sequence_check_enabled())
1991019995
{
19911-
helper_assembly_.register_scanner(&sequence_validator_);
19996+
helper_assembly_.register_scanner(&sequence_validator_ );
19997+
helper_assembly_.register_scanner(&sequence_validator_3tkns_);
1991219998
}
1991319999
}
1991420000
}
@@ -20084,9 +20170,10 @@ namespace exprtk
2008420170
{
2008520171
if (helper_assembly_.error_token_scanner)
2008620172
{
20087-
lexer::helper::bracket_checker* bracket_checker_ptr = 0;
20088-
lexer::helper::numeric_checker* numeric_checker_ptr = 0;
20089-
lexer::helper::sequence_validator* sequence_validator_ptr = 0;
20173+
lexer::helper::bracket_checker* bracket_checker_ptr = 0;
20174+
lexer::helper::numeric_checker* numeric_checker_ptr = 0;
20175+
lexer::helper::sequence_validator* sequence_validator_ptr = 0;
20176+
lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
2009020177

2009120178
if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
2009220179
{
@@ -20134,6 +20221,26 @@ namespace exprtk
2013420221
sequence_validator_ptr->clear_errors();
2013520222
}
2013620223
}
20224+
else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
20225+
{
20226+
for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
20227+
{
20228+
std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
20229+
20230+
set_error(
20231+
make_error(parser_error::e_token,
20232+
error_token.first,
20233+
"ERR007 - Invalid token sequence: '" +
20234+
error_token.first.value + "' and '" +
20235+
error_token.second.value + "'",
20236+
exprtk_error_location));
20237+
}
20238+
20239+
if (sequence_validator3_ptr->error_count())
20240+
{
20241+
sequence_validator3_ptr->clear_errors();
20242+
}
20243+
}
2013720244
}
2013820245

2013920246
return false;
@@ -24055,10 +24162,14 @@ namespace exprtk
2405524162
if (null_initialisation)
2405624163
result = expression_generator_(T(0.0));
2405724164
else if (vec_to_vec_initialiser)
24165+
{
24166+
expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
24167+
2405824168
result = expression_generator_(
2405924169
details::e_assign,
24060-
node_allocator_.allocate<vector_node_t>(vec_holder),
24170+
vec_node,
2406124171
vec_initilizer_list[0]);
24172+
}
2406224173
else
2406324174
result = node_allocator_
2406424175
.allocate<details::vector_assignment_node<T> >(
@@ -26293,15 +26404,19 @@ namespace exprtk
2629326404
return (*this)(operation,branch);
2629426405
}
2629526406

26296-
inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
26407+
inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
2629726408
{
26298-
if ((0 == b0) || (0 == b1))
26299-
return error_node();
26300-
else
26409+
expression_node_ptr result = error_node();
26410+
26411+
if ((0 != b0) && (0 != b1))
2630126412
{
2630226413
expression_node_ptr branch[2] = { b0, b1 };
26303-
return expression_generator<Type>::operator()(operation,branch);
26414+
result = expression_generator<Type>::operator()(operation, branch);
26415+
b0 = branch[0];
26416+
b1 = branch[1];
2630426417
}
26418+
26419+
return result;
2630526420
}
2630626421

2630726422
inline expression_node_ptr conditional(expression_node_ptr condition,
@@ -34672,13 +34787,14 @@ namespace exprtk
3467234787

3467334788
lexer::helper::helper_assembly helper_assembly_;
3467434789

34675-
lexer::helper::commutative_inserter commutative_inserter_;
34676-
lexer::helper::operator_joiner operator_joiner_2_;
34677-
lexer::helper::operator_joiner operator_joiner_3_;
34678-
lexer::helper::symbol_replacer symbol_replacer_;
34679-
lexer::helper::bracket_checker bracket_checker_;
34680-
lexer::helper::numeric_checker numeric_checker_;
34681-
lexer::helper::sequence_validator sequence_validator_;
34790+
lexer::helper::commutative_inserter commutative_inserter_;
34791+
lexer::helper::operator_joiner operator_joiner_2_;
34792+
lexer::helper::operator_joiner operator_joiner_3_;
34793+
lexer::helper::symbol_replacer symbol_replacer_;
34794+
lexer::helper::bracket_checker bracket_checker_;
34795+
lexer::helper::numeric_checker numeric_checker_;
34796+
lexer::helper::sequence_validator sequence_validator_;
34797+
lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
3468234798

3468334799
template <typename ParserType>
3468434800
friend void details::disable_type_checking(ParserType& p);
@@ -38236,9 +38352,9 @@ namespace exprtk
3823638352
namespace information
3823738353
{
3823838354
static const char* library = "Mathematical Expression Toolkit";
38239-
static const char* version = "2.718281828459045235360287471352662497757247093699"
38240-
"95957496696762772407663035354759457138217852516642";
38241-
static const char* date = "20180913";
38355+
static const char* version = "2.7182818284590452353602874713526624977572470936999"
38356+
"595749669676277240766303535475945713821785251664274";
38357+
static const char* date = "20181216";
3824238358

3824338359
static inline std::string data()
3824438360
{

exprtk/exprtk_test.cpp

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,10 @@ inline bool run_test02()
26742674
template <typename T>
26752675
inline bool run_test03()
26762676
{
2677+
typedef exprtk::symbol_table<T> symbol_table_t;
2678+
typedef exprtk::expression<T> expression_t;
2679+
typedef exprtk::parser<T> parser_t;
2680+
26772681
std::string expression_string = "A+A0+aA+Aa0+b+B1+Bb+bB1+A+A0+AA+AA0+B+B1+BB+BB1+a+a0+aa+aa0+b+b1+bb+bb1+"
26782682
"c+C2+Cc+Cc2+D+D3+dD+dD3+C+C2+CC+CC2+D+D3+DD+DD3+c+c2+cc+cc2+d+d3+dd+dd3+"
26792683
"E+E4+eE+Ee4+f+F5+Ff+fF5+E+E4+EE+EE4+F+F5+FF+FF5+e+e4+ee+ee4+f+f5+ff+ff5+"
@@ -2711,9 +2715,9 @@ inline bool run_test03()
27112715

27122716
for (std::size_t r = 0; r < rounds; ++r)
27132717
{
2714-
exprtk::symbol_table<T> symbol_table_0;
2715-
exprtk::symbol_table<T> symbol_table_1;
2716-
exprtk::expression<T> expression;
2718+
symbol_table_t symbol_table_0;
2719+
symbol_table_t symbol_table_1;
2720+
expression_t expression;
27172721

27182722
std::vector<T> v;
27192723
v.resize(variable_list_size);
@@ -2812,25 +2816,34 @@ inline bool run_test03()
28122816
"1 v y",
28132817
"x v 1",
28142818
"y v 1",
2815-
2819+
28162820
"(x == 'a string' )",
28172821
"(x == 'a string'[1:2] )",
28182822
"(x == 'a string' + 'b string' )",
28192823
"(x == ('a string' + 'b string')[3:5])",
28202824
"('a string' == x )",
28212825
"('a string'[1:2] == x )",
28222826
"('a string' + 'b string' == x )",
2823-
"(('a string' + 'b string')[3:5] == x)"
2827+
"(('a string' + 'b string')[3:5] == x)",
2828+
2829+
"var a; var b; 3in(a)+sin(b) ",
2830+
"var a; var b; sin(a)+3in(b) ",
2831+
"var a; var b; sqrt(a)<3in(8) ",
2832+
"var a; var b; (1.99-3in((b-b))) ",
2833+
"var a; var b; ((3in(sin((b+b)))/1.06)-a) ",
2834+
"var a; var b; ((sin(3in((b+b)))/1.06)-a) ",
2835+
"var a; var b; (3in(x*(y+z))+cos(x*(y-z))) ",
2836+
"var a; var b; (cos(x*(y+z))+3in(x*(y-z))) "
28242837
};
28252838

28262839
const std::size_t invalid_expr_size = sizeof(invalid_expr) / sizeof(std::string);
28272840

28282841
{
28292842
for (std::size_t i = 0; i < invalid_expr_size; ++i)
28302843
{
2831-
exprtk::symbol_table<T> symbol_table;
2832-
2833-
exprtk::expression<T> expression;
2844+
symbol_table_t symbol_table;
2845+
expression_t expression;
2846+
parser_t parser;
28342847

28352848
T x = T(0);
28362849
std::string s;
@@ -2840,8 +2853,6 @@ inline bool run_test03()
28402853
symbol_table.add_stringvar("s",s);
28412854
symbol_table.add_vector ("v",v);
28422855

2843-
exprtk::parser<T> parser;
2844-
28452856
if (parser.compile(invalid_expr[i],expression))
28462857
{
28472858
printf("run_test03() - Error: [1] Invalid expression compiled successfuly. Expression: %s\n",
@@ -2857,14 +2868,13 @@ inline bool run_test03()
28572868
std::string s;
28582869
std::vector<T> v(10, T(1.234));
28592870

2860-
exprtk::symbol_table<T> symbol_table;
2871+
symbol_table_t symbol_table;
2872+
parser_t parser;
28612873

28622874
symbol_table.add_variable ("x",x);
28632875
symbol_table.add_stringvar("s",s);
28642876
symbol_table.add_vector ("v",v);
28652877

2866-
exprtk::parser<T> parser;
2867-
28682878
for (std::size_t i = 0; i < invalid_expr_size; ++i)
28692879
{
28702880
exprtk::expression<T> expression;
@@ -2878,6 +2888,64 @@ inline bool run_test03()
28782888
}
28792889
}
28802890
}
2891+
2892+
{
2893+
const std::string base_expression =
2894+
"1+(2+2(3+3(4+4cos(((((a+((x*(e-tan((cos((((((b/(tan(((1.60*a)-0.34))-0.76))-x)+y)-3.27)+a))/pi))))^a))+y)*b)-e))+e)/z)+w)+"
2895+
"(((b+(a/((((tan((b*((((((a-(cos((cos(tan(((a+a)*3.33)))-b))/2.52))*x)/b)+3.07)^0.86)+b)))*3.95)/0.39)*y)+a)))*a)*z)";
2896+
2897+
const std::string mod =
2898+
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^+-/*,;:<>=%?[]{}() #&'\"\\\t\r\n";
2899+
2900+
symbol_table_t symbol_table;
2901+
expression_t expression;
2902+
parser_t parser;
2903+
2904+
T a = T(1.1 );
2905+
T b = T(2.2 );
2906+
T c = T(3.3 );
2907+
T d = T(4.5 );
2908+
T e = T(4.5 );
2909+
T x = T(2.123456);
2910+
T y = T(3.123456);
2911+
T z = T(4.123456);
2912+
T w = T(5.123456);
2913+
2914+
symbol_table.add_variable("a", a);
2915+
symbol_table.add_variable("b", b);
2916+
symbol_table.add_variable("c", c);
2917+
symbol_table.add_variable("d", d);
2918+
symbol_table.add_variable("e", e);
2919+
2920+
symbol_table.add_variable("x", x);
2921+
symbol_table.add_variable("y", y);
2922+
symbol_table.add_variable("z", z);
2923+
symbol_table.add_variable("w", w);
2924+
2925+
expression.register_symbol_table(symbol_table);
2926+
2927+
T total = T(0);
2928+
2929+
for (std::size_t j = 0; j < base_expression.size(); ++j)
2930+
{
2931+
std::string expression_str = base_expression;
2932+
const char old_c = base_expression[j];
2933+
2934+
for (std::size_t i = 0; i < mod.size(); ++i)
2935+
{
2936+
expression_str[j] = mod[i];
2937+
2938+
if (parser.compile(expression_str, expression))
2939+
{
2940+
total += expression.value();
2941+
}
2942+
}
2943+
2944+
expression_str[j] = old_c;
2945+
}
2946+
2947+
if (total == T(12345.6789)) { printf(" "); }
2948+
}
28812949
}
28822950

28832951
return true;

0 commit comments

Comments
 (0)