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
|
||||
};
|
||||
|
||||
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 bool process(const std::string& /*unknown_symbol*/,
|
||||
usr_symbol_type& st,
|
||||
T& default_value,
|
||||
std::string& error_message)
|
||||
usr_symbol_type& st,
|
||||
T& default_value,
|
||||
std::string& error_message)
|
||||
{
|
||||
if (e_usrmode_default != mode)
|
||||
return false;
|
||||
|
||||
st = e_usr_variable_type;
|
||||
default_value = T(0);
|
||||
error_message.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool process(const std::string& /* unknown_symbol */,
|
||||
symbol_table_t& /* symbol_table */,
|
||||
std::string& /* error_message */)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enum collect_type
|
||||
|
@ -19948,6 +19970,11 @@ namespace exprtk
|
|||
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()
|
||||
{
|
||||
resolve_unknown_symbol_ = false;
|
||||
|
@ -24539,63 +24566,93 @@ namespace exprtk
|
|||
{
|
||||
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;
|
||||
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();
|
||||
|
||||
switch (usr_symbol_type)
|
||||
if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
|
||||
{
|
||||
case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol,default_value);
|
||||
break;
|
||||
bool create_result = false;
|
||||
|
||||
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)
|
||||
switch (usr_symbol_type)
|
||||
{
|
||||
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(
|
||||
make_error(parser_error::e_symtab,
|
||||
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(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR184 - Undefined symbol: '" + symbol + "'"));
|
||||
"ERR185 - Undefined symbol: '" + symbol + "'"));
|
||||
|
||||
return error_node();
|
||||
}
|
||||
|
@ -24701,7 +24758,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_symtab,
|
||||
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();
|
||||
}
|
||||
|
@ -24726,7 +24783,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_numeric,
|
||||
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();
|
||||
}
|
||||
|
@ -24752,7 +24809,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR187 - Expected ')' instead of: '" + current_token().value + "'"));
|
||||
"ERR188 - Expected ')' instead of: '" + current_token().value + "'"));
|
||||
|
||||
free_node(node_allocator_,branch);
|
||||
|
||||
|
@ -24776,7 +24833,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR188 - Expected ']' instead of: '" + current_token().value + "'"));
|
||||
"ERR189 - Expected ']' instead of: '" + current_token().value + "'"));
|
||||
|
||||
free_node(node_allocator_,branch);
|
||||
|
||||
|
@ -24800,7 +24857,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR189 - Expected '}' instead of: '" + current_token().value + "'"));
|
||||
"ERR190 - Expected '}' instead of: '" + current_token().value + "'"));
|
||||
|
||||
free_node(node_allocator_,branch);
|
||||
|
||||
|
@ -24839,7 +24896,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR190 - Premature end of expression[1]"));
|
||||
"ERR191 - Premature end of expression[1]"));
|
||||
|
||||
return error_node();
|
||||
}
|
||||
|
@ -24848,7 +24905,7 @@ namespace exprtk
|
|||
set_error(
|
||||
make_error(parser_error::e_syntax,
|
||||
current_token(),
|
||||
"ERR191 - Premature end of expression[2]"));
|
||||
"ERR192 - Premature end of expression[2]"));
|
||||
|
||||
return error_node();
|
||||
}
|
||||
|
|
75
readme.txt
75
readme.txt
|
@ -2841,7 +2841,7 @@ simple user defined USR:
|
|||
T& default_value,
|
||||
std::string& error_message)
|
||||
{
|
||||
if (0 != unknown_symbol.find('var_'))
|
||||
if (0 != unknown_symbol.find("var_"))
|
||||
{
|
||||
error_message = "Invalid symbol: " + unknown_symbol;
|
||||
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
|
||||
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]
|
||||
|
@ -4658,4 +4729,4 @@ ExprTk and their structural representations.
|
|||
| | | |
|
||||
| +--<--- [,] <-----+ |
|
||||
| |
|
||||
+-------------------------------------------------------------+
|
||||
+-------------------------------------------------------------+
|
||||
|
|
Loading…
Reference in New Issue