1

为简单起见,我将对整个问题进行粗俗化。

我正在研究仅使用运算符 OR 和 AND(目前)的布尔算术。

我的布尔表达式存储在一个变量和运算符交替的向量中(类似于“a OR b”的 [a, ||, b])。

我想知道是否可以像我写的那样链接我的向量:

std::vector<xxx> v = {true, &&, (, false, ||, true, )};
// result = true && (false || true) = true
bool result = vector[0] vector[1] vector[2] vector[3] vector[4] vector[5] vector[6];

我知道存在算术评估算法(例如 Shunting-yard),但我想避免使用它们并改用 c++ 评估器。我想我可以重载运算符来处理简单的表达式,但是一旦括号出现,我就卡住了。

如果已经提出并回答了这个问题,我深表歉意,我只是不知道在我的搜索中使用什么关键字!

提前谢谢你,即使只是一个线索也会很好:)

4

5 回答 5

2

您可以使用表达式模板来执行此操作。您的一些布尔文字必须像bool_(true)使用适当的运算符创建自定义对象一样,但除此之外,就好像您真的使用了 C++。

当然,通常只使用 lambda 或为此编写函数更简单,除非您需要在运行时内省/修改树或类似的东西。

于 2013-03-06T15:04:27.947 回答
1

首先,您不能真正存储任何类型vector的原始 C++ 运算符或语法元素,所以,等等。(*

不过,您可以将它们存储为文字:

std::vector<std::string> expression = { "2", "+", "3" };

但是,不能为此使用“c++ 评估器”;C++ 是一种编译语言,因此不可能在运行时使用相同的逻辑(从技术上讲,它可以通过 LLVM 之类的东西来实现,但它肯定是一种矫枉过正)。在这种情况下,您最好使用自定义评估器。

在编译时也可以使用 TMP,但我不确定这是否是您想要的。

于 2013-03-06T14:51:16.220 回答
1

您可以使用 c++ 源代码生成文件,编译并运行它。像这样的东西:

std::vector<xxx> v = {true, *, (, false, +, true, )};
std::ofstream src("temp.cpp");
src <<
    "#include <iostream>\n"
    "int main() {\n"
    "bool result = ";
for (auto i: v)
    src << i << ' ';
src <<
    ";\n"
    "std::cout << result;\n"
    "}\n";
src.close();
system("g++ temp.cpp -o temp");
system("temp");

我忽略了权限、临时文件名、输出重定向等各个方面。

于 2013-03-06T15:15:24.573 回答
0

一种解决方案是使,运算符过载。但这会在处理括号时给您带来问题。通常你不会通过线性解析这样的表达式找到正确的结果。

表示表达式的正常方式是树。然后遍历树计算最终值。遍历通常使用递归完成。

所以这是一个两阶段的过程

1:构建树

2:递归计算表达式树

如果您希望将其表示为图表,请查看boost::graph

于 2013-03-06T14:48:33.940 回答
0

就像 AxelOmega 说的 - 你可以使用boost::spirit. 语法很简单:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_bool.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

template <class Iterator>
struct bool_grammar : qi::grammar<Iterator, bool(), qi::space_type> {
        qi::rule<Iterator, bool(), qi::space_type> rGroup, rBool, rName, rOr, rAnd;

        bool_grammar() : bool_grammar::base_type(rOr) {
                rGroup  = '(' >> rOr >> ')';
                rBool   = qi::bool_ | rGroup;
                rAnd    = rBool[qi::_val = qi::_1] >>
                          *('&' >> rBool[qi::_val = qi::_val && qi::_1]);
                rOr     = rAnd[qi::_val = qi::_1] >>
                          *('|' >> rAnd[qi::_val = qi::_val || qi::_1]);
        }
};

您还需要一个函数来调用解析器并检查结果

bool parse(const std::string& value) {
        bool_grammar<std::string::const_iterator> g;
        std::string::const_iterator it  = value.begin();
        std::string::const_iterator end = value.end();

        bool s;
        if (qi::phrase_parse(it, end, g, qi::space, s) == false || it != end) {
                // error
        }

        return s;
}

现在只需将其合并vector为一个string并使用 parse 函数:

parse("(true | false) & true | false") ;

如果您对bool结果不感兴趣并且想要创建可操作的树,您还可以将综合属性更改为某个自定义类。

于 2013-03-06T16:17:45.457 回答