From 40547691a0e4dff35b204cb8cad8fcee44aa1065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Sun, 29 May 2016 16:27:11 +0200 Subject: [PATCH] Started implementing PDDL domain parser. --- apps/plasp-app/main.cpp | 29 +++++++--- include/plasp/pddl/Description.h | 43 +++++++++++++++ include/plasp/pddl/Domain.h | 35 ++++++++++++ include/plasp/pddl/Identifier.h | 32 +++++++++++ include/plasp/utils/Parser.h | 28 +++++++--- src/CMakeLists.txt | 6 +++ src/plasp/pddl/Description.cpp | 87 ++++++++++++++++++++++++++++++ src/plasp/pddl/Domain.cpp | 92 ++++++++++++++++++++++++++++++++ src/plasp/utils/Parser.cpp | 7 +++ 9 files changed, 347 insertions(+), 12 deletions(-) create mode 100644 include/plasp/pddl/Description.h create mode 100644 include/plasp/pddl/Domain.h create mode 100644 include/plasp/pddl/Identifier.h create mode 100644 src/plasp/pddl/Description.cpp create mode 100644 src/plasp/pddl/Domain.cpp diff --git a/apps/plasp-app/main.cpp b/apps/plasp-app/main.cpp index 8f7783a..dbd298c 100644 --- a/apps/plasp-app/main.cpp +++ b/apps/plasp-app/main.cpp @@ -1,7 +1,10 @@ +#include #include +#include #include +#include #include #include @@ -13,7 +16,8 @@ int main(int argc, char **argv) description.add_options() ("help,h", "Display this help message.") ("version,v", "Display version information.") - ("input,i", po::value(), "Specify the SAS input file."); + ("input,i", po::value(), "Specify the SAS input file.") + ("format,f", po::value()->default_value("SAS"), "Specify the file format (SAS or PDDL)."); po::positional_options_description positionalOptionsDescription; positionalOptionsDescription.add("input", -1); @@ -59,11 +63,24 @@ int main(int argc, char **argv) try { - const auto sasDescription = variablesMap.count("input") - ? plasp::sas::Description::fromFile(variablesMap["input"].as()) - : plasp::sas::Description::fromStream(std::cin); - const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription); - sasTranslator.translate(std::cout); + auto format = variablesMap["format"].as(); + std::transform(format.begin(), format.end(), format.begin(), ::tolower); + + if (format == "sas") + { + const auto sasDescription = variablesMap.count("input") + ? plasp::sas::Description::fromFile(variablesMap["input"].as()) + : plasp::sas::Description::fromStream(std::cin); + const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription); + sasTranslator.translate(std::cout); + } + else if (format == "pddl") + { + const auto pddlDescription = variablesMap.count("input") + ? plasp::pddl::Description::fromFile(variablesMap["input"].as()) + : plasp::pddl::Description::fromStream(std::cin); + //std::cout << pddlDescription << std::endl; + } } catch (const std::exception &e) { diff --git a/include/plasp/pddl/Description.h b/include/plasp/pddl/Description.h new file mode 100644 index 0000000..a699d98 --- /dev/null +++ b/include/plasp/pddl/Description.h @@ -0,0 +1,43 @@ +#ifndef __PLASP__PDDL__DESCRIPTION_H +#define __PLASP__PDDL__DESCRIPTION_H + +#include + +#include +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Description +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class Description +{ + public: + static Description fromStream(std::istream &istream); + static Description fromFile(const boost::filesystem::path &path); + + public: + + private: + Description() = default; + + void parseContent(utils::Parser &parser); + void parseSection(utils::Parser &parser); + + std::unique_ptr m_domain; + //std::unique_ptr m_problem; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/plasp/pddl/Domain.h b/include/plasp/pddl/Domain.h new file mode 100644 index 0000000..e260463 --- /dev/null +++ b/include/plasp/pddl/Domain.h @@ -0,0 +1,35 @@ +#ifndef __PLASP__PDDL__DOMAIN_H +#define __PLASP__PDDL__DOMAIN_H + +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Domain +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class Domain +{ + public: + static Domain fromPDDL(utils::Parser &parser); + + private: + Domain() = default; + + void parseSection(utils::Parser &parser); + + std::string m_name; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/plasp/pddl/Identifier.h b/include/plasp/pddl/Identifier.h new file mode 100644 index 0000000..e1abc92 --- /dev/null +++ b/include/plasp/pddl/Identifier.h @@ -0,0 +1,32 @@ +#ifndef __PLASP__PDDL__IDENTIFIER_H +#define __PLASP__PDDL__IDENTIFIER_H + +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Identifier +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const auto isIdentifier = + [](const auto character) + { + return character != '?' + && character != '(' + && character != ')' + && character != ';' + && std::isgraph(character); + }; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/plasp/utils/Parser.h b/include/plasp/utils/Parser.h index f54991f..c6e9481 100644 --- a/include/plasp/utils/Parser.h +++ b/include/plasp/utils/Parser.h @@ -28,12 +28,17 @@ class Parser size_t column() const; CharacterType currentCharacter() const; + void advance(); + bool atEndOfFile() const; template Type parse(); - template - std::string parseIdentifier(WhiteSpacePredicate whiteSpacePredicate, CharacterPredicate characterPredicate); + template + std::string parseIdentifier(CharacterPredicate characterPredicate, WhiteSpacePredicate whiteSpacePredicate); + + template + std::string parseIdentifier(CharacterPredicate characterPredicate); template void expect(const Type &expectedValue); @@ -51,7 +56,6 @@ class Parser private: void checkStream() const; - void advance(); bool advanceIf(CharacterType expectedCharacter); @@ -68,8 +72,8 @@ class Parser //////////////////////////////////////////////////////////////////////////////////////////////////// -template -std::string Parser::parseIdentifier(WhiteSpacePredicate whiteSpacePredicate, CharacterPredicate characterPredicate) +template +std::string Parser::parseIdentifier(CharacterPredicate characterPredicate, WhiteSpacePredicate whiteSpacePredicate) { skipWhiteSpace(whiteSpacePredicate); @@ -89,12 +93,24 @@ std::string Parser::parseIdentifier(WhiteSpacePredicate whiteSpacePredicate, Cha //////////////////////////////////////////////////////////////////////////////////////////////////// +template +std::string Parser::parseIdentifier(CharacterPredicate characterPredicate) +{ + return parseIdentifier(characterPredicate, + [&](const auto character) + { + return std::isspace(character); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + template void Parser::skipWhiteSpace(WhiteSpacePredicate whiteSpacePredicate) { checkStream(); - while (whiteSpacePredicate(*m_position)) + while (m_position != EndOfFile && whiteSpacePredicate(*m_position)) advance(); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f90d47..7aea3d2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,9 @@ set(target plasp) file(GLOB core_sources "plasp/*.cpp") file(GLOB core_headers "../include/plasp/*.h") +file(GLOB pddl_sources "plasp/pddl/*.cpp") +file(GLOB pddl_headers "../include/plasp/pddl/*.h") + file(GLOB sas_sources "plasp/sas/*.cpp") file(GLOB sas_headers "../include/plasp/sas/*.h") @@ -21,6 +24,9 @@ set(sources ${core_sources} ${core_headers} + ${pddl_sources} + ${pddl_headers} + ${sas_sources} ${sas_headers} diff --git a/src/plasp/pddl/Description.cpp b/src/plasp/pddl/Description.cpp new file mode 100644 index 0000000..8584108 --- /dev/null +++ b/src/plasp/pddl/Description.cpp @@ -0,0 +1,87 @@ +#include + +#include +#include + +#include + +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Description +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Description Description::fromStream(std::istream &istream) +{ + Description description; + + utils::Parser parser(istream); + + while (true) + { + parser.skipWhiteSpace(); + + if (parser.atEndOfFile()) + break; + + description.parseContent(parser); + } + + return description; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Description Description::fromFile(const boost::filesystem::path &path) +{ + if (!boost::filesystem::is_regular_file(path)) + throw std::runtime_error("File does not exist: \"" + path.string() + "\""); + + std::ifstream fileStream(path.string(), std::ios::in); + + return Description::fromStream(fileStream); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void Description::parseContent(utils::Parser &parser) +{ + std::cout << "Parsing file content" << std::endl; + + parser.expect("(define"); + parseSection(parser); + parser.expect(")"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void Description::parseSection(utils::Parser &parser) +{ + // Parse domain/problem identifier + parser.expect("("); + + const auto sectionIdentifier = parser.parse(); + + std::cout << "Parsing section " << sectionIdentifier << std::endl; + + if (sectionIdentifier == "domain") + m_domain = std::make_unique(Domain::fromPDDL(parser)); + //else if (sectionIdentifier == "problem") + // m_problem = std::make_unique(Problem::fromPDDL(parser)); + else + throw utils::ParserException(parser.row(), parser.column(), "Unknown PDDL section \"" + sectionIdentifier + "\""); + + parser.expect(")"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/src/plasp/pddl/Domain.cpp b/src/plasp/pddl/Domain.cpp new file mode 100644 index 0000000..922be9d --- /dev/null +++ b/src/plasp/pddl/Domain.cpp @@ -0,0 +1,92 @@ +#include + +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Domain +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Domain Domain::fromPDDL(utils::Parser &parser) +{ + Domain domain; + + domain.m_name = parser.parseIdentifier(isIdentifier); + + std::cout << "Parsing domain " << domain.m_name << std::endl; + + parser.expect(")"); + + while (true) + { + parser.skipWhiteSpace(); + + std::cout << parser.currentCharacter() << std::endl; + + if (parser.currentCharacter() == ')') + break; + + domain.parseSection(parser); + } + + return domain; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void Domain::parseSection(utils::Parser &parser) +{ + parser.expect("(:"); + + const auto sectionIdentifier = parser.parseIdentifier(isIdentifier); + + const auto skipSection = + [&]() + { + std::cout << "Skipping section " << sectionIdentifier << std::endl; + + size_t openParentheses = 1; + + while (true) + { + const auto character = parser.currentCharacter(); + parser.advance(); + + if (character == '(') + openParentheses++; + else if (character == ')') + { + openParentheses--; + + if (openParentheses == 0) + return; + } + } + }; + + if (sectionIdentifier == "requirements") + skipSection(); + else if (sectionIdentifier == "types") + skipSection(); + else if (sectionIdentifier == "constants") + skipSection(); + else if (sectionIdentifier == "predicates") + skipSection(); + else if (sectionIdentifier == "functions") + skipSection(); + else if (sectionIdentifier == "constraints") + skipSection(); + else if (sectionIdentifier == "action") + skipSection(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/src/plasp/utils/Parser.cpp b/src/plasp/utils/Parser.cpp index 55892a8..94f091e 100644 --- a/src/plasp/utils/Parser.cpp +++ b/src/plasp/utils/Parser.cpp @@ -63,6 +63,13 @@ Parser::CharacterType Parser::currentCharacter() const //////////////////////////////////////////////////////////////////////////////////////////////////// +bool Parser::atEndOfFile() const +{ + return m_position == EndOfFile; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void Parser::checkStream() const { if (m_position == EndOfFile)