背景
我有一个结构:
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。
- 将终端存储为 a
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
}
我可以使用
(eventObj + offset)
. 如何将其转换为正确的数据类型以进行比较?目前,AST 终端节点中的所有字段值都是
std::string
. 如何在分词器或解析步骤中将其转换为正确的类型?我可以将 AST 节点存储为std::pair<std::string, std::any>
但仍需要std::any_cast
.
如果我能以某种方式将类型信息存储在字段映射中,这两个问题都可以解决。我不确定如何。