Implemented predicate signature checks.
This commit is contained in:
parent
e364d01cf4
commit
6ce4eecb18
34
lib/pddlparse/include/pddlparse/detail/SignatureMatching.h
Normal file
34
lib/pddlparse/include/pddlparse/detail/SignatureMatching.h
Normal 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
|
140
lib/pddlparse/src/pddlparse/detail/SignatureMatching.cpp
Normal file
140
lib/pddlparse/src/pddlparse/detail/SignatureMatching.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Reference in New Issue
Block a user