为简单起见,我要贬低整个问题。
我正在使用运算符OR和AND(现在)进行布尔运算。
我的布尔表达式存储在一个变量和一个运算符的向量中(类似于[a,||,b]的“a OR 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 ++评估器。 我想我可以重载操作符来处理简单的表达式,但是一旦括号出现我就卡住了。
如果已经提出并回答了这个问题我很抱歉,我只是不知道在我的搜索中使用哪些关键字!
提前谢谢你,即使只是一个线索也不错:)
答案 0 :(得分:2)
您可以使用表达式模板执行此操作。你的一些布尔文字必须像bool_(true)
一样用适当的运算符创建自定义对象,但除此之外,它就好像你真的使用过C ++一样。
当然,使用lambda或为此编写函数通常更简单,除非你需要在运行时内省或修改树。
答案 1 :(得分:1)
首先,您无法在任何类型的vector
中存储原始C ++运算符或语法元素,因此(
,*
等等进行。
您可以将它们存储为文字,但是:
std::vector<std::string> expression = { "2", "+", "3" };
然而,不可能为此使用“c ++评估者”; C ++是一种编译语言,因此不可能在运行时使用相同的逻辑(技术上可以通过像LLVM这样的东西,但它肯定会是一种过度杀伤力)。在这种情况下,您最好使用自定义评估程序。
在编译时也可以使用TMP,但我不确定这是你想要的。
答案 2 :(得分: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");
我忽略了各种方面,如权限,临时文件名,输出重定向等。
答案 3 :(得分:0)
一种解决方案是重载,
运算符。但是这会在处理括号时给你带来麻烦。通常,你不会通过线性解析这样的表达式来找到正确的结果。
表示表达式的常规方式是树。然后遍历树以计算最终值。遍历通常使用递归完成。
所以这是一个两阶段的过程
1:构建树
2:递归计算表达式树
如果您希望将其表示为图表,请查看boost::graph
答案 4 :(得分: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("(true | false) & true | false") ;
如果您对bool
结果不感兴趣并且想要创建一个可以操作的树,您还可以将合成属性更改为某个自定义类。