Refactored parsing of expressions, all classes parse from opening to closing parenthesis now.

This commit is contained in:
Patrick Lühne 2016-06-09 17:51:10 +02:00
parent 04aac10f1d
commit 9506dcb31e
19 changed files with 355 additions and 347 deletions

View File

@ -16,38 +16,17 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class And: public NAry
class And: public NAry<And>
{
public:
template<typename ExpressionParser>
static AndPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
static const std::string Identifier;
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
private:
And() = default;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
AndPointer And::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<And>(And());
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
context.logger.parserWarning(context.parser, "\"and\" expressions should not be empty");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -19,17 +19,18 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class Binary: public Expression
{
public:
template<typename ExpressionParser>
static std::unique_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
const Expression *leftArgument() const;
const Expression *rightArgument() const;
protected:
template<typename ExpressionParser>
void parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
private:
ExpressionPointer m_leftArgument;
ExpressionPointer m_rightArgument;
@ -37,14 +38,48 @@ class Binary: public Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
void Binary::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
std::unique_ptr<Derived> Binary<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.probe<std::string>("(")
|| !parser.probeIdentifier(Derived::Identifier))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Derived>();
// Assume that expression identifier (imply, exists, etc.) is already parsed
// Parse arguments of the expression
m_leftArgument = parseExpression(context, expressionContext);
m_rightArgument = parseExpression(context, expressionContext);
expression->m_leftArgument = parseExpression(context, expressionContext);
expression->m_rightArgument = parseExpression(context, expressionContext);
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const Expression *Binary<Derived>::leftArgument() const
{
return m_leftArgument.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const Expression *Binary<Derived>::rightArgument() const
{
return m_rightArgument.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -16,38 +16,17 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Either: public NAry
class Either: public NAry<Either>
{
public:
template<typename ExpressionParser>
static EitherPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
static const std::string Identifier;
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
private:
Either() = default;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
EitherPointer Either::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Either>(Either());
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
throw ConsistencyException("\"and\" expressions should not be empty");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -16,35 +16,17 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Imply: public Binary
class Imply: public Binary<Imply>
{
public:
template<typename ExpressionParser>
static ImplyPointer parse(Context &context, ExpressionContext &parameters,
ExpressionParser parseExpression);
static const std::string Identifier;
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
private:
Imply() = default;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
ImplyPointer Imply::parse(Context &context, ExpressionContext &parameters,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Imply>(Imply());
expression->Binary::parse(context, parameters, parseExpression);
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -19,14 +19,16 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class NAry: public Expression
{
public:
const Expressions &arguments() const;
protected:
template<typename ExpressionParser>
void parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression);
static std::unique_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
const Expressions &arguments() const;
private:
Expressions m_arguments;
@ -34,19 +36,49 @@ class NAry: public Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
void NAry::parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression)
std::unique_ptr<Derived> NAry<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
context.parser.skipWhiteSpace();
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.probe<std::string>("(")
|| !parser.probeIdentifier(Derived::Identifier))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Derived>();
parser.skipWhiteSpace();
// Assume that expression identifier (and, or, etc.) is already parsed
// Parse arguments of the expression
while (context.parser.currentCharacter() != ')')
while (parser.currentCharacter() != ')')
{
m_arguments.emplace_back(parseExpression(context, expressionContext));
expression->m_arguments.emplace_back(parseExpression(context, expressionContext));
context.parser.skipWhiteSpace();
parser.skipWhiteSpace();
}
if (expression->m_arguments.empty())
context.logger.parserWarning(context.parser, "\"" + Derived::Identifier + "\" expressions should not be empty");
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const Expressions &NAry<Derived>::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -30,8 +30,6 @@ class Not: public Expression
const Expression &argument() const;
private:
Not() = default;
ExpressionPointer m_argument;
};
@ -41,6 +39,17 @@ template<typename ExpressionParser>
NotPointer Not::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.probe<std::string>("(")
|| !parser.probeIdentifier("not"))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Not>(Not());
context.parser.skipWhiteSpace();
@ -48,6 +57,8 @@ NotPointer Not::parse(Context &context, ExpressionContext &expressionContext,
// Parse argument
expression->m_argument = parseExpression(context, expressionContext);
parser.expect<std::string>(")");
return expression;
}

View File

@ -16,38 +16,17 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Or: public NAry
class Or: public NAry<Or>
{
public:
template<typename ExpressionParser>
static OrPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
static const std::string Identifier;
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
private:
Or() = default;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
OrPointer Or::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Or>(Or());
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
throw ConsistencyException("\"or\" expressions should not be empty");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -19,9 +19,8 @@ namespace expressions
class Predicate: public Expression
{
public:
static PredicatePointer parse(std::string name, Context &context,
ExpressionContext &expressionContext);
static PredicatePointer parse(std::string name, Context &context, const Problem &problem);
static PredicatePointer parse(Context &context, ExpressionContext &expressionContext);
static PredicatePointer parse(Context &context, const Problem &problem);
public:
void accept(ExpressionVisitor &expressionVisitor) const override;

View File

@ -42,9 +42,9 @@ void Action::parseDeclaration(Context &context, Domain &domain)
{
context.parser.expect<std::string>(":");
if (context.parser.probe<std::string>("precondition"))
if (context.parser.probeIdentifier("precondition"))
action->m_precondition = parsePreconditionExpression(context, expressionContext);
else if (context.parser.probe<std::string>("effect"))
else if (context.parser.probeIdentifier("effect"))
action->m_effect = parseEffectExpression(context, expressionContext);
context.parser.skipWhiteSpace();

View File

@ -26,10 +26,7 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier, Context &context,
ExpressionContext &expressionContext);
ExpressionPointer parseEffectBodyExpressionContent(const std::string &expressionIdentifier,
Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -45,194 +42,187 @@ inline void warnUnsupported(Context &context, const std::string &expressionIdent
ExpressionPointer parsePreconditionExpression(Context &context,
ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
auto &parser = context.parser;
const auto expressionIdentifier = context.parser.parseIdentifier(isIdentifier);
parser.skipWhiteSpace();
ExpressionPointer expression;
if (expressionIdentifier == "and")
{
expression = expressions::And::parse(context, expressionContext,
parsePreconditionExpression);
}
else if (expressionIdentifier == "forall"
|| expressionIdentifier == "preference")
if ((expression = expressions::And::parse(context, expressionContext, parsePreconditionExpression)))
return expression;
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("forall")
|| parser.probeIdentifier("preference"))
{
// TODO: refactor
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
warnUnsupported(context, expressionIdentifier);
skipSection(parser);
return nullptr;
}
else
expression = parseExpressionContent(expressionIdentifier, context, expressionContext);
context.parser.expect<std::string>(")");
return expression;
parser.seek(position);
return parseExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
auto &parser = context.parser;
const auto expressionIdentifier = context.parser.parseIdentifier(isIdentifier);
parser.skipWhiteSpace();
auto expression = parseExpressionContent(expressionIdentifier, context, expressionContext);
ExpressionPointer expression;
context.parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier, Context &context,
ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();
if (expressionIdentifier == "and")
return expressions::And::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "or")
return expressions::Or::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "not")
return expressions::Not::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "imply")
return expressions::Imply::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "exists"
|| expressionIdentifier == "forall"
|| expressionIdentifier == "-"
|| expressionIdentifier == "="
|| expressionIdentifier == "*"
|| expressionIdentifier == "+"
|| expressionIdentifier == "-"
|| expressionIdentifier == "/"
|| expressionIdentifier == ">"
|| expressionIdentifier == "<"
|| expressionIdentifier == "="
|| expressionIdentifier == ">="
|| expressionIdentifier == "<=")
if ((expression = expressions::And::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Or::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Not::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Imply::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("exists")
|| parser.probeIdentifier("forall")
|| parser.probeIdentifier("-")
|| parser.probeIdentifier("=")
|| parser.probeIdentifier("*")
|| parser.probeIdentifier("+")
|| parser.probeIdentifier("-")
|| parser.probeIdentifier("/")
|| parser.probeIdentifier(">")
|| parser.probeIdentifier("<")
|| parser.probeIdentifier("=")
|| parser.probeIdentifier(">=")
|| parser.probeIdentifier("<="))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
warnUnsupported(context, expressionIdentifier);
skipSection(parser);
return nullptr;
}
auto &predicateDeclarations = expressionContext.domain.predicates();
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
// Check if predicate with that name exists
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == expressionIdentifier;
});
// If predicate exists, parse it
if (match != predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, expressionContext);
throw utils::ParserException(context.parser, "Unknown expression \"" + expressionIdentifier + "\"");
parser.seek(position);
throw utils::ParserException(context.parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectExpression(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
const auto expressionIdentifier = context.parser.parseIdentifier(isIdentifier);
auto &parser = context.parser;
ExpressionPointer expression;
if (expressionIdentifier == "and")
expression = expressions::And::parse(context, expressionContext, parseEffectExpression);
else if (expressionIdentifier == "forall"
|| expressionIdentifier == "when")
if ((expression = expressions::And::parse(context, expressionContext, parseEffectExpression)))
return expression;
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("forall")
|| parser.probeIdentifier("when"))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
warnUnsupported(context, expressionIdentifier);
skipSection(parser);
return nullptr;
}
else
expression = parseEffectBodyExpressionContent(expressionIdentifier, context, expressionContext);
context.parser.expect<std::string>(")");
return expression;
parser.seek(position);
return parseEffectBodyExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectBodyExpressionContent(const std::string &expressionIdentifier,
Context &context, ExpressionContext &expressionContext)
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
ExpressionPointer expression;
if (expressionIdentifier == "not")
return expressions::Not::parse(context, expressionContext, parsePredicate);
if (expressionIdentifier == "="
|| expressionIdentifier == "assign"
|| expressionIdentifier == "scale-up"
|| expressionIdentifier == "scale-down"
|| expressionIdentifier == "increase"
|| expressionIdentifier == "decrease")
if ((expression = expressions::Not::parse(context, expressionContext, parsePredicate))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("=")
|| parser.probeIdentifier("assign")
|| parser.probeIdentifier("scale-up")
|| parser.probeIdentifier("scale-down")
|| parser.probeIdentifier("increase")
|| parser.probeIdentifier("decrease"))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
warnUnsupported(context, expressionIdentifier);
skipSection(parser);
return nullptr;
}
const auto &predicateDeclarations = expressionContext.domain.predicates();
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
// Check if predicate with that name exists
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == expressionIdentifier;
});
// If predicate exists, parse it
if (match != predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, expressionContext);
throw utils::ParserException(context.parser, "Expression \"" + expressionIdentifier + "\" not allowed in this context");
parser.seek(position);
throw utils::ParserException(context.parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
const auto predicateName = context.parser.parseIdentifier(isIdentifier);
ExpressionPointer expression;
const auto &predicateDeclarations = expressionContext.domain.predicates();
// Check if predicate with that name exists
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
// If predicate exists, parse it
if (match == predicateDeclarations.cend())
throw utils::ParserException(context.parser, "Unknown predicate \"" + predicateName + "\"");
expression = expressions::Predicate::parse(predicateName, context, expressionContext);
context.parser.expect<std::string>(")");
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
throw utils::ParserException(context.parser, "Expected predicate");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -27,31 +27,54 @@ inline void warnUnsupported(Context &context, const std::string &expressionIdent
std::unique_ptr<InitialState> InitialState::parseDeclaration(Context &context, const Problem &problem)
{
auto &parser = context.parser;
auto initialState = std::make_unique<InitialState>(InitialState());
const auto parseInitialStateElement =
[&]()
{
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, problem)))
return expression;
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("at")
|| parser.probeIdentifier("=")
|| parser.probeIdentifier("not"))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
warnUnsupported(context, expressionIdentifier);
return ExpressionPointer();
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(context.parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
};
parser.skipWhiteSpace();
while (context.parser.currentCharacter() != ')')
{
context.parser.expect<std::string>("(");
ExpressionPointer expression;
const auto expressionIdentifier = context.parser.parseIdentifier(isIdentifier);
if ((expression = parseInitialStateElement()))
initialState->m_facts.emplace_back(std::move(expression));
if (expressionIdentifier == "at"
|| expressionIdentifier == "="
|| expressionIdentifier == "not")
{
warnUnsupported(context, expressionIdentifier);
continue;
}
// If none of the above types apply, the content is a predicate over constants and objects
initialState->m_facts.emplace_back(expressions::Predicate::parse(expressionIdentifier, context, problem));
context.parser.expect<std::string>(")");
context.parser.skipWhiteSpace();
parser.skipWhiteSpace();
}
return initialState;

View File

@ -15,6 +15,10 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string And::Identifier = "and";
////////////////////////////////////////////////////////////////////////////////////////////////////
void And::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const
{
expressionVisitor.visit(*this);

View File

@ -1,38 +0,0 @@
#include <plasp/pddl/expressions/Binary.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Binary
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Binary::leftArgument() const
{
return m_leftArgument.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Binary::rightArgument() const
{
return m_rightArgument.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -15,6 +15,10 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Either::Identifier = "either";
////////////////////////////////////////////////////////////////////////////////////////////////////
void Either::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const
{
expressionVisitor.visit(*this);

View File

@ -15,6 +15,10 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Imply::Identifier = "imply";
////////////////////////////////////////////////////////////////////////////////////////////////////
void Imply::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const
{
expressionVisitor.visit(*this);

View File

@ -1,31 +0,0 @@
#include <plasp/pddl/expressions/NAry.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NAry
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expressions &NAry::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -15,6 +15,10 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Or::Identifier = "or";
////////////////////////////////////////////////////////////////////////////////////////////////////
void Or::accept(plasp::pddl::ExpressionVisitor &expressionVisitor) const
{
expressionVisitor.visit(*this);

View File

@ -5,6 +5,7 @@
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/Reference.h>
#include <plasp/pddl/expressions/Variable.h>
@ -29,12 +30,36 @@ Predicate::Predicate()
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(std::string name, Context &context,
ExpressionContext &expressionContext)
PredicatePointer Predicate::parse(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.probe<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier(isIdentifier);
const auto &predicates = expressionContext.domain.predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
parser.seek(position);
return nullptr;
}
auto predicate = std::make_unique<Predicate>(Predicate());
predicate->m_name = name;
predicate->m_name = predicateName;
context.parser.skipWhiteSpace();
@ -63,16 +88,43 @@ PredicatePointer Predicate::parse(std::string name, Context &context,
// TODO: check that signature matches one of the declared ones
parser.expect<std::string>(")");
return predicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(std::string name, Context &context, const Problem &problem)
PredicatePointer Predicate::parse(Context &context, const Problem &problem)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.probe<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier(isIdentifier);
const auto &predicates = problem.domain().predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
parser.seek(position);
return nullptr;
}
auto predicate = std::make_unique<Predicate>(Predicate());
predicate->m_name = name;
predicate->m_name = predicateName;
context.parser.skipWhiteSpace();

View File

@ -65,6 +65,7 @@ void Variable::parseDeclaration(Context &context, Variables &parameters)
void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
auto &variables = expressionContext.parameters;
// Parse and store variable itself
@ -72,10 +73,10 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
auto &variable = variables.back();
context.parser.skipWhiteSpace();
parser.skipWhiteSpace();
// Check if the variable has a type declaration
if (!context.parser.probe('-'))
if (!parser.probe('-'))
return;
const auto setType =
@ -93,18 +94,11 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
});
};
context.parser.skipWhiteSpace();
parser.skipWhiteSpace();
// Parse argument of "either" type (always begins with opening parenthesis)
if (context.parser.currentCharacter() == '(')
if ((variable->m_eitherExpression = Either::parse(context, expressionContext, parseExistingPrimitiveType)))
{
context.parser.expect<std::string>("(");
context.parser.expect<std::string>("either");
variable->m_eitherExpression = Either::parse(context, expressionContext, parseExistingPrimitiveType);
context.parser.expect<std::string>(")");
setType(variable->m_eitherExpression.get());
return;
}
@ -119,9 +113,15 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expressionContext)
{
while (context.parser.currentCharacter() != ')')
auto &parser = context.parser;
while (parser.currentCharacter() != ')')
{
parseTypedDeclaration(context, expressionContext);
parser.skipWhiteSpace();
}
if (expressionContext.parameters.empty())
return;
@ -133,7 +133,7 @@ void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expre
expressionContext.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (expressionContext.hasRequirement(Requirement::Type::Typing))
throw utils::ParserException(context.parser, "Variable has undeclared type");
throw utils::ParserException(parser, "Variable has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////