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

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

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();
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
// 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>(")");
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");
}
////////////////////////////////////////////////////////////////////////////////////////////////////