diff --git a/reading_machine/include/Config.hpp b/reading_machine/include/Config.hpp index 464286f2ca3370381bc068fee911a889e038959a..697418c0f75a671b99f6123dfe4540f8a3ed0775 100644 --- a/reading_machine/include/Config.hpp +++ b/reading_machine/include/Config.hpp @@ -93,6 +93,7 @@ class Config bool hasStack(int relativeIndex) const; String getState() const; void setState(const std::string state); + bool stateIsDone() const; }; diff --git a/reading_machine/include/Strategy.hpp b/reading_machine/include/Strategy.hpp index 60dbfa90d424d42dd866c33f02a7a40435826d75..e1bc580c2dadc42d896c2c4156c6c7a8248cb274 100644 --- a/reading_machine/include/Strategy.hpp +++ b/reading_machine/include/Strategy.hpp @@ -5,6 +5,10 @@ class Strategy { + public : + + static inline std::pair<std::string, int> endMovement{"", 0}; + private : enum Type @@ -15,6 +19,13 @@ class Strategy Type type; std::map<std::pair<std::string, std::string>, std::string> edges; + std::map<std::string, bool> isDone; + std::vector<std::string> defaultCycle; + + private : + + std::pair<std::string, int> getMovementSequential(const Config & c, const std::string & transition); + std::pair<std::string, int> getMovementIncremental(const Config & c, const std::string & transition); public : diff --git a/reading_machine/src/Config.cpp b/reading_machine/src/Config.cpp index 919ab2517da772a56539b3a3d8a22cae802f62ef..a8d8134ac62d4a0b75a159b6df9094941311c6fe 100644 --- a/reading_machine/src/Config.cpp +++ b/reading_machine/src/Config.cpp @@ -340,3 +340,11 @@ void Config::setState(const std::string state) this->state = state; } +bool Config::stateIsDone() const +{ + if (!rawInput.empty()) + return rawInputOnlySeparatorsLeft(); + + return !has(0, wordIndex+1, 0); +} + diff --git a/reading_machine/src/Strategy.cpp b/reading_machine/src/Strategy.cpp index 2d5e9ae9af696cfc936dbcb5c19d46ed5961c213..afb1e3fc97408280589871f8d7dae6dbdc4b343b 100644 --- a/reading_machine/src/Strategy.cpp +++ b/reading_machine/src/Strategy.cpp @@ -9,28 +9,97 @@ Strategy::Strategy(const std::vector<std::string_view> & lines) for (unsigned int i = 1; i < lines.size(); i++) { auto splited = util::split(lines[i], ' '); + std::pair<std::string, std::string> key; + std::string value; + if (splited.size() == 2) - edges[std::pair<std::string,std::string>(splited[0], "")] = splited[1]; + { + key = std::pair<std::string,std::string>(splited[0], ""); + value = splited[1]; + defaultCycle.emplace_back(value); + } else if (splited.size() == 3) - edges[std::pair<std::string,std::string>(splited[0], splited[1])] = splited[2]; + { + key = std::pair<std::string,std::string>(splited[0], splited[1]); + value = splited[1]; + } else util::myThrow(fmt::format("Invalid strategy line '{}'", lines[i])); + + if (edges.count(key)) + util::myThrow(fmt::format("Edge {} {} defined twice", key.first, key.second)); + edges[key] = value; + isDone[key.first] = false; } + + if (edges.empty()) + util::myThrow("Strategy is empty"); + defaultCycle.pop_back(); + std::reverse(defaultCycle.begin(), defaultCycle.end()); + + for (auto & s : defaultCycle) + fmt::print("{}\n", s); } std::pair<std::string, int> Strategy::getMovement(const Config & c, const std::string & transition) +{ + if (c.stateIsDone()) + isDone[c.getState()] = true; + + while (defaultCycle.size() && isDone[defaultCycle.back()]) + defaultCycle.pop_back(); + + if (type == Type::Sequential) + return getMovementSequential(c, transition); + + return getMovementIncremental(c, transition); +} + +std::pair<std::string, int> Strategy::getMovementSequential(const Config & c, const std::string & transition) +{ + auto foundSpecific = edges.find(std::make_pair(c.getState(), transition)); + auto foundGeneric = edges.find(std::make_pair(c.getState(), "")); + + std::string target; + + if (foundSpecific != edges.end()) + target = foundSpecific->second; + else if (foundGeneric != edges.end()) + target = foundGeneric->second; + + if (target.empty()) + util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition)); + + if (!c.stateIsDone()) + return {c.getState(), (c.getState() == target) && edges.size() > 1 ? 0 : 1}; + + if (!isDone[target]) + return {target, -c.getWordIndex()}; + + return endMovement; +} + +std::pair<std::string, int> Strategy::getMovementIncremental(const Config & c, const std::string & transition) { auto foundSpecific = edges.find(std::make_pair(c.getState(), transition)); auto foundGeneric = edges.find(std::make_pair(c.getState(), "")); + std::string target; + if (foundSpecific != edges.end()) - return {foundSpecific->second, 1}; + target = foundSpecific->second; + else if (foundGeneric != edges.end()) + target = foundGeneric->second; + + if (target.empty()) + util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition)); - if (foundGeneric != edges.end()) - return {foundGeneric->second, 1}; + if (!isDone[target]) + return {target, target == defaultCycle.back() ? 1 : 0}; - util::myThrow(fmt::format("no suitable movement found for current state '{}' and transition '{}'", c.getState(), transition)); + if (defaultCycle.empty()) + return endMovement; - return {"", 0}; + return {defaultCycle.back(), 1}; }