diff --git a/lib/pddlparse/include/pddlparse/ASTForward.h b/lib/pddlparse/include/pddlparse/ASTForward.h index c14d06e..6a520b5 100644 --- a/lib/pddlparse/include/pddlparse/ASTForward.h +++ b/lib/pddlparse/include/pddlparse/ASTForward.h @@ -173,6 +173,24 @@ using Preconditions = std::vector; //////////////////////////////////////////////////////////////////////////////////////////////////// +class ConditionalEffect; + +namespace detail +{ +using ConditionalEffectT = Variant< + AtomicFormula, + AndPointer, + NotPointer, + UnsupportedPointer>; +} + +class ConditionalEffect : public detail::ConditionalEffectT +{ + using detail::ConditionalEffectT::ConditionalEffectT; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + class Effect; namespace detail @@ -182,7 +200,7 @@ using EffectT = Variant< AndPointer, ForAllPointer, NotPointer, - WhenPointer, + WhenPointer, UnsupportedPointer>; } diff --git a/lib/pddlparse/include/pddlparse/detail/parsing/Effect.h b/lib/pddlparse/include/pddlparse/detail/parsing/Effect.h new file mode 100644 index 0000000..5e67f22 --- /dev/null +++ b/lib/pddlparse/include/pddlparse/detail/parsing/Effect.h @@ -0,0 +1,27 @@ +#ifndef __PDDL_PARSE__DETAIL__PARSING__EFFECT_H +#define __PDDL_PARSE__DETAIL__PARSING__EFFECT_H + +#include +#include +#include +#include + +namespace pddl +{ +namespace detail +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Effect +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseEffect(Context &context, ASTContext &astContext, VariableStack &variableStack); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/lib/pddlparse/include/pddlparse/detail/parsing/Precondition.h b/lib/pddlparse/include/pddlparse/detail/parsing/Precondition.h index fb27a86..f6a99da 100644 --- a/lib/pddlparse/include/pddlparse/detail/parsing/Precondition.h +++ b/lib/pddlparse/include/pddlparse/detail/parsing/Precondition.h @@ -18,6 +18,7 @@ namespace detail //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parsePrecondition(Context &context, ASTContext &astContext, VariableStack &variableStack); +std::experimental::optional parsePreconditionBody(Context &context, ASTContext &astContext, VariableStack &variableStack); //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp index 5f3fbc8..8051ab9 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp @@ -3,8 +3,8 @@ #include #include #include +#include #include -// TODO: remove #include #include @@ -159,26 +159,18 @@ void ActionParser::parsePreconditionSection(ast::Action &action) //////////////////////////////////////////////////////////////////////////////////////////////////// -void ActionParser::parseEffectSection(ast::Action &) +void ActionParser::parseEffectSection(ast::Action &action) { auto &tokenizer = m_context.tokenizer; tokenizer.expect(":effect"); - tokenizer.expect("("); - m_context.warningCallback(tokenizer.location(), "effect parser under construction, section is currently ignored"); + VariableStack variableStack; + variableStack.push(&action.parameters); - // TODO: reimplement - //VariableStack variableStack; - //variableStack.push(&action.parameters); + ASTContext astContext(m_domain); - //ASTContext astContext(m_domain); - - //action.precondition = parseEffect(m_context, astContext, variableStack); - - //tokenizer.expect(")"); - - skipSection(tokenizer); + action.effect = parseEffect(m_context, astContext, variableStack); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Effect.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Effect.cpp new file mode 100644 index 0000000..d8b0f0e --- /dev/null +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Effect.cpp @@ -0,0 +1,154 @@ +#include + +#include +#include +#include +#include +#include +#include + +namespace pddl +{ +namespace detail +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Effect +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack); +std::experimental::optional parseConditionalEffect(Context &context, ASTContext &astContext, VariableStack &variableStack); +std::experimental::optional parseConditionalEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseEffect(Context &context, ASTContext &astContext, VariableStack &variableStack) +{ + auto &tokenizer = context.tokenizer; + + tokenizer.skipWhiteSpace(); + + std::experimental::optional effect; + + if ((effect = parseAnd(context, astContext, variableStack, parseEffect)) + || (effect = parseForAll(context, astContext, variableStack, parseEffect)) + || (effect = parseWhen(context, astContext, variableStack, parsePreconditionBody, parseConditionalEffect))) + { + return std::move(effect.value()); + } + + return parseEffectBody(context, astContext, variableStack); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack) +{ + auto &tokenizer = context.tokenizer; + + tokenizer.skipWhiteSpace(); + + // Test unsupported expressions first + const auto position = tokenizer.position(); + + tokenizer.expect("("); + tokenizer.skipWhiteSpace(); + + const auto expressionIdentifierPosition = tokenizer.position(); + + if (tokenizer.testIdentifierAndReturn("=") + || tokenizer.testIdentifierAndReturn("assign") + || tokenizer.testIdentifierAndReturn("scale-up") + || tokenizer.testIdentifierAndReturn("scale-down") + || tokenizer.testIdentifierAndReturn("increase") + || tokenizer.testIdentifierAndReturn("decrease")) + { + tokenizer.seek(position); + return parseUnsupported(context); + } + + tokenizer.seek(position); + + // Now, test supported expressions + std::experimental::optional effect; + + if ((effect = parseNot(context, astContext, variableStack, parsePredicate)) + || (effect = parsePredicate(context, astContext, variableStack))) + { + return std::move(effect.value()); + } + + tokenizer.seek(expressionIdentifierPosition); + const auto expressionIdentifier = tokenizer.getIdentifier(); + + tokenizer.seek(position); + throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in effect body"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseConditionalEffect(Context &context, ASTContext &astContext, VariableStack &variableStack) +{ + auto &tokenizer = context.tokenizer; + + tokenizer.skipWhiteSpace(); + + std::experimental::optional conditionalEffect; + + if ((conditionalEffect = parseAnd(context, astContext, variableStack, parseConditionalEffectBody))) + return std::move(conditionalEffect.value()); + + return parseConditionalEffectBody(context, astContext, variableStack); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::experimental::optional parseConditionalEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack) +{ + auto &tokenizer = context.tokenizer; + + tokenizer.skipWhiteSpace(); + + // Test unsupported expressions first + const auto position = tokenizer.position(); + + tokenizer.expect("("); + tokenizer.skipWhiteSpace(); + + const auto expressionIdentifierPosition = tokenizer.position(); + + if (tokenizer.testIdentifierAndReturn("=") + || tokenizer.testIdentifierAndReturn("assign") + || tokenizer.testIdentifierAndReturn("scale-up") + || tokenizer.testIdentifierAndReturn("scale-down") + || tokenizer.testIdentifierAndReturn("increase") + || tokenizer.testIdentifierAndReturn("decrease")) + { + tokenizer.seek(position); + return parseUnsupported(context); + } + + tokenizer.seek(position); + + // Now, test supported expressions + std::experimental::optional conditionalEffect; + + if ((conditionalEffect = parseNot(context, astContext, variableStack, parsePredicate)) + || (conditionalEffect = parsePredicate(context, astContext, variableStack))) + { + return std::move(conditionalEffect.value()); + } + + tokenizer.seek(expressionIdentifierPosition); + const auto expressionIdentifier = tokenizer.getIdentifier(); + + tokenizer.seek(position); + throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in conditional effect body"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp index 493a02d..dd165a3 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp @@ -17,24 +17,13 @@ namespace detail // //////////////////////////////////////////////////////////////////////////////////////////////////// -std::experimental::optional parsePreconditionBody(Context &context, ASTContext &astContext, VariableStack &variableStack); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - std::experimental::optional parsePrecondition(Context &context, ASTContext &astContext, VariableStack &variableStack) { auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); - std::experimental::optional precondition; - - if ((precondition = parseAnd(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseForAll(context, astContext, variableStack, parsePrecondition))) - { - return std::move(precondition.value()); - } - + // Test unsupported expressions first const auto position = tokenizer.position(); tokenizer.expect("("); @@ -45,6 +34,17 @@ std::experimental::optional parsePrecondition(Context &contex return parseUnsupported(context); } + tokenizer.seek(position); + + // Now, test supported expressions + std::experimental::optional precondition; + + if ((precondition = parseAnd(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseForAll(context, astContext, variableStack, parsePrecondition))) + { + return std::move(precondition.value()); + } + tokenizer.seek(position); return parsePreconditionBody(context, astContext, variableStack); } @@ -57,19 +57,7 @@ std::experimental::optional parsePreconditionBody(Context &co tokenizer.skipWhiteSpace(); - std::experimental::optional precondition; - - if ((precondition = parseAnd(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseOr(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseExists(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseForAll(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseNot(context, astContext, variableStack, parsePrecondition)) - || (precondition = parseImply(context, astContext, variableStack, parsePrecondition)) - || (precondition = parsePredicate(context, astContext, variableStack))) - { - return std::move(precondition.value()); - } - + // Test unsupported expressions first const auto position = tokenizer.position(); tokenizer.expect("("); @@ -93,11 +81,27 @@ std::experimental::optional parsePreconditionBody(Context &co return parseUnsupported(context); } + tokenizer.seek(position); + + // Now, test supported expressions + std::experimental::optional precondition; + + if ((precondition = parseAnd(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseOr(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseExists(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseForAll(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseNot(context, astContext, variableStack, parsePrecondition)) + || (precondition = parseImply(context, astContext, variableStack, parsePrecondition)) + || (precondition = parsePredicate(context, astContext, variableStack))) + { + return std::move(precondition.value()); + } + tokenizer.seek(expressionIdentifierPosition); const auto expressionIdentifier = tokenizer.getIdentifier(); tokenizer.seek(position); - throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context"); + throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in precondition body"); } ////////////////////////////////////////////////////////////////////////////////////////////////////