std::string Consequent::toString() const { std::stringstream ss; for (std::size_t i = 0; i < conclusions().size(); ++i) { ss << conclusions().at(i)->toString(); if (i + 1 < conclusions().size()) ss << " " << Rule::andKeyword() << " "; } return ss.str(); }
void Consequent::unload() { for (std::size_t i = 0; i < conclusions().size(); ++i) { delete conclusions().at(i); } conclusions().clear(); }
void Consequent::load(const std::string& consequent, const Engine* engine) { unload(); setText(consequent); if (Op::trim(consequent).empty()) { throw Exception("[syntax error] consequent is empty", FL_AT); } /** Extracts the list of propositions from the consequent The rules are: 1) After a variable comes 'is' or '=', 2) After 'is' comes a hedge or a term 3) After a hedge comes a hedge or a term 4) After a term comes operators 'and' or 'with' 5) After operator 'and' comes a variable 6) After operator 'with' comes a float */ enum FSM { S_VARIABLE = 1, S_IS = 2, S_HEDGE = 4, S_TERM = 8, S_AND = 16, S_WITH = 32 }; int state = S_VARIABLE; Proposition* proposition = fl::null; std::stringstream tokenizer(consequent); std::string token; try { while (tokenizer >> token) { if (state bitand S_VARIABLE) { if (engine->hasOutputVariable(token)) { proposition = new Proposition; proposition->variable = engine->getOutputVariable(token); conclusions().push_back(proposition); state = S_IS; continue; } } if (state bitand S_IS) { if (token == Rule::isKeyword()) { state = S_HEDGE bitor S_TERM; continue; } } if (state bitand S_HEDGE) { HedgeFactory* factory = FactoryManager::instance()->hedge(); if (factory->hasConstructor(token)) { Hedge* hedge = factory->constructObject(token); proposition->hedges.push_back(hedge); state = S_HEDGE bitor S_TERM; continue; } } if (state bitand S_TERM) { if (proposition->variable->hasTerm(token)) { proposition->term = proposition->variable->getTerm(token); state = S_AND bitor S_WITH; continue; } } if (state bitand S_AND) { if (token == Rule::andKeyword()) { state = S_VARIABLE; continue; } } //if reached this point, there was an error: if (state bitand S_VARIABLE) { std::ostringstream ex; ex << "[syntax error] consequent expected output variable, but found <" << token << ">"; throw Exception(ex.str(), FL_AT); } if (state bitand S_IS) { std::ostringstream ex; ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << ">, " "but found <" << token << ">"; throw Exception(ex.str(), FL_AT); } if ((state bitand S_HEDGE) or (state bitand S_TERM)) { std::ostringstream ex; ex << "[syntax error] consequent expected hedge or term, but found <" << token << ">"; throw Exception(ex.str(), FL_AT); } if ((state bitand S_AND) or (state bitand S_WITH)) { std::ostringstream ex; ex << "[syntax error] consequent expected operator <" << Rule::andKeyword() << "> " << "or keyword <" << Rule::withKeyword() << ">, " << "but found <" << token << ">"; throw Exception(ex.str(), FL_AT); } std::ostringstream ex; ex << "[syntax error] unexpected token <" << token << "> in consequent"; throw Exception(ex.str(), FL_AT); } if (not ((state bitand S_AND) or (state bitand S_WITH))) { //only acceptable final state if (state bitand S_VARIABLE) { std::ostringstream ex; ex << "[syntax error] consequent expected output variable after <" << token << ">"; throw Exception(ex.str(), FL_AT); } if (state bitand S_IS) { std::ostringstream ex; ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << "> " "after <" << token << ">"; throw Exception(ex.str(), FL_AT); } if ((state bitand S_HEDGE) or (state bitand S_TERM)) { std::ostringstream ex; ex << "[syntax error] consequent expected hedge or term after <" << token << ">"; throw Exception(ex.str(), FL_AT); } } } catch (...) { unload(); throw; } }
bool Consequent::isLoaded() { return not conclusions().empty(); }