2 #include "booleanevaluator.h"
6 BooleanEvaluator::BooleanEvaluator(const ValueFunction &f):
7 func([&f](const string &value, const string *){ return f(value); }),
11 BooleanEvaluator::BooleanEvaluator(const CompareFunction &f):
16 bool BooleanEvaluator::evaluate(const string &str)
20 for(auto i=str.begin();; ++i)
22 if(i!=str.end() && (isalnum(*i) || (!buf.empty() && (*i=='_' || *i=='-'))))
29 throw runtime_error("syntax error at "+buf);
31 char op = (op_stack.empty() ? 0 : op_stack.back());
32 if(op=='=' || op=='^')
35 string var = var_stack.back();
37 bool value = (func(var, &buf) == (op=='='));
38 value_stack.push_back(value);
41 var_stack.push_back(buf);
51 else if(ops.find(*i)!=string::npos)
54 throw runtime_error("syntax error at "+string(1, *i));
60 bool value = pop_value();
61 if(!value_stack.empty())
62 throw runtime_error("too many values");
67 void BooleanEvaluator::push_op(char op)
69 if(last_was_op!=is_unary(op))
70 throw runtime_error("syntax error at "+string(1, op));
71 // TODO Disallow mixing of ! and =/^
72 if(is_logic(op) && !var_stack.empty())
73 value_stack.push_back(pop_value());
76 collapse(precedence(op));
77 op_stack.push_back(op);
81 bool BooleanEvaluator::pop_value()
83 if(!var_stack.empty())
85 string var = var_stack.back();
89 else if(!value_stack.empty())
91 bool value = value_stack.back();
92 value_stack.pop_back();
96 throw runtime_error("value stack underflow");
99 void BooleanEvaluator::collapse(unsigned until)
101 while(!op_stack.empty())
103 char op = op_stack.back();
104 if(precedence(op)<until)
108 bool value1 = pop_value();
116 bool value2 = pop_value();
118 value1 = (value1 && value2);
120 value1 = (value1 || value2);
122 value_stack.push_back(value1);
126 unsigned BooleanEvaluator::precedence(char op)
130 else if(op=='=' || op=='^')
138 bool BooleanEvaluator::is_unary(char op)
143 bool BooleanEvaluator::is_logic(char op)
145 return (op=='&' || op=='|' || op=='!');