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/AST.h>
|
||||
#include <pddlparse/Exception.h>
|
||||
#include <pddlparse/detail/SignatureMatching.h>
|
||||
#include <pddlparse/detail/parsing/Constant.h>
|
||||
#include <pddlparse/detail/parsing/Variable.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)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
const auto previousPosition = tokenizer.position();
|
||||
|
||||
@ -28,26 +31,9 @@ std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &conte
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
const auto predicateName = tokenizer.getIdentifier();
|
||||
|
||||
const auto name = tokenizer.getIdentifier();
|
||||
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();
|
||||
|
||||
// Parse arguments
|
||||
@ -80,14 +66,26 @@ std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &conte
|
||||
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>(")");
|
||||
|
||||
// TODO: add matching predicate declaration
|
||||
return std::make_unique<ast::Predicate>(std::move(arguments), nullptr);
|
||||
return std::make_unique<ast::Predicate>(std::move(arguments), declaration);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user