diff --git a/include/plasp/pddl/Expression.h b/include/plasp/pddl/Expression.h index d5e128c..fb2f009 100644 --- a/include/plasp/pddl/Expression.h +++ b/include/plasp/pddl/Expression.h @@ -31,6 +31,9 @@ namespace expressions class And; using AndPointer = std::unique_ptr; +class At; +using AtPointer = std::unique_ptr; + class Constant; using ConstantPointer = std::unique_ptr; using Constants = std::vector; @@ -72,6 +75,7 @@ class Expression enum class Type { And, + At, Binary, Constant, Either, @@ -104,6 +108,9 @@ class ExpressionCRTP: public Expression //////////////////////////////////////////////////////////////////////////////////////////////////// +ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext); +ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext); + ExpressionPointer parsePreconditionExpression(Context &context, ExpressionContext &expressionContext); ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext); diff --git a/include/plasp/pddl/InitialState.h b/include/plasp/pddl/InitialState.h index fbbd5f8..ccb1733 100644 --- a/include/plasp/pddl/InitialState.h +++ b/include/plasp/pddl/InitialState.h @@ -17,7 +17,8 @@ namespace pddl class InitialState { public: - static std::unique_ptr parseDeclaration(Context &context, const Problem &problem); + static std::unique_ptr parseDeclaration(Context &context, + ExpressionContext &expressionContext); public: const Expressions &facts() const; diff --git a/include/plasp/pddl/expressions/At.h b/include/plasp/pddl/expressions/At.h new file mode 100644 index 0000000..5495ca7 --- /dev/null +++ b/include/plasp/pddl/expressions/At.h @@ -0,0 +1,104 @@ +#ifndef __PLASP__PDDL__EXPRESSIONS__AT_H +#define __PLASP__PDDL__EXPRESSIONS__AT_H + +#include +#include +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// At +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class At: public ExpressionCRTP +{ + public: + static const Expression::Type ExpressionType = Expression::Type::At; + + template + static AtPointer parse(Context &context, ExpressionContext &expressionContext, + ExpressionParser parseExpression); + + static const size_t TimePointStart = std::numeric_limits::max(); + static const size_t TimePointEnd = std::numeric_limits::max() - 1; + + public: + At(); + + size_t timePoint() const; + + const Expression *argument() const; + + private: + void setArgument(const Expression *argument); + void setArgument(ExpressionPointer &&argument); + + size_t m_timePoint; + + const Expression *m_argument; + ExpressionPointer m_argumentStorage; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +AtPointer At::parse(Context &context, ExpressionContext &expressionContext, + ExpressionParser parseExpression) +{ + auto &parser = context.parser; + + const auto position = parser.position(); + + if (!parser.probe("(") + || !parser.probeIdentifier("at", isIdentifier)) + { + parser.seek(position); + return nullptr; + } + + size_t timePoint; + + const auto timePointPosition = parser.position(); + + if (parser.probeIdentifier("start", isIdentifier)) + timePoint = TimePointStart; + else if (parser.probeIdentifier("end", isIdentifier)) + timePoint = TimePointEnd; + else if (parser.probeNumber()) + { + parser.seek(timePointPosition); + timePoint = parser.parse(); + } + else + { + parser.seek(position); + return nullptr; + } + + auto expression = std::make_unique(At()); + + context.parser.skipWhiteSpace(); + + // Parse argument + expression->setArgument(parseExpression(context, expressionContext)); + + parser.expect(")"); + + return expression; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} + +#endif diff --git a/include/plasp/utils/Parser.h b/include/plasp/utils/Parser.h index 78db6dd..2d821bc 100644 --- a/include/plasp/utils/Parser.h +++ b/include/plasp/utils/Parser.h @@ -79,6 +79,8 @@ class Parser template bool probeIdentifier(const std::string &identifier, CharacterPredicate characterPredicate); + bool probeNumber(); + template void expect(const Type &expectedValue); diff --git a/src/plasp/pddl/Expression.cpp b/src/plasp/pddl/Expression.cpp index 8f1fec3..fd6b667 100644 --- a/src/plasp/pddl/Expression.cpp +++ b/src/plasp/pddl/Expression.cpp @@ -229,5 +229,54 @@ ExpressionPointer parsePredicate(Context &context, ExpressionContext &expression //////////////////////////////////////////////////////////////////////////////////////////////////// +ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext) +{ + ExpressionPointer expression; + + if ((expression = parseAtomicFormula(context, expressionContext)) + || (expression = expressions::Not::parse(context, expressionContext, parseAtomicFormula))) + { + return expression; + } + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext) +{ + auto &parser = context.parser; + + ExpressionPointer expression; + + if ((expression = expressions::Predicate::parse(context, expressionContext))) + return expression; + + const auto position = parser.position(); + + parser.expect("("); + + const auto expressionIdentifierPosition = parser.position(); + + if (parser.probeIdentifier("=", isIdentifier)) + { + parser.seek(expressionIdentifierPosition); + const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); + + parser.seek(position); + warnUnsupported(context, expressionIdentifier); + + parser.seek(expressionIdentifierPosition); + skipSection(parser); + + return nullptr; + } + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + } } diff --git a/src/plasp/pddl/InitialState.cpp b/src/plasp/pddl/InitialState.cpp index 0c37f23..741441d 100644 --- a/src/plasp/pddl/InitialState.cpp +++ b/src/plasp/pddl/InitialState.cpp @@ -1,8 +1,11 @@ #include #include +#include #include #include +#include +#include #include #include @@ -24,7 +27,8 @@ inline void warnUnsupported(Context &context, const std::string &expressionIdent //////////////////////////////////////////////////////////////////////////////////////////////////// -std::unique_ptr InitialState::parseDeclaration(Context &context, const Problem &problem) +std::unique_ptr InitialState::parseDeclaration(Context &context, + ExpressionContext &expressionContext) { auto &parser = context.parser; @@ -35,8 +39,12 @@ std::unique_ptr InitialState::parseDeclaration(Context &context, c { ExpressionPointer expression; - if ((expression = expressions::Predicate::parse(context, problem))) + // TODO: do not allow negative initial state literals + if ((expression = parseLiteral(context, expressionContext)) + || (expression = expressions::At::parse(context, expressionContext, parseLiteral))) + { return expression; + } const auto position = parser.position(); @@ -44,9 +52,7 @@ std::unique_ptr InitialState::parseDeclaration(Context &context, c const auto expressionIdentifierPosition = parser.position(); - if (parser.probeIdentifier("at", isIdentifier) - || parser.probeIdentifier("=", isIdentifier) - || parser.probeIdentifier("not", isIdentifier)) + if (parser.probeIdentifier("=", isIdentifier)) { parser.seek(expressionIdentifierPosition); const auto expressionIdentifier = parser.parseIdentifier(isIdentifier); diff --git a/src/plasp/pddl/Problem.cpp b/src/plasp/pddl/Problem.cpp index 1824885..e521a3a 100644 --- a/src/plasp/pddl/Problem.cpp +++ b/src/plasp/pddl/Problem.cpp @@ -332,7 +332,11 @@ void Problem::parseInitialStateSection() parser.expect(":"); parser.expect("init"); - m_initialState = InitialState::parseDeclaration(m_context, *this); + // TODO: remove workaround + expressions::Variables noParameters; + ExpressionContext expressionContext(m_domain, this, noParameters); + + m_initialState = InitialState::parseDeclaration(m_context, expressionContext); parser.expect(")"); } @@ -349,7 +353,6 @@ void Problem::parseGoalSection() // TODO: remove workaround expressions::Variables noParameters; - ExpressionContext expressionContext(m_domain, this, noParameters); m_goal = parsePreconditionExpression(m_context, expressionContext); diff --git a/src/plasp/pddl/TranslatorASP.cpp b/src/plasp/pddl/TranslatorASP.cpp index 511ee70..b8befa5 100644 --- a/src/plasp/pddl/TranslatorASP.cpp +++ b/src/plasp/pddl/TranslatorASP.cpp @@ -84,8 +84,11 @@ void TranslatorASP::checkSupport() const std::for_each(preconditionArguments.cbegin(), preconditionArguments.cend(), [&](const auto &argument) { - if (argument->expressionType() != Expression::Type::Predicate) + if (argument->expressionType() != Expression::Type::Predicate + && argument->expressionType() != Expression::Type::Not) + { throw utils::TranslatorException("Only predicates supported in preconditions currently"); + } }); } } diff --git a/src/plasp/pddl/expressions/At.cpp b/src/plasp/pddl/expressions/At.cpp new file mode 100644 index 0000000..1a40799 --- /dev/null +++ b/src/plasp/pddl/expressions/At.cpp @@ -0,0 +1,48 @@ +#include + +namespace plasp +{ +namespace pddl +{ +namespace expressions +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// At +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +At::At() +: m_argument{nullptr} +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void At::setArgument(const Expression *argument) +{ + m_argumentStorage = nullptr; + m_argument = argument; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void At::setArgument(ExpressionPointer &&argument) +{ + m_argumentStorage = std::move(argument); + m_argument = m_argumentStorage.get(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const Expression *At::argument() const +{ + return m_argument; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} diff --git a/src/plasp/utils/Parser.cpp b/src/plasp/utils/Parser.cpp index 98f461d..c1aacc4 100644 --- a/src/plasp/utils/Parser.cpp +++ b/src/plasp/utils/Parser.cpp @@ -528,6 +528,17 @@ void Parser::expect(const bool &expectedValue) //////////////////////////////////////////////////////////////////////////////////////////////////// +bool Parser::probeNumber() +{ + while (!std::iswspace(currentCharacter())) + if (!std::isdigit(currentCharacter())) + return false; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void Parser::removeComments(const std::string &startSequence, const std::string &endSequence, bool removeEnd) { const auto inPosition = m_stream.tellg();