Ensure that division is left assosiative in UDQ parser

This commit is contained in:
Joakim Hove 2020-10-22 14:40:32 +02:00
parent d9a7d6326f
commit 80a023794e
2 changed files with 44 additions and 11 deletions

View File

@ -140,21 +140,39 @@ UDQASTNode UDQParser::parse_pow() {
UDQASTNode UDQParser::parse_mul() {
auto left = this->parse_pow();
auto current = this->current();
if (this->empty())
return left;
std::vector<UDQASTNode> nodes;
{
std::unique_ptr<UDQASTNode> current_node;
while (true) {
auto node = this->parse_pow();
if (current_node) {
current_node->set_right(node);
nodes.push_back(*current_node);
} else
nodes.push_back(node);
if (current.type == UDQTokenType::binary_op_mul || current.type == UDQTokenType::binary_op_div) {
this->next();
if (this->empty())
return UDQASTNode(UDQTokenType::error);
if (this->empty())
break;
auto right = this->parse_mul();
return UDQASTNode(current.type, current.value, left, right);
auto current_token = this->current();
if (current_token.type == UDQTokenType::binary_op_mul || current_token.type == UDQTokenType::binary_op_div) {
current_node.reset( new UDQASTNode(current_token.type, current_token.value) );
this->next();
if (this->empty())
return UDQASTNode( UDQTokenType::error );
} else break;
}
}
return left;
UDQASTNode top_node = nodes.back();
if (nodes.size() > 1) {
UDQASTNode * current = &top_node;
for (std::size_t index = nodes.size() - 1; index > 0; index--) {
current->set_left(nodes[index - 1]);
current = current->get_left();
}
}
return top_node;
}

View File

@ -2264,3 +2264,18 @@ TSTEP
}
}
BOOST_AUTO_TEST_CASE(UDQ_DIV_TEST) {
KeywordLocation location;
UDQFunctionTable udqft;
UDQParams udqp;
UDQDefine def_div(udqp, "FU", location, {"128", "/", "2", "/", "4", "/", "8"});
SummaryState st(std::chrono::system_clock::now());
UDQState udq_state(udqp.undefinedValue());
UDQContext context(udqft, st, udq_state);
auto res_div = def_div.eval(context);
BOOST_CHECK_EQUAL( res_div[0].get() , 2.0);
}