support OR with proper precedence

This commit is contained in:
Ari Lazier 2015-11-09 12:13:01 -08:00
parent 5bdc6eba93
commit 4b3417736f
1 changed files with 45 additions and 0 deletions

View File

@ -121,6 +121,28 @@ template<> struct action< and_ext >
static void apply( const input & in, ParserState & state ) static void apply( const input & in, ParserState & state )
{ {
std::cout << "<and>" << in.string() << std::endl; std::cout << "<and>" << in.string() << std::endl;
// if we were put into an OR group we need to rearrange
auto current = state.current();
if (current->type == Predicate::Type::Or) {
auto &sub_preds = state.current()->sub_predicates;
auto second_last = sub_preds[sub_preds.size()-2];
if (second_last.type == Predicate::Type::And) {
// if we are in an OR group and second to last predicate group is
// an AND group then move the last predicate inside
second_last.sub_predicates.push_back(sub_preds.back());
sub_preds.pop_back();
}
else {
// otherwise combine last two into a new AND group
Predicate pred;
pred.type = Predicate::Type::And;
pred.sub_predicates = { second_last, sub_preds.back() };
sub_preds.pop_back();
sub_preds.pop_back();
sub_preds.push_back(pred);
}
}
} }
}; };
@ -129,6 +151,29 @@ template<> struct action< or_ext >
static void apply( const input & in, ParserState & state ) static void apply( const input & in, ParserState & state )
{ {
std::cout << "<or>" << in.string() << std::endl; std::cout << "<or>" << in.string() << std::endl;
// if already an OR group do nothing
auto current = state.current();
if (current->type == Predicate::Type::Or) {
return;
}
// if only two predicates in the group, then convert to OR
auto &sub_preds = state.current()->sub_predicates;
if (sub_preds.size()) {
current->type = Predicate::Type::Or;
return;
}
// split the current group into to groups which are ORed together
Predicate pred1, pred2;
pred1.type = Predicate::Type::And;
pred2.type = Predicate::Type::And;
pred1.sub_predicates.insert(sub_preds.begin(), sub_preds.back());
pred2.sub_predicates.push_back(sub_preds.back());
current->type = Predicate::Type::Or;
sub_preds = { pred1, pred2 };
} }
}; };