diff --git a/app/include/plasp-app/Commands.h b/app/include/plasp-app/Commands.h new file mode 100644 index 0000000..1da1972 --- /dev/null +++ b/app/include/plasp-app/Commands.h @@ -0,0 +1,29 @@ +#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/CommonOptions.h index 7255b18..74d3944 100644 --- a/app/include/plasp-app/CommonOptions.h +++ b/app/include/plasp-app/CommonOptions.h @@ -1,7 +1,7 @@ #ifndef __PLASP_APP__COMMON_OPTIONS_H #define __PLASP_APP__COMMON_OPTIONS_H -#include +#include #include #include @@ -17,10 +17,6 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// -namespace po = boost::program_options; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - class OptionException : public pddl::Exception { public: @@ -29,10 +25,9 @@ class OptionException : public pddl::Exception //////////////////////////////////////////////////////////////////////////////////////////////////// -po::options_description basicOptions(); -po::options_description outputOptions(); -po::options_description parserOptions(); -po::positional_options_description parserPositionalOptions(); +void addBasicOptions(cxxopts::Options &options); +void addOutputOptions(cxxopts::Options &options); +void addParserOptions(cxxopts::Options &options); //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,9 +57,9 @@ struct ParserOptions //////////////////////////////////////////////////////////////////////////////////////////////////// -BasicOptions parseBasicOptions(const po::variables_map &variablesMap); -OutputOptions parseOutputOptions(const po::variables_map &variablesMap); -ParserOptions parseParserOptions(const po::variables_map &variablesMap); +BasicOptions parseBasicOptions(cxxopts::Options &options); +OutputOptions parseOutputOptions(cxxopts::Options &options); +ParserOptions parseParserOptions(cxxopts::Options &options); //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/app/include/plasp-app/commands/Translate.h b/app/include/plasp-app/commands/Translate.h new file mode 100644 index 0000000..23461c4 --- /dev/null +++ b/app/include/plasp-app/commands/Translate.h @@ -0,0 +1,6 @@ +#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 new file mode 100644 index 0000000..db3a3ee --- /dev/null +++ b/app/src/plasp-app/Commands.cpp @@ -0,0 +1,36 @@ +#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/CommonOptions.cpp index e49c6ec..f849d6d 100644 --- a/app/src/plasp-app/CommonOptions.cpp +++ b/app/src/plasp-app/CommonOptions.cpp @@ -6,72 +6,54 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// -po::options_description basicOptions() +void addBasicOptions(cxxopts::Options &options) { - po::options_description basicOptions("Basic options"); - basicOptions.add_options() - ("help,h", po::bool_switch(), "Display this help message") - ("version,v", po::bool_switch(), "Display version information") - ("warnings-as-errors", po::bool_switch(), "Treat warnings as errors"); - - return basicOptions; + options.add_options("basic") + ("h,help", "Display this help message") + ("v,version", "Display version information") + ("warnings-as-errors", "Treat warnings as errors"); } //////////////////////////////////////////////////////////////////////////////////////////////////// -po::options_description outputOptions() +void addOutputOptions(cxxopts::Options &options) { - po::options_description outputOptions("Output options"); - outputOptions.add_options() - ("color", po::value()->default_value("auto"), "Colorize output (always, never, auto)") - ("log-priority,p", po::value()->default_value("info"), "Log messages starting from this priority (debug, info, warning, error)"); - - return outputOptions; + options.add_options("output") + ("color", "Colorize output (always, never, auto)", cxxopts::value()->default_value("auto")) + ("p,log-priority", "Log messages starting from this priority (debug, info, warning, error)", cxxopts::value()->default_value("info")); } //////////////////////////////////////////////////////////////////////////////////////////////////// -po::options_description parserOptions() +void addParserOptions(cxxopts::Options &options) { - po::options_description parserOptions("Parser options options"); - parserOptions.add_options() - ("input,i", po::value>(), "Input files (in PDDL or SAS format)") - ("parsing-mode", po::value()->default_value("strict"), "Parsing mode (strict, compatibility)") - ("language,l", po::value()->default_value("auto"), "Input language (pddl, sas, auto)"); - - return parserOptions; + options.add_options("parser") + ("i,input", "Input files (in PDDL or SAS format)", cxxopts::value>()) + ("parsing-mode", "Parsing mode (strict, compatibility)", cxxopts::value()->default_value("strict")) + ("l,language", "Input language (pddl, sas, auto)", cxxopts::value()->default_value("auto")); + options.parse_positional("input"); } //////////////////////////////////////////////////////////////////////////////////////////////////// -po::positional_options_description parserPositionalOptions() -{ - po::positional_options_description positionalOptions; - positionalOptions.add("input", -1); - - return positionalOptions; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -BasicOptions parseBasicOptions(const po::variables_map &variablesMap) +BasicOptions parseBasicOptions(cxxopts::Options &options) { BasicOptions basicOptions; - basicOptions.help = variablesMap["help"].as(); - basicOptions.version = variablesMap["version"].as(); - basicOptions.warningsAsErrors = variablesMap["warnings-as-errors"].as(); + basicOptions.help = options["help"].as(); + basicOptions.version = options["version"].as(); + basicOptions.warningsAsErrors = options["warnings-as-errors"].as(); return basicOptions; } //////////////////////////////////////////////////////////////////////////////////////////////////// -OutputOptions parseOutputOptions(const po::variables_map &variablesMap) +OutputOptions parseOutputOptions(cxxopts::Options &options) { OutputOptions outputOptions; - const auto colorPolicy = variablesMap["color"].as(); + const auto colorPolicy = options["color"].as(); if (colorPolicy == "auto") outputOptions.colorPolicy = colorlog::ColorStream::ColorPolicy::Auto; @@ -82,7 +64,7 @@ OutputOptions parseOutputOptions(const po::variables_map &variablesMap) else throw OptionException("unknown color policy “" + colorPolicy + "”"); - const auto logPriorityString = variablesMap["log-priority"].as(); + const auto logPriorityString = options["log-priority"].as(); try { @@ -98,21 +80,21 @@ OutputOptions parseOutputOptions(const po::variables_map &variablesMap) //////////////////////////////////////////////////////////////////////////////////////////////////// -ParserOptions parseParserOptions(const po::variables_map &variablesMap) +ParserOptions parseParserOptions(cxxopts::Options &options) { ParserOptions parserOptions; - const auto parsingModeString = variablesMap["parsing-mode"].as(); + const auto parsingModeString = options["parsing-mode"].as(); if (parsingModeString == "compatibility") parserOptions.parsingMode = pddl::Mode::Compatibility; else if (parsingModeString != "strict") throw OptionException("unknown parsing mode “" + parsingModeString + "”"); - if (variablesMap.count("input")) - parserOptions.inputFiles = variablesMap["input"].as>(); + if (options.count("input")) + parserOptions.inputFiles = options["input"].as>(); - const auto languageName = variablesMap["language"].as(); + const auto languageName = options["language"].as(); parserOptions.language = plasp::Language::fromString(languageName); if (parserOptions.language == plasp::Language::Type::Unknown) diff --git a/app/src/plasp-app/commands/Translate.cpp b/app/src/plasp-app/commands/Translate.cpp new file mode 100644 index 0000000..966462c --- /dev/null +++ b/app/src/plasp-app/commands/Translate.cpp @@ -0,0 +1,166 @@ +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +int translate(int argc, char **argv) +{ + cxxopts::Options options("plasp translate", "Translate PDDL to ASP."); + + addBasicOptions(options); + addOutputOptions(options); + addParserOptions(options); + + const auto printHelp = + [&]() + { + std::cout << options.help({"", "basic", "output", "parser"}); + }; + + options.parse(argc, argv); + + const auto basicOptions = parseBasicOptions(options); + const auto outputOptions = parseOutputOptions(options); + const auto parserOptions = parseParserOptions(options); + + if (basicOptions.help) + { + printHelp(); + return EXIT_SUCCESS; + } + + if (basicOptions.version) + { + std::cout << Version << std::endl; + return EXIT_SUCCESS; + } + + colorlog::Logger logger; + logger.setColorPolicy(outputOptions.colorPolicy); + logger.setLogPriority(outputOptions.logPriority); + + if (basicOptions.warningsAsErrors) + logger.setAbortPriority(colorlog::Priority::Warning); + + const auto printCompatibilityInfo = + [&]() + { + if (parserOptions.parsingMode != pddl::Mode::Compatibility) + logger.log(colorlog::Priority::Info, "try using --parsing-mode=compatibility for extended legacy feature support"); + }; + + try + { + tokenize::Tokenizer tokenizer; + + if (!parserOptions.inputFiles.empty()) + std::for_each(parserOptions.inputFiles.cbegin(), parserOptions.inputFiles.cend(), + [&](const auto &inputFile) + { + tokenizer.read(inputFile); + }); + else + { + logger.log(colorlog::Priority::Info, "reading from stdin"); + tokenizer.read("std::cin", std::cin); + } + + const auto detectLanguage = + [&]() + { + if (parserOptions.language == plasp::Language::Type::Automatic) + return plasp::detectLanguage(tokenizer); + + return parserOptions.language; + }; + + const auto language = detectLanguage(); + + // TODO: get rid of unknown language type, use exception instead + if (language == plasp::Language::Type::Unknown) + { + logger.log(colorlog::Priority::Error, "unknown input language"); + std::cout << std::endl; + printHelp(); + return EXIT_FAILURE; + } + + if (language == plasp::Language::Type::PDDL) + { + const auto logWarning = + [&](const auto &location, const auto &warning) + { + logger.log(colorlog::Priority::Warning, location, warning); + }; + + auto context = pddl::Context(std::move(tokenizer), logWarning); + context.mode = parserOptions.parsingMode; + auto description = pddl::parseDescription(context); + auto normalizedDescription = pddl::normalize(std::move(description)); + const auto translator = plasp::pddl::TranslatorASP(std::move(normalizedDescription), logger.outputStream()); + translator.translate(); + } + else if (language == plasp::Language::Type::SAS) + { + const auto description = plasp::sas::Description::fromTokenizer(std::move(tokenizer)); + const auto translator = plasp::sas::TranslatorASP(description, logger.outputStream()); + translator.translate(); + } + } + catch (const tokenize::TokenizerException &e) + { + logger.log(colorlog::Priority::Error, e.location(), e.message().c_str()); + + printCompatibilityInfo(); + + return EXIT_FAILURE; + } + catch (const pddl::ParserException &e) + { + if (e.location()) + logger.log(colorlog::Priority::Error, e.location().value(), e.message().c_str()); + else + logger.log(colorlog::Priority::Error, e.message().c_str()); + + printCompatibilityInfo(); + + return EXIT_FAILURE; + } + catch (const plasp::TranslatorException &e) + { + logger.log(colorlog::Priority::Error, e.what()); + return EXIT_FAILURE; + } + catch (const std::exception &e) + { + logger.log(colorlog::Priority::Error, e.what()); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/app/src/plasp-app/main.cpp b/app/src/plasp-app/main.cpp index 199a193..e073abd 100644 --- a/app/src/plasp-app/main.cpp +++ b/app/src/plasp-app/main.cpp @@ -2,183 +2,64 @@ #include #include -#include +#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include +#include #include +#include int main(int argc, char **argv) { - namespace po = boost::program_options; - - po::options_description description; - description.add(basicOptions()); - description.add(outputOptions()); - description.add(parserOptions()); - - po::variables_map variablesMap; - const auto printHelp = [&]() { - std::cout << "Usage: plasp [options] file..." << std::endl; - std::cout << "Translate PDDL to ASP." << std::endl; + // 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; + }; - std::cout << description; + const auto printVersion = + [&]() + { + std::cout << Version << std::endl; }; colorlog::Logger logger; + if (argc < 2) + { + printHelp(); + return EXIT_FAILURE; + } + try { - po::store(po::command_line_parser(argc, argv) - .options(description) - .positional(parserPositionalOptions()) - .run(), - variablesMap); - po::notify(variablesMap); + switch (parseCommand(argv[1])) + { + case Command::Help: + printHelp(); + return EXIT_SUCCESS; + case Command::Version: + printVersion(); + return EXIT_SUCCESS; + case Command::Translate: + return translate(argc - 1, &argv[1]); + default: + exit(EXIT_FAILURE); + } } - catch (const po::error &e) + catch (std::exception &exception) { - logger.log(colorlog::Priority::Error, e.what()); + logger.log(colorlog::Priority::Error, exception.what()); std::cout << std::endl; printHelp(); return EXIT_FAILURE; } - BasicOptions basicOptions; - OutputOptions outputOptions; - ParserOptions parserOptions; - - try - { - basicOptions = parseBasicOptions(variablesMap); - - if (basicOptions.help) - { - printHelp(); - return EXIT_SUCCESS; - } - - if (basicOptions.version) - { - std::cout << Version << std::endl; - return EXIT_SUCCESS; - } - - if (basicOptions.warningsAsErrors) - logger.setAbortPriority(colorlog::Priority::Warning); - - const auto outputOptions = parseOutputOptions(variablesMap); - - logger.setColorPolicy(outputOptions.colorPolicy); - logger.setLogPriority(outputOptions.logPriority); - - parserOptions = parseParserOptions(variablesMap); - } - catch (const OptionException &e) - { - logger.log(colorlog::Priority::Error, e.what()); - std::cout << std::endl; - printHelp(); - return EXIT_FAILURE; - } - - const auto printCompatibilityInfo = - [&]() - { - if (parserOptions.parsingMode != pddl::Mode::Compatibility) - logger.log(colorlog::Priority::Info, "try using --parsing-mode=compatibility for extended legacy feature support"); - }; - - try - { - tokenize::Tokenizer tokenizer; - - std::for_each(parserOptions.inputFiles.cbegin(), parserOptions.inputFiles.cend(), - [&](const auto &inputFile) - { - tokenizer.read(inputFile); - }); - - if (parserOptions.inputFiles.empty()) - tokenizer.read("std::cin", std::cin); - - if (parserOptions.language == plasp::Language::Type::Automatic) - parserOptions.language = plasp::detectLanguage(tokenizer); - - if (parserOptions.language == plasp::Language::Type::PDDL) - { - const auto logWarning = - [&](const auto &location, const auto &warning) - { - logger.log(colorlog::Priority::Warning, location, warning); - }; - - auto context = pddl::Context(std::move(tokenizer), logWarning); - context.mode = parserOptions.parsingMode; - auto description = pddl::parseDescription(context); - auto normalizedDescription = pddl::normalize(std::move(description)); - const auto translator = plasp::pddl::TranslatorASP(std::move(normalizedDescription), logger.outputStream()); - translator.translate(); - } - else if (parserOptions.language == plasp::Language::Type::SAS) - { - const auto description = plasp::sas::Description::fromTokenizer(std::move(tokenizer)); - const auto translator = plasp::sas::TranslatorASP(description, logger.outputStream()); - translator.translate(); - } - else - throw std::runtime_error("language detection failed"); - } - catch (const tokenize::TokenizerException &e) - { - logger.log(colorlog::Priority::Error, e.location(), e.message().c_str()); - - printCompatibilityInfo(); - - return EXIT_FAILURE; - } - catch (const pddl::ParserException &e) - { - if (e.location()) - logger.log(colorlog::Priority::Error, e.location().value(), e.message().c_str()); - else - logger.log(colorlog::Priority::Error, e.message().c_str()); - - printCompatibilityInfo(); - - return EXIT_FAILURE; - } - catch (const plasp::TranslatorException &e) - { - logger.log(colorlog::Priority::Error, e.what()); - return EXIT_FAILURE; - } - catch (const std::exception &e) - { - logger.log(colorlog::Priority::Error, e.what()); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + return EXIT_FAILURE; }