diff --git a/include/plasp/pddl/Expression.h b/include/plasp/pddl/Expression.h index 481093b..3c1879c 100644 --- a/include/plasp/pddl/Expression.h +++ b/include/plasp/pddl/Expression.h @@ -33,6 +33,7 @@ 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); //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/plasp/pddl/expressions/AndExpression.h b/include/plasp/pddl/expressions/AndExpression.h index 924d96e..c09f25e 100644 --- a/include/plasp/pddl/expressions/AndExpression.h +++ b/include/plasp/pddl/expressions/AndExpression.h @@ -39,7 +39,7 @@ std::unique_ptr AndExpression::parse(utils::Parser &parser, Conte expression->NAryExpression::parse(parser, context, parameters, parseExpression); if (expression->arguments().empty()) - throw ConsistencyException("Expressions should not be empty"); + throw ConsistencyException("\"and\" expressions should not be empty"); return expression; } diff --git a/include/plasp/pddl/expressions/OrExpression.h b/include/plasp/pddl/expressions/OrExpression.h new file mode 100644 index 0000000..d234099 --- /dev/null +++ b/include/plasp/pddl/expressions/OrExpression.h @@ -0,0 +1,53 @@ +#ifndef __PLASP__PDDL__EXPRESSION__OR_EXPRESSION_H +#define __PLASP__PDDL__EXPRESSION__OR_EXPRESSION_H + +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// OrExpression +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class OrExpression: public NAryExpression +{ + public: + template + static std::unique_ptr parse(utils::Parser &parser, Context &context, const Variables ¶meters, ExpressionParser parseExpression); + + public: + void accept(ExpressionVisitor &expressionVisitor) const override; + + private: + OrExpression() = default; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::unique_ptr OrExpression::parse(utils::Parser &parser, Context &context, const Variables ¶meters, ExpressionParser parseExpression) +{ + auto expression = std::make_unique(OrExpression()); + + expression->NAryExpression::parse(parser, context, parameters, parseExpression); + + if (expression->arguments().empty()) + throw ConsistencyException("\"or\" expressions should not be empty"); + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} + +#endif diff --git a/include/plasp/pddl/expressions/PredicateExpression.h b/include/plasp/pddl/expressions/PredicateExpression.h new file mode 100644 index 0000000..8381284 --- /dev/null +++ b/include/plasp/pddl/expressions/PredicateExpression.h @@ -0,0 +1,42 @@ +#ifndef __PLASP__PDDL__EXPRESSION__PREDICATE_EXPRESSION_H +#define __PLASP__PDDL__EXPRESSION__PREDICATE_EXPRESSION_H + +#include +#include +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// PredicateExpression +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class PredicateExpression: public Expression +{ + public: + static std::unique_ptr parse(std::string name, utils::Parser &parser, Context &context, const Variables ¶meters); + + public: + void accept(ExpressionVisitor &expressionVisitor) const override; + + private: + PredicateExpression() = default; + + std::string m_name; + Variables m_arguments; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} + +#endif diff --git a/src/plasp/pddl/Action.cpp b/src/plasp/pddl/Action.cpp index 24113c9..cbf7927 100644 --- a/src/plasp/pddl/Action.cpp +++ b/src/plasp/pddl/Action.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace plasp { @@ -52,7 +53,8 @@ Action &Action::parseDeclaration(utils::Parser &parser, Context &context) if (sectionIdentifier == "precondition") action->m_precondition = parsePreconditionExpression(parser, context, action->m_parameters); - //else if (sectionIdentifier == "effect") + else if (sectionIdentifier == "effect") + throw utils::ParserException(parser.row(), parser.column(), "Action effects are currently unsupported"); // action->m_effect = parseEffectExpression(parser, context); } diff --git a/src/plasp/pddl/Expression.cpp b/src/plasp/pddl/Expression.cpp index 0bf0b90..d55efee 100644 --- a/src/plasp/pddl/Expression.cpp +++ b/src/plasp/pddl/Expression.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include namespace plasp @@ -16,6 +18,10 @@ namespace pddl // //////////////////////////////////////////////////////////////////////////////////////////////////// +std::unique_ptr parseExpressionBody(const std::string &expressionIdentifier, utils::Parser &parser, Context &context, const Variables ¶meters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + std::unique_ptr parsePreconditionExpression(utils::Parser &parser, Context &context, const Variables ¶meters) { parser.skipWhiteSpace(); @@ -24,26 +30,24 @@ std::unique_ptr parsePreconditionExpression(utils::Parser &parser, C const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); - std::cout << "Parsing identifier " << expressionIdentifier << std::endl; + std::cout << "Parsing precondition expression " << expressionIdentifier << std::endl; std::unique_ptr expression; - const auto throwNotAllowed = + const auto throwUnsupported = [&]() { - throw utils::ParserException(parser.row(), parser.column(), "Expression of type \"" + expressionIdentifier + "\" not allowed in preference declaration"); + 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 == "or") - throwNotAllowed(); - else if (expressionIdentifier == "not") - throwNotAllowed(); - else if (expressionIdentifier == "exists") - throwNotAllowed(); + else if (expressionIdentifier == "forall") + throwUnsupported(); + else if (expressionIdentifier == "preference") + throwUnsupported(); else - throw utils::ParserException(parser.row(), parser.column(), "Undeclared expression \"" + expressionIdentifier + "\""); + expression = parseExpressionBody(expressionIdentifier, parser, context, parameters); parser.expect(")"); @@ -52,5 +56,79 @@ std::unique_ptr parsePreconditionExpression(utils::Parser &parser, C //////////////////////////////////////////////////////////////////////////////////////////////////// +std::unique_ptr parseExpression(utils::Parser &parser, Context &context, const Variables ¶meters) +{ + parser.skipWhiteSpace(); + + parser.expect("("); + + const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); + + auto expression = parseExpressionBody(expressionIdentifier, parser, context, parameters); + + parser.expect(")"); + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::unique_ptr parseExpressionBody(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") + expression = expressions::OrExpression::parse(parser, context, parameters, parseExpression); + else if (expressionIdentifier == "not" + || expressionIdentifier == "imply" + || expressionIdentifier == "exists" + || expressionIdentifier == "forall" + || expressionIdentifier == "-" + || expressionIdentifier == "=" + || expressionIdentifier == "*" + || expressionIdentifier == "+" + || expressionIdentifier == "-" + || expressionIdentifier == "/" + || expressionIdentifier == ">" + || expressionIdentifier == "<" + || expressionIdentifier == "=" + || expressionIdentifier == ">=" + || expressionIdentifier == "<=") + { + throwUnsupported(); + } + 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(), "Undeclared expression \"" + expressionIdentifier + "\""); + } + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + } } diff --git a/src/plasp/pddl/expressions/AndExpression.cpp b/src/plasp/pddl/expressions/AndExpression.cpp index 5dddbac..0b274c9 100644 --- a/src/plasp/pddl/expressions/AndExpression.cpp +++ b/src/plasp/pddl/expressions/AndExpression.cpp @@ -1,8 +1,6 @@ #include -#include #include -#include namespace plasp { diff --git a/src/plasp/pddl/expressions/OrExpression.cpp b/src/plasp/pddl/expressions/OrExpression.cpp new file mode 100644 index 0000000..428e4aa --- /dev/null +++ b/src/plasp/pddl/expressions/OrExpression.cpp @@ -0,0 +1,27 @@ +#include + +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// OrExpression +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void OrExpression::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const +{ + expressionVisitor.visit(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} diff --git a/src/plasp/pddl/expressions/PredicateExpression.cpp b/src/plasp/pddl/expressions/PredicateExpression.cpp new file mode 100644 index 0000000..45c7c37 --- /dev/null +++ b/src/plasp/pddl/expressions/PredicateExpression.cpp @@ -0,0 +1,46 @@ +#include + +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// PredicateExpression +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +std::unique_ptr PredicateExpression::parse(std::string name, utils::Parser &parser, Context &context, const Variables ¶meters) +{ + auto expression = std::make_unique(PredicateExpression()); + + expression->m_name = name; + + parser.skipWhiteSpace(); + + // Parse arguments + while (parser.currentCharacter() != ')') + Variable::parseTyped(parser, context, expression->m_arguments); + + std::cout << "Parsed " << expression->m_arguments.size() << " arguments" << std::endl; + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void PredicateExpression::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const +{ + expressionVisitor.visit(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +}