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

This commit is contained in:
Arash Partow 2017-04-12 14:35:13 +10:00
parent 63c2644981
commit a2af37c630
2 changed files with 174 additions and 46 deletions

View File

@ -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();
}

View File

@ -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.
| | | |
| +--<--- [,] <-----+ |
| |
+-------------------------------------------------------------+
+-------------------------------------------------------------+