From f6c9e19a60b1317465919712a17aacfe79314cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Fri, 8 Sep 2017 21:26:38 +0200 Subject: [PATCH] Outsourced parsing of common options in plasp app. --- app/include/plasp-app/CommonOptions.h | 71 ++++++++ app/include/plasp-app/Version.h | 14 ++ app/src/CMakeLists.txt | 9 +- app/src/main.cpp | 235 -------------------------- app/src/plasp-app/CommonOptions.cpp | 122 +++++++++++++ app/src/plasp-app/main.cpp | 184 ++++++++++++++++++++ 6 files changed, 396 insertions(+), 239 deletions(-) create mode 100644 app/include/plasp-app/CommonOptions.h create mode 100644 app/include/plasp-app/Version.h delete mode 100644 app/src/main.cpp create mode 100644 app/src/plasp-app/CommonOptions.cpp create mode 100644 app/src/plasp-app/main.cpp diff --git a/app/include/plasp-app/CommonOptions.h b/app/include/plasp-app/CommonOptions.h new file mode 100644 index 0000000..7255b18 --- /dev/null +++ b/app/include/plasp-app/CommonOptions.h @@ -0,0 +1,71 @@ +#ifndef __PLASP_APP__COMMON_OPTIONS_H +#define __PLASP_APP__COMMON_OPTIONS_H + +#include + +#include +#include + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Common Options +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace po = boost::program_options; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class OptionException : public pddl::Exception +{ + public: + using Exception::Exception; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +po::options_description basicOptions(); +po::options_description outputOptions(); +po::options_description parserOptions(); +po::positional_options_description parserPositionalOptions(); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct BasicOptions +{ + bool help = false; + bool version = false; + bool warningsAsErrors = false; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct OutputOptions +{ + colorlog::ColorStream::ColorPolicy colorPolicy = colorlog::ColorStream::ColorPolicy::Auto; + colorlog::Priority logPriority = colorlog::Priority::Info; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct ParserOptions +{ + std::vector inputFiles; + pddl::Mode parsingMode = pddl::Mode::Strict; + plasp::Language::Type language = plasp::Language::Type::Automatic; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BasicOptions parseBasicOptions(const po::variables_map &variablesMap); +OutputOptions parseOutputOptions(const po::variables_map &variablesMap); +ParserOptions parseParserOptions(const po::variables_map &variablesMap); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/app/include/plasp-app/Version.h b/app/include/plasp-app/Version.h new file mode 100644 index 0000000..24a9dec --- /dev/null +++ b/app/include/plasp-app/Version.h @@ -0,0 +1,14 @@ +#ifndef __PLASP_APP__VERSION_H +#define __PLASP_APP__VERSION_H + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Version +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +static constexpr const auto Version = "plasp version 3.1.0-git"; + +#endif diff --git a/app/src/CMakeLists.txt b/app/src/CMakeLists.txt index caa9458..4894110 100644 --- a/app/src/CMakeLists.txt +++ b/app/src/CMakeLists.txt @@ -2,11 +2,11 @@ set(target plasp-app) find_package(Boost 1.55.0 COMPONENTS program_options iostreams system REQUIRED) -file(GLOB core_sources "*.cpp") -file(GLOB core_headers "../include/*.h") +file(GLOB core_sources "plasp-app/*.cpp") +file(GLOB core_headers "../include/plasp-app/*.h") -file(GLOB commands_sources "commands/*.cpp") -file(GLOB commands_headers "../include/commands/*.h") +file(GLOB commands_sources "plasp-app/commands/*.cpp") +file(GLOB commands_headers "../include/plasp-app/commands/*.h") set(includes ${Boost_INCLUDE_DIRS} @@ -15,6 +15,7 @@ set(includes ${PROJECT_SOURCE_DIR}/lib/colorlog/include ${PROJECT_SOURCE_DIR}/lib/variant/include ${PROJECT_SOURCE_DIR}/lib/pddl/include + ${PROJECT_SOURCE_DIR}/app/include ) set(sources diff --git a/app/src/main.cpp b/app/src/main.cpp deleted file mode 100644 index 803d864..0000000 --- a/app/src/main.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#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; - - bool warningsAsErrors; - - po::options_description description("Allowed options"); - description.add_options() - ("help,h", "Display this help message") - ("version,v", "Display version information") - ("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)") - ("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)") - ("warnings-as-errors", po::bool_switch(&warningsAsErrors), "Treat warnings as errors"); - - po::positional_options_description positionalOptionsDescription; - positionalOptionsDescription.add("input", -1); - - po::variables_map variablesMap; - - const auto printHelp = - [&]() - { - std::cout << "Usage: plasp [options] file..." << std::endl; - std::cout << "Translate PDDL to ASP." << std::endl << std::endl; - - std::cout << description; - }; - - colorlog::Logger logger; - - try - { - po::store(po::command_line_parser(argc, argv) - .options(description) - .positional(positionalOptionsDescription) - .run(), - variablesMap); - po::notify(variablesMap); - } - catch (const po::error &e) - { - logger.log(colorlog::Priority::Error, e.what()); - std::cout << std::endl; - printHelp(); - return EXIT_FAILURE; - } - - if (variablesMap.count("help")) - { - printHelp(); - return EXIT_SUCCESS; - } - - if (variablesMap.count("version")) - { - std::cout << "plasp version 3.1.0-git" << std::endl; - return EXIT_SUCCESS; - } - - if (warningsAsErrors) - logger.setAbortPriority(colorlog::Priority::Warning); - - auto parsingMode = pddl::Mode::Strict; - - const auto parsingModeString = variablesMap["parsing-mode"].as(); - - if (parsingModeString == "compatibility") - parsingMode = pddl::Mode::Compatibility; - else if (parsingModeString != "strict") - { - logger.log(colorlog::Priority::Error, "unknown parsing mode “" + parsingModeString + "”"); - std::cout << std::endl; - printHelp(); - return EXIT_FAILURE; - } - - const auto printCompatibilityInfo = - [&]() - { - if (parsingMode != pddl::Mode::Compatibility) - logger.log(colorlog::Priority::Info, "try using --parsing-mode=compatibility for extended legacy feature support"); - }; - - const auto colorPolicy = variablesMap["color"].as(); - - if (colorPolicy == "auto") - logger.setColorPolicy(colorlog::ColorStream::ColorPolicy::Auto); - else if (colorPolicy == "never") - logger.setColorPolicy(colorlog::ColorStream::ColorPolicy::Never); - else if (colorPolicy == "always") - logger.setColorPolicy(colorlog::ColorStream::ColorPolicy::Always); - else - { - logger.log(colorlog::Priority::Error, "unknown color policy “" + colorPolicy + "”"); - std::cout << std::endl; - printHelp(); - return EXIT_FAILURE; - } - - const auto logPriorityString = variablesMap["log-priority"].as(); - - try - { - const auto logPriority = colorlog::priorityFromName(logPriorityString.c_str()); - logger.setLogPriority(logPriority); - } - catch (const std::exception &e) - { - logger.log(colorlog::Priority::Error, ("unknown log priorty “" + logPriorityString + "”").c_str()); - logger.errorStream() << std::endl; - printHelp(); - return EXIT_FAILURE; - } - - try - { - tokenize::Tokenizer tokenizer; - - if (variablesMap.count("input")) - { - const auto &inputFiles = variablesMap["input"].as>(); - - std::for_each(inputFiles.cbegin(), inputFiles.cend(), - [&](const auto &inputFile) - { - tokenizer.read(inputFile); - }); - } - else - tokenizer.read("std::cin", std::cin); - - const auto detectLanguage = - [&]() - { - const auto languageName = variablesMap["language"].as(); - const auto language = plasp::Language::fromString(languageName); - - if (language == plasp::Language::Type::Automatic) - return plasp::detectLanguage(tokenizer); - - return language; - }; - - const auto language = detectLanguage(); - - 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 = 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/CommonOptions.cpp b/app/src/plasp-app/CommonOptions.cpp new file mode 100644 index 0000000..e49c6ec --- /dev/null +++ b/app/src/plasp-app/CommonOptions.cpp @@ -0,0 +1,122 @@ +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Common Options +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +po::options_description basicOptions() +{ + 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; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +po::options_description outputOptions() +{ + 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; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +po::options_description parserOptions() +{ + 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; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +po::positional_options_description parserPositionalOptions() +{ + po::positional_options_description positionalOptions; + positionalOptions.add("input", -1); + + return positionalOptions; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +BasicOptions parseBasicOptions(const po::variables_map &variablesMap) +{ + BasicOptions basicOptions; + + basicOptions.help = variablesMap["help"].as(); + basicOptions.version = variablesMap["version"].as(); + basicOptions.warningsAsErrors = variablesMap["warnings-as-errors"].as(); + + return basicOptions; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +OutputOptions parseOutputOptions(const po::variables_map &variablesMap) +{ + OutputOptions outputOptions; + + const auto colorPolicy = variablesMap["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 = variablesMap["log-priority"].as(); + + try + { + outputOptions.logPriority = colorlog::priorityFromName(logPriorityString.c_str()); + } + catch (const std::exception &e) + { + throw OptionException(e.what()); + } + + return outputOptions; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ParserOptions parseParserOptions(const po::variables_map &variablesMap) +{ + ParserOptions parserOptions; + + const auto parsingModeString = variablesMap["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>(); + + const auto languageName = variablesMap["language"].as(); + parserOptions.language = plasp::Language::fromString(languageName); + + if (parserOptions.language == plasp::Language::Type::Unknown) + throw OptionException("unknown input language “" + languageName + "”"); + + return parserOptions; +} diff --git a/app/src/plasp-app/main.cpp b/app/src/plasp-app/main.cpp new file mode 100644 index 0000000..199a193 --- /dev/null +++ b/app/src/plasp-app/main.cpp @@ -0,0 +1,184 @@ +#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; + + std::cout << description; + }; + + colorlog::Logger logger; + + try + { + po::store(po::command_line_parser(argc, argv) + .options(description) + .positional(parserPositionalOptions()) + .run(), + variablesMap); + po::notify(variablesMap); + } + catch (const po::error &e) + { + logger.log(colorlog::Priority::Error, e.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; +}