Implemented compatibility mode to support old instances.

This commit is contained in:
Patrick Lühne 2017-06-17 22:18:39 +02:00
parent dde277cc3e
commit 615167e7cd
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
9 changed files with 52 additions and 9 deletions

View File

@ -3,6 +3,7 @@
#include <functional>
#include <pddlparse/Mode.h>
#include <pddlparse/Tokenizer.h>
namespace pddl
@ -27,9 +28,10 @@ struct Context
Context() = default;
~Context() = default;
explicit Context(Tokenizer &&tokenizer, WarningCallback warningCallback)
explicit Context(Tokenizer &&tokenizer, WarningCallback warningCallback, Mode mode = Mode::Strict)
: tokenizer{std::move(tokenizer)},
warningCallback{warningCallback}
warningCallback{warningCallback},
mode{mode}
{
}
@ -40,6 +42,8 @@ struct Context
Tokenizer tokenizer;
WarningCallback warningCallback;
Mode mode;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,27 @@
#ifndef __PDDL_PARSE__MODE_H
#define __PDDL_PARSE__MODE_H
#include <functional>
#include <pddlparse/Tokenizer.h>
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Mode
//
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class Mode
{
Strict,
Compatibility
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@ -2,6 +2,7 @@
#include <algorithm>
#include <pddlparse/Exception.h>
#include <pddlparse/detail/parsing/Requirement.h>
namespace pddl
@ -59,7 +60,10 @@ void checkRequirement(ast::Domain &domain, ast::Requirement requirement, Context
if (hasRequirement(domain, requirement))
return;
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared, silently adding requirement");
if (context.mode == Mode::Compatibility)
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared, silently adding requirement");
else
throw ParserException(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
domain.requirements.push_back(requirement);
}
@ -71,7 +75,10 @@ void checkRequirement(ast::Problem &problem, ast::Requirement requirement, Conte
if (hasRequirement(problem, requirement))
return;
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared, silently adding requirement");
if (context.mode == Mode::Compatibility)
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared, silently adding requirement");
else
throw ParserException(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
problem.requirements.push_back(requirement);
}

View File

@ -107,7 +107,7 @@ void ActionParser::findSections(ast::Action &action)
setSectionPosition("precondition", m_preconditionPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("effect"))
setSectionPosition("effect", m_effectPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("vars"))
else if (m_context.mode == Mode::Compatibility && tokenizer.testIdentifierAndSkip("vars"))
setSectionPosition("vars", m_varsPosition, position, true);
else
{

View File

@ -71,7 +71,7 @@ void DescriptionParser::findSections()
tokenizer.expect<std::string>("(");
if (tokenizer.testAndReturn<std::string>("in-package"))
if (m_context.mode == Mode::Compatibility && tokenizer.testAndReturn<std::string>("in-package"))
{
m_context.warningCallback(tokenizer.location(), "“in-package” section is not part of the PDDL 3.1 specification, ignoring section");

View File

@ -35,6 +35,9 @@ ast::PrimitiveTypePointer parsePrimitiveType(Context &context, ast::Domain &doma
// If the type has not been declared yet, add it but issue a warning
if (matchingType == types.end())
{
if (context.mode != Mode::Compatibility)
throw ParserException(tokenizer.location(), "primitive type “" + typeName + "” used without or before declaration");
context.warningCallback(tokenizer.location(), "primitive type “" + typeName + "” used without or before declaration, silently adding declaration");
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));

View File

@ -66,7 +66,7 @@ std::experimental::optional<ast::Requirement> parseRequirement(Context &context)
if (matchingRequirement != requirementNameMap.cend())
return matchingRequirement->second;
if (requirementName == "goal-utilities" || requirementName == "domain-axioms")
if (context.mode == Mode::Compatibility && (requirementName == "goal-utilities" || requirementName == "domain-axioms"))
context.warningCallback(tokenizer.location(), "" + requirementName + "” requirement is not part of the PDDL 3.1 specification, ignoring requirement");
return std::experimental::nullopt;

View File

@ -33,7 +33,7 @@ TEST_CASE("[PDDL parser acceptance] All official PDDL domains are parsed without
{
pddl::Tokenizer tokenizer;
tokenizer.read(domainFile);
pddl::Context context(std::move(tokenizer), ignoreWarnings);
pddl::Context context(std::move(tokenizer), ignoreWarnings, pddl::Mode::Compatibility);
CHECK_NOTHROW(pddl::parseDescription(context));
}
@ -67,7 +67,7 @@ TEST_CASE("[PDDL parser acceptance] The first instance for all official PDDL dom
pddl::Tokenizer tokenizer;
tokenizer.read(domainFile);
tokenizer.read(instanceFile);
pddl::Context context(std::move(tokenizer), ignoreWarnings);
pddl::Context context(std::move(tokenizer), ignoreWarnings, pddl::Mode::Compatibility);
CHECK_NOTHROW(pddl::parseDescription(context));
}

View File

@ -188,6 +188,8 @@ TEST_CASE("[PDDL parser] The official PDDL instances are parsed correctly", "[PD
SECTION("“either” type in zenotravel domain")
{
context.mode = pddl::Mode::Compatibility;
const auto domainFile = pddlInstanceBasePath / "ipc-2002" / "domains" / "zenotravel-numeric-hand-coded" / "domain.pddl";
context.tokenizer.read(domainFile);
auto description = pddl::parseDescription(context);