Started reimplementing problem parser.

This commit is contained in:
Patrick Lühne 2017-06-13 19:52:15 +02:00
parent 06b9632b70
commit a7c4fdb242
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
43 changed files with 2566 additions and 278 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "lib/catch"]
path = lib/catch
url = https://github.com/philsquared/Catch
[submodule "lib/variant"]
path = lib/variant
url = https://github.com/mapbox/variant

View File

@ -26,7 +26,7 @@ namespace ast
struct Constant
{
explicit Constant(ConstantDeclaration &declaration)
explicit Constant(ConstantDeclaration *declaration)
: declaration{declaration}
{
}
@ -36,7 +36,7 @@ struct Constant
Constant(Constant &&other) = default;
Constant &operator=(Constant &&other) = default;
ConstantDeclaration &declaration;
ConstantDeclaration *declaration;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -51,8 +51,8 @@ struct ConstantDeclaration
ConstantDeclaration(const ConstantDeclaration &other) = delete;
ConstantDeclaration &operator=(const ConstantDeclaration &&other) = delete;
ConstantDeclaration(ConstantDeclaration &&other) = default;
ConstantDeclaration &operator=(ConstantDeclaration &&other) = default;
ConstantDeclaration(ConstantDeclaration &&other) = delete;
ConstantDeclaration &operator=(ConstantDeclaration &&other) = delete;
std::string name;
std::experimental::optional<Type> type;
@ -79,7 +79,7 @@ struct Dummy
struct PrimitiveType
{
explicit PrimitiveType(PrimitiveTypeDeclaration &declaration)
explicit PrimitiveType(PrimitiveTypeDeclaration *declaration)
: declaration{declaration}
{
}
@ -89,7 +89,7 @@ struct PrimitiveType
PrimitiveType(PrimitiveType &&other) = default;
PrimitiveType &operator=(PrimitiveType &&other) = default;
PrimitiveTypeDeclaration &declaration;
PrimitiveTypeDeclaration *declaration;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -103,11 +103,11 @@ struct PrimitiveTypeDeclaration
PrimitiveTypeDeclaration(const PrimitiveTypeDeclaration &other) = delete;
PrimitiveTypeDeclaration &operator=(const PrimitiveTypeDeclaration &&other) = delete;
PrimitiveTypeDeclaration(PrimitiveTypeDeclaration &&other) = default;
PrimitiveTypeDeclaration &operator=(PrimitiveTypeDeclaration &&other) = default;
PrimitiveTypeDeclaration(PrimitiveTypeDeclaration &&other) = delete;
PrimitiveTypeDeclaration &operator=(PrimitiveTypeDeclaration &&other) = delete;
std::string name;
std::vector<PrimitiveType> parentTypes;
std::vector<PrimitiveTypePointer> parentTypes;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -127,7 +127,7 @@ struct Unsupported
struct Variable
{
explicit Variable(VariableDeclaration &declaration)
explicit Variable(VariableDeclaration *declaration)
: declaration{declaration}
{
}
@ -137,7 +137,7 @@ struct Variable
Variable(Variable &&other) = default;
Variable &operator=(Variable &&other) = default;
VariableDeclaration &declaration;
VariableDeclaration *declaration;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -152,8 +152,8 @@ struct VariableDeclaration
VariableDeclaration(const VariableDeclaration &other) = delete;
VariableDeclaration &operator=(const VariableDeclaration &&other) = delete;
VariableDeclaration(VariableDeclaration &&other) = default;
VariableDeclaration &operator=(VariableDeclaration &&other) = default;
VariableDeclaration(VariableDeclaration &&other) = delete;
VariableDeclaration &operator=(VariableDeclaration &&other) = delete;
std::string name;
std::experimental::optional<Type> type;
@ -165,7 +165,7 @@ struct VariableDeclaration
struct Predicate
{
explicit Predicate(PredicateDeclaration &declaration)
explicit Predicate(PredicateDeclaration *declaration)
: declaration{declaration}
{
}
@ -176,8 +176,7 @@ struct Predicate
Predicate &operator=(Predicate &&other) = default;
Terms arguments;
PredicateDeclaration &declaration;
PredicateDeclaration *declaration;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -416,9 +415,9 @@ struct Action
std::string name;
ast::VariableDeclarations parameters;
std::experimental::optional<ast::Precondition> precondition;
std::experimental::optional<ast::Effect> effect;
VariableDeclarations parameters;
std::experimental::optional<Precondition> precondition;
std::experimental::optional<Effect> effect;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -429,15 +428,15 @@ struct Domain
Domain(const Domain &other) = delete;
Domain &operator=(const Domain &&other) = delete;
Domain(Domain &&other) = default;
Domain &operator=(Domain &&other) = default;
Domain(Domain &&other) = delete;
Domain &operator=(Domain &&other) = delete;
std::string name;
Requirements requirements;
ast::PrimitiveTypeDeclarations types;
ast::ConstantDeclarations constants;
ast::PredicateDeclarations predicates;
std::vector<Action> actions;
PrimitiveTypeDeclarations types;
ConstantDeclarations constants;
PredicateDeclarations predicates;
Actions actions;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -451,7 +450,7 @@ struct InitialState
InitialState(InitialState &&other) = default;
InitialState &operator=(InitialState &&other) = default;
ast::Facts facts;
Facts facts;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -460,17 +459,22 @@ struct Problem
{
Problem() = default;
Problem(Domain *domain)
: domain{domain}
{
}
Problem(const Problem &other) = delete;
Problem &operator=(const Problem &&other) = delete;
Problem(Problem &&other) = default;
Problem &operator=(Problem &&other) = default;
Domain &domain;
Domain *domain;
std::string name;
Requirements requirements;
ast::ConstantDeclarations objects;
ConstantDeclarations objects;
InitialState initialState;
std::experimental::optional<ast::Goal> goal;
std::experimental::optional<Goal> goal;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -512,8 +516,8 @@ struct Description
Description(Description &&other) = default;
Description &operator=(Description &&other) = default;
Domain domain;
std::experimental::optional<Problem> problem;
DomainPointer domain;
std::experimental::optional<ProblemPointer> problem;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -26,27 +26,37 @@ namespace ast
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Constant;
using ConstantPointer = std::unique_ptr<Constant>;
struct ConstantDeclaration;
using ConstantDeclarations = std::vector<ConstantDeclaration>;
using ConstantDeclarationPointer = std::unique_ptr<ConstantDeclaration>;
using ConstantDeclarations = std::vector<ConstantDeclarationPointer>;
struct Dummy;
using DummyPointer = std::unique_ptr<Dummy>;
struct PrimitiveType;
using PrimitiveTypes = std::vector<PrimitiveType>;
using PrimitiveTypePointer = std::unique_ptr<PrimitiveType>;
using PrimitiveTypes = std::vector<PrimitiveTypePointer>;
struct PrimitiveTypeDeclaration;
using PrimitiveTypeDeclarations = std::vector<PrimitiveTypeDeclaration>;
using PrimitiveTypeDeclarationPointer = std::unique_ptr<PrimitiveTypeDeclaration>;
using PrimitiveTypeDeclarations = std::vector<PrimitiveTypeDeclarationPointer>;
struct Unsupported;
using UnsupportedPointer = std::unique_ptr<Unsupported>;
struct Variable;
using Variables = std::vector<Variable>;
using VariablePointer = std::unique_ptr<Variable>;
using Variables = std::vector<VariablePointer>;
struct VariableDeclaration;
using VariableDeclarations = std::vector<VariableDeclaration>;
using VariableDeclarationPointer = std::unique_ptr<VariableDeclaration>;
using VariableDeclarations = std::vector<VariableDeclarationPointer>;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Compounds
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Predicate;
using Predicates = std::vector<Predicate>;
using PredicatePointer = std::unique_ptr<Predicate>;
using Predicates = std::vector<PredicatePointer>;
struct PredicateDeclaration;
using PredicateDeclarations = std::vector<PredicateDeclaration>;
using PredicateDeclarationPointer = std::unique_ptr<PredicateDeclaration>;
using PredicateDeclarations = std::vector<PredicateDeclarationPointer>;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions
@ -55,29 +65,53 @@ using PredicateDeclarations = std::vector<PredicateDeclaration>;
template<class Argument>
struct And;
template<class Argument>
using AndPointer = std::unique_ptr<And<Argument>>;
template<class Argument>
struct At;
template<class Argument>
using AtPointer = std::unique_ptr<At<Argument>>;
template<class Argument>
struct Either;
template<class Argument>
using EitherPointer = std::unique_ptr<Either<Argument>>;
template<class Argument>
struct Exists;
template<class Argument>
using ExistsPointer = std::unique_ptr<Exists<Argument>>;
template<class Argument>
struct ForAll;
template<class Argument>
using ForAllPointer = std::unique_ptr<ForAll<Argument>>;
template<class Argument>
struct Imply;
template<class Argument>
using ImplyPointer = std::unique_ptr<Imply<Argument>>;
template<class Argument>
struct Not;
template<class Argument>
using NotPointer = std::unique_ptr<Not<Argument>>;
template<class Argument>
struct Or;
template<class Argument>
using OrPointer = std::unique_ptr<Or<Argument>>;
template<class ArgumentLeft, class ArgumentRight>
struct When;
template<class ArgumentLeft, class ArgumentRight>
using WhenPointer = std::unique_ptr<When<ArgumentLeft, ArgumentRight>>;
////////////////////////////////////////////////////////////////////////////////////////////////////
// PDDL Structure
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Action;
using ActionPointer = std::unique_ptr<Action>;
using Actions = std::vector<ActionPointer>;
struct Description;
using DescriptionPointer = std::unique_ptr<Description>;
struct Domain;
using DomainPointer = std::unique_ptr<Domain>;
struct Problem;
using ProblemPointer = std::unique_ptr<Problem>;
enum class Requirement;
using Requirements = std::vector<Requirement>;
@ -88,8 +122,8 @@ using Requirements = std::vector<Requirement>;
namespace detail
{
using TermT = Variant<
Constant,
Variable>;
ConstantPointer,
VariablePointer>;
}
class Term : public detail::TermT
@ -104,8 +138,8 @@ using Terms = std::vector<Term>;
namespace detail
{
using AtomicFormulaT = Variant<
Predicate,
Unsupported>;
PredicatePointer,
UnsupportedPointer>;
}
class AtomicFormula : public detail::AtomicFormulaT
@ -121,13 +155,13 @@ namespace detail
{
using PreconditionT = Variant<
AtomicFormula,
And<Precondition>,
Exists<Precondition>,
ForAll<Precondition>,
Imply<Precondition>,
Not<Precondition>,
Or<Precondition>,
Unsupported>;
AndPointer<Precondition>,
ExistsPointer<Precondition>,
ForAllPointer<Precondition>,
ImplyPointer<Precondition>,
NotPointer<Precondition>,
OrPointer<Precondition>,
UnsupportedPointer>;
}
class Precondition : public detail::PreconditionT
@ -145,11 +179,11 @@ namespace detail
{
using EffectT = Variant<
AtomicFormula,
And<Effect>,
ForAll<Effect>,
Not<Effect>,
When<Precondition, Effect>,
Unsupported>;
AndPointer<Effect>,
ForAllPointer<Effect>,
NotPointer<Effect>,
WhenPointer<Precondition, Effect>,
UnsupportedPointer>;
}
class Effect : public detail::EffectT
@ -162,8 +196,8 @@ class Effect : public detail::EffectT
namespace detail
{
using TypeT = Variant<
Either<PrimitiveType>,
PrimitiveType>;
EitherPointer<PrimitiveTypePointer>,
PrimitiveTypePointer>;
}
class Type : public detail::TypeT
@ -177,7 +211,7 @@ namespace detail
{
using LiteralT = Variant<
AtomicFormula,
Not<AtomicFormula>>;
NotPointer<AtomicFormula>>;
}
class Literal : public detail::LiteralT
@ -193,7 +227,7 @@ namespace detail
{
using FactT = Variant<
AtomicFormula,
At<Literal>>;
AtPointer<Literal>>;
}
class Fact : public detail::FactT

View File

@ -0,0 +1,49 @@
#ifndef __PDDL_PARSE__CONTEXT_H
#define __PDDL_PARSE__CONTEXT_H
#include <functional>
#include <pddlparse/Tokenizer.h>
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Context
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Context
{
constexpr static const char *auxiliaryPrefix()
{
return "__plasp_";
}
// TODO: replace std::string with char *
using WarningCallback = std::function<void (tokenize::Location, const std::string &)>;
Context() = default;
~Context() = default;
explicit Context(Tokenizer &&tokenizer, WarningCallback warningCallback)
: tokenizer{std::move(tokenizer)},
warningCallback{warningCallback}
{
}
Context(const Context &other) = delete;
Context &operator=(const Context &other) = delete;
Context(Context &&other) = default;
Context &operator=(Context &&other) = default;
Tokenizer tokenizer;
WarningCallback warningCallback;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef __PDDL_PARSE__PARSE_H
#define __PDDL_PARSE__PARSE_H
#include <experimental/optional>
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parse
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Description parseDescription(Context &context);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@ -1,233 +1,20 @@
#ifndef __PDDL_PARSE__VARIANT_H
#define __PDDL_PARSE__VARIANT_H
#include <cassert>
#include <memory>
#include <ostream>
#include <type_traits>
#include <mapbox/variant.hpp>
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variant (from clingo, written by Roland Kaminski)
//
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace detail {
template <class T, class... U>
struct TypeInList : std::false_type { };
template <class T, class... U>
struct TypeInList<T, T, U...> : std::true_type { };
template <class T, class V, class... U>
struct TypeInList<T, V, U...> : TypeInList<T, U...> { };
template <unsigned, class... U>
struct VariantHolder;
template <unsigned n>
struct VariantHolder<n> {
bool check_type() const { return type_ == 0; }
void emplace() { }
void emplace2() { }
void copy(VariantHolder const &) { }
void destroy() {
type_ = 0;
data_ = nullptr;
}
void print(std::ostream &) const { }
void swap(VariantHolder &other) {
std::swap(type_, other.type_);
std::swap(data_, other.data_);
}
unsigned type_ = 0;
void *data_ = nullptr;
};
template <unsigned n, class T, class... U>
struct VariantHolder<n, T, U...> : VariantHolder<n+1, U...>{
using Helper = VariantHolder<n+1, U...>;
using Helper::check_type;
using Helper::emplace;
using Helper::emplace2;
using Helper::data_;
using Helper::type_;
bool check_type(T *) const { return type_ == n; }
template <class... Args>
void emplace(T *, Args&& ...x) {
data_ = new T{std::forward<Args>(x)...};
type_ = n;
}
// NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467
template <class... Args>
void emplace2(T *, Args&& ...x) {
data_ = new T(std::forward<Args>(x)...);
type_ = n;
}
void copy(VariantHolder const &src) {
if (src.type_ == n) {
data_ = new T(*static_cast<T const*>(src.data_));
type_ = src.type_;
}
Helper::copy(src);
}
// NOTE: workaround for visual studio (C++14 can also simply use auto)
# define CLINGO_VARIANT_RETURN(Type) decltype(std::declval<V>().visit(std::declval<Type&>(), std::declval<Args>()...))
template <class V, class... Args>
using Ret_ = CLINGO_VARIANT_RETURN(T);
template <class V, class... Args>
using ConstRet_ = CLINGO_VARIANT_RETURN(T const);
// non-const
template <class V, class U1, class... U2, class... Args>
auto accept_(V &&visitor, Args &&... args) -> CLINGO_VARIANT_RETURN(T) {
static_assert(std::is_same<Ret_<V, Args...>, typename Helper::template Ret_<V, Args...>>::value, "");
return n == type_
? visitor.visit(*static_cast<T*>(data_), std::forward<Args>(args)...)
: Helper::template accept<V>(std::forward<V>(visitor), std::forward<Args>(args)...);
}
template <class V, class... Args>
auto accept_(V &&visitor, Args &&... args) -> CLINGO_VARIANT_RETURN(T) {
assert(n == type_);
return visitor.visit(*static_cast<T*>(data_), std::forward<Args>(args)...);
}
template <class V, class... Args>
auto accept(V &&visitor, Args &&... args) -> CLINGO_VARIANT_RETURN(T) {
return accept_<V, U...>(std::forward<V>(visitor), std::forward<Args>(args)...);
}
// const
template <class V, class U1, class... U2, class... Args>
auto accept_(V &&visitor, Args &&... args) const -> CLINGO_VARIANT_RETURN(T const) {
static_assert(std::is_same<ConstRet_<V, Args...>, typename Helper::template ConstRet_<V, Args...>>::value, "");
return n == type_
? visitor.visit(*static_cast<T const *>(data_), std::forward<Args>(args)...)
: Helper::template accept<V>(std::forward<V>(visitor), std::forward<Args>(args)...);
}
template <class V, class... Args>
auto accept_(V &&visitor, Args &&... args) const -> CLINGO_VARIANT_RETURN(T const) {
assert(n == type_);
return visitor.visit(*static_cast<T const *>(data_), std::forward<Args>(args)...);
}
template <class V, class... Args>
auto accept(V &&visitor, Args &&... args) const -> CLINGO_VARIANT_RETURN(T const) {
return accept_<V, U...>(std::forward<V>(visitor), std::forward<Args>(args)...);
}
# undef CLINGO_VARIANT_RETURN
void destroy() {
if (n == type_) { delete static_cast<T*>(data_); }
Helper::destroy();
}
void print(std::ostream &out) const {
if (n == type_) { out << *static_cast<T const*>(data_); }
Helper::print(out);
}
};
}
template <class... T>
class Variant {
using Holder = detail::VariantHolder<1, T...>;
public:
Variant(Variant const &other) : Variant(other.data_) { }
Variant(Variant &&other) noexcept { data_.swap(other.data_); }
template <class U>
Variant(U &&u, typename std::enable_if<detail::TypeInList<U, T...>::value>::type * = nullptr) { emplace2<U>(std::forward<U>(u)); }
template <class U>
Variant(U &u, typename std::enable_if<detail::TypeInList<U, T...>::value>::type * = nullptr) { emplace2<U>(u); }
template <class U>
Variant(U const &u, typename std::enable_if<detail::TypeInList<U, T...>::value>::type * = nullptr) { emplace2<U>(u); }
template <class U, class... Args>
static Variant make(Args&& ...args) {
Variant<T...> x;
x.data_.emplace(static_cast<U*>(nullptr), std::forward<Args>(args)...);
return std::move(x);
}
~Variant() { data_.destroy(); }
Variant &operator=(Variant const &other) { return *this = other.data_; }
Variant &operator=(Variant &&other) noexcept { return *this = std::move(other.data_); }
template <class U>
typename std::enable_if<detail::TypeInList<U, T...>::value, Variant>::type &operator=(U &&u) {
emplace2<U>(std::forward<U>(u));
return *this;
}
template <class U>
typename std::enable_if<detail::TypeInList<U, T...>::value, Variant>::type &operator=(U &u) {
emplace2<U>(u);
return *this;
}
template <class U>
typename std::enable_if<detail::TypeInList<U, T...>::value, Variant>::type &operator=(U const &u) {
emplace2<U>(u);
return *this;
}
template <class U>
U &get() {
if (!data_.check_type(static_cast<U*>(nullptr))) { throw std::bad_cast(); }
return *static_cast<U*>(data_.data_);
}
template <class U>
U const &get() const {
if (!data_.check_type(static_cast<U*>(nullptr))) { throw std::bad_cast(); }
return *static_cast<U*>(data_.data_);
}
template <class U, class... Args>
void emplace(Args&& ...args) {
Variant<T...> x;
x.data_.emplace(static_cast<U*>(nullptr), std::forward<Args>(args)...);
data_.swap(x.data_);
}
template <class U>
bool is() const { return data_.check_type(static_cast<U*>(nullptr)); }
void swap(Variant &other) { data_.swap(other.data_); }
template <class V, class... Args>
typename Holder::template Ret_<V, Args...> accept(V &&visitor, Args &&... args) {
return data_.accept(std::forward<V>(visitor), std::forward<Args>(args)...);
}
template <class V, class... Args>
typename Holder::template ConstRet_<V, Args...> accept(V &&visitor, Args &&... args) const {
return data_.accept(std::forward<V>(visitor), std::forward<Args>(args)...);
}
friend std::ostream &operator<<(std::ostream &out, Variant const &x) {
x.data_.print(out);
return out;
}
private:
Variant() { }
Variant(Holder const &data) {
data_.copy(data);
}
Variant &operator=(Holder const &data) {
Variant x(data);
data_.swap(x.data_);
return *this;
}
Variant &operator=(Holder &&data) noexcept {
Holder x;
x.swap(data);
// Destroy the old data_ only after securing the new data
// Otherwise, data would be destroyed together with data_ if it was a descendant of data_
data_.destroy();
x.swap(data_);
return *this;
}
template <class U, class... Args>
void emplace2(Args&& ...args) {
Variant<T...> x;
x.data_.emplace2(static_cast<U*>(nullptr), std::forward<Args>(args)...);
data_.swap(x.data_);
}
private:
Holder data_;
};
template<class... Types>
using Variant = mapbox::util::variant<Types...>;
////////////////////////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,48 @@
#ifndef __PDDL_PARSE__DETAIL__AST_CONTEXT_H
#define __PDDL_PARSE__DETAIL__AST_CONTEXT_H
#include <pddlparse/AST.h>
#include <pddlparse/detail/VariableStack.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ASTContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ASTContext
{
ASTContext(ast::Description &description)
: domain{description.domain.get()},
problem{description.problem.value() ? std::experimental::optional<ast::Problem *>(description.problem.value().get()) : std::experimental::nullopt}
{
}
ASTContext(ast::Domain &domain)
: domain{&domain}
{
}
ASTContext(ast::Problem &problem)
: domain{problem.domain},
problem{&problem}
{
}
ast::Domain *domain;
std::experimental::optional<ast::Problem *> problem;
VariableStack variables;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,161 @@
#ifndef __PDDL_PARSE__DETAIL__AST_COPY_H
#define __PDDL_PARSE__DETAIL__AST_COPY_H
#include <pddlparse/AST.h>
namespace pddl
{
namespace ast
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ASTCopy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Primitives
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Constant deepCopy(Constant &other);
inline PrimitiveType deepCopy(PrimitiveType &other);
inline Variable deepCopy(Variable &other);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions: Base Classes
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived, class ArgumentLeft, class ArgumentRight = ArgumentLeft>
inline Binary<Derived, ArgumentLeft, ArgumentRight> deepCopy(Binary<Derived, ArgumentLeft, ArgumentRight> &other);
template<class Derived, class Argument>
inline NAry<Derived, Argument> deepCopy(NAry<Derived, Argument> &other);
template<class Derived, class Argument>
inline Quantified<Derived, Argument> deepCopy(Quantified<Derived, Argument> &other);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Argument>
inline At<Argument> deepCopy(At<Argument> &other);
template<class Argument>
inline Not<Argument> deepCopy(Not<Argument> &other);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Variants
////////////////////////////////////////////////////////////////////////////////////////////////////
inline ast::Term deepCopy(ast::Term &other);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Primitives
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant deepCopy(Constant &other)
{
return Constant(other.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType deepCopy(PrimitiveType &other)
{
return PrimitiveType(other.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable deepCopy(Variable &other)
{
return Variable(other.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions: Base Classes
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived, class ArgumentLeft, class ArgumentRight>
Binary<Derived, ArgumentLeft, ArgumentRight> deepCopy(Binary<Derived, ArgumentLeft, ArgumentRight> &other)
{
auto argumentLeft = deepCopy(other.argumentLeft);
auto argumentRight = deepCopy(other.argumentRight);
return Binary<Derived, ArgumentLeft, ArgumentRight>(std::move(argumentLeft), std::move(argumentRight));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived, class Argument>
NAry<Derived, Argument> deepCopy(NAry<Derived, Argument> &other)
{
typename NAry<Derived, Argument>::Arguments arguments;
arguments.reserve(other.arguments.size());
for (auto &argument : other.arguments)
arguments.emplace_back(deepCopy(argument));
return NAry<Derived, Argument>(std::move(arguments));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived, class Argument>
Quantified<Derived, Argument> deepCopy(Quantified<Derived, Argument> &other)
{
auto argument = deepCopy(other.argument);
return Quantified<Derived, Argument>(std::move(argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Argument>
At<Argument> deepCopy(At<Argument> &other)
{
auto argument = deepCopy(other.argument);
return At<Argument>(other.timePoint, std::move(argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Argument>
Not<Argument> deepCopy(Not<Argument> &other)
{
auto argument = deepCopy(other.argument);
return Not<Argument>(std::move(argument));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Variants
////////////////////////////////////////////////////////////////////////////////////////////////////
struct DeepCopyVisitor
{
template<class Argument>
Argument visit(Argument &other)
{
return deepCopy(other);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Unique Pointers
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
std::unique_ptr<T> deepCopy(std::unique_ptr<T> &other)
{
return std::make_unique<T>(deepCopy(*other));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,33 @@
#ifndef __PDDL_PARSE__DETAIL__REQUIREMENTS_H
#define __PDDL_PARSE__DETAIL__REQUIREMENTS_H
#include <iostream>
#include <pddlparse/Context.h>
#include <pddlparse/detail/ASTContext.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirements
//
////////////////////////////////////////////////////////////////////////////////////////////////////
bool hasRequirement(const ast::Domain &domain, ast::Requirement requirement);
bool hasRequirement(const ast::Problem &problem, ast::Requirement requirement);
bool hasRequirement(const ASTContext &astContext, ast::Requirement requirement);
void checkRequirement(ast::Domain &domain, ast::Requirement requirement, Context &context);
void checkRequirement(ast::Problem &problem, ast::Requirement requirement, Context &context);
void checkRequirement(ASTContext &astContext, ast::Requirement requirement, Context &context);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,127 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__AST_H
#define __PDDL_PARSE__DETAIL__PARSING__AST_H
#include <pddlparse/AST.h>
#include <pddlparse/detail/parsing/Parser.h>
#include <pddlparse/detail/parsing/Utils.h>
namespace pddl
{
namespace detail
{
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ParseAST
//
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
// Primitives
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Parser<ast::Constant>
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Parser<ast::ConstantDeclaration>
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Parser<ast::PrimitiveType>
{
std::experimental::optional<ast::PrimitiveType> parse(Context &context, ASTContext &astContext)
{
auto &tokenizer = context.tokenizer;
auto &types = astContext.description.domain.types;
tokenizer.skipWhiteSpace();
auto typeName = tokenizer.getIdentifier();
if (typeName.empty())
throw tokenize::TokenizerException(tokenizer.location(), "no type supplied");
auto matchingType = std::find_if(types.begin(), types.end(),
[&](auto &primitiveTypeDeclaration)
{
return primitiveTypeDeclaration->name == typeName;
});
if (matchingType == types.end())
{
// Only “object” is allowed as an implicit type
if (typeName == "object" || typeName == "objects")
{
context.warningCallback(tokenizer.location(), "primitive type “" + typeName + "” should be declared");
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));
return ast::PrimitiveType(types.back());
}
else
throw tokenize::TokenizerException(tokenizer.location(), "type “" + typeName + "” used but never declared");
}
auto &type = *matchingType;
return ast::PrimitiveType(type);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Parser<ast::PrimitiveTypeDeclaration>
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Parser<ast::Unsupported>
{
std::experimental::optional<ast::Unsupported> parse(Context &context, ASTContext &)
{
auto &tokenizer = context.tokenizer;
ast::Unsupported unsupported;
tokenizer.expect<std::string>("(");
unsupported.type = tokenizer.getIdentifier();
context.warningCallback(tokenizer.location(), "expression type “" + unsupported.type + "” currently unsupported in this context");
skipSection(tokenizer);
return unsupported;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// Expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Argument>
struct Parser<ast::And<Argument>>
{
template<typename ArgumentParser>
std::experimental::optional<ast::And<Argument>> parse(Context &context, ASTContext &astContext, ArgumentParser parseArgument)
{
return Parser<ast::NAry<ast::And<Argument>, Argument>>::parse(context, astContext, parseArgument);
}
};
*/
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__ACTION_H
#define __PDDL_PARSE__DETAIL__PARSING__ACTION_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddAction(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,26 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__CONSTANT_H
#define __PDDL_PARSE__DETAIL__PARSING__CONSTANT_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::ConstantPointer parseConstant(Context &context, ast::Domain &domain);
ast::ConstantPointer parseConstant(Context &context, ast::Problem &problem);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,26 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__CONSTANT_DECLARATION_H
#define __PDDL_PARSE__DETAIL__PARSING__CONSTANT_DECLARATION_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ConstantDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddConstantDeclarations(Context &context, ast::Domain &domain);
void parseAndAddConstantDeclarations(Context &context, ast::Problem &problem);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,39 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__DESCRIPTION_H
#define __PDDL_PARSE__DETAIL__PARSING__DESCRIPTION_H
#include <experimental/optional>
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class DescriptionParser
{
public:
DescriptionParser(Context &context);
ast::Description parse();
private:
void findSections();
Context &m_context;
tokenize::Stream::Position m_domainPosition;
tokenize::Stream::Position m_problemPosition;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,50 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__DOMAIN_H
#define __PDDL_PARSE__DETAIL__PARSING__DOMAIN_H
#include <experimental/optional>
#include <pddlparse/AST.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class DomainParser
{
public:
DomainParser(Context &context);
ast::DomainPointer parse();
private:
void findSections(ast::Domain &domain);
void parseRequirementSection(ast::Domain &domain);
void computeDerivedRequirements(ast::Domain &domain);
void parseTypeSection(ast::Domain &domain);
void parseConstantSection(ast::Domain &domain);
void parsePredicateSection(ast::Domain &domain);
void parseActionSection(ast::Domain &domain);
Context &m_context;
tokenize::Stream::Position m_requirementsPosition;
tokenize::Stream::Position m_typesPosition;
tokenize::Stream::Position m_constantsPosition;
tokenize::Stream::Position m_predicatesPosition;
std::vector<tokenize::Stream::Position> m_actionPositions;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__INITIAL_STATE_H
#define __PDDL_PARSE__DETAIL__PARSING__INITIAL_STATE_H
#include <pddlparse/Context.h>
#include <pddlparse/detail/ASTContext.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::InitialState parseInitialState(Context &context, ASTContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,43 @@
#ifndef __PDDL_PARSE__DETAIL__PARSER_H
#define __PDDL_PARSE__DETAIL__PARSER_H
#include <experimental/optional>
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
#include <pddlparse/detail/ASTContext.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parser
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
struct Parser
{
};
template<class T, typename... ArgumentParser>
std::experimental::optional<T> parse(Context &context, ASTContext &astContext, ArgumentParser... argumentParsers)
{
return detail::Parser<T>().parse(context, astContext, argumentParsers...);
}
template<class T>
std::experimental::optional<T> parse(Context &context, ASTContext &astContext)
{
return detail::Parser<T>().parse(context, astContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__PREDICATE_DECLARATION_H
#define __PDDL_PARSE__DETAIL__PARSING__PREDICATE_DECLARATION_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddPredicateDeclarations(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__PRIMITIVE_TYPE_H
#define __PDDL_PARSE__DETAIL__PARSING__PRIMITIVE_TYPE_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::PrimitiveTypePointer parsePrimitiveType(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__PRIMITIVE_TYPE_DECLARATION_H
#define __PDDL_PARSE__DETAIL__PARSING__PRIMITIVE_TYPE_DECLARATION_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveTypeDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddPrimitiveTypeDeclarations(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,51 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__PROBLEM_H
#define __PDDL_PARSE__DETAIL__PARSING__PROBLEM_H
#include <experimental/optional>
#include <pddlparse/AST.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ProblemParser
{
public:
ProblemParser(Context &context, ast::Domain &domain);
ast::ProblemPointer parse();
private:
void findSections(ast::Problem &problem);
void parseDomainSection(ast::Problem &problem);
void parseRequirementSection(ast::Problem &problem);
void computeDerivedRequirements(ast::Problem &problem);
void parseObjectSection(ast::Problem &problem);
void parseInitialStateSection(ast::Problem &problem);
void parseGoalSection(ast::Problem &problem);
Context &m_context;
ast::Domain &m_domain;
tokenize::Stream::Position m_domainPosition;
tokenize::Stream::Position m_requirementsPosition;
tokenize::Stream::Position m_objectsPosition;
tokenize::Stream::Position m_initialStatePosition;
tokenize::Stream::Position m_goalPosition;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,26 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__REQUIREMENT_H
#define __PDDL_PARSE__DETAIL__PARSING__REQUIREMENT_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Requirement parseRequirement(Context &context);
const char *toString(const ast::Requirement &requirement);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__VARIABLE_H
#define __PDDL_PARSE__DETAIL__PARSING__VARIABLE_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Variable parseVariable(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef __PDDL_PARSE__DETAIL__PARSING__VARIABLE_DECLARATION_H
#define __PDDL_PARSE__DETAIL__PARSING__VARIABLE_DECLARATION_H
#include <pddlparse/ASTForward.h>
#include <pddlparse/Context.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VariableDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::VariableDeclarations parseVariableDeclarations(Context &context, ast::Domain &domain);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -12,6 +12,7 @@ file(GLOB detail_parsing_headers "../include/pddlparse/detail/parsing/*.h")
set(includes
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/../../lib/tokenize/include
${PROJECT_SOURCE_DIR}/../../lib/variant/include
)
set(sources

View File

@ -0,0 +1,22 @@
#include <pddlparse/Parse.h>
#include <pddlparse/AST.h>
#include <pddlparse/detail/parsing/Description.h>
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parse
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Description parseDescription(Context &context)
{
return detail::DescriptionParser(context).parse();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}

View File

@ -0,0 +1,92 @@
#include <pddlparse/detail/Requirements.h>
#include <algorithm>
#include <pddlparse/detail/parsing/Requirement.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirements
//
////////////////////////////////////////////////////////////////////////////////////////////////////
bool hasRequirement(const ast::Domain &domain, ast::Requirement requirement)
{
const auto match = std::find_if(domain.requirements.cbegin(), domain.requirements.cend(),
[&](const auto &declaredRequirement)
{
return declaredRequirement == requirement;
});
return match != domain.requirements.cend();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool hasRequirement(const ast::Problem &problem, ast::Requirement requirement)
{
const auto match = std::find_if(problem.requirements.cbegin(), problem.requirements.cend(),
[&](const auto &declaredRequirement)
{
return declaredRequirement == requirement;
});
if (match != problem.requirements.cend())
return true;
return hasRequirement(problem.domain, requirement);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool hasRequirement(const ASTContext &astContext, ast::Requirement requirement)
{
if (astContext.problem)
return hasRequirement(*astContext.problem.value(), requirement);
return hasRequirement(*astContext.domain, requirement);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void checkRequirement(ast::Domain &domain, ast::Requirement requirement, Context &context)
{
if (hasRequirement(domain, requirement))
return;
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
domain.requirements.push_back(requirement);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void checkRequirement(ast::Problem &problem, ast::Requirement requirement, Context &context)
{
if (hasRequirement(problem, requirement))
return;
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
problem.requirements.push_back(requirement);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void checkRequirement(ASTContext &astContext, ast::Requirement requirement, Context &context)
{
if (astContext.problem)
checkRequirement(*astContext.problem.value(), requirement, context);
else
checkRequirement(*astContext.domain, requirement, context);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,68 @@
#include <pddlparse/detail/parsing/Action.h>
#include <pddlparse/AST.h>
// TODO: remove
#include <pddlparse/detail/parsing/Utils.h>
#include <pddlparse/detail/parsing/VariableDeclaration.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddAction(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("action");
auto action = std::make_unique<ast::Action>();
action->name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(":parameters");
tokenizer.expect<std::string>("(");
// Read parameters
action->parameters = parseVariableDeclarations(context, domain);
tokenizer.expect<std::string>(")");
// TODO: reimplement
skipSection(tokenizer);
/*
// Parse preconditions and effects
while (!tokenizer.testAndReturn(')'))
{
tokenizer.expect<std::string>(":");
if (tokenizer.testIdentifierAndSkip("precondition"))
// TODO: reimplement
//action->precondition = parsePreconditionExpression(context, expressionContext);
skipSection(tokenizer);
else if (tokenizer.testIdentifierAndSkip("effect"))
// TODO: reimplement
//action->effect = parseEffectExpression(context, expressionContext);
skipSection(tokenizer);
tokenizer.skipWhiteSpace();
}*/
// Store new action
domain.actions.emplace_back(std::move(action));
//tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,69 @@
#include <pddlparse/detail/parsing/Constant.h>
#include <pddlparse/AST.h>
#include <pddlparse/ParserException.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
std::experimental::optional<ast::ConstantPointer> findConstant(const std::string &constantName, ast::ConstantDeclarations &constantDeclarations)
{
const auto matchingConstant = std::find_if(constantDeclarations.begin(), constantDeclarations.end(),
[&](const auto &constantDeclaration)
{
return constantDeclaration->name == constantName;
});
if (matchingConstant == constantDeclarations.end())
return std::experimental::nullopt;
return std::make_unique<ast::Constant>(matchingConstant->get());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::ConstantPointer parseConstant(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
const auto constantName = tokenizer.getIdentifier();
auto constant = findConstant(constantName, domain.constants);
if (constant)
return std::move(constant.value());
throw ParserException(tokenizer.location(), "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::ConstantPointer parseConstant(Context &context, ast::Problem &problem)
{
auto &tokenizer = context.tokenizer;
const auto constantName = tokenizer.getIdentifier();
auto constant = findConstant(constantName, problem.domain->constants);
if (constant)
return std::move(constant.value());
auto object = findConstant(constantName, problem.objects);
if (object)
return std::move(object.value());
throw ParserException(tokenizer.location(), "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,78 @@
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
#include <pddlparse/AST.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/ASTCopy.h>
#include <pddlparse/detail/parsing/PrimitiveType.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ConstantDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddUntypedConstantDeclaration(Context &context, ast::ConstantDeclarations &constantDeclarations)
{
auto &tokenizer = context.tokenizer;
auto constantName = tokenizer.getIdentifier();
assert(constantName != "-");
constantDeclarations.emplace_back(std::make_unique<ast::ConstantDeclaration>(std::move(constantName)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddConstantDeclarations(Context &context, ast::Domain &domain, ast::ConstantDeclarations &constantDeclarations)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
// Index on the first element of the current inheritance list
size_t inheritanceIndex = 0;
while (tokenizer.currentCharacter() != ')')
{
parseAndAddUntypedConstantDeclaration(context, constantDeclarations);
tokenizer.skipWhiteSpace();
if (!tokenizer.testAndSkip<char>('-'))
continue;
// If existing, parse and store parent type
auto parentType = parsePrimitiveType(context, domain);
for (size_t i = inheritanceIndex; i < constantDeclarations.size(); i++)
constantDeclarations[i]->type = ast::deepCopy(parentType);
// All types up to now are labeled with their parent types
inheritanceIndex = constantDeclarations.size() + 1;
tokenizer.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddConstantDeclarations(Context &context, ast::Domain &domain)
{
parseAndAddConstantDeclarations(context, domain, domain.constants);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddConstantDeclarations(Context &context, ast::Problem &problem)
{
parseAndAddConstantDeclarations(context, *problem.domain, problem.objects);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,107 @@
#include <pddlparse/detail/parsing/Description.h>
#include <pddlparse/AST.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/parsing/Domain.h>
#include <pddlparse/detail/parsing/Problem.h>
#include <pddlparse/detail/parsing/Utils.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
DescriptionParser::DescriptionParser(Context &context)
: m_context{context},
m_domainPosition{-1},
m_problemPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Description DescriptionParser::parse()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.removeComments(";", "\n", false);
findSections();
if (m_domainPosition == -1)
throw ParserException("no PDDL domain specified");
tokenizer.seek(m_domainPosition);
auto domain = DomainParser(m_context).parse();
// If no problem is given, return just the domain
if (m_problemPosition == -1)
return {std::move(domain), std::experimental::nullopt};
tokenizer.seek(m_problemPosition);
auto problem = ProblemParser(m_context, *domain).parse();
// TODO: check consistency
// * check typing requirement
// * check that typing is used consistently
// * check that constants, variables, and predicates aren't declared twice
// * check section order
// * check that preconditions and effects are well-formed
return {std::move(domain), std::move(problem)};
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DescriptionParser::findSections()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.skipWhiteSpace();
while (!tokenizer.atEnd())
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
if (tokenizer.testAndSkip<std::string>("domain"))
{
if (m_domainPosition != -1)
throw ParserException(tokenizer.location(), "PDDL description may not contain two domains");
m_domainPosition = position;
skipSection(tokenizer);
skipSection(tokenizer);
}
else if (m_context.tokenizer.testAndSkip<std::string>("problem"))
{
if (m_problemPosition != -1)
throw ParserException("PDDL description may not contain two problems currently");
m_problemPosition = position;
skipSection(tokenizer);
skipSection(tokenizer);
}
else
{
const auto sectionIdentifier = tokenizer.get<std::string>();
throw ParserException(tokenizer.location(), "unknown PDDL section “" + sectionIdentifier + "");
}
tokenizer.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,300 @@
#include <pddlparse/detail/parsing/Domain.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/Requirements.h>
#include <pddlparse/detail/parsing/Action.h>
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
#include <pddlparse/detail/parsing/PredicateDeclaration.h>
#include <pddlparse/detail/parsing/PrimitiveTypeDeclaration.h>
#include <pddlparse/detail/parsing/Requirement.h>
#include <pddlparse/detail/parsing/Utils.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
DomainParser::DomainParser(Context &context)
: m_context{context},
m_requirementsPosition{-1},
m_typesPosition{-1},
m_constantsPosition{-1},
m_predicatesPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::DomainPointer DomainParser::parse()
{
auto domain = std::make_unique<ast::Domain>();
findSections(*domain);
auto &tokenizer = m_context.tokenizer;
if (m_requirementsPosition != -1)
{
tokenizer.seek(m_requirementsPosition);
parseRequirementSection(*domain);
}
if (m_typesPosition != -1)
{
tokenizer.seek(m_typesPosition);
parseTypeSection(*domain);
}
if (m_constantsPosition != -1)
{
tokenizer.seek(m_constantsPosition);
parseConstantSection(*domain);
}
if (m_predicatesPosition != -1)
{
tokenizer.seek(m_predicatesPosition);
parsePredicateSection(*domain);
}
for (size_t i = 0; i < m_actionPositions.size(); i++)
if (m_actionPositions[i] != -1)
{
tokenizer.seek(m_actionPositions[i]);
parseActionSection(*domain);
}
computeDerivedRequirements(*domain);
return domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::findSections(ast::Domain &domain)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("domain");
domain.name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != -1)
{
tokenizer.seek(value);
throw tokenize::TokenizerException(tokenizer.location(), "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
tokenizer.skipWhiteSpace();
// Find sections
while (tokenizer.currentCharacter() != ')')
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
const auto sectionIdentifierPosition = tokenizer.position();
// Save the parser position of the individual sections for later parsing
if (tokenizer.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("types"))
setSectionPosition("types", m_typesPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("constants"))
setSectionPosition("constants", m_constantsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("predicates"))
setSectionPosition("predicates", m_predicatesPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("action"))
{
m_actionPositions.emplace_back(-1);
setSectionPosition("action", m_actionPositions.back(), position);
}
else if (tokenizer.testIdentifierAndSkip("functions")
|| tokenizer.testIdentifierAndSkip("constraints")
|| tokenizer.testIdentifierAndSkip("durative-action")
|| tokenizer.testIdentifierAndSkip("derived"))
{
tokenizer.seek(sectionIdentifierPosition);
const auto sectionIdentifier = tokenizer.getIdentifier();
m_context.warningCallback(tokenizer.location(), "section type “" + sectionIdentifier + "” currently unsupported");
tokenizer.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer.location(), "unknown domain section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(tokenizer);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::parseRequirementSection(ast::Domain &domain)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("requirements");
while (tokenizer.currentCharacter() != ')')
{
tokenizer.expect<std::string>(":");
domain.requirements.emplace_back(parseRequirement(m_context));
tokenizer.skipWhiteSpace();
}
// TODO: do this check only once the problem is parsed
// If no requirements are specified, assume STRIPS
if (domain.requirements.empty())
domain.requirements.emplace_back(ast::Requirement::STRIPS);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::computeDerivedRequirements(ast::Domain &domain)
{
const auto addRequirementUnique =
[&](auto requirement)
{
if (hasRequirement(domain, requirement))
return;
domain.requirements.push_back(requirement);
};
if (hasRequirement(domain, ast::Requirement::ADL))
{
addRequirementUnique(ast::Requirement::STRIPS);
addRequirementUnique(ast::Requirement::Typing);
addRequirementUnique(ast::Requirement::NegativePreconditions);
addRequirementUnique(ast::Requirement::DisjunctivePreconditions);
addRequirementUnique(ast::Requirement::Equality);
addRequirementUnique(ast::Requirement::QuantifiedPreconditions);
addRequirementUnique(ast::Requirement::ConditionalEffects);
}
if (hasRequirement(domain, ast::Requirement::QuantifiedPreconditions))
{
addRequirementUnique(ast::Requirement::ExistentialPreconditions);
addRequirementUnique(ast::Requirement::UniversalPreconditions);
}
if (hasRequirement(domain, ast::Requirement::Fluents))
{
addRequirementUnique(ast::Requirement::NumericFluents);
addRequirementUnique(ast::Requirement::ObjectFluents);
}
if (hasRequirement(domain, ast::Requirement::TimedInitialLiterals))
addRequirementUnique(ast::Requirement::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::parseTypeSection(ast::Domain &domain)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("types");
checkRequirement(domain, ast::Requirement::Typing, m_context);
tokenizer.skipWhiteSpace();
// Store types and their parent types
while (tokenizer.currentCharacter() != ')')
{
if (tokenizer.currentCharacter() == '(')
throw ParserException(tokenizer.location(), "only primitive types are allowed in type section");
parseAndAddPrimitiveTypeDeclarations(m_context, domain);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::parseConstantSection(ast::Domain &domain)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("constants");
// Store constants
parseAndAddConstantDeclarations(m_context, domain);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::parsePredicateSection(ast::Domain &domain)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("predicates");
tokenizer.skipWhiteSpace();
// Store predicates
parseAndAddPredicateDeclarations(m_context, domain);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DomainParser::parseActionSection(ast::Domain &domain)
{
parseAndAddAction(m_context, domain);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,79 @@
#include <pddlparse/detail/parsing/InitialState.h>
#include <pddlparse/AST.h>
// TODO: remove
#include <pddlparse/detail/parsing/Utils.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::InitialState parseInitialState(Context &context, ASTContext &)
{
auto &tokenizer = context.tokenizer;
ast::InitialState initialState;
// TODO: reimplement
/*const auto parseInitialStateElement =
[&]() -> ExpressionPointer
{
ExpressionPointer expression;
// TODO: do not allow negative initial state literals
if ((expression = parseLiteral(context, expressionContext))
|| (expression = expressions::At::parse(context, expressionContext, parseLiteral)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("="))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
};
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
ast::Expression expression;
if ((expression = parseInitialStateElement()))
initialState->m_facts.emplace_back(std::move(expression));
tokenizer.skipWhiteSpace();
}*/
skipSection(tokenizer);
return initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,53 @@
#include <pddlparse/detail/parsing/PredicateDeclaration.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/ASTContext.h>
#include <pddlparse/detail/parsing/VariableDeclaration.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddPredicateDeclaration(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.expect<std::string>("(");
auto name = tokenizer.getIdentifier();
tokenizer.skipWhiteSpace();
// Parse parameters
auto parameters = parseVariableDeclarations(context, domain);
tokenizer.expect<std::string>(")");
domain.predicates.emplace_back(std::make_unique<ast::PredicateDeclaration>(std::move(name), std::move(parameters)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddPredicateDeclarations(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
parseAndAddPredicateDeclaration(context, domain);
tokenizer.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,55 @@
#include <pddlparse/detail/parsing/PrimitiveType.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/Requirements.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::PrimitiveTypePointer parsePrimitiveType(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
auto &types = domain.types;
tokenizer.skipWhiteSpace();
auto typeName = tokenizer.getIdentifier();
if (typeName.empty())
throw tokenize::TokenizerException(tokenizer.location(), "no type supplied");
auto matchingType = std::find_if(types.begin(), types.end(),
[&](auto &primitiveTypeDeclaration)
{
return primitiveTypeDeclaration->name == typeName;
});
if (matchingType == types.end())
{
// Only “object” is allowed as an implicit type
if (typeName == "object" || typeName == "objects")
{
context.warningCallback(tokenizer.location(), "primitive type “" + typeName + "” should be declared");
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));
return std::make_unique<ast::PrimitiveType>(types.back().get());
}
else
throw tokenize::TokenizerException(tokenizer.location(), "type “" + typeName + "” used but never declared");
}
return std::make_unique<ast::PrimitiveType>(matchingType->get());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,77 @@
#include <pddlparse/detail/parsing/PrimitiveTypeDeclaration.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/ASTCopy.h>
#include <pddlparse/detail/parsing/PrimitiveType.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveTypeDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::PrimitiveTypeDeclarationPointer &parseAndAddUntypedPrimitiveTypeDeclaration(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
auto typeName = tokenizer.getIdentifier();
auto &types = domain.types;
const auto matchingPrimitiveType = std::find_if(types.begin(), types.end(),
[&](const auto &primitiveType)
{
return primitiveType->name == typeName;
});
// Return existing primitive type
if (matchingPrimitiveType != types.cend())
return *matchingPrimitiveType;
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));
return types.back();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddPrimitiveTypeDeclarations(Context &context, ast::Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
// Index on the first element of the current inheritance list
size_t inheritanceIndex = 0;
while (tokenizer.currentCharacter() != ')')
{
parseAndAddUntypedPrimitiveTypeDeclaration(context, domain);
tokenizer.skipWhiteSpace();
if (!tokenizer.testAndSkip<char>('-'))
continue;
// If existing, parse and store parent type
auto parentType = parsePrimitiveType(context, domain);
auto &types = domain.types;
for (size_t i = inheritanceIndex; i < types.size(); i++)
types[i]->parentTypes.emplace_back(ast::deepCopy(parentType));
// All types up to now are labeled with their parent types
inheritanceIndex = types.size() + 1;
tokenizer.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,297 @@
#include <pddlparse/detail/parsing/Problem.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/Requirements.h>
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
#include <pddlparse/detail/parsing/InitialState.h>
#include <pddlparse/detail/parsing/Requirement.h>
#include <pddlparse/detail/parsing/Utils.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ProblemParser::ProblemParser(Context &context, ast::Domain &domain)
: m_context{context},
m_domain{domain},
m_domainPosition{-1},
m_requirementsPosition{-1},
m_objectsPosition{-1},
m_initialStatePosition{-1},
m_goalPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::ProblemPointer ProblemParser::parse()
{
auto problem = std::make_unique<ast::Problem>(&m_domain);
findSections(*problem);
auto &tokenizer = m_context.tokenizer;
if (m_domainPosition == -1)
throw ParserException(tokenizer.location(), "problem description does not specify a corresponding domain");
tokenizer.seek(m_domainPosition);
parseDomainSection(*problem);
if (m_requirementsPosition != -1)
{
tokenizer.seek(m_requirementsPosition);
parseRequirementSection(*problem);
}
if (m_objectsPosition != -1)
{
tokenizer.seek(m_objectsPosition);
parseObjectSection(*problem);
}
if (m_initialStatePosition == -1)
throw ParserException(tokenizer.location(), "problem description does not specify an initial state");
tokenizer.seek(m_initialStatePosition);
parseInitialStateSection(*problem);
if (m_goalPosition == -1)
throw ParserException(tokenizer.location(), "problem description does not specify a goal");
tokenizer.seek(m_goalPosition);
parseGoalSection(*problem);
return problem;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::findSections(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("problem");
problem.name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != -1)
{
tokenizer.seek(value);
throw tokenize::TokenizerException(tokenizer.location(), "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
const auto sectionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("domain"))
setSectionPosition("domain", m_domainPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("objects"))
setSectionPosition("objects", m_objectsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("init"))
setSectionPosition("init", m_initialStatePosition, position, true);
else if (tokenizer.testIdentifierAndSkip("goal"))
setSectionPosition("goal", m_goalPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("constraints")
|| tokenizer.testIdentifierAndSkip("metric")
|| tokenizer.testIdentifierAndSkip("length"))
{
tokenizer.seek(sectionIdentifierPosition);
const auto sectionIdentifier = tokenizer.getIdentifier();
m_context.warningCallback(tokenizer.location(), "section type “" + sectionIdentifier + "” currently unsupported");
tokenizer.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer.location(), "unknown problem section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(tokenizer);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::parseDomainSection(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("domain");
tokenizer.skipWhiteSpace();
const auto domainName = tokenizer.getIdentifier();
if (problem.domain->name != domainName)
throw tokenize::TokenizerException(tokenizer.location(), "domains do not match (“" + problem.domain->name + "” and “" + domainName + "”)");
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::parseRequirementSection(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("requirements");
while (tokenizer.currentCharacter() != ')')
{
tokenizer.expect<std::string>(":");
problem.requirements.emplace_back(parseRequirement(m_context));
tokenizer.skipWhiteSpace();
}
// TODO: do this check only once the problem is parsed
// If no requirements are specified, assume STRIPS
if (problem.requirements.empty())
problem.requirements.emplace_back(ast::Requirement::STRIPS);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: refactor, exists identically in DomainParser
void ProblemParser::computeDerivedRequirements(ast::Problem &problem)
{
const auto addRequirementUnique =
[&](const auto requirement)
{
if (hasRequirement(problem, requirement))
return;
problem.requirements.push_back(ast::Requirement(requirement));
};
if (hasRequirement(problem, ast::Requirement::ADL))
{
addRequirementUnique(ast::Requirement::STRIPS);
addRequirementUnique(ast::Requirement::Typing);
addRequirementUnique(ast::Requirement::NegativePreconditions);
addRequirementUnique(ast::Requirement::DisjunctivePreconditions);
addRequirementUnique(ast::Requirement::Equality);
addRequirementUnique(ast::Requirement::QuantifiedPreconditions);
addRequirementUnique(ast::Requirement::ConditionalEffects);
}
if (hasRequirement(problem, ast::Requirement::QuantifiedPreconditions))
{
addRequirementUnique(ast::Requirement::ExistentialPreconditions);
addRequirementUnique(ast::Requirement::UniversalPreconditions);
}
if (hasRequirement(problem, ast::Requirement::Fluents))
{
addRequirementUnique(ast::Requirement::NumericFluents);
addRequirementUnique(ast::Requirement::ObjectFluents);
}
if (hasRequirement(problem, ast::Requirement::TimedInitialLiterals))
addRequirementUnique(ast::Requirement::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::parseObjectSection(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("objects");
// Store constants
parseAndAddConstantDeclarations(m_context, problem);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::parseInitialStateSection(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("init");
ASTContext astContext(problem);
// TODO: reimplement
//problem.initialState = parseInitialState(m_context, astContext);
//tokenizer.expect<std::string>(")");
skipSection(tokenizer);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ProblemParser::parseGoalSection(ast::Problem &problem)
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("goal");
ASTContext expressionContext(problem);
// TODO: reimplement
//problem.goal = parsePreconditionExpression(m_context, expressionContext);
//tokenizer.expect<std::string>(")");
skipSection(tokenizer);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,102 @@
#include <pddlparse/detail/parsing/Requirement.h>
#include <cstring>
#include <map>
#include <pddlparse/AST.h>
#include <pddlparse/ParserException.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct CompareStrings
{
bool operator()(const char *lhs, const char *rhs) const
{
return std::strcmp(lhs, rhs) < 0;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
using RequirementNameMap = std::map<const char *, ast::Requirement, CompareStrings>;
static const RequirementNameMap requirementNameMap =
{
{"strips", ast::Requirement::STRIPS},
{"typing", ast::Requirement::Typing},
{"negative-preconditions", ast::Requirement::NegativePreconditions},
{"disjunctive-preconditions", ast::Requirement::DisjunctivePreconditions},
{"equality", ast::Requirement::Equality},
{"existential-preconditions", ast::Requirement::ExistentialPreconditions},
{"universal-preconditions", ast::Requirement::UniversalPreconditions},
{"quantified-preconditions", ast::Requirement::QuantifiedPreconditions},
{"conditional-effects", ast::Requirement::ConditionalEffects},
{"fluents", ast::Requirement::Fluents},
{"numeric-fluents", ast::Requirement::NumericFluents},
{"object-fluents", ast::Requirement::ObjectFluents},
{"adl", ast::Requirement::ADL},
{"durative-actions", ast::Requirement::DurativeActions},
{"duration-inequalities", ast::Requirement::DurationInequalities},
{"continuous-effects", ast::Requirement::ContinuousEffects},
{"derived-predicates", ast::Requirement::DerivedPredicates},
{"timed-initial-literals", ast::Requirement::TimedInitialLiterals},
{"preferences", ast::Requirement::Preferences},
{"constraints", ast::Requirement::Constraints},
{"action-costs", ast::Requirement::ActionCosts},
{"goal-utilities", ast::Requirement::GoalUtilities},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Requirement parseRequirement(Tokenizer &tokenizer)
{
const auto requirementName = tokenizer.getIdentifier();
const auto matchingRequirement = requirementNameMap.find(requirementName.c_str());
if (matchingRequirement == requirementNameMap.cend())
throw ParserException(tokenizer.location(), "unknown PDDL requirement “" + requirementName + "");
return matchingRequirement->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::Requirement parseRequirement(Context &context)
{
auto &tokenizer = context.tokenizer;
auto requirement = parseRequirement(tokenizer);
if (requirement == ast::Requirement::GoalUtilities)
context.warningCallback(tokenizer.location(), "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
return requirement;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const char *toString(const ast::Requirement &requirement)
{
const auto matchingRequirement = std::find_if(requirementNameMap.cbegin(), requirementNameMap.cend(),
[&](const auto &requirementNamePair)
{
return requirementNamePair.second == requirement;
});
assert(matchingRequirement != requirementNameMap.cend());
return matchingRequirement->first;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -0,0 +1,69 @@
#include <pddlparse/detail/parsing/VariableDeclaration.h>
#include <pddlparse/AST.h>
#include <pddlparse/ParserException.h>
#include <pddlparse/detail/ASTCopy.h>
#include <pddlparse/detail/parsing/PrimitiveType.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VariableDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void parseAndAddUntypedVariableDeclaration(Context &context, ast::VariableDeclarations &variableDeclarations)
{
auto &tokenizer = context.tokenizer;
tokenizer.expect<std::string>("?");
auto variableName = tokenizer.getIdentifier();
assert(variableName != "-");
variableDeclarations.emplace_back(std::make_unique<ast::VariableDeclaration>(std::move(variableName)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ast::VariableDeclarations parseVariableDeclarations(Context &context, ast::Domain &domain)
{
ast::VariableDeclarations variableDeclarations;
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
// Index on the first element of the current inheritance list
size_t inheritanceIndex = 0;
while (tokenizer.currentCharacter() != ')')
{
parseAndAddUntypedVariableDeclaration(context, variableDeclarations);
tokenizer.skipWhiteSpace();
if (!tokenizer.testAndSkip<char>('-'))
continue;
// If existing, parse and store parent type
auto parentType = parsePrimitiveType(context, domain);
for (size_t i = inheritanceIndex; i < variableDeclarations.size(); i++)
variableDeclarations[i]->type = ast::deepCopy(parentType);
// All types up to now are labeled with their parent types
inheritanceIndex = variableDeclarations.size() + 1;
tokenizer.skipWhiteSpace();
}
return variableDeclarations;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -5,6 +5,8 @@ file(GLOB core_sources "*.cpp")
set(includes
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/../../lib/catch/single_include
${PROJECT_SOURCE_DIR}/../../lib/tokenize/include
${PROJECT_SOURCE_DIR}/../../lib/variant/include
)
set(libraries
@ -18,4 +20,4 @@ target_link_libraries(${target} ${libraries})
add_custom_target(run-pddlparse-tests
COMMAND ${CMAKE_BINARY_DIR}/bin/pddlparse-tests
DEPENDS ${target}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/../../tests)

View File

@ -0,0 +1,90 @@
/*#include <catch.hpp>
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[parser] The Blocksworld domain is parsed correctly", "[parser]")
{
const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};
pddl::Tokenizer tokenizer;
tokenizer.read("data/blocksworld-domain.pddl");
pddl::Context context(std::move(tokenizer), ignoreWarnings);
const auto description = pddl::parseDescription(context);
REQUIRE_NOTHROW(description.domain());
const auto &domain = description.domain();
// Name
CHECK(domain.name() == "blocks");
// Requirements
REQUIRE(domain.requirements().size() == 2u);
CHECK(domain.requirements()[0].type() == Requirement::Type::STRIPS);
CHECK(domain.requirements()[1].type() == Requirement::Type::Typing);
// Types
REQUIRE(domain.types().size() == 1u);
const auto &block = *domain.types()[0];
CHECK(block.name() == "block");
REQUIRE(block.parentTypes().size() == 0u);
// Predicates
REQUIRE(domain.predicates().size() == 5u);
const auto &on = *domain.predicates()[0];
CHECK(on.name() == "on");
REQUIRE(on.parameters().size() == 2u);
CHECK(on.parameters()[0]->name() == "x");
const auto &onArgument0Type = on.parameters()[0]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument0Type == &block);
CHECK(on.parameters()[1]->name() == "y");
const auto &onArgument1Type = on.parameters()[1]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument1Type == &block);
const auto &handempty = *domain.predicates()[3];
CHECK(handempty.name() == "handempty");
CHECK(handempty.parameters().empty());
// Actions
REQUIRE(domain.actions().size() == 4u);
const auto &pickUp = *domain.actions()[0];
CHECK(pickUp.name() == "pick-up");
REQUIRE(pickUp.parameters().size() == 1u);
CHECK(pickUp.parameters()[0]->name() == "x");
CHECK(pickUp.parameters()[0]->type() == &block);
const auto &pickUpPre = pickUp.precondition()->as<expressions::And>();
REQUIRE(pickUpPre.arguments().size() == 3u);
const auto &pickUpPre0 = pickUpPre.arguments()[0]->as<expressions::Predicate>();
CHECK(pickUpPre0.name() == "clear");
REQUIRE(pickUpPre0.arguments().size() == 1u);
const auto &pickUpPre00 = pickUpPre0.arguments()[0]->as<expressions::Variable>();
CHECK(pickUpPre00.name() == "x");
CHECK(pickUpPre00.type() == &block);
CHECK(&pickUpPre00 == pickUp.parameters()[0].get());
const auto &pickUpPre2 = pickUpPre.arguments()[2]->as<expressions::Predicate>();
CHECK(pickUpPre2.name() == "handempty");
CHECK(pickUpPre2.arguments().empty());
const auto &pickUpEff = pickUp.effect()->as<expressions::And>();
REQUIRE(pickUpEff.arguments().size() == 4u);
const auto &pickUpEff0 = pickUpEff.arguments()[0]->as<expressions::Not>();
const auto &pickUpEff00 = pickUpEff0.argument()->as<expressions::Predicate>();
CHECK(pickUpEff00.name() == "ontable");
REQUIRE(pickUpEff00.arguments().size() == 1u);
const auto &pickUpEff000 = pickUpEff00.arguments()[0]->as<expressions::Variable>();
CHECK(pickUpEff000.name() == "x");
CHECK(pickUpEff000.type() == &block);
}
*/

View File

@ -1,2 +1,22 @@
#define CATCH_CONFIG_MAIN
/*#define CATCH_CONFIG_MAIN
#include <catch.hpp>
*/
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};
pddl::Tokenizer tokenizer;
tokenizer.read("data/blocksworld-domain.pddl");
tokenizer.read("data/blocksworld-problem.pddl");
pddl::Context context(std::move(tokenizer), ignoreWarnings);
const auto description = pddl::parseDescription(context);
std::cout << description.domain->requirements.size() << std::endl;
}

1
lib/variant Submodule

@ -0,0 +1 @@
Subproject commit d2588a8f1d6b5d480d228e6d8a906ce634bdea9a