C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
63c2644981
commit
a2af37c630
145
exprtk.hpp
145
exprtk.hpp
|
@ -18792,20 +18792,42 @@ namespace exprtk
|
||||||
e_usr_constant_type = 1
|
e_usr_constant_type = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum usr_mode
|
||||||
|
{
|
||||||
|
e_usrmode_default = 0,
|
||||||
|
e_usrmode_extended = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
usr_mode mode;
|
||||||
|
|
||||||
|
unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
|
||||||
|
: mode(m)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual ~unknown_symbol_resolver()
|
virtual ~unknown_symbol_resolver()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual bool process(const std::string& /*unknown_symbol*/,
|
virtual bool process(const std::string& /*unknown_symbol*/,
|
||||||
usr_symbol_type& st,
|
usr_symbol_type& st,
|
||||||
T& default_value,
|
T& default_value,
|
||||||
std::string& error_message)
|
std::string& error_message)
|
||||||
{
|
{
|
||||||
|
if (e_usrmode_default != mode)
|
||||||
|
return false;
|
||||||
|
|
||||||
st = e_usr_variable_type;
|
st = e_usr_variable_type;
|
||||||
default_value = T(0);
|
default_value = T(0);
|
||||||
error_message.clear();
|
error_message.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool process(const std::string& /* unknown_symbol */,
|
||||||
|
symbol_table_t& /* symbol_table */,
|
||||||
|
std::string& /* error_message */)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum collect_type
|
enum collect_type
|
||||||
|
@ -19948,6 +19970,11 @@ namespace exprtk
|
||||||
unknown_symbol_resolver_ = &default_usr_;
|
unknown_symbol_resolver_ = &default_usr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
|
||||||
|
{
|
||||||
|
enable_unknown_symbol_resolver(&usr);
|
||||||
|
}
|
||||||
|
|
||||||
inline void disable_unknown_symbol_resolver()
|
inline void disable_unknown_symbol_resolver()
|
||||||
{
|
{
|
||||||
resolve_unknown_symbol_ = false;
|
resolve_unknown_symbol_ = false;
|
||||||
|
@ -24539,63 +24566,93 @@ namespace exprtk
|
||||||
{
|
{
|
||||||
if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
|
if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
|
||||||
{
|
{
|
||||||
T default_value = T(0);
|
symbol_table_t& symtab = symtab_store_.get_symbol_table();
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
|
|
||||||
|
|
||||||
if (unknown_symbol_resolver_->process(symbol,usr_symbol_type,default_value,error_message))
|
if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
|
||||||
{
|
{
|
||||||
bool create_result = false;
|
T default_value = T(0);
|
||||||
|
typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
|
||||||
|
|
||||||
symbol_table_t& symtab = symtab_store_.get_symbol_table();
|
if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
|
||||||
|
|
||||||
switch (usr_symbol_type)
|
|
||||||
{
|
{
|
||||||
case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol,default_value);
|
bool create_result = false;
|
||||||
break;
|
|
||||||
|
|
||||||
case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol,default_value);
|
switch (usr_symbol_type)
|
||||||
break;
|
|
||||||
|
|
||||||
default : create_result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (create_result)
|
|
||||||
{
|
|
||||||
expression_node_ptr var = symtab_store_.get_variable(symbol);
|
|
||||||
|
|
||||||
if (var)
|
|
||||||
{
|
{
|
||||||
if (symtab_store_.is_constant_node(symbol))
|
case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default : create_result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create_result)
|
||||||
|
{
|
||||||
|
expression_node_ptr var = symtab_store_.get_variable(symbol);
|
||||||
|
|
||||||
|
if (var)
|
||||||
{
|
{
|
||||||
var = expression_generator_(var->value());
|
if (symtab_store_.is_constant_node(symbol))
|
||||||
|
{
|
||||||
|
var = expression_generator_(var->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
lodge_symbol(symbol,e_st_variable);
|
||||||
|
|
||||||
|
if (!post_variable_process(symbol))
|
||||||
|
return error_node();
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
lodge_symbol(symbol,e_st_variable);
|
|
||||||
|
|
||||||
if (!post_variable_process(symbol))
|
|
||||||
return error_node();
|
|
||||||
|
|
||||||
next_token();
|
|
||||||
|
|
||||||
return var;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_symtab,
|
make_error(parser_error::e_symtab,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR183 - Failed to create variable: '" + symbol + "'"));
|
"ERR183 - Failed to create variable: '" + symbol + "'" +
|
||||||
|
(error_message.empty() ? "" : " - " + error_message)));
|
||||||
|
|
||||||
return error_node();
|
|
||||||
}
|
}
|
||||||
|
else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
|
||||||
|
{
|
||||||
|
if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
|
||||||
|
{
|
||||||
|
static bool usr_extmode_active = false;
|
||||||
|
|
||||||
|
if (!usr_extmode_active)
|
||||||
|
{
|
||||||
|
usr_extmode_active = true;
|
||||||
|
expression_node_ptr result = parse_symtab_symbol();
|
||||||
|
usr_extmode_active = false;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_error(
|
||||||
|
make_error(parser_error::e_symtab,
|
||||||
|
current_token(),
|
||||||
|
"ERR184 - Failed to resolve symbol: '" + symbol + "'" +
|
||||||
|
(error_message.empty() ? "" : " - " + error_message)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_node();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR184 - Undefined symbol: '" + symbol + "'"));
|
"ERR185 - Undefined symbol: '" + symbol + "'"));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -24701,7 +24758,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_symtab,
|
make_error(parser_error::e_symtab,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR185 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value));
|
"ERR186 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -24726,7 +24783,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_numeric,
|
make_error(parser_error::e_numeric,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR186 - Failed to convert '" + current_token().value + "' to a number"));
|
"ERR187 - Failed to convert '" + current_token().value + "' to a number"));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -24752,7 +24809,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR187 - Expected ')' instead of: '" + current_token().value + "'"));
|
"ERR188 - Expected ')' instead of: '" + current_token().value + "'"));
|
||||||
|
|
||||||
free_node(node_allocator_,branch);
|
free_node(node_allocator_,branch);
|
||||||
|
|
||||||
|
@ -24776,7 +24833,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR188 - Expected ']' instead of: '" + current_token().value + "'"));
|
"ERR189 - Expected ']' instead of: '" + current_token().value + "'"));
|
||||||
|
|
||||||
free_node(node_allocator_,branch);
|
free_node(node_allocator_,branch);
|
||||||
|
|
||||||
|
@ -24800,7 +24857,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR189 - Expected '}' instead of: '" + current_token().value + "'"));
|
"ERR190 - Expected '}' instead of: '" + current_token().value + "'"));
|
||||||
|
|
||||||
free_node(node_allocator_,branch);
|
free_node(node_allocator_,branch);
|
||||||
|
|
||||||
|
@ -24839,7 +24896,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR190 - Premature end of expression[1]"));
|
"ERR191 - Premature end of expression[1]"));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
@ -24848,7 +24905,7 @@ namespace exprtk
|
||||||
set_error(
|
set_error(
|
||||||
make_error(parser_error::e_syntax,
|
make_error(parser_error::e_syntax,
|
||||||
current_token(),
|
current_token(),
|
||||||
"ERR191 - Premature end of expression[2]"));
|
"ERR192 - Premature end of expression[2]"));
|
||||||
|
|
||||||
return error_node();
|
return error_node();
|
||||||
}
|
}
|
||||||
|
|
75
readme.txt
75
readme.txt
|
@ -2841,7 +2841,7 @@ simple user defined USR:
|
||||||
T& default_value,
|
T& default_value,
|
||||||
std::string& error_message)
|
std::string& error_message)
|
||||||
{
|
{
|
||||||
if (0 != unknown_symbol.find('var_'))
|
if (0 != unknown_symbol.find("var_"))
|
||||||
{
|
{
|
||||||
error_message = "Invalid symbol: " + unknown_symbol;
|
error_message = "Invalid symbol: " + unknown_symbol;
|
||||||
return false;
|
return false;
|
||||||
|
@ -2884,6 +2884,77 @@ USR's process method will be invoked. The USR in the example will only
|
||||||
variables, all other unknown symbols will result in a compilation
|
variables, all other unknown symbols will result in a compilation
|
||||||
error being raised.
|
error being raised.
|
||||||
|
|
||||||
|
In the example above the callback of the USR that is invoked during
|
||||||
|
the unknown symbol resolution process only allows for scalar variables
|
||||||
|
to be defined and resolved - as that is the simplest and most common
|
||||||
|
form.
|
||||||
|
|
||||||
|
There is also an extended version of the callback that can be
|
||||||
|
overridden that will allow for more control and choice over the type
|
||||||
|
of symbol being resolved. The following is an example definition of
|
||||||
|
said extended callback:
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct my_usr : public parser_t::unknown_symbol_resolver
|
||||||
|
{
|
||||||
|
typedef typename parser_t::unknown_symbol_resolver usr_t;
|
||||||
|
|
||||||
|
my_usr()
|
||||||
|
: usr_t(usr_t::e_usrmode_extended)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual bool process(const std::string& unknown_symbol,
|
||||||
|
symbol_table_t& symbol_table,
|
||||||
|
std::string& error_message)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (0 == unknown_symbol.find("var_"))
|
||||||
|
{
|
||||||
|
// Default value of zero
|
||||||
|
result = symbol_table.create_variable(unknown_symbol,0);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
error_message = "Failed to create variable...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (0 == unknown_symbol.find("str_"))
|
||||||
|
{
|
||||||
|
// Default value of empty string
|
||||||
|
result = symbol_table.create_stringvar(unknown_symbol,"");
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
error_message = "Failed to create string variable...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error_message = "Indeterminable symbol type.";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
In the example above, the USR callback when invoked will pass the
|
||||||
|
primary symbol table associated with the expression being parsed. The
|
||||||
|
symbol resolution business logic can then determine under what
|
||||||
|
conditions a symbol will be resolved including its type (scalar,
|
||||||
|
string, vector etc) and default value. When the callback successfully
|
||||||
|
returns the symbol parsing and resolution process will again be
|
||||||
|
executed by the parser. The idea here is that given the primary symbol
|
||||||
|
table will now have the previously detected unknown symbol registered,
|
||||||
|
it will be correctly resolved and the general parsing processing can
|
||||||
|
then resume as per normal.
|
||||||
|
|
||||||
|
Note: In order to have the USR's extended mode callback be invoked It
|
||||||
|
is necessary to pass the e_usrmode_extended enum value during the
|
||||||
|
constructor of the user defined USR.
|
||||||
|
|
||||||
|
Note: The primary symbol table for an expression is the first symbol
|
||||||
|
table to be registered with that instance of the expression.
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
[SECTION 19 - ENABLING & DISABLING FEATURES]
|
[SECTION 19 - ENABLING & DISABLING FEATURES]
|
||||||
|
@ -4658,4 +4729,4 @@ ExprTk and their structural representations.
|
||||||
| | | |
|
| | | |
|
||||||
| +--<--- [,] <-----+ |
|
| +--<--- [,] <-----+ |
|
||||||
| |
|
| |
|
||||||
+-------------------------------------------------------------+
|
+-------------------------------------------------------------+
|
||||||
|
|
Loading…
Reference in New Issue