diff --git a/include/plasp/pddl/Expression.h b/include/plasp/pddl/Expression.h index 3c1879c..0627c9d 100644 --- a/include/plasp/pddl/Expression.h +++ b/include/plasp/pddl/Expression.h @@ -35,6 +35,8 @@ class Expression std::unique_ptr parsePreconditionExpression(utils::Parser &parser, Context &context, const Variables ¶meters); std::unique_ptr parseExpression(utils::Parser &parser, Context &context, const Variables ¶meters); +std::unique_ptr parseEffectExpression(utils::Parser &parser, Context &context, const Variables ¶meters); + //////////////////////////////////////////////////////////////////////////////////////////////////// } diff --git a/include/plasp/pddl/expressions/NAryExpression.h b/include/plasp/pddl/expressions/NAryExpression.h index 377daef..5574745 100644 --- a/include/plasp/pddl/expressions/NAryExpression.h +++ b/include/plasp/pddl/expressions/NAryExpression.h @@ -40,8 +40,6 @@ class NAryExpression: public Expression template void NAryExpression::parse(utils::Parser &parser, Context &context, const Variables ¶meters, ExpressionParser parseExpression) { - std::cout << "Parsing n-ary predicate" << std::endl; - parser.skipWhiteSpace(); // Assume that expression identifier (and, or, etc.) is already parsed diff --git a/src/plasp/pddl/Action.cpp b/src/plasp/pddl/Action.cpp index cbf7927..3f96c0c 100644 --- a/src/plasp/pddl/Action.cpp +++ b/src/plasp/pddl/Action.cpp @@ -54,8 +54,7 @@ Action &Action::parseDeclaration(utils::Parser &parser, Context &context) if (sectionIdentifier == "precondition") action->m_precondition = parsePreconditionExpression(parser, context, action->m_parameters); else if (sectionIdentifier == "effect") - throw utils::ParserException(parser.row(), parser.column(), "Action effects are currently unsupported"); - // action->m_effect = parseEffectExpression(parser, context); + action->m_effect = parseEffectExpression(parser, context, action->m_parameters); } parser.expect(")"); diff --git a/src/plasp/pddl/Expression.cpp b/src/plasp/pddl/Expression.cpp index d55efee..135b4e4 100644 --- a/src/plasp/pddl/Expression.cpp +++ b/src/plasp/pddl/Expression.cpp @@ -18,7 +18,15 @@ namespace pddl // //////////////////////////////////////////////////////////////////////////////////////////////////// -std::unique_ptr parseExpressionBody(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters); +std::unique_ptr parseExpressionContent(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters); +std::unique_ptr parseEffectBodyExpressionContent(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void throwUnsupported(const utils::Parser &parser, const std::string &expressionIdentifier) +{ + throw utils::ParserException(parser.row(), parser.column(), "Expression type \"" + expressionIdentifier + "\" currently unsupported"); +} //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -30,24 +38,17 @@ std::unique_ptr parsePreconditionExpression(utils::Parser &parser, C const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); - std::cout << "Parsing precondition expression " << expressionIdentifier << std::endl; - std::unique_ptr expression; - const auto throwUnsupported = - [&]() - { - throw utils::ParserException(parser.row(), parser.column(), "Expression type \"" + expressionIdentifier + "\" unsupported"); - }; - if (expressionIdentifier == "and") expression = expressions::AndExpression::parse(parser, context, parameters, parsePreconditionExpression); - else if (expressionIdentifier == "forall") - throwUnsupported(); - else if (expressionIdentifier == "preference") - throwUnsupported(); + else if (expressionIdentifier == "forall" + || expressionIdentifier == "preference") + { + throwUnsupported(parser, expressionIdentifier); + } else - expression = parseExpressionBody(expressionIdentifier, parser, context, parameters); + expression = parseExpressionContent(expressionIdentifier, parser, context, parameters); parser.expect(")"); @@ -64,7 +65,7 @@ std::unique_ptr parseExpression(utils::Parser &parser, Context &cont const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); - auto expression = parseExpressionBody(expressionIdentifier, parser, context, parameters); + auto expression = parseExpressionContent(expressionIdentifier, parser, context, parameters); parser.expect(")"); @@ -73,20 +74,12 @@ std::unique_ptr parseExpression(utils::Parser &parser, Context &cont //////////////////////////////////////////////////////////////////////////////////////////////////// -std::unique_ptr parseExpressionBody(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters) +std::unique_ptr parseExpressionContent(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters) { parser.skipWhiteSpace(); - std::cout << "Parsing expression " << expressionIdentifier << std::endl; - std::unique_ptr expression; - const auto throwUnsupported = - [&]() - { - throw utils::ParserException(parser.row(), parser.column(), "Expression type \"" + expressionIdentifier + "\" unsupported"); - }; - if (expressionIdentifier == "and") expression = expressions::AndExpression::parse(parser, context, parameters, parseExpression); else if (expressionIdentifier == "or") @@ -107,7 +100,7 @@ std::unique_ptr parseExpressionBody(const std::string &expressionIde || expressionIdentifier == ">=" || expressionIdentifier == "<=") { - throwUnsupported(); + throwUnsupported(parser, expressionIdentifier); } else { @@ -122,7 +115,73 @@ std::unique_ptr parseExpressionBody(const std::string &expressionIde if (match != context.predicates.cend()) expression = expressions::PredicateExpression::parse(expressionIdentifier, parser, context, parameters); else - throw utils::ParserException(parser.row(), parser.column(), "Undeclared expression \"" + expressionIdentifier + "\""); + throw utils::ParserException(parser.row(), parser.column(), "Expression \"" + expressionIdentifier + "\" not allowed in this context"); + } + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::unique_ptr parseEffectExpression(utils::Parser &parser, Context &context, const Variables ¶meters) +{ + parser.skipWhiteSpace(); + + parser.expect("("); + + const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); + + std::cout << "Parsing effect expression " << expressionIdentifier << std::endl; + + std::unique_ptr expression; + + if (expressionIdentifier == "and") + expression = expressions::AndExpression::parse(parser, context, parameters, parseEffectExpression); + else if (expressionIdentifier == "forall" + || expressionIdentifier == "when") + { + throwUnsupported(parser, expressionIdentifier); + } + else + expression = parseEffectBodyExpressionContent(expressionIdentifier, parser, context, parameters); + + parser.expect(")"); + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::unique_ptr parseEffectBodyExpressionContent(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters) +{ + parser.skipWhiteSpace(); + + std::unique_ptr expression; + + if (expressionIdentifier == "not" + || expressionIdentifier == "=" + || expressionIdentifier == "assign" + || expressionIdentifier == "scale-up" + || expressionIdentifier == "scale-down" + || expressionIdentifier == "increase" + || expressionIdentifier == "decrease") + { + throwUnsupported(parser, expressionIdentifier); + } + else + { + // Check if predicate with that name exists + const auto match = std::find_if(context.predicates.cbegin(), context.predicates.cend(), + [&](const auto &predicate) + { + return predicate->name() == expressionIdentifier; + }); + + // If predicate exists, parse it + if (match != context.predicates.cend()) + expression = expressions::PredicateExpression::parse(expressionIdentifier, parser, context, parameters); + else + throw utils::ParserException(parser.row(), parser.column(), "Expression \"" + expressionIdentifier + "\" not allowed in this context"); } return expression; diff --git a/src/plasp/pddl/expressions/PredicateExpression.cpp b/src/plasp/pddl/expressions/PredicateExpression.cpp index 45c7c37..88d3450 100644 --- a/src/plasp/pddl/expressions/PredicateExpression.cpp +++ b/src/plasp/pddl/expressions/PredicateExpression.cpp @@ -27,7 +27,7 @@ std::unique_ptr PredicateExpression::parse(std::string name while (parser.currentCharacter() != ')') Variable::parseTyped(parser, context, expression->m_arguments); - std::cout << "Parsed " << expression->m_arguments.size() << " arguments" << std::endl; + // TODO: check that signature matches one of the declared ones return expression; }