#ifndef __PLASP__PDDL__EXPRESSIONS__QUANTIFIED_H #define __PLASP__PDDL__EXPRESSIONS__QUANTIFIED_H #include #include #include #include #include namespace plasp { namespace pddl { namespace expressions { //////////////////////////////////////////////////////////////////////////////////////////////////// // // Quantified // //////////////////////////////////////////////////////////////////////////////////////////////////// class Quantified: public Expression { public: void setArgument(ExpressionPointer argument); ExpressionPointer argument() const; Variables &variables(); const Variables &variables() const; protected: Variables m_variables; ExpressionPointer m_argument; }; //////////////////////////////////////////////////////////////////////////////////////////////////// template class QuantifiedCRTP: public Quantified { public: template static boost::intrusive_ptr parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression); public: Type expressionType() const override final { return Derived::ExpressionType; } ExpressionPointer copy() override; ExpressionPointer reduced() override; ExpressionPointer existentiallyQuantified() override; ExpressionPointer simplified() override; ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override; void collectParameters(std::set ¶meters) override; void print(std::ostream &ostream) const override; }; //////////////////////////////////////////////////////////////////////////////////////////////////// template template boost::intrusive_ptr QuantifiedCRTP::parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression) { auto &tokenizer = context.tokenizer; const auto position = tokenizer.position(); if (!tokenizer.testAndSkip("(") || !tokenizer.testIdentifierAndSkip(Derived::Identifier)) { tokenizer.seek(position); return nullptr; } auto expression = boost::intrusive_ptr(new Derived); // Parse variable list tokenizer.expect("("); Variable::parseTypedDeclarations(context, expressionContext, expression->m_variables); tokenizer.expect(")"); // Push newly parsed variables to the stack expressionContext.variables.push(&expression->m_variables); // Parse argument of the expression expression->Quantified::setArgument(parseExpression(context, expressionContext)); // Clean up variable stack expressionContext.variables.pop(); tokenizer.expect(")"); return expression; } //////////////////////////////////////////////////////////////////////////////////////////////////// template ExpressionPointer QuantifiedCRTP::copy() { auto result = new Derived; result->m_argument = m_argument->copy(); return result; } //////////////////////////////////////////////////////////////////////////////////////////////////// inline void Quantified::setArgument(ExpressionPointer expression) { m_argument = expression; } //////////////////////////////////////////////////////////////////////////////////////////////////// inline ExpressionPointer Quantified::argument() const { return m_argument; } //////////////////////////////////////////////////////////////////////////////////////////////////// inline Variables &Quantified::variables() { return m_variables; } //////////////////////////////////////////////////////////////////////////////////////////////////// inline const Variables &Quantified::variables() const { return m_variables; } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline ExpressionPointer QuantifiedCRTP::reduced() { BOOST_ASSERT(m_argument); m_argument = m_argument->reduced(); // Child quantifiers may not move before this quantifier, the order matters return this; } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline ExpressionPointer QuantifiedCRTP::existentiallyQuantified() { BOOST_ASSERT(m_argument); m_argument = m_argument->existentiallyQuantified(); return this; } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline ExpressionPointer QuantifiedCRTP::simplified() { BOOST_ASSERT(m_argument); m_argument = m_argument->simplified(); // Associate same-type children, such as (forall (?x) (forall (?y) (...))) if (m_argument->expressionType() != Derived::ExpressionType) return this; auto &quantifiedExpression = m_argument->template as(); // Unify variables m_variables.insert(m_variables.end(), quantifiedExpression.variables().begin(), quantifiedExpression.variables().end()); // Move child expression up m_argument = quantifiedExpression.argument(); // TODO: introduce/handle boolean values return this; } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline ExpressionPointer QuantifiedCRTP::decomposed(DerivedPredicates &derivedPredicates) { derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size())); auto derivedPredicate = derivedPredicates.back(); m_argument = m_argument->decomposed(derivedPredicates); derivedPredicate->setPreconditions({{this}}); return derivedPredicate; } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline void QuantifiedCRTP::collectParameters(std::set ¶meters) { m_argument->collectParameters(parameters); // Remove bound variables for (const auto &variable : m_variables) parameters.erase(variable); } //////////////////////////////////////////////////////////////////////////////////////////////////// template inline void QuantifiedCRTP::print(std::ostream &ostream) const { ostream << "(" << Derived::Identifier << " ("; for (size_t i = 0; i < m_variables.size(); i++) { if (i > 0) ostream << " "; m_variables[i]->print(ostream); } ostream << ") "; m_argument->print(ostream); ostream << ")"; } //////////////////////////////////////////////////////////////////////////////////////////////////// } } } #endif