微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

结构成员上的布尔表达式求值器

如何解决结构成员上的布尔表达式求值器

背景

我有一个结构:

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")
  )
);

有成堆的工作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。