diff --git a/CMakeLists.txt b/CMakeLists.txt index ec639a3..f9682f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ option(PLASP_BUILD_STATIC "Build static binaries" OFF) set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -Werror ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "-g ${CMAKE_CXX_FLAGS_DEBUG}") -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/app/include/plasp-app/Command.h b/app/include/plasp-app/Command.h new file mode 100644 index 0000000..96fbf87 --- /dev/null +++ b/app/include/plasp-app/Command.h @@ -0,0 +1,43 @@ +#ifndef __PLASP_APP__COMMAND_H +#define __PLASP_APP__COMMAND_H + +#include + +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Command +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +class Command +{ + protected: + void addOptionGroupsTo(cxxopts::Options &options) + { + forEach(m_optionGroups, + [&](auto &optionGroup) + { + optionGroup.addTo(options); + }); + } + + void parseOptionGroups(cxxopts::Options &options) + { + forEach(m_optionGroups, + [&](auto &optionGroup) + { + optionGroup.parse(options); + }); + } + + std::tuple m_optionGroups; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/app/include/plasp-app/Commands.h b/app/include/plasp-app/Commands.h deleted file mode 100644 index 1da1972..0000000 --- a/app/include/plasp-app/Commands.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __PLASP_APP__COMMANDS_H -#define __PLASP_APP__COMMANDS_H - -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Commands -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - -enum class Command -{ - Help, - Version, - CheckSyntax, - Requirements, - PrettyPrint, - Normalize, - Translate -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -Command parseCommand(const std::string &commandString); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -#endif diff --git a/app/include/plasp-app/CommonOptions.h b/app/include/plasp-app/OptionGroups.h similarity index 65% rename from app/include/plasp-app/CommonOptions.h rename to app/include/plasp-app/OptionGroups.h index 74d3944..d756fa1 100644 --- a/app/include/plasp-app/CommonOptions.h +++ b/app/include/plasp-app/OptionGroups.h @@ -1,5 +1,5 @@ -#ifndef __PLASP_APP__COMMON_OPTIONS_H -#define __PLASP_APP__COMMON_OPTIONS_H +#ifndef __PLASP_APP__OPTION_GROUPS_H +#define __PLASP_APP__OPTION_GROUPS_H #include @@ -13,7 +13,7 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // -// Common Options +// Option Groups // //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -25,14 +25,12 @@ class OptionException : public pddl::Exception //////////////////////////////////////////////////////////////////////////////////////////////////// -void addBasicOptions(cxxopts::Options &options); -void addOutputOptions(cxxopts::Options &options); -void addParserOptions(cxxopts::Options &options); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -struct BasicOptions +struct OptionGroupBasic { + void addTo(cxxopts::Options &options); + void parse(cxxopts::Options &options); + void printHelp(std::ostream &stream); + bool help = false; bool version = false; bool warningsAsErrors = false; @@ -40,16 +38,24 @@ struct BasicOptions //////////////////////////////////////////////////////////////////////////////////////////////////// -struct OutputOptions +struct OptionGroupOutput { + void addTo(cxxopts::Options &options); + void parse(cxxopts::Options &options); + void printHelp(std::ostream &stream); + colorlog::ColorStream::ColorPolicy colorPolicy = colorlog::ColorStream::ColorPolicy::Auto; colorlog::Priority logPriority = colorlog::Priority::Info; }; //////////////////////////////////////////////////////////////////////////////////////////////////// -struct ParserOptions +struct OptionGroupParser { + void addTo(cxxopts::Options &options); + void parse(cxxopts::Options &options); + void printHelp(std::ostream &stream); + std::vector inputFiles; pddl::Mode parsingMode = pddl::Mode::Strict; plasp::Language::Type language = plasp::Language::Type::Automatic; @@ -57,10 +63,4 @@ struct ParserOptions //////////////////////////////////////////////////////////////////////////////////////////////////// -BasicOptions parseBasicOptions(cxxopts::Options &options); -OutputOptions parseOutputOptions(cxxopts::Options &options); -ParserOptions parseParserOptions(cxxopts::Options &options); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - #endif diff --git a/app/include/plasp-app/Utils.h b/app/include/plasp-app/Utils.h new file mode 100644 index 0000000..889d9c0 --- /dev/null +++ b/app/include/plasp-app/Utils.h @@ -0,0 +1,46 @@ +#ifndef __PLASP_APP__UTILS_H +#define __PLASP_APP__UTILS_H + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Command +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +auto makeIndexDispatcher(std::index_sequence) +{ + return + [](auto &&f) + { + (f(std::integral_constant{}), ...); + }; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +auto makeIndexDispatcher() +{ + return makeIndexDispatcher(std::make_index_sequence{}); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void forEach(Tuple &&tuple, Functor &&functor) +{ + constexpr auto n = std::tuple_size>::value; + auto dispatcher = makeIndexDispatcher(); + dispatcher( + [&functor, &tuple](auto index) + { + functor(std::get(std::forward(tuple))); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/app/include/plasp-app/commands/CommandTranslate.h b/app/include/plasp-app/commands/CommandTranslate.h new file mode 100644 index 0000000..b791785 --- /dev/null +++ b/app/include/plasp-app/commands/CommandTranslate.h @@ -0,0 +1,21 @@ +#ifndef __PLASP_APP__COMMANDS__TRANSLATE_H +#define __PLASP_APP__COMMANDS__TRANSLATE_H + +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Command Translate +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class CommandTranslate : public Command +{ + public: + int run(int argc, char **argv); +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/app/include/plasp-app/commands/Translate.h b/app/include/plasp-app/commands/Translate.h deleted file mode 100644 index 23461c4..0000000 --- a/app/include/plasp-app/commands/Translate.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __PLASP_APP__COMMANDS__TRANSLATE_H -#define __PLASP_APP__COMMANDS__TRANSLATE_H - -int translate(int argc, char **argv); - -#endif diff --git a/app/src/plasp-app/Commands.cpp b/app/src/plasp-app/Commands.cpp deleted file mode 100644 index db3a3ee..0000000 --- a/app/src/plasp-app/Commands.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Commands -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - -static const std::map commandNames = - { - {"help", Command::Help}, - {"-h", Command::Help}, - {"--help", Command::Help}, - {"version", Command::Version}, - {"-v", Command::Version}, - {"--version", Command::Version}, - {"check-syntax", Command::CheckSyntax}, - {"requirements", Command::Requirements}, - {"pretty-print", Command::PrettyPrint}, - {"normalize", Command::Normalize}, - {"translate", Command::Translate}, - }; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -Command parseCommand(const std::string &commandString) -{ - const auto matchingCommand = commandNames.find(commandString); - - if (matchingCommand == commandNames.cend()) - throw std::runtime_error(std::string("“") + commandString + "” is not a plasp command"); - - return matchingCommand->second; -} diff --git a/app/src/plasp-app/CommonOptions.cpp b/app/src/plasp-app/OptionGroups.cpp similarity index 56% rename from app/src/plasp-app/CommonOptions.cpp rename to app/src/plasp-app/OptionGroups.cpp index f849d6d..aea6dc7 100644 --- a/app/src/plasp-app/CommonOptions.cpp +++ b/app/src/plasp-app/OptionGroups.cpp @@ -1,22 +1,31 @@ -#include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// // -// Common Options +// Option Groups // //////////////////////////////////////////////////////////////////////////////////////////////////// -void addBasicOptions(cxxopts::Options &options) +void OptionGroupBasic::addTo(cxxopts::Options &options) { options.add_options("basic") - ("h,help", "Display this help message") - ("v,version", "Display version information") - ("warnings-as-errors", "Treat warnings as errors"); + ("h,help", "Display this help message") + ("v,version", "Display version information") + ("warnings-as-errors", "Treat warnings as errors"); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void addOutputOptions(cxxopts::Options &options) +void OptionGroupBasic::parse(cxxopts::Options &options) +{ + help = options["help"].as(); + version = options["version"].as(); + warningsAsErrors = options["warnings-as-errors"].as(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void OptionGroupOutput::addTo(cxxopts::Options &options) { options.add_options("output") ("color", "Colorize output (always, never, auto)", cxxopts::value()->default_value("auto")) @@ -25,7 +34,34 @@ void addOutputOptions(cxxopts::Options &options) //////////////////////////////////////////////////////////////////////////////////////////////////// -void addParserOptions(cxxopts::Options &options) +void OptionGroupOutput::parse(cxxopts::Options &options) +{ + const auto colorPolicyString = options["color"].as(); + + if (colorPolicyString == "auto") + colorPolicy = colorlog::ColorStream::ColorPolicy::Auto; + else if (colorPolicyString == "never") + colorPolicy = colorlog::ColorStream::ColorPolicy::Never; + else if (colorPolicyString == "always") + colorPolicy = colorlog::ColorStream::ColorPolicy::Always; + else + throw OptionException("unknown color policy “" + colorPolicyString + "”"); + + const auto logPriorityString = options["log-priority"].as(); + + try + { + logPriority = colorlog::priorityFromName(logPriorityString.c_str()); + } + catch (const std::exception &e) + { + throw OptionException(e.what()); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void OptionGroupParser::addTo(cxxopts::Options &options) { options.add_options("parser") ("i,input", "Input files (in PDDL or SAS format)", cxxopts::value>()) @@ -36,69 +72,21 @@ void addParserOptions(cxxopts::Options &options) //////////////////////////////////////////////////////////////////////////////////////////////////// -BasicOptions parseBasicOptions(cxxopts::Options &options) +void OptionGroupParser::parse(cxxopts::Options &options) { - BasicOptions basicOptions; - - basicOptions.help = options["help"].as(); - basicOptions.version = options["version"].as(); - basicOptions.warningsAsErrors = options["warnings-as-errors"].as(); - - return basicOptions; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -OutputOptions parseOutputOptions(cxxopts::Options &options) -{ - OutputOptions outputOptions; - - const auto colorPolicy = options["color"].as(); - - if (colorPolicy == "auto") - outputOptions.colorPolicy = colorlog::ColorStream::ColorPolicy::Auto; - else if (colorPolicy == "never") - outputOptions.colorPolicy = colorlog::ColorStream::ColorPolicy::Never; - else if (colorPolicy == "always") - outputOptions.colorPolicy = colorlog::ColorStream::ColorPolicy::Always; - else - throw OptionException("unknown color policy “" + colorPolicy + "”"); - - const auto logPriorityString = options["log-priority"].as(); - - try - { - outputOptions.logPriority = colorlog::priorityFromName(logPriorityString.c_str()); - } - catch (const std::exception &e) - { - throw OptionException(e.what()); - } - - return outputOptions; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -ParserOptions parseParserOptions(cxxopts::Options &options) -{ - ParserOptions parserOptions; - const auto parsingModeString = options["parsing-mode"].as(); if (parsingModeString == "compatibility") - parserOptions.parsingMode = pddl::Mode::Compatibility; + parsingMode = pddl::Mode::Compatibility; else if (parsingModeString != "strict") throw OptionException("unknown parsing mode “" + parsingModeString + "”"); if (options.count("input")) - parserOptions.inputFiles = options["input"].as>(); + inputFiles = options["input"].as>(); const auto languageName = options["language"].as(); - parserOptions.language = plasp::Language::fromString(languageName); + language = plasp::Language::fromString(languageName); - if (parserOptions.language == plasp::Language::Type::Unknown) + if (language == plasp::Language::Type::Unknown) throw OptionException("unknown input language “" + languageName + "”"); - - return parserOptions; } diff --git a/app/src/plasp-app/commands/Translate.cpp b/app/src/plasp-app/commands/CommandTranslate.cpp similarity index 86% rename from app/src/plasp-app/commands/Translate.cpp rename to app/src/plasp-app/commands/CommandTranslate.cpp index 966462c..2b243ac 100644 --- a/app/src/plasp-app/commands/Translate.cpp +++ b/app/src/plasp-app/commands/CommandTranslate.cpp @@ -1,4 +1,5 @@ -#include +#include + #include #include @@ -23,18 +24,19 @@ #include #include -#include -#include #include -#include -int translate(int argc, char **argv) +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Command Translate +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +int CommandTranslate::run(int argc, char **argv) { cxxopts::Options options("plasp translate", "Translate PDDL to ASP."); - addBasicOptions(options); - addOutputOptions(options); - addParserOptions(options); + addOptionGroupsTo(options); const auto printHelp = [&]() @@ -44,9 +46,11 @@ int translate(int argc, char **argv) options.parse(argc, argv); - const auto basicOptions = parseBasicOptions(options); - const auto outputOptions = parseOutputOptions(options); - const auto parserOptions = parseParserOptions(options); + parseOptionGroups(options); + + const auto &basicOptions = std::get(m_optionGroups); + const auto &outputOptions = std::get(m_optionGroups); + const auto &parserOptions = std::get(m_optionGroups); if (basicOptions.help) { diff --git a/app/src/plasp-app/main.cpp b/app/src/plasp-app/main.cpp index e073abd..bca0ed2 100644 --- a/app/src/plasp-app/main.cpp +++ b/app/src/plasp-app/main.cpp @@ -7,9 +7,58 @@ #include #include -#include +#include #include -#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Main +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +enum class CommandType +{ + Help, + Version, + CheckSyntax, + Requirements, + PrettyPrint, + Normalize, + Translate +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static const std::map commandNames = + { + {"help", CommandType::Help}, + {"-h", CommandType::Help}, + {"--help", CommandType::Help}, + {"version", CommandType::Version}, + {"-v", CommandType::Version}, + {"--version", CommandType::Version}, + {"check-syntax", CommandType::CheckSyntax}, + {"requirements", CommandType::Requirements}, + {"pretty-print", CommandType::PrettyPrint}, + {"normalize", CommandType::Normalize}, + {"translate", CommandType::Translate}, + }; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const auto parseCommandType = + [](const std::string &commandString) + { + const auto matchingCommand = commandNames.find(commandString); + + if (matchingCommand == commandNames.cend()) + throw std::runtime_error(std::string("“") + commandString + "” is not a plasp command"); + + return matchingCommand->second; + }; + +//////////////////////////////////////////////////////////////////////////////////////////////////// int main(int argc, char **argv) { @@ -19,8 +68,7 @@ int main(int argc, char **argv) // TODO: add list of available commands std::cout << "ASP planning tools for PDDL." << std::endl - << "Usage: plasp []" << std::endl - << "Translate PDDL to ASP." << std::endl; + << "Usage: plasp []" << std::endl; }; const auto printVersion = @@ -39,16 +87,16 @@ int main(int argc, char **argv) try { - switch (parseCommand(argv[1])) + switch (parseCommandType(argv[1])) { - case Command::Help: + case CommandType::Help: printHelp(); return EXIT_SUCCESS; - case Command::Version: + case CommandType::Version: printVersion(); return EXIT_SUCCESS; - case Command::Translate: - return translate(argc - 1, &argv[1]); + case CommandType::Translate: + return CommandTranslate().run(argc - 1, &argv[1]); default: exit(EXIT_FAILURE); } diff --git a/doc/building.md b/doc/building.md index 8bc91b4..037c109 100644 --- a/doc/building.md +++ b/doc/building.md @@ -1,6 +1,6 @@ # Building -`plasp` requires a C++14 compiler (preferrably GCC ≥ 6.1 or clang ≥ 3.8), the `boost` libraries (≥ 1.55), and CMake for building. +`plasp` requires a C++17 compiler (preferrably GCC ≥ 6.1 or clang ≥ 3.8), the `boost` libraries (≥ 1.55), and CMake for building. ```bash $ git clone https://github.com/potassco/plasp.git