Started implementing predicate parsing.

This commit is contained in:
Patrick Lühne 2016-05-31 16:43:25 +02:00
parent 5f763e90fc
commit 2654a6ff23
10 changed files with 404 additions and 19 deletions

View File

@ -1,6 +1,7 @@
#ifndef __PLASP__PDDL__CONTEXT_H
#define __PLASP__PDDL__CONTEXT_H
#include <plasp/pddl/Predicate.h>
#include <plasp/pddl/Type.h>
namespace plasp
@ -14,9 +15,11 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Context
class Context
{
TypeHashMap types;
public:
TypeHashMap types;
PredicateHashMap predicates;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -4,6 +4,7 @@
#include <unordered_map>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Predicate.h>
#include <plasp/pddl/Requirement.h>
#include <plasp/pddl/Type.h>
#include <plasp/utils/Parser.h>
@ -28,6 +29,7 @@ class Domain
const std::string &name() const;
const Requirements &requirements() const;
const TypeHashMap &types() const;
const PredicateHashMap &predicates() const;
private:
Domain(Context &context);
@ -40,6 +42,8 @@ class Domain
void parseTypingSection(utils::Parser &parser);
void parsePredicateSection(utils::Parser &parser);
void checkConsistency();
Context &m_context;

View File

@ -0,0 +1,87 @@
#ifndef __PLASP__PDDL__PREDICATE_H
#define __PLASP__PDDL__PREDICATE_H
#include <unordered_map>
#include <vector>
#include <boost/functional/hash.hpp>
#include <plasp/pddl/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
struct PredicateHashMapKey
{
std::string name;
size_t arity;
bool operator==(const PredicateHashMapKey &other) const
{
return arity == other.arity && name == other.name;
}
};
class Predicate;
using PredicateHashMap = std::unordered_map<PredicateHashMapKey, Predicate>;
////////////////////////////////////////////////////////////////////////////////////////////////////
class Predicate
{
public:
static Predicate &parseDeclaration(utils::Parser &parser, Context &context);
public:
const std::string &name() const;
const Variables &arguments() const;
bool isDeclared() const;
private:
Predicate(std::string name);
void setDeclared();
bool m_isDeclared;
std::string m_name;
Variables m_arguments;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace std
{
template<>
struct hash<plasp::pddl::PredicateHashMapKey>
{
std::size_t operator()(const plasp::pddl::PredicateHashMapKey &key) const
{
std::size_t seed = 0;
boost::hash_combine(seed, key.name);
boost::hash_combine(seed, key.arity);
return seed;
}
};
}
#endif

View File

@ -30,7 +30,7 @@ class Type
{
public:
static Type &parse(utils::Parser &parser, Context &context);
static Type &parseWithInheritance(utils::Parser &parser, Context &context);
static Type &parseDeclaration(utils::Parser &parser, Context &context);
public:
const std::string &name() const;

View File

@ -0,0 +1,56 @@
#ifndef __PLASP__PDDL__VARIABLE_H
#define __PLASP__PDDL__VARIABLE_H
#include <vector>
#include <plasp/pddl/Type.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
class Variable;
using Variables = std::vector<Variable>;
////////////////////////////////////////////////////////////////////////////////////////////////////
class Variable
{
public:
static Variable parse(utils::Parser &parser, Context &context);
public:
const std::string &name() const;
const Type &type() const;
void setDirty(bool isDirty = true);
bool isDirty() const;
void setType(const Type &type);
private:
Variable(std::string name);
bool m_isDirty;
std::string m_name;
const Type *m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -74,6 +74,13 @@ const TypeHashMap &Domain::types() const
////////////////////////////////////////////////////////////////////////////////////////////////////
const PredicateHashMap &Domain::predicates() const
{
return m_context.predicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseSection(utils::Parser &parser)
{
parser.expect<std::string>("(:");
@ -111,7 +118,7 @@ void Domain::parseSection(utils::Parser &parser)
else if (sectionIdentifier == "constants")
skipSection();
else if (sectionIdentifier == "predicates")
skipSection();
parsePredicateSection(parser);
else if (sectionIdentifier == "functions")
skipSection();
else if (sectionIdentifier == "constraints")
@ -124,17 +131,16 @@ void Domain::parseSection(utils::Parser &parser)
void Domain::parseRequirementsSection(utils::Parser &parser)
{
while (true)
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
parser.skipWhiteSpace();
if (parser.currentCharacter() == ')')
break;
if (parser.currentCharacter() == ':')
parser.advance();
m_requirements.emplace_back(Requirement::parse(parser));
parser.skipWhiteSpace();
}
if (m_requirements.empty())
@ -204,10 +210,29 @@ void Domain::computeDerivedRequirements()
void Domain::parseTypingSection(utils::Parser &parser)
{
parser.skipWhiteSpace();
// Store types and their parent types
while (parser.currentCharacter() != ')')
{
Type::parseWithInheritance(parser, m_context);
Type::parseDeclaration(parser, m_context);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parsePredicateSection(utils::Parser &parser)
{
parser.skipWhiteSpace();
// Store predicates and their arguments
while (parser.currentCharacter() != ')')
{
Predicate::parseDeclaration(parser, m_context);
parser.skipWhiteSpace();
}
@ -234,6 +259,16 @@ void Domain::checkConsistency()
if (!type.second.isDeclared())
throw ConsistencyException("Type \"" + type.second.name() + "\" used but never declared");
});
// Verify that all used predicates have been declared
std::for_each(m_context.predicates.cbegin(), m_context.predicates.cend(),
[&](const auto &predicate)
{
if (!predicate.second.isDeclared())
throw ConsistencyException("Predicate \"" + predicate.second.name() + "\" used but never declared");
});
// Verify that all variables have types
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,111 @@
#include <plasp/pddl/Predicate.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Identifier.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Predicate::Predicate(std::string name)
: m_isDeclared{false},
m_name{name}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Predicate &Predicate::parseDeclaration(utils::Parser &parser, Context &context)
{
parser.expect<std::string>("(");
const auto predicateName = parser.parseIdentifier(isIdentifier);
Predicate predicate(predicateName);
// Flag predicate as correctly declared in the types section
predicate.setDeclared();
parser.skipWhiteSpace();
// Parse arguments
while (parser.currentCharacter() != ')')
{
predicate.m_arguments.emplace_back(Variable::parse(parser, context));
parser.skipWhiteSpace();
// Check if the variable has a type declaration
if (!parser.advanceIf('-'))
continue;
// Parse argument type
const auto &type = Type::parse(parser, context);
// Set the argument type for all previously flagged arguments
std::for_each(predicate.m_arguments.begin(), predicate.m_arguments.end(),
[&](auto &argument)
{
if (!argument.isDirty())
return;
argument.setType(type);
argument.setDirty(false);
});
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
const auto predicateArity = predicate.m_arguments.size();
const PredicateHashMapKey key = {predicateName, predicateArity};
const auto insertionResult = context.predicates.emplace(std::make_pair(key, std::move(predicate)));
std::cout << "Emplaced " << insertionResult.first->second.name() << std::endl;
return insertionResult.first->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Predicate::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Predicate::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variables &Predicate::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -48,19 +48,19 @@ Type &Type::parse(utils::Parser &parser, Context &context)
// Flag type for potentially upcoming parent type declaration
type.setDirty();
// Flag type as correctly declared in the types section
type.setDeclared();
return type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Type &Type::parseWithInheritance(utils::Parser &parser, Context &context)
Type &Type::parseDeclaration(utils::Parser &parser, Context &context)
{
// Parse and store type
auto &type = parse(parser, context);
// Flag type as correctly declared in the types section
type.setDeclared();
parser.skipWhiteSpace();
// Check for type inheritance
@ -72,6 +72,10 @@ Type &Type::parseWithInheritance(utils::Parser &parser, Context &context)
parentType.setDirty(false);
// Type object is an implicit primitive type
if (parentType.name() == "object")
parentType.setDeclared();
// Assign parent type to all types that were previously flagged
std::for_each(context.types.begin(), context.types.end(),
[&](auto &childType)

View File

@ -0,0 +1,81 @@
#include <plasp/pddl/Variable.h>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Identifier.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable::Variable(std::string name)
: m_isDirty{false},
m_name(name)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable Variable::parse(utils::Parser &parser, Context &context)
{
parser.skipWhiteSpace();
parser.expect<std::string>("?");
const auto variableName = parser.parseIdentifier(isIdentifier);
Variable variable(variableName);
variable.setDirty();
return variable;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Variable::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Variable::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setType(const Type &type)
{
m_type = &type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Type &Variable::type() const
{
BOOST_ASSERT(m_type != nullptr);
return *m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -56,11 +56,15 @@ TEST_F(PDDLParserTests, ParseBlocksWorldDomain)
ASSERT_EQ(domain.types().size(), 1u);
const auto blockType = domain.types().find("block");
ASSERT_NE(blockType, domain.types().cend());
const auto block = domain.types().find("block");
ASSERT_NE(block, domain.types().cend());
ASSERT_EQ(blockType->second.name(), "block");
ASSERT_EQ(blockType->second.parentTypes().size(), 0u);
ASSERT_EQ(block->second.name(), "block");
ASSERT_EQ(block->second.parentTypes().size(), 0u);
ASSERT_EQ(domain.predicates().size(), 5u);
const auto on = domain.predicates().find({"on", 2});
}
catch (const std::exception &e)
{