我正在尝试为布尔表达式创建一个解析器。表达式中的符号是从类似XML的数据结构中读取的。
为
之类的东西实现解析器很简单a.b == 'some value'
使用&#34;未知符号解析器使用ExprTK&#34;通过返回<a><b>some value</b></a>
的字符串值将a.b解析为字符串。
但现在考虑XML <a><b>5</b></a>
有没有办法编写一个允许评估a.b == 5
和a.b == '5'
的未知符号解析器?
答案 0 :(得分:7)
最初,在ExprTk中,变量(用户定义或表达式本地)只能是一种类型(标量,字符串或矢量标量)。所以如果你的表达是:
a.b == 5
然后这是一个无效的表达式,因为变量a.b只能有一个类型 - 标量或字符串,但不能同时包含两者。
但是,如果你想要两个单独的表达式使用相同的变量名但在不同的上下文中,如下所示:
a.b == '5'
var_x := 2; var_x + 7
str_y := 'abc'; str_y + '123' == 'abc123'
然后是,ExprTk的USR(未知符号解析器)功能确实提供了一种在调用期间确定未知符号类型的方法 USR 回调,允许正确编译表达式。
举个例子,我们假设我们要定义一个仅用前缀 &#34; var _&#34; 来解析未知符号的USR和 &#34; str _&#34; 分别包含Scalar和String类型。
示例表达式可能如下所示:
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::parser<double> parser_t;
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;
//Is this unknown symbol in the format var_xyz ?
if (0 == unknown_symbol.find("var_"))
{
const T default_scalar = T(0);
result = symbol_table.create_variable(unknown_symbol, default_scalar);
if (!result)
{
error_message =
"Failed to create variable(" + unknown_symbol + ") in primary symbol table";
}
}
//Is this unknown symbol in the format str_xyz ?
else if (0 == unknown_symbol.find("str_"))
{
const std::string default_string = "N/A";
result = symbol_table.create_stringvar(unknown_symbol,default_string)
if (!result)
{
error_message =
"Failed to create string variable(" + unknown_symbol + ") in primary symbol table";
}
}
else
error_message = "Indeterminable symbol type.";
return result;
}
};
以下是一个使用扩展回调机制的USR示例,它将解析上述格式的变量,并将它们添加到正在解析的表达式的主符号表中:
PIVOT
其余的代码是相同的:一个用解析器注册实例化的USR,然后用所述解析器继续编译它们的表达式。
有关详细信息,请查看 Section 18 - Unknown Unknowns