From 83e68bbad3741c4dab30b3f69442ee618bac6b09 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Mon, 28 Aug 2023 08:06:48 +0200 Subject: [PATCH 01/62] added keys and doors to walkable tiles changed key init value handling --- util/Grid.cpp | 6 +++++- util/PrismModulesPrinter.cpp | 10 ++++++++-- util/PrismModulesPrinter.h | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/util/Grid.cpp b/util/Grid.cpp index 1184e1e..d13c2b5 100644 --- a/util/Grid.cpp +++ b/util/Grid.cpp @@ -130,6 +130,9 @@ void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { walkable.push_back(agent); walkable.insert(walkable.end(), adversaries.begin(), adversaries.end()); walkable.insert(walkable.end(), lava.begin(), lava.end()); + walkable.insert(walkable.end(), keys.begin(), keys.end()); + walkable.insert(walkable.end(), lockedDoors.begin(), lockedDoors.end()); + for(auto const& c : walkable) { if(isBlocked(c.getNorth())) northRestriction.push_back(c); if(isBlocked(c.getEast())) eastRestriction.push_back(c); @@ -178,10 +181,11 @@ void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { size_t agentIndex = 0; for(auto agentNameAndPosition = agentNameAndPositionMap.begin(); agentNameAndPosition != agentNameAndPositionMap.end(); ++agentNameAndPosition, agentIndex++) { AgentName agentName = agentNameAndPosition->first; + //std::cout << "Agent Name: " << agentName << std::endl; bool agentWithView = std::find(gridOptions.agentsWithView.begin(), gridOptions.agentsWithView.end(), agentName) != gridOptions.agentsWithView.end(); bool agentWithProbabilisticBehaviour = std::find(gridOptions.agentsWithProbabilisticBehaviour.begin(), gridOptions.agentsWithProbabilisticBehaviour.end(), agentName) != gridOptions.agentsWithProbabilisticBehaviour.end(); std::set slipperyActions; - printer.printInitStruct(os, agentName); + printer.printInitStruct(os, agentName, keys); if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, gridOptions.probabilitiesForActions); else printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView); for(auto const& c : slipperyNorth) { diff --git a/util/PrismModulesPrinter.cpp b/util/PrismModulesPrinter.cpp index f6aca04..0b15af2 100644 --- a/util/PrismModulesPrinter.cpp +++ b/util/PrismModulesPrinter.cpp @@ -253,7 +253,7 @@ namespace prism { std::ostream& PrismModulesPrinter::printBooleansForKeys(std::ostream &os, const AgentName &agentName, const cells &keys) { for(auto const& key : keys) { - os << "\t" << agentName << "_has_"<< key.getColor() << "_key : bool init false;\n"; + os << "\t" << agentName << "_has_"<< key.getColor() << "_key : bool;\n";//init false;\n"; } os << "\n"; return os; @@ -292,7 +292,7 @@ namespace prism { return os; } - std::ostream& PrismModulesPrinter::printInitStruct(std::ostream &os, const AgentName &agentName) { + std::ostream& PrismModulesPrinter::printInitStruct(std::ostream &os, const AgentName &agentName, const cells &keys) { os << "init\n"; os << "\t(!AgentIsInGoal & !AgentIsInLava & !AgentDone & !AgentIsOnWall)"; if(enforceOneWays) { @@ -300,8 +300,14 @@ namespace prism { } else { os << " & ( !AgentIsOnSlippery ) "; } + + for (auto const& key : keys) { + os << " & ( !" << agentName << "_has_" << key.getColor() << "_key )"; + } + os << "\nendinit\n\n"; + return os; } diff --git a/util/PrismModulesPrinter.h b/util/PrismModulesPrinter.h index 7a196fc..12dc99f 100644 --- a/util/PrismModulesPrinter.h +++ b/util/PrismModulesPrinter.h @@ -66,7 +66,7 @@ namespace prism { std::ostream& printActionsForKeys(std::ostream &os, const AgentName &agentName, const cells &keys); std::ostream& printBooleansForBackground(std::ostream &os, const AgentName &agentName, const std::map &backgroundTiles); std::ostream& printActionsForBackground(std::ostream &os, const AgentName &agentName, const std::map &backgroundTiles); - std::ostream& printInitStruct(std::ostream &os, const AgentName &agentName); + std::ostream& printInitStruct(std::ostream &os, const AgentName &agentName, const cells &keys); std::ostream& printModule(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &boundaries, const coordinates& initialPosition, const cells &keys, const std::map &backgroundTiles, const bool agentWithView, const std::vector &probabilities = {}); std::ostream& printMovementActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const bool agentWithView, const float &probability = 1.0); std::ostream& printDoneActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex); From 56e569890e33f948b430bea4de1d81a83c01173f Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Wed, 30 Aug 2023 12:04:34 +0200 Subject: [PATCH 02/62] added basic config parser added unlocked door handling --- main.cpp | 27 +++++++++++++- util/ConfigGrammar.h | 72 ++++++++++++++++++++++++++++++++++++ util/Grid.cpp | 11 ++++++ util/Grid.h | 2 + util/PrismModulesPrinter.cpp | 10 +++-- 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 util/ConfigGrammar.h diff --git a/main.cpp b/main.cpp index 58de07f..aa6b336 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include "util/OptionParser.h" #include "util/MinigridGrammar.h" #include "util/Grid.h" +#include "util/ConfigGrammar.h" #include #include @@ -54,6 +55,9 @@ int main(int argc, char* argv[]) { auto enforceOneWays = optionParser.add("f", "force-oneways", "Enforce encoding of oneways. This entails that slippery tiles do not allow turning and have prob 1 to shift the agent by one and makes turning impossible if in a one tile wide section of the grid."); + auto configFilename = optionParser.add, popl::Attribute::optional>("c", "config-file", "Filename of the predicate configuration file."); + + try { optionParser.parse(argc, argv); @@ -100,7 +104,7 @@ int main(int argc, char* argv[]) { std::fstream file {outputFilename->value(0), file.trunc | file.out}; std::fstream infile {inputFilename->value(0), infile.in}; - std::string line, content, background, rewards; + std::string line, content, background, rewards, config; std::cout << "\n"; bool parsingBackground = false; bool parsingStateRewards = false; @@ -126,6 +130,14 @@ int main(int argc, char* argv[]) { std::cout << "\n"; + if (configFilename->is_set()) { + std::fstream configFile {configFilename->value(0), configFile.in}; + while (std::getline(configFile, line) && !line.empty()) { + std::cout << "Configuration :\t" << line << "\n"; + config += line + "\n"; + } + } + pos_iterator_t contentFirst(content.begin()); pos_iterator_t contentIter = contentFirst; pos_iterator_t contentLast(content.end()); @@ -134,15 +146,28 @@ int main(int argc, char* argv[]) { pos_iterator_t backgroundIter = backgroundFirst; pos_iterator_t backgroundLast(background.end()); MinigridParser backgroundParser(backgroundFirst); + pos_iterator_t configFirst(config.begin()); + pos_iterator_t configIter = configFirst; + pos_iterator_t configLast(config.end()); + ConfigParser configParser(configFirst); cells contentCells; cells backgroundCells; + std::vector configurations; std::map stateRewards; try { bool ok = phrase_parse(contentIter, contentLast, contentParser, qi::space, contentCells); // TODO if(background is not empty) { ok &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells); // TODO } + if (configFilename->is_set()) { + ok &= phrase_parse(configIter, configLast, configParser, qi::space, configurations); + } + + std::cout << "Found " << configurations.size() << "configs" << std::endl; + for (auto& config : configurations) { + std::cout << config << std::endl; + } boost::escaped_list_separator seps('\\', ';', '\n'); Tokenizer csvParser(rewards, seps); diff --git a/util/ConfigGrammar.h b/util/ConfigGrammar.h new file mode 100644 index 0000000..597df96 --- /dev/null +++ b/util/ConfigGrammar.h @@ -0,0 +1,72 @@ +#pragma once + +#include "cell.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace qi = boost::spirit::qi; +namespace phoenix = boost::phoenix; + +typedef std::vector expressions; + +struct Configuration +{ + expressions expressions_; + std::string derivation_; + + Configuration() = default; + Configuration(expressions expressions, std::string derivation) : expressions_(expressions), derivation_(derivation) {} + ~Configuration() = default; + Configuration(const Configuration&) = default; + + friend std::ostream& operator << (std::ostream& os, const Configuration& config) { + os << "Configuration" << std::endl; + + for (auto& expression : config.expressions_) { + os << "Expression=" << expression << std::endl; + } + + return os << "Derviation=" << config.derivation_; + } +}; + + +BOOST_FUSION_ADAPT_STRUCT( + Configuration, + (expressions, expressions_) + (std::string, derivation_) +) + + +template + struct ConfigParser : qi::grammar> +{ + ConfigParser(It first) : ConfigParser::base_type(config_) + { + using namespace qi; + + expression_ = +char_("a-zA-Z_0-9"); + expressions_ = (expression_ % ','); + row_ = (expressions_ > ';' > expression_); + config_ = (row_ % "\n"); + + BOOST_SPIRIT_DEBUG_NODE(expression_); + BOOST_SPIRIT_DEBUG_NODE(expressions_); + BOOST_SPIRIT_DEBUG_NODE(config_); + } + + private: + + qi::rule expressions_; + qi::rule expression_; + qi::rule row_; + qi::rule> config_; +}; \ No newline at end of file diff --git a/util/Grid.cpp b/util/Grid.cpp index d13c2b5..3036503 100644 --- a/util/Grid.cpp +++ b/util/Grid.cpp @@ -31,6 +31,9 @@ Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, co std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lockedDoors), [](cell c) { return c.type == Type::LockedDoor; }); + std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(unlockedDoors), [](cell c) { + return c.type == Type::Door; + }); std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) { return c.type == Type::Goal; }); @@ -105,6 +108,13 @@ bool Grid::isLockedDoor(coordinates p) { }) != lockedDoors.end(); } +bool Grid::isUnlockedDoor(coordinates p) { + return std::find_if(unlockedDoors.begin(), unlockedDoors.end(), + [p](cell cell) { + return cell.row == p.first && cell.column == p.second; + }) != unlockedDoors.end(); +} + bool Grid::isKey(coordinates p) { return std::find_if(keys.begin(), keys.end(), [p](cell cell) { @@ -132,6 +142,7 @@ void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { walkable.insert(walkable.end(), lava.begin(), lava.end()); walkable.insert(walkable.end(), keys.begin(), keys.end()); walkable.insert(walkable.end(), lockedDoors.begin(), lockedDoors.end()); + walkable.insert(walkable.end(), unlockedDoors.begin(), unlockedDoors.end()); for(auto const& c : walkable) { if(isBlocked(c.getNorth())) northRestriction.push_back(c); diff --git a/util/Grid.h b/util/Grid.h index 84c2eb2..a17fb42 100644 --- a/util/Grid.h +++ b/util/Grid.h @@ -25,6 +25,7 @@ class Grid { bool isBlocked(coordinates p); bool isWall(coordinates p); bool isLockedDoor(coordinates p); + bool isUnlockedDoor(coordinates p); bool isKey(coordinates p); bool isBox(coordinates p); void printToPrism(std::ostream &os, const prism::ModelType& modelType); @@ -51,6 +52,7 @@ class Grid { cells slipperySouth; cells slipperyWest; cells lockedDoors; + cells unlockedDoors; cells boxes; cells lava; diff --git a/util/PrismModulesPrinter.cpp b/util/PrismModulesPrinter.cpp index 0b15af2..12c0c4e 100644 --- a/util/PrismModulesPrinter.cpp +++ b/util/PrismModulesPrinter.cpp @@ -608,10 +608,12 @@ namespace prism { os << "endrewards\n"; } - os << "rewards \"SafetyNoBFSAndGoal\"\n"; - if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone: 100;\n"; - if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; - os << "endrewards\n"; + if (!goals.empty() || !lava.empty()) { + os << "rewards \"SafetyNoBFSAndGoal\"\n"; + if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone: 100;\n"; + if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; + os << "endrewards\n"; + } os << "rewards \"Time\"\n"; os << "\t!AgentIsInGoal : -1;\n"; From 0a0d836968de3964287f56d1be6dd75b32efbead Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Thu, 31 Aug 2023 09:29:40 +0200 Subject: [PATCH 03/62] added config print --- main.cpp | 5 ++--- util/ConfigGrammar.h | 32 ++++++++++++++++++++++++-------- util/Grid.cpp | 6 +++++- util/Grid.h | 3 ++- util/PrismModulesPrinter.cpp | 21 +++++++++++++++++++++ util/PrismModulesPrinter.h | 3 +++ 6 files changed, 57 insertions(+), 13 deletions(-) diff --git a/main.cpp b/main.cpp index aa6b336..19d3c25 100644 --- a/main.cpp +++ b/main.cpp @@ -133,7 +133,7 @@ int main(int argc, char* argv[]) { if (configFilename->is_set()) { std::fstream configFile {configFilename->value(0), configFile.in}; while (std::getline(configFile, line) && !line.empty()) { - std::cout << "Configuration :\t" << line << "\n"; + std::cout << "Configuration:\t" << line << "\n"; config += line + "\n"; } } @@ -164,7 +164,6 @@ int main(int argc, char* argv[]) { ok &= phrase_parse(configIter, configLast, configParser, qi::space, configurations); } - std::cout << "Found " << configurations.size() << "configs" << std::endl; for (auto& config : configurations) { std::cout << config << std::endl; } @@ -180,7 +179,7 @@ int main(int argc, char* argv[]) { if(ok) { Grid grid(contentCells, backgroundCells, gridOptions, stateRewards); //grid.printToPrism(std::cout, prism::ModelType::MDP); - grid.printToPrism(file, prism::ModelType::MDP); + grid.printToPrism(file, configurations ,prism::ModelType::MDP); } } catch(qi::expectation_failure const& e) { std::cout << "expected: "; print_info(e.what_); diff --git a/util/ConfigGrammar.h b/util/ConfigGrammar.h index 597df96..71aa54d 100644 --- a/util/ConfigGrammar.h +++ b/util/ConfigGrammar.h @@ -17,30 +17,37 @@ namespace phoenix = boost::phoenix; typedef std::vector expressions; +enum class ConfigType : char { + Label = 'L', + Formula = 'F', +}; + struct Configuration { expressions expressions_; std::string derivation_; + ConfigType type_ {ConfigType::Label}; Configuration() = default; - Configuration(expressions expressions, std::string derivation) : expressions_(expressions), derivation_(derivation) {} + Configuration(expressions expressions, std::string derivation, ConfigType type) : expressions_(expressions), derivation_(derivation), type_(type) {} ~Configuration() = default; Configuration(const Configuration&) = default; friend std::ostream& operator << (std::ostream& os, const Configuration& config) { - os << "Configuration" << std::endl; + os << "Configuration with Type: " << static_cast(config.type_) << std::endl; for (auto& expression : config.expressions_) { - os << "Expression=" << expression << std::endl; + os << "\tExpression=" << expression << std::endl; } - return os << "Derviation=" << config.derivation_; + return os << "\tDerviation=" << config.derivation_; } }; BOOST_FUSION_ADAPT_STRUCT( Configuration, + (ConfigType, type_) (expressions, expressions_) (std::string, derivation_) ) @@ -52,21 +59,30 @@ template ConfigParser(It first) : ConfigParser::base_type(config_) { using namespace qi; - - expression_ = +char_("a-zA-Z_0-9"); + //F:(AgentCannotMoveSouth & AgentCannotMoveNorth) | (AgentCannotMoveEast & AgentCannotMoveWest) ;AgentCannotTurn + configType_.add + ("L", ConfigType::Label) + ("F", ConfigType::Formula); + + expression_ = -qi::char_('!') > + char_("a-zA-Z_0-9"); expressions_ = (expression_ % ','); - row_ = (expressions_ > ';' > expression_); + row_ = (configType_ > ':' > expressions_ > ';' > expression_); + // row_ = (expressions_ > ';' > expression_); config_ = (row_ % "\n"); + BOOST_SPIRIT_DEBUG_NODE(configType_); BOOST_SPIRIT_DEBUG_NODE(expression_); BOOST_SPIRIT_DEBUG_NODE(expressions_); BOOST_SPIRIT_DEBUG_NODE(config_); } private: + + qi::symbols configType_; + qi::rule expressions_; qi::rule expression_; qi::rule row_; qi::rule> config_; -}; \ No newline at end of file +}; diff --git a/util/Grid.cpp b/util/Grid.cpp index 3036503..b45266c 100644 --- a/util/Grid.cpp +++ b/util/Grid.cpp @@ -129,7 +129,7 @@ bool Grid::isBox(coordinates p) { }) != boxes.end(); } -void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { +void Grid::printToPrism(std::ostream& os, std::vector& configuration ,const prism::ModelType& modelType) { cells northRestriction; cells eastRestriction; cells southRestriction; @@ -225,6 +225,10 @@ void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { //if(!stateRewards.empty()) { printer.printRewards(os, agentName, stateRewards, lava, goals, backgroundTiles); //} + + if (!configuration.empty()) { + printer.printConfiguration(os, configuration); + } } } diff --git a/util/Grid.h b/util/Grid.h index a17fb42..4aaab9a 100644 --- a/util/Grid.h +++ b/util/Grid.h @@ -7,6 +7,7 @@ #include "MinigridGrammar.h" #include "PrismModulesPrinter.h" +#include "ConfigGrammar.h" struct GridOptions { std::vector agentsToBeConsidered; @@ -28,7 +29,7 @@ class Grid { bool isUnlockedDoor(coordinates p); bool isKey(coordinates p); bool isBox(coordinates p); - void printToPrism(std::ostream &os, const prism::ModelType& modelType); + void printToPrism(std::ostream &os, std::vector& configuration, const prism::ModelType& modelType); std::array getWalkableDirOf8Neighborhood(cell c); diff --git a/util/PrismModulesPrinter.cpp b/util/PrismModulesPrinter.cpp index 12c0c4e..9d50860 100644 --- a/util/PrismModulesPrinter.cpp +++ b/util/PrismModulesPrinter.cpp @@ -218,6 +218,27 @@ namespace prism { return os; } + std::ostream& PrismModulesPrinter::printConfiguration(std::ostream& os, const std::vector& configurations) { + os << "\n// Configuration\n"; + + for (auto& configuration : configurations) { + if (configuration.type_ == ConfigType::Label) { + os << "label \"" << configuration.derivation_ << "\" = "; + } + else if (configuration.type_ == ConfigType::Formula) { + os << "formula " << configuration.derivation_ << " = "; + } + + for (auto& expr : configuration.expressions_) { + os << expr; + } + + os << ";\n"; + } + + return os; + } + std::ostream& PrismModulesPrinter::printAvoidanceLabel(std::ostream &os, const std::vector agentNames, const int &distance) { os << "label avoidance = "; bool first = true; diff --git a/util/PrismModulesPrinter.h b/util/PrismModulesPrinter.h index 12dc99f..22031d3 100644 --- a/util/PrismModulesPrinter.h +++ b/util/PrismModulesPrinter.h @@ -3,6 +3,7 @@ #include #include #include "MinigridGrammar.h" +#include "ConfigGrammar.h" #include "PrismPrinter.h" namespace prism { @@ -76,6 +77,8 @@ namespace prism { std::ostream& printRewards(std::ostream &os, const AgentName &agentName, const std::map &stateRewards, const cells &lava, const cells &goals, const std::map &backgroundTiles); + std::ostream& printConfiguration(std::ostream &os, const std::vector& configurations); + std::string moveGuard(const size_t &agentIndex); std::string moveUpdate(const size_t &agentIndex); From 42d0f4d6d96dbb8614e589ea3a799361eb711a39 Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Fri, 1 Sep 2023 10:26:42 +0200 Subject: [PATCH 04/62] changed to yaml config --- CMakeLists.txt | 4 +- main.cpp | 24 ++---- util/CMakeLists.txt | 1 + util/ConfigGrammar.h | 88 ---------------------- util/ConfigYaml.cpp | 150 +++++++++++++++++++++++++++++++++++++ util/ConfigYaml.h | 115 ++++++++++++++++++++++++++++ util/Grid.h | 2 +- util/PrismModulesPrinter.h | 2 +- 8 files changed, 278 insertions(+), 108 deletions(-) delete mode 100644 util/ConfigGrammar.h create mode 100644 util/ConfigYaml.cpp create mode 100644 util/ConfigYaml.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ca1571..1a7c5c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,11 @@ project( VERSION 0.1 LANGUAGES CXX) +find_package(yaml-cpp) + add_executable(main ${SRCS} main.cpp ) -target_link_libraries(main pthread) +target_link_libraries(main pthread yaml-cpp) diff --git a/main.cpp b/main.cpp index 19d3c25..1eaa0c7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,13 +1,14 @@ #include "util/OptionParser.h" #include "util/MinigridGrammar.h" #include "util/Grid.h" -#include "util/ConfigGrammar.h" +#include "util/ConfigYaml.h" #include #include #include #include + std::vector parseCommaSeparatedString(std::string const& str) { std::vector result; std::stringstream stream(str); @@ -20,6 +21,7 @@ std::vector parseCommaSeparatedString(std::string const& str) { return result; } + struct printer { typedef boost::spirit::utf8_string string; @@ -104,7 +106,7 @@ int main(int argc, char* argv[]) { std::fstream file {outputFilename->value(0), file.trunc | file.out}; std::fstream infile {inputFilename->value(0), infile.in}; - std::string line, content, background, rewards, config; + std::string line, content, background, rewards; std::cout << "\n"; bool parsingBackground = false; bool parsingStateRewards = false; @@ -129,15 +131,6 @@ int main(int argc, char* argv[]) { } std::cout << "\n"; - - if (configFilename->is_set()) { - std::fstream configFile {configFilename->value(0), configFile.in}; - while (std::getline(configFile, line) && !line.empty()) { - std::cout << "Configuration:\t" << line << "\n"; - config += line + "\n"; - } - } - pos_iterator_t contentFirst(content.begin()); pos_iterator_t contentIter = contentFirst; pos_iterator_t contentLast(content.end()); @@ -146,11 +139,7 @@ int main(int argc, char* argv[]) { pos_iterator_t backgroundIter = backgroundFirst; pos_iterator_t backgroundLast(background.end()); MinigridParser backgroundParser(backgroundFirst); - pos_iterator_t configFirst(config.begin()); - pos_iterator_t configIter = configFirst; - pos_iterator_t configLast(config.end()); - ConfigParser configParser(configFirst); - + cells contentCells; cells backgroundCells; std::vector configurations; @@ -161,7 +150,8 @@ int main(int argc, char* argv[]) { ok &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells); // TODO } if (configFilename->is_set()) { - ok &= phrase_parse(configIter, configLast, configParser, qi::space, configurations); + YamlConfigParser parser(configFilename->value(0)); + configurations = parser.parseConfiguration(); } for (auto& config : configurations) { diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index f5884fe..877fde4 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -5,4 +5,5 @@ list(APPEND SRCS ${CMAKE_CURRENT_LIST_DIR}/PrismModulesPrinter.cpp ${CMAKE_CURRENT_LIST_DIR}/popl.hpp ${CMAKE_CURRENT_LIST_DIR}/OptionParser.cpp + ${CMAKE_CURRENT_LIST_DIR}/ConfigYaml.cpp ) diff --git a/util/ConfigGrammar.h b/util/ConfigGrammar.h deleted file mode 100644 index 71aa54d..0000000 --- a/util/ConfigGrammar.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -#include "cell.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace qi = boost::spirit::qi; -namespace phoenix = boost::phoenix; - -typedef std::vector expressions; - -enum class ConfigType : char { - Label = 'L', - Formula = 'F', -}; - -struct Configuration -{ - expressions expressions_; - std::string derivation_; - ConfigType type_ {ConfigType::Label}; - - Configuration() = default; - Configuration(expressions expressions, std::string derivation, ConfigType type) : expressions_(expressions), derivation_(derivation), type_(type) {} - ~Configuration() = default; - Configuration(const Configuration&) = default; - - friend std::ostream& operator << (std::ostream& os, const Configuration& config) { - os << "Configuration with Type: " << static_cast(config.type_) << std::endl; - - for (auto& expression : config.expressions_) { - os << "\tExpression=" << expression << std::endl; - } - - return os << "\tDerviation=" << config.derivation_; - } -}; - - -BOOST_FUSION_ADAPT_STRUCT( - Configuration, - (ConfigType, type_) - (expressions, expressions_) - (std::string, derivation_) -) - - -template - struct ConfigParser : qi::grammar> -{ - ConfigParser(It first) : ConfigParser::base_type(config_) - { - using namespace qi; - //F:(AgentCannotMoveSouth & AgentCannotMoveNorth) | (AgentCannotMoveEast & AgentCannotMoveWest) ;AgentCannotTurn - configType_.add - ("L", ConfigType::Label) - ("F", ConfigType::Formula); - - expression_ = -qi::char_('!') > + char_("a-zA-Z_0-9"); - expressions_ = (expression_ % ','); - row_ = (configType_ > ':' > expressions_ > ';' > expression_); - // row_ = (expressions_ > ';' > expression_); - config_ = (row_ % "\n"); - - BOOST_SPIRIT_DEBUG_NODE(configType_); - BOOST_SPIRIT_DEBUG_NODE(expression_); - BOOST_SPIRIT_DEBUG_NODE(expressions_); - BOOST_SPIRIT_DEBUG_NODE(config_); - } - - private: - - qi::symbols configType_; - - - qi::rule expressions_; - qi::rule expression_; - qi::rule row_; - qi::rule> config_; -}; diff --git a/util/ConfigYaml.cpp b/util/ConfigYaml.cpp new file mode 100644 index 0000000..4e5d6ef --- /dev/null +++ b/util/ConfigYaml.cpp @@ -0,0 +1,150 @@ +#include "ConfigYaml.h" +#include + +std::ostream& operator <<(std::ostream &os, const Label& label) { + os << "\"" << label.label_ << "\"" << "=" << label.text_; + return os; +} + +std::ostream& operator << (std::ostream &os, const Formula& formula) { + os << formula.formula_ << "=" << formula.content_; + return os; +} + +std::ostream& operator << (std::ostream& os, const Action& action) { + os << action.action_; + return os; +} + +std::ostream& operator << (std::ostream& os, const Module& module) { + os << "Module: " << module.module_ << std::endl; + for (auto& action : module.actions_) { + os << action << std::endl; + } + return os; +} + +YAML::Node YAML::convert::encode(const Module& rhs) { + YAML::Node node; + + node.push_back(rhs.module_); + node.push_back(rhs.actions_); + + return node; +} + +bool YAML::convert::decode(const YAML::Node& node, Module& rhs) { + if (!node.Type() == NodeType::Map) { + return false; + } + rhs.actions_ = node["actions"].as>(); + rhs.module_ = node["module"].as(); + return true; +} + +YAML::Node YAML::convert::encode(const Action& rhs) { + YAML::Node node; + + node.push_back(rhs.action_); + node.push_back(rhs.guard_); + node.push_back(rhs.overwrite_); + node.push_back(rhs.update_); + + return node; +} + +bool YAML::convert::decode(const YAML::Node& node, Action& rhs) { + if (!node.Type() == NodeType::Map) { + return false; + } + + rhs.action_ = node["action"].as(); + rhs.guard_ = node["guard"].as(); + rhs.update_ = node["update"].as(); + + if (node["overwrite"]) { + rhs.overwrite_ = node["overwrite"].as(); + } + + return true; +} + + +YAML::Node YAML::convert