结构成员上的布尔表达式计算器



背景

我有一个结构:

struct event {
uint16_t id;
uint8_t type;
std::string name;
// many more fields (either string or integer types)
};

布尔表达式(存储在字符串中(:

name = "xyz" and (id = 10 or type = 5)

我有一个事件对象(数千(std::vector<event>的向量,想检查它们是否满足布尔表达式。

到目前为止我已经实施的事情

  • 我实现了一个标记化器和一个递归下降解析器,将布尔表达式转换为AST
  • 将终端存储为std::pair<std::string, std::string>,其中第一个值是结构字段名称,第二个值是值。例如,std::pair<"name", "acbd">
  • 我穿过树,每当它看到一个终端树节点时:
bool match(const event& ev, const ast::node& node) {
if (node.first == "name") {
return (ev.name == node.second);
} else if (node.first == "id") {
return (ev.id == std::stoi(node.second));
} else if (node.first == "type") {
return (ev.type == std::stoi(node.second));
} // more else if blocks for each member of event struct
...
}

问题

该结构包含10个成员。我想避免不必要的比较。在最坏的情况下,AST终端节点(例如,pair<"type", "5000">(可能导致10个比较。

我试着构建这个查找图:

std::map<std::string, std::size_t> fields;
fields["name"] = offsetof(event, name);
fields["id"] = offsetof(event, id);
fields["type"] = offsetof(event, type);

使用这个映射,我可以将match()简化为:

bool match(const event& ev, const ast::node& node) {
const auto offset = fields[node.first];
return ((ev + offset) == node.second); // DOESN'T WORK
}
  1. 我可以使用(eventObj + offset)访问偏移量处的结构成员。如何将其转换为正确的数据类型以便进行比较?

  2. 目前,AST终端节点中的所有字段值都是std::string。如何在标记化或解析步骤中将其转换为正确的类型?我可以将AST节点存储为std::pair<std::string, std::any>,但仍然需要std::any_cast的类型信息。

如果我能以某种方式将类型信息存储在字段映射中,这两个问题都可以解决。我不知道怎么做。

构建从字段名称到std::function<std::function<bool(event const&)>(std::string const&)>的映射,如:

lookup["name"]=[](auto str){
return [val=std::move(str)](auto& e){
return e.name==val;
};
};

现在您可以将您的配对转换为测试函数。

现在你的

name = "xyz" and (id = 10 or type = 5)

变为

tree(
lookup["name"]("xyz"), 
std::logical_and<>{},
tree(
lookup["id"]("17"),
std::logical_or<>{},
lookup["type"]("5")
)
);

成堆的工作。

相关内容

  • 没有找到相关文章