diff --git a/include/plasp/pddl/Context.h b/include/plasp/pddl/Context.h new file mode 100644 index 0000000..def3ba1 --- /dev/null +++ b/include/plasp/pddl/Context.h @@ -0,0 +1,27 @@ +#ifndef __PLASP__PDDL__CONTEXT_H +#define __PLASP__PDDL__CONTEXT_H + +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Context +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +struct Context +{ + TypeHashMap types; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/plasp/pddl/Description.h b/include/plasp/pddl/Description.h index d066740..73c556b 100644 --- a/include/plasp/pddl/Description.h +++ b/include/plasp/pddl/Description.h @@ -32,6 +32,7 @@ class Description void parseContent(utils::Parser &parser); void parseSection(utils::Parser &parser); + Context m_context; std::unique_ptr m_domain; //std::unique_ptr m_problem; }; diff --git a/include/plasp/pddl/Domain.h b/include/plasp/pddl/Domain.h index fb06477..b7bf001 100644 --- a/include/plasp/pddl/Domain.h +++ b/include/plasp/pddl/Domain.h @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -21,17 +22,15 @@ namespace pddl class Domain { public: - static Domain fromPDDL(utils::Parser &parser); - - using TypesHashMap = std::unordered_map; + static Domain fromPDDL(utils::Parser &parser, Context &context); public: const std::string &name() const; const Requirement::Types &requirements() const; - const TypesHashMap &types() const; + const TypeHashMap &types() const; private: - Domain() = default; + Domain(Context &context); void parseSection(utils::Parser &parser); @@ -43,9 +42,10 @@ class Domain void checkConsistency(); + Context &m_context; + std::string m_name; Requirement::Types m_requirements; - TypesHashMap m_types; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/plasp/pddl/Type.h b/include/plasp/pddl/Type.h index 31dada2..9720c91 100644 --- a/include/plasp/pddl/Type.h +++ b/include/plasp/pddl/Type.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -18,21 +19,30 @@ namespace pddl // //////////////////////////////////////////////////////////////////////////////////////////////////// +class Context; + +class Type; +using TypeHashMap = std::unordered_map; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + class Type { public: - Type(std::string name); + static void parsePDDL(utils::Parser &parser, Context &context); public: - void setDirty(bool isDirty = true); - bool isDirty() const; - const std::string &name() const; - - void addParentType(const Type &parentType); const std::vector &parentTypes() const; private: + Type(std::string name); + + void setDirty(bool isDirty = true); + bool isDirty() const; + + void addParentType(const Type &parentType); + bool m_isDirty; std::string m_name; diff --git a/src/plasp/pddl/Description.cpp b/src/plasp/pddl/Description.cpp index 303ca88..93052e6 100644 --- a/src/plasp/pddl/Description.cpp +++ b/src/plasp/pddl/Description.cpp @@ -81,7 +81,7 @@ void Description::parseSection(utils::Parser &parser) std::cout << "Parsing section " << sectionIdentifier << std::endl; if (sectionIdentifier == "domain") - m_domain = std::make_unique(Domain::fromPDDL(parser)); + m_domain = std::make_unique(Domain::fromPDDL(parser, m_context)); //else if (sectionIdentifier == "problem") // m_problem = std::make_unique(Problem::fromPDDL(parser)); else diff --git a/src/plasp/pddl/Domain.cpp b/src/plasp/pddl/Domain.cpp index fbbb706..0a0a031 100644 --- a/src/plasp/pddl/Domain.cpp +++ b/src/plasp/pddl/Domain.cpp @@ -17,9 +17,16 @@ namespace pddl // //////////////////////////////////////////////////////////////////////////////////////////////////// -Domain Domain::fromPDDL(utils::Parser &parser) +Domain::Domain(Context &context) +: m_context(context) { - Domain domain; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Domain Domain::fromPDDL(utils::Parser &parser, Context &context) +{ + Domain domain(context); domain.m_name = parser.parseIdentifier(isIdentifier); @@ -60,9 +67,9 @@ const Requirement::Types &Domain::requirements() const //////////////////////////////////////////////////////////////////////////////////////////////////// -const Domain::TypesHashMap &Domain::types() const +const TypeHashMap &Domain::types() const { - return m_types; + return m_context.types; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -193,48 +200,12 @@ void Domain::computeDerivedRequirements() void Domain::parseTypingSection(utils::Parser &parser) { - // Parses a single type identifier - const auto parseType = - [&]() -> auto & - { - parser.skipWhiteSpace(); - - const auto typeName = parser.parseIdentifier(isIdentifier); - const auto insertionResult = m_types.emplace(std::make_pair(typeName, Type(typeName))); - auto &type = insertionResult.first->second; - - // Flag type for potentially upcoming parent type declaration - type.setDirty(); - - parser.skipWhiteSpace(); - - return type; - }; - // Parses a type and potentially its parent type while (parser.currentCharacter() != ')') { - parseType(); + Type::parsePDDL(parser, m_context); - // Check for type inheritance - if (!parser.advanceIf('-')) - continue; - - // If existing, parse parent type - auto &parentType = parseType(); - - parentType.setDirty(false); - - // Assign parent type to all types that were previously flagged - std::for_each(m_types.begin(), m_types.end(), - [&](auto &childType) - { - if (!childType.second.isDirty()) - return; - - childType.second.addParentType(parentType); - childType.second.setDirty(false); - }); + parser.skipWhiteSpace(); } parser.expect(")"); @@ -244,7 +215,7 @@ void Domain::parseTypingSection(utils::Parser &parser) void Domain::checkConsistency() { - if (!m_types.empty() && !hasRequirement(Requirement::Type::Typing)) + if (!m_context.types.empty() && !hasRequirement(Requirement::Type::Typing)) { throw ConsistencyException("Domain contains typing information but does not declare typing requirement"); diff --git a/src/plasp/pddl/Type.cpp b/src/plasp/pddl/Type.cpp index ce8cf71..9b4f173 100644 --- a/src/plasp/pddl/Type.cpp +++ b/src/plasp/pddl/Type.cpp @@ -1,5 +1,10 @@ #include +#include + +#include +#include + namespace plasp { namespace pddl @@ -13,12 +18,69 @@ namespace pddl Type::Type(std::string name) : m_isDirty{false}, - m_name{name} + m_name(name) { } //////////////////////////////////////////////////////////////////////////////////////////////////// +void Type::parsePDDL(utils::Parser &parser, Context &context) +{ + // Parses a single type identifier + const auto parseType = + [&]() -> auto & + { + parser.skipWhiteSpace(); + + const auto typeName = parser.parseIdentifier(isIdentifier); + const auto match = context.types.find(typeName); + const auto typeExists = (match != context.types.cend()); + + if (typeExists) + { + auto &type = match->second; + + type.setDirty(); + + return type; + } + + const auto insertionResult = context.types.emplace(std::make_pair(typeName, Type(typeName))); + auto &type = insertionResult.first->second; + + // Flag type for potentially upcoming parent type declaration + type.setDirty(); + + return type; + }; + + parseType(); + + parser.skipWhiteSpace(); + + // Check for type inheritance + if (!parser.advanceIf('-')) + return; + + // If existing, parse parent type + auto &parentType = parseType(); + + parentType.setDirty(false); + + // Assign parent type to all types that were previously flagged + std::for_each(context.types.begin(), context.types.end(), + [&](auto &childType) + { + if (!childType.second.isDirty()) + return; + + childType.second.addParentType(parentType); + childType.second.setDirty(false); + }); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void Type::setDirty(bool isDirty) { m_isDirty = isDirty;