diff --git a/lib/pddlparse/include/pddlparse/Context.h b/lib/pddlparse/include/pddlparse/Context.h index 6859944..a4cf884 100644 --- a/lib/pddlparse/include/pddlparse/Context.h +++ b/lib/pddlparse/include/pddlparse/Context.h @@ -3,6 +3,7 @@ #include +#include #include 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; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/pddlparse/include/pddlparse/Mode.h b/lib/pddlparse/include/pddlparse/Mode.h new file mode 100644 index 0000000..c3a663e --- /dev/null +++ b/lib/pddlparse/include/pddlparse/Mode.h @@ -0,0 +1,27 @@ +#ifndef __PDDL_PARSE__MODE_H +#define __PDDL_PARSE__MODE_H + +#include + +#include + +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Mode +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +enum class Mode +{ + Strict, + Compatibility +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} + +#endif diff --git a/lib/pddlparse/src/pddlparse/detail/Requirements.cpp b/lib/pddlparse/src/pddlparse/detail/Requirements.cpp index aab3477..123a222 100644 --- a/lib/pddlparse/src/pddlparse/detail/Requirements.cpp +++ b/lib/pddlparse/src/pddlparse/detail/Requirements.cpp @@ -2,6 +2,7 @@ #include +#include #include 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); } diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp index d377070..351b0fb 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp @@ -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 { diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp index 7931bb4..9c4e4d7 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp @@ -71,7 +71,7 @@ void DescriptionParser::findSections() tokenizer.expect("("); - if (tokenizer.testAndReturn("in-package")) + if (m_context.mode == Mode::Compatibility && tokenizer.testAndReturn("in-package")) { m_context.warningCallback(tokenizer.location(), "“in-package” section is not part of the PDDL 3.1 specification, ignoring section"); diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp index 11344e3..ef42997 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp @@ -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(std::move(typeName))); diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp index 04acb3d..2f82ca8 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp @@ -66,7 +66,7 @@ std::experimental::optional 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; diff --git a/lib/pddlparse/tests/TestAcceptanceOfOfficialPDDLInstances.cpp b/lib/pddlparse/tests/TestAcceptanceOfOfficialPDDLInstances.cpp index 12e0ed9..4aea19a 100644 --- a/lib/pddlparse/tests/TestAcceptanceOfOfficialPDDLInstances.cpp +++ b/lib/pddlparse/tests/TestAcceptanceOfOfficialPDDLInstances.cpp @@ -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)); } diff --git a/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp b/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp index af47818..c4fa60a 100644 --- a/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp +++ b/lib/pddlparse/tests/TestOfficialPDDLInstances.cpp @@ -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);