Implemented variable type requirement checking.

This commit is contained in:
Patrick Lühne 2016-06-08 01:05:36 +02:00
parent 75fbb5fb48
commit 7bd2782fc8
9 changed files with 30 additions and 92 deletions

View File

@ -36,16 +36,11 @@ class PrimitiveType: public Expression
const std::string &name() const;
const std::vector<const PrimitiveType *> &parentTypes() const;
bool isDeclared() const;
private:
void setDirty(bool isDirty = true);
bool isDirty() const;
void setDeclared();
bool m_isDirty;
bool m_isDeclared;
std::string m_name;

View File

@ -20,8 +20,10 @@ class Variable: public Expression
{
public:
static void parseTypedDeclaration(Context &context, ExpressionContext &expressionContext);
static void parseTypedDeclarations(Context &context, ExpressionContext &expressionContext);
static const Variable *parseAndFind(Context &context, const ExpressionContext &expressionContext);
static const Variable *parseAndFind(Context &context,
const ExpressionContext &expressionContext);
public:
void accept(ExpressionVisitor &expressionVisitor) const override;

View File

@ -40,12 +40,7 @@ void Action::parseDeclaration(Context &context, Domain &domain)
ExpressionContext expressionContext(domain, action->m_parameters);
// Read parameters
while (context.parser.currentCharacter() != ')')
{
expressions::Variable::parseTypedDeclaration(context, expressionContext);
context.parser.skipWhiteSpace();
}
expressions::Variable::parseTypedDeclarations(context, expressionContext);
context.parser.expect<std::string>(")");

View File

@ -111,8 +111,6 @@ void Description::findSections()
if (m_context.parser.probe<std::string>("domain"))
{
std::cout << "Found domain at " << position << std::endl;
if (m_domainPosition != -1)
throw utils::ParserException(m_context.parser, "PDDL description may not contain two domains");

View File

@ -315,52 +315,6 @@ void Domain::parseActionSection()
void Domain::checkConsistency()
{
// TODO: implement requirement declaration checking
// Verify that typing requirement is correctly declared if used
if (!m_primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing))
{
m_context.logger.parserWarning(m_context.parser, "Domain contains typing information but does not declare typing requirement");
m_requirements.push_back(Requirement(Requirement::Type::Typing));
}
// Verify that all variables and constants have types if and only if typing enabled
if (hasRequirement(Requirement::Type::Typing))
{
const auto acceptType =
[&](const auto *type)
{
return ((type == nullptr) != this->hasRequirement(Requirement::Type::Typing));
};
std::for_each(m_constants.cbegin(), m_constants.cend(),
[&](const auto &constant)
{
if (!acceptType(constant->type()))
throw ConsistencyException("Constant \"" + constant->name() + "\" has no type");
});
std::for_each(m_predicateDeclarations.cbegin(), m_predicateDeclarations.cend(),
[&](const auto &predicateDeclaration)
{
std::for_each(predicateDeclaration->arguments().cbegin(), predicateDeclaration->arguments().cend(),
[&](const auto &argument)
{
if (!acceptType(argument->type()))
throw ConsistencyException("Variable \"" + argument->name() + "\" has no type");
});
});
}
// Verify that all used types have been declared
std::for_each(m_primitiveTypes.cbegin(), m_primitiveTypes.cend(),
[&](const auto &type)
{
if (!type->isDeclared())
throw ConsistencyException("Type \"" + type->name() + "\" used but never declared");
});
// Verify that all used constants have been declared
std::for_each(m_constants.cbegin(), m_constants.cend(),
[&](const auto &constant)

View File

@ -45,12 +45,7 @@ void PredicateDeclaration::parse(Context &context, Domain &domain)
ExpressionContext expressionContext(domain, predicate->m_parameters);
// Parse arguments
while (context.parser.currentCharacter() != ')')
{
expressions::Variable::parseTypedDeclaration(context, expressionContext);
context.parser.skipWhiteSpace();
}
expressions::Variable::parseTypedDeclarations(context, expressionContext);
context.parser.expect<std::string>(")");

View File

@ -23,8 +23,7 @@ namespace expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType()
: m_isDirty{true},
m_isDeclared{false}
: m_isDirty{true}
{
}
@ -32,7 +31,6 @@ PrimitiveType::PrimitiveType()
PrimitiveType::PrimitiveType(std::string name)
: m_isDirty{true},
m_isDeclared{false},
m_name{name}
{
BOOST_ASSERT(!m_name.empty());
@ -61,13 +59,11 @@ void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
auto *type = match->get();
type->setDirty();
type->setDeclared();
return;
}
types.emplace_back(std::make_unique<PrimitiveType>(typeName));
types.back()->setDeclared();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -93,9 +89,6 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
parentType->setDirty(false);
// Flag parent tpe as correctly declared in the types section
parentType->setDeclared();
// Assign parent type to all types that were previously flagged
std::for_each(types.begin(), types.end(),
[&](auto &childType)
@ -164,20 +157,6 @@ bool PrimitiveType::isDirty() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PrimitiveType::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &PrimitiveType::name() const
{
return m_name;

View File

@ -5,6 +5,7 @@
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
@ -67,8 +68,6 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
if (!context.parser.probe('-'))
return;
// TODO: do not allow nested either expressions
const auto setType =
[&](const auto *type)
{
@ -108,6 +107,27 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expressionContext)
{
while (context.parser.currentCharacter() != ')')
parseTypedDeclaration(context, expressionContext);
if (expressionContext.parameters.empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (expressionContext.parameters.back()->type() != nullptr);
const auto typingDeclared = expressionContext.domain.hasRequirement(Requirement::Type::Typing);
if (!typingUsed && typingDeclared)
throw utils::ParserException(context.parser, "Object has undeclared type");
if (typingUsed && !typingDeclared)
throw utils::ParserException(context.parser, "Typing used but not declared as a requirement");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variable *Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();

View File

@ -255,10 +255,10 @@ bool Parser::probe<std::string>(const std::string &expectedValue)
{
BOOST_ASSERT(!std::isspace(expectedValue[0]));
skipWhiteSpace();
const auto previousPosition = position();
skipWhiteSpace();
const auto match = std::find_if(expectedValue.cbegin(), expectedValue.cend(),
[&](const auto &expectedCharacter)
{