Action::Condition has lhs and rhs member properties

This commit is contained in:
Joakim Hove 2019-09-13 20:24:56 +02:00
parent 8efe3cf6a6
commit 4078451840
4 changed files with 162 additions and 61 deletions

View File

@ -21,10 +21,28 @@
#define ACTIONX_CONDITION_HPP
#include <string>
#include <vector>
namespace Opm {
namespace Action {
class Quantity {
public:
Quantity() = default;
Quantity(const std::string& arg) :
quantity(arg)
{}
void add_arg(const std::string& arg);
std::string quantity;
std::vector<std::string> args;
};
class Condition {
public:
@ -44,14 +62,14 @@ enum class Comparator {
};
void add_token(const std::string& token);
Condition(const std::string& quant);
std::string cmp_string() const;
Condition(const std::vector<std::string>& tokens, const std::pair<std::string, std::size_t>& location);
std::string quantity;
Quantity lhs;
Quantity rhs;
Logical logic = Logical::END;
Comparator cmp = Comparator::INVALID;
std::string cmp_string;
};

View File

@ -60,44 +60,11 @@ ActionX::ActionX(const DeckKeyword& kw, std::time_t start_time) :
for (size_t record_index = 1; record_index < kw.size(); record_index++) {
const auto& record = kw.getRecord(record_index);
const auto& cond_tokens = record.getItem("CONDITION").getData<std::string>();
Condition cond(cond_tokens[0]);
for (const auto& token : cond_tokens) {
for (const auto& token : cond_tokens)
tokens.push_back(token);
cond.add_token(token);
{
auto token_type = Parser::get_type(token);
if (token_type == TokenType::op_eq)
cond.cmp = Condition::Comparator::EQUAL;
if (token_type == TokenType::op_gt)
cond.cmp = Condition::Comparator::GREATER;
if (token_type == TokenType::op_lt)
cond.cmp = Condition::Comparator::LESS;
if (token_type == TokenType::op_le)
cond.cmp = Condition::Comparator::LESS_EQUAL;
if (token_type == TokenType::op_ge)
cond.cmp = Condition::Comparator::GREATER_EQUAL;
}
}
{
auto token_type = Parser::get_type(cond_tokens.back());
if (token_type == TokenType::op_and)
cond.logic = Condition::Logical::AND;
else if (token_type == TokenType::op_or)
cond.logic = Condition::Logical::OR;
}
if (cond.cmp == Condition::Comparator::INVALID) {
const auto& location = kw.location();
throw std::invalid_argument("Could not determine comparison type for ACTIONX keyword at " + location.first + ":" + std::to_string(location.second));
}
this->m_conditions.push_back(std::move(cond));
this->m_conditions.emplace_back(cond_tokens, kw.location());
}
this->condition = Action::AST(tokens);
}

View File

@ -19,37 +19,113 @@
#include <string>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Condition.hpp>
#include "ActionValue.hpp"
#include "ActionParser.hpp"
namespace Opm {
namespace Action {
void Condition::add_token(const std::string& token) {
namespace {
Condition::Comparator comparator(TokenType tt) {
if (tt == TokenType::op_eq)
return Condition::Comparator::EQUAL;
if (tt == TokenType::op_gt)
return Condition::Comparator::GREATER;
if (tt == TokenType::op_lt)
return Condition::Comparator::LESS;
if (tt == TokenType::op_le)
return Condition::Comparator::LESS_EQUAL;
if (tt == TokenType::op_ge)
return Condition::Comparator::GREATER_EQUAL;
return Condition::Comparator::INVALID;
}
Condition::Condition(const std::string& quant) :
quantity(quant)
{}
std::string Condition::cmp_string() const {
if (this->cmp == Comparator::EQUAL)
std::string cmp2string(Condition::Comparator cmp) {
if (cmp == Condition::Comparator::EQUAL)
return "=";
if (this->cmp == Comparator::GREATER)
if (cmp == Condition::Comparator::GREATER)
return ">";
if (this->cmp == Comparator::LESS)
if (cmp == Condition::Comparator::LESS)
return "<";
if (this->cmp == Comparator::LESS_EQUAL)
if (cmp == Condition::Comparator::LESS_EQUAL)
return "<=";
if (this->cmp == Comparator::GREATER_EQUAL)
if (cmp == Condition::Comparator::GREATER_EQUAL)
return ">=";
}
throw std::logic_error("Bug in opm/flow - should not be here");
}
std::string strip_quotes(const std::string& s) {
if (s[0] == '\'')
return s.substr(1, s.size() - 2);
else
return s;
}
}
void Quantity::add_arg(const std::string& arg) {
this->args.push_back(strip_quotes(arg));
}
Condition::Condition(const std::vector<std::string>& tokens, const std::pair<std::string, std::size_t>& location) {
this->lhs = Quantity(tokens[0]);
std::size_t token_index = 1;
while (true) {
if (token_index >= tokens.size())
break;
auto comp = comparator( Parser::get_type(tokens[token_index]) );
if (comp == Comparator::INVALID) {
this->lhs.add_arg(tokens[token_index]);
token_index += 1;
} else {
this->cmp = comp;
this->cmp_string = cmp2string(this->cmp);
token_index += 1;
break;
}
}
if (token_index >= tokens.size())
throw std::invalid_argument("Could not determine right hand side / comparator for ACTIONX keyword at " + location.first + ":" + std::to_string(location.second));
this->rhs = Quantity(tokens[token_index]);
token_index++;
while (true) {
if (token_index >= tokens.size())
break;
auto token_type = Parser::get_type(tokens[token_index]);
if (token_type == TokenType::op_and)
this->logic = Condition::Logical::AND;
else if (token_type == TokenType::op_or)
this->logic = Condition::Logical::OR;
else
this->rhs.add_arg(tokens[token_index]);
token_index++;
}
}
}
}

View File

@ -596,6 +596,42 @@ BOOST_AUTO_TEST_CASE(TestFieldAND) {
}
}
BOOST_AUTO_TEST_CASE(Conditions) {
auto location = std::make_pair<std::string, std::size_t>("FILE", 0);
// Missing comparator
BOOST_CHECK_THROW(Action::Condition cond({"WWCT", "OPX"}, location), std::invalid_argument);
// Missing right hand side
BOOST_CHECK_THROW(Action::Condition cond({"WWCT", "OPX", ">"}, location), std::invalid_argument);
Action::Condition cond({"WWCT", "OPX", ">", "0.75", "AND"}, location);
BOOST_CHECK(cond.cmp == Action::Condition::Comparator::GREATER);
BOOST_CHECK(cond.cmp_string == ">" );
BOOST_CHECK_EQUAL(cond.lhs.quantity, "WWCT");
BOOST_CHECK_EQUAL(cond.lhs.args.size(), 1);
BOOST_CHECK_EQUAL(cond.lhs.args[0], "OPX");
BOOST_CHECK_EQUAL(cond.rhs.quantity, "0.75");
BOOST_CHECK_EQUAL(cond.rhs.args.size(), 0);
BOOST_CHECK(cond.logic == Action::Condition::Logical::AND);
Action::Condition cond2({"WWCT", "OPX", "<=", "WSOPR", "OPX", "235"}, location);
BOOST_CHECK(cond2.cmp == Action::Condition::Comparator::LESS_EQUAL);
BOOST_CHECK(cond2.cmp_string == "<=" );
BOOST_CHECK_EQUAL(cond2.lhs.quantity, "WWCT");
BOOST_CHECK_EQUAL(cond2.lhs.args.size(), 1);
BOOST_CHECK_EQUAL(cond2.lhs.args[0], "OPX");
BOOST_CHECK_EQUAL(cond2.rhs.quantity, "WSOPR");
BOOST_CHECK_EQUAL(cond2.rhs.args.size(), 2);
BOOST_CHECK_EQUAL(cond2.rhs.args[0], "OPX");
BOOST_CHECK_EQUAL(cond2.rhs.args[1], "235");
BOOST_CHECK(cond2.logic == Action::Condition::Logical::END);
}
BOOST_AUTO_TEST_CASE(SCAN2) {
const auto deck_string = std::string{ R"(
SCHEDULE
@ -605,7 +641,7 @@ TSTEP
ACTIONX
'B' /
WWCT 'OPX' > 0.75 AND / -- The spaces will/should be normalized in Condition::expression()
WWCT 'OPX' > 0.75 AND /
FPR < 100 /
/
@ -672,12 +708,16 @@ TSTEP
BOOST_CHECK_EQUAL(conditions.size() , 2);
const auto& cond0 = conditions[0];
BOOST_CHECK_EQUAL(cond0.quantity, "WWCT");
BOOST_CHECK_EQUAL(cond0.lhs.quantity, "WWCT");
BOOST_CHECK(cond0.cmp == Action::Condition::Comparator::GREATER);
BOOST_CHECK(cond0.logic == Action::Condition::Logical::AND);
BOOST_CHECK_EQUAL(cond0.lhs.args.size(), 1);
BOOST_CHECK_EQUAL(cond0.lhs.args[0], "OPX");
BOOST_CHECK_EQUAL(cond0.rhs.args.size(), 0);
BOOST_CHECK_EQUAL(cond0.rhs.quantity, "0.75");
const auto& cond1 = conditions[1];
BOOST_CHECK_EQUAL(cond1.quantity, "FPR");
BOOST_CHECK_EQUAL(cond1.lhs.quantity, "FPR");
BOOST_CHECK(cond1.cmp == Action::Condition::Comparator::LESS);
BOOST_CHECK(cond1.logic == Action::Condition::Logical::END);
@ -689,18 +729,18 @@ TSTEP
const auto& actB = actions2.get("B");
const auto& condB = actB.conditions();
BOOST_CHECK_EQUAL(condB.size() , 1);
BOOST_CHECK_EQUAL(condB[0].quantity, "FWCT");
BOOST_CHECK_EQUAL(condB[0].lhs.quantity, "FWCT");
BOOST_CHECK(condB[0].cmp == Action::Condition::Comparator::LESS_EQUAL);
BOOST_CHECK(condB[0].logic == Action::Condition::Logical::END);
BOOST_CHECK_EQUAL(condB[0].cmp_string(), "<=");
BOOST_CHECK_EQUAL(condB[0].cmp_string, "<=");
const auto& actA = actions2.get("A");
const auto& condA = actA.conditions();
BOOST_CHECK_EQUAL(condA.size() , 1);
BOOST_CHECK_EQUAL(condA[0].quantity, "WOPR");
BOOST_CHECK_EQUAL(condA[0].lhs.quantity, "WOPR");
BOOST_CHECK(condA[0].cmp == Action::Condition::Comparator::EQUAL);
BOOST_CHECK(condA[0].logic == Action::Condition::Logical::END);
BOOST_CHECK_EQUAL(condA[0].cmp_string() , "=");
BOOST_CHECK_EQUAL(condA[0].cmp_string , "=");
std::size_t index = 0;
for (const auto& act : actions2) {