Implemented predicate signature checks.

This commit is contained in:
Patrick Lühne 2017-06-18 04:19:42 +02:00
parent e364d01cf4
commit 6ce4eecb18
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
3 changed files with 194 additions and 22 deletions

View File

@ -0,0 +1,34 @@
#ifndef __PDDL_PARSE__DETAIL__SIGNATURE_MATCHING_H
#define __PDDL_PARSE__DETAIL__SIGNATURE_MATCHING_H
#include <string>
#include <pddlparse/AST.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SignatureMatching
//
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::PrimitiveTypeDeclaration &lhs, const ast::PrimitiveTypeDeclaration &rhs);
bool matches(const ast::Either<ast::PrimitiveTypePointer> &lhs, const ast::PrimitiveTypeDeclaration &rhs);
bool matches(const ast::PrimitiveTypeDeclaration &lhs, const ast::Either<ast::PrimitiveTypePointer> &rhs);
bool matches(const ast::Either<ast::PrimitiveTypePointer> &lhs, const ast::Either<ast::PrimitiveTypePointer> &rhs);
bool matches(const ast::VariableDeclaration &lhs, const std::experimental::optional<ast::Type> &rhs);
bool matches(const ast::ConstantDeclaration &lhs, const std::experimental::optional<ast::Type> &rhs);
bool matches(const ast::Term &lhs, const std::experimental::optional<ast::Type> &rhs);
bool matches(const std::string &predicateName, const ast::Predicate::Arguments &predicateArguments, const ast::PredicateDeclaration &predicateDeclaration);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,140 @@
#include <pddlparse/detail/SignatureMatching.h>
namespace pddl
{
namespace detail
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SignatureMatching
//
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::PrimitiveTypeDeclaration &lhs, const ast::PrimitiveTypeDeclaration &rhs)
{
// TODO: check if this assumption is correct
// With typing enabled, all objects inherit from “object”
if (rhs.name == "object")
return true;
// Two types match if rhs is lhs or one of its ancestors
if (&lhs == &rhs)
return true;
for (const auto &lhsParentType : lhs.parentTypes)
if (matches(*lhsParentType->declaration, rhs))
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::PrimitiveTypeDeclaration &lhs, const ast::Either<ast::PrimitiveTypePointer> &rhs)
{
for (const auto &rhsType : rhs.arguments)
if (matches(lhs, *rhsType->declaration))
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::Either<ast::PrimitiveTypePointer> &lhs, const ast::PrimitiveTypeDeclaration &rhs)
{
if (lhs.arguments.size() != 1)
return false;
// Strictly speaking, a 1-ary either is identical to its argument
return matches(*lhs.arguments[0]->declaration, rhs);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::Either<ast::PrimitiveTypePointer> &lhs, const ast::Either<ast::PrimitiveTypePointer> &rhs)
{
// All of the types in lhs must have a match in rhs
for (const auto &lhsType : lhs.arguments)
if (!matches(*lhsType->declaration, rhs))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool matches(const T &lhs, const ast::Type &rhs)
{
return rhs.match(
[&](const ast::PrimitiveTypePointer &x){return matches(lhs, *x->declaration);},
[&](const ast::EitherPointer<ast::PrimitiveTypePointer> &x){return matches(lhs, *x);});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::Type &lhs, const ast::Type &rhs)
{
return lhs.match(
[&](const ast::PrimitiveTypePointer &x){return matches(*x->declaration, rhs);},
[&](const ast::EitherPointer<ast::PrimitiveTypePointer> &x){return matches(*x, rhs);});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::VariableDeclaration &lhs, const std::experimental::optional<ast::Type> &rhs)
{
if (!lhs.type && !rhs)
return true;
// If typing is enabled, all objects have to be typed
assert(lhs.type);
assert(rhs);
return matches(lhs.type.value(), rhs.value());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::ConstantDeclaration &lhs, const std::experimental::optional<ast::Type> &rhs)
{
if (!lhs.type && !rhs)
return true;
// If typing is enabled, all objects have to be typed
assert(lhs.type);
assert(rhs);
return matches(lhs.type.value(), rhs.value());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const ast::Term &lhs, const std::experimental::optional<ast::Type> &rhs)
{
return lhs.match([&](const auto &x){return matches(*x->declaration, rhs);});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool matches(const std::string &predicateName, const ast::Predicate::Arguments &predicateArguments, const ast::PredicateDeclaration &predicateDeclaration)
{
if (predicateName != predicateDeclaration.name)
return false;
if (predicateArguments.size() != predicateDeclaration.parameters.size())
return false;
for (size_t i = 0; i < predicateArguments.size(); i++)
if (!matches(predicateArguments[i], predicateDeclaration.parameters[i]->type))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,6 +1,8 @@
#include <pddlparse/detail/parsing/Predicate.h> #include <pddlparse/detail/parsing/Predicate.h>
#include <pddlparse/AST.h> #include <pddlparse/AST.h>
#include <pddlparse/Exception.h>
#include <pddlparse/detail/SignatureMatching.h>
#include <pddlparse/detail/parsing/Constant.h> #include <pddlparse/detail/parsing/Constant.h>
#include <pddlparse/detail/parsing/Variable.h> #include <pddlparse/detail/parsing/Variable.h>
#include <pddlparse/detail/parsing/VariableDeclaration.h> #include <pddlparse/detail/parsing/VariableDeclaration.h>
@ -19,6 +21,7 @@ namespace detail
std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &context, ASTContext &astContext, VariableStack &variableStack) std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &context, ASTContext &astContext, VariableStack &variableStack)
{ {
auto &tokenizer = context.tokenizer; auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
const auto previousPosition = tokenizer.position(); const auto previousPosition = tokenizer.position();
@ -28,26 +31,9 @@ std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &conte
return std::experimental::nullopt; return std::experimental::nullopt;
} }
const auto predicateName = tokenizer.getIdentifier(); const auto name = tokenizer.getIdentifier();
ast::Predicate::Arguments arguments; ast::Predicate::Arguments arguments;
/*const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
tokenizer.seek(position);
return std::experimental::nullopt;
}
auto predicate = PredicatePointer(new Predicate);
predicate->m_name = predicateName;*/
tokenizer.skipWhiteSpace(); tokenizer.skipWhiteSpace();
// Parse arguments // Parse arguments
@ -80,14 +66,26 @@ std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &conte
return std::experimental::nullopt; return std::experimental::nullopt;
} }
//const auto &predicates = astContext.domain->predicates; const auto &predicates = astContext.domain->predicates;
// TODO: check that signature matches one of the declared ones const auto matchingPredicateDeclaration = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicateDeclaration)
{
return matches(name, arguments, *predicateDeclaration);
});
if (matchingPredicateDeclaration == predicates.cend())
{
// TODO: enumerate candidates and why they are incompatible
tokenizer.seek(previousPosition);
throw ParserException(tokenizer.location(), "no matching declaration found for predicate “" + name + "");
}
auto *declaration = matchingPredicateDeclaration->get();
tokenizer.expect<std::string>(")"); tokenizer.expect<std::string>(")");
// TODO: add matching predicate declaration return std::make_unique<ast::Predicate>(std::move(arguments), declaration);
return std::make_unique<ast::Predicate>(std::move(arguments), nullptr);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////