patrick
/
plasp
Archived
1
0
Fork 0

Refactoring to make parsing expressions consistent across PDDL domains and problems.

This commit is contained in:
Patrick Lühne 2016-06-07 13:26:19 +02:00
parent d5fa00a4a4
commit b612122180
32 changed files with 458 additions and 221 deletions

View File

@ -21,7 +21,7 @@ namespace pddl
class Action
{
public:
static Action &parseDeclaration(Context &context);
static void parseDeclaration(Context &context, Domain &domain);
public:
const std::string &name() const;

View File

@ -5,11 +5,6 @@
#include <unordered_map>
#include <vector>
#include <plasp/pddl/Action.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/utils/Logger.h>
namespace plasp
@ -33,17 +28,6 @@ class Context
utils::Parser &parser;
utils::Logger logger;
expressions::PrimitiveTypes primitiveTypes;
//std::unordered_map<std::string, expressions::PrimitiveType *> primitiveTypesHashMap;
expressions::Constants constants;
//std::unordered_map<std::string, expressions::Constant *> constantsHashMap;
expressions::PredicateDeclarations predicateDeclarations;
//std::unordered_map<expressions::PredicateHashMapKey, expressions::Predicate *> predicatesHashMap;
std::vector<std::unique_ptr<Action>> actions;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -33,6 +33,8 @@ class Description
void parseContent();
void parseSection();
void checkConsistency();
utils::Parser m_parser;
Context m_context;

View File

@ -1,8 +1,12 @@
#ifndef __PLASP__PDDL__DOMAIN_H
#define __PLASP__PDDL__DOMAIN_H
#include <plasp/pddl/Action.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/Requirement.h>
namespace plasp
@ -19,19 +23,32 @@ namespace pddl
class Domain
{
public:
static Domain fromPDDL(Context &context);
public:
const std::string &name() const;
const Requirements &requirements() const;
const expressions::PrimitiveTypes &types() const;
const expressions::Constants &constants() const;
const expressions::PredicateDeclarations &predicates() const;
const std::vector<std::unique_ptr<Action>> &actions() const;
private:
Domain(Context &context);
public:
void readPDDL();
bool isDeclared() const;
const std::string &name() const;
const Requirements &requirements() const;
expressions::PrimitiveTypes &types();
const expressions::PrimitiveTypes &types() const;
expressions::Constants &constants();
const expressions::Constants &constants() const;
expressions::PredicateDeclarations &predicates();
const expressions::PredicateDeclarations &predicates() const;
std::vector<std::unique_ptr<Action>> &actions();
const std::vector<std::unique_ptr<Action>> &actions() const;
void checkConsistency();
private:
void parseSection();
void parseRequirementSection();
@ -46,12 +63,15 @@ class Domain
void parseActionSection();
void checkConsistency();
Context &m_context;
bool m_isDeclared;
std::string m_name;
Requirements m_requirements;
expressions::PrimitiveTypes m_primitiveTypes;
expressions::Constants m_constants;
expressions::PredicateDeclarations m_predicateDeclarations;
std::vector<std::unique_ptr<Action>> m_actions;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -17,7 +17,10 @@ namespace pddl
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
class Domain;
class ExpressionContext;
class ExpressionVisitor;
class Problem;
class Expression;
using ExpressionPointer = std::unique_ptr<Expression>;
@ -77,10 +80,11 @@ class Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePreconditionExpression(Context &context,
const expressions::Variables &parameters);
ExpressionPointer parseExpression(Context &context, const expressions::Variables &parameters);
ExpressionContext &expressionContext);
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseEffectExpression(Context &context, const expressions::Variables &parameters);
ExpressionPointer parseEffectExpression(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,46 @@
#ifndef __PLASP__PDDL__EXPRESSION_CONTEXT_H
#define __PLASP__PDDL__EXPRESSION_CONTEXT_H
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Requirement.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ExpressionContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ExpressionContext
{
public:
ExpressionContext(Domain &domain, expressions::Variables &parameters)
: domain(domain),
problem(nullptr),
parameters(parameters)
{
}
ExpressionContext(Domain &domain, Problem *problem, expressions::Variables &parameters)
: domain(domain),
problem{problem},
parameters(parameters)
{
}
Domain &domain;
Problem *problem;
expressions::Variables &parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -19,15 +19,25 @@ namespace pddl
class Problem
{
public:
static Problem fromPDDL(Context &context);
Problem(Context &context, Domain &domain);
void readPDDL();
bool isDeclared() const;
Domain &domain();
const Domain &domain() const;
public:
const std::string &name() const;
const Requirements &requirements() const;
private:
Problem(Context &context);
expressions::Constants &objects();
const expressions::Constants &objects() const;
void checkConsistency();
private:
void parseSection();
void parseRequirementSection();
@ -36,9 +46,9 @@ class Problem
void parseObjectSection();
void checkConsistency();
Context &m_context;
Domain &m_domain;
bool m_isDeclared;
std::string m_name;
Requirements m_requirements;

View File

@ -20,7 +20,7 @@ class And: public NAry
{
public:
template<typename ExpressionParser>
static AndPointer parse(Context &context, const Variables &parameters,
static AndPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
@ -33,12 +33,12 @@ class And: public NAry
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
AndPointer And::parse(Context &context, const Variables &parameters,
AndPointer And::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<And>(And());
expression->NAry::parse(context, parameters, parseExpression);
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
throw ConsistencyException("\"and\" expressions should not be empty");

View File

@ -27,7 +27,8 @@ class Binary: public Expression
protected:
template<typename ExpressionParser>
void parse(Context &context, const Variables &parameters, ExpressionParser parseExpression);
void parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
private:
ExpressionPointer m_leftArgument;
@ -37,12 +38,13 @@ class Binary: public Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
void Binary::parse(Context &context, const Variables &parameters, ExpressionParser parseExpression)
void Binary::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
// Assume that expression identifier (imply, exists, etc.) is already parsed
// Parse arguments of the expression
m_leftArgument = parseExpression(context, parameters);
m_rightArgument = parseExpression(context, parameters);
m_leftArgument = parseExpression(context, expressionContext);
m_rightArgument = parseExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -22,10 +22,10 @@ namespace expressions
class Constant: public Expression
{
public:
static ConstantPointer parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context, Constants &constants);
static void parseTypedDeclaration(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Problem &problem);
static Constant *parseExisting(Context &context);
static Constant *parseAndFind(Context &context, const ExpressionContext &expressionContext);
// TODO: method for lazy creation if not existing
@ -38,6 +38,11 @@ class Constant: public Expression
bool isDeclared() const;
private:
static ConstantPointer parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context, Domain &domain, Constants &constants);
static Constant *parseAndFind(const std::string &constantName, const Constants &constants);
Constant();
void setDirty(bool isDirty = true);

View File

@ -20,7 +20,7 @@ class Either: public NAry
{
public:
template<typename ExpressionParser>
static EitherPointer parse(Context &context, const Variables &parameters,
static EitherPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
@ -33,12 +33,12 @@ class Either: public NAry
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
EitherPointer Either::parse(Context &context, const Variables &parameters,
EitherPointer Either::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Either>(Either());
expression->NAry::parse(context, parameters, parseExpression);
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
throw ConsistencyException("\"and\" expressions should not be empty");

View File

@ -20,7 +20,7 @@ class Imply: public Binary
{
public:
template<typename ExpressionParser>
static ImplyPointer parse(Context &context, const Variables &parameters,
static ImplyPointer parse(Context &context, ExpressionContext &parameters,
ExpressionParser parseExpression);
public:
@ -33,7 +33,7 @@ class Imply: public Binary
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
ImplyPointer Imply::parse(Context &context, const Variables &parameters,
ImplyPointer Imply::parse(Context &context, ExpressionContext &parameters,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Imply>(Imply());

View File

@ -26,7 +26,7 @@ class NAry: public Expression
protected:
template<typename ExpressionParser>
void parse(Context &context, const Variables &parameters, ExpressionParser parseExpression);
void parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression);
private:
Expressions m_arguments;
@ -35,7 +35,7 @@ class NAry: public Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
void NAry::parse(Context &context, const Variables &parameters, ExpressionParser parseExpression)
void NAry::parse(Context &context, ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
context.parser.skipWhiteSpace();
@ -43,7 +43,7 @@ void NAry::parse(Context &context, const Variables &parameters, ExpressionParser
// Parse arguments of the expression
while (context.parser.currentCharacter() != ')')
{
m_arguments.emplace_back(parseExpression(context, parameters));
m_arguments.emplace_back(parseExpression(context, expressionContext));
context.parser.skipWhiteSpace();
}

View File

@ -21,7 +21,7 @@ class Not: public Expression
{
public:
template<typename ExpressionParser>
static NotPointer parse(Context &context, const Variables &parameters,
static NotPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
@ -38,7 +38,7 @@ class Not: public Expression
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
NotPointer Not::parse(Context &context, const Variables &parameters,
NotPointer Not::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Not>(Not());
@ -46,7 +46,7 @@ NotPointer Not::parse(Context &context, const Variables &parameters,
context.parser.skipWhiteSpace();
// Parse argument
expression->m_argument = parseExpression(context, parameters);
expression->m_argument = parseExpression(context, expressionContext);
return expression;
}

View File

@ -20,7 +20,7 @@ class Or: public NAry
{
public:
template<typename ExpressionParser>
static OrPointer parse(Context &context, const Variables &parameters,
static OrPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
@ -33,11 +33,12 @@ class Or: public NAry
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
OrPointer Or::parse(Context &context, const Variables &parameters, ExpressionParser parseExpression)
OrPointer Or::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto expression = std::make_unique<Or>(Or());
expression->NAry::parse(context, parameters, parseExpression);
expression->NAry::parse(context, expressionContext, parseExpression);
if (expression->arguments().empty())
throw ConsistencyException("\"or\" expressions should not be empty");

View File

@ -20,7 +20,7 @@ class Predicate: public Expression
{
public:
static PredicatePointer parse(std::string name, Context &context,
const Variables &parameters);
ExpressionContext &expressionContext);
public:
void accept(ExpressionVisitor &expressionVisitor) const override;

View File

@ -19,7 +19,7 @@ namespace expressions
class PredicateDeclaration: public Expression
{
public:
static void parse(Context &context);
static void parse(Context &context, Domain &domain);
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
@ -37,7 +37,7 @@ class PredicateDeclaration: public Expression
bool m_isDeclared;
std::string m_name;
Variables m_arguments;
Variables m_parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -22,12 +22,15 @@ namespace expressions
class PrimitiveType: public Expression
{
public:
static PrimitiveType *parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context);
static void parseDeclaration(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Domain &domain);
static PrimitiveType *parseExisting(Context &context);
static PrimitiveType *parseAndFindOrCreate(Context &context, Domain &domain);
public:
PrimitiveType();
PrimitiveType(std::string name);
void accept(ExpressionVisitor &expressionVisitor) const override;
const std::string &name() const;
@ -36,11 +39,6 @@ class PrimitiveType: public Expression
bool isDeclared() const;
private:
static PrimitiveType *create(std::string name, Context &context);
private:
PrimitiveType();
void setDirty(bool isDirty = true);
bool isDirty() const;

View File

@ -16,7 +16,8 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExistingPrimitiveType(Context &context, const Variables &parameters);
ExpressionPointer parseExistingPrimitiveType(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -19,11 +19,9 @@ namespace expressions
class Variable: public Expression
{
public:
static VariablePointer parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context, ExpressionContext &expressionContext);
static void parseTypedDeclaration(Context &context, Variables &parameters);
static const Variable *parseExisting(Context &context, const Variables &variables);
static const Variable *parseAndFind(Context &context, const ExpressionContext &expressionContext);
public:
void accept(ExpressionVisitor &expressionVisitor) const override;
@ -36,6 +34,9 @@ class Variable: public Expression
void setType(const Expression *type);
private:
static void parseDeclaration(Context &context, Variables &parameters);
private:
Variable();

View File

@ -3,6 +3,8 @@
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Type.h>
#include <plasp/utils/IO.h>
@ -26,20 +28,21 @@ Action::Action(std::string name)
////////////////////////////////////////////////////////////////////////////////////////////////////
Action &Action::parseDeclaration(Context &context)
void Action::parseDeclaration(Context &context, Domain &domain)
{
const auto actionName = context.parser.parseIdentifier(isIdentifier);
auto action = std::make_unique<Action>(Action(actionName));
context.parser.expect<std::string>(":parameters");
context.parser.expect<std::string>("(");
ExpressionContext expressionContext(domain, action->m_parameters);
// Read parameters
while (context.parser.currentCharacter() != ')')
{
expressions::Variable::parseTypedDeclaration(context, action->m_parameters);
expressions::Variable::parseTypedDeclaration(context, expressionContext);
context.parser.skipWhiteSpace();
}
@ -54,17 +57,15 @@ Action &Action::parseDeclaration(Context &context)
const auto sectionIdentifier = context.parser.parseIdentifier(isIdentifier);
if (sectionIdentifier == "precondition")
action->m_precondition = parsePreconditionExpression(context, action->m_parameters);
action->m_precondition = parsePreconditionExpression(context, expressionContext);
else if (sectionIdentifier == "effect")
action->m_effect = parseEffectExpression(context, action->m_parameters);
action->m_effect = parseEffectExpression(context, expressionContext);
context.parser.skipWhiteSpace();
}
// Store new action
context.actions.emplace_back(std::move(action));
return *context.actions.back();
expressionContext.domain.actions().emplace_back(std::move(action));
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -31,6 +31,9 @@ Description Description::fromStream(std::istream &istream)
{
Description description(istream);
description.m_domain = std::make_unique<Domain>(Domain(description.m_context));
description.m_problem = std::make_unique<Problem>(Problem(description.m_context, *description.m_domain));
while (true)
{
description.m_context.parser.skipWhiteSpace();
@ -41,6 +44,8 @@ Description Description::fromStream(std::istream &istream)
description.parseContent();
}
description.checkConsistency();
return description;
}
@ -89,14 +94,36 @@ void Description::parseSection()
std::cout << "Parsing section " << sectionIdentifier << std::endl;
if (sectionIdentifier == "domain")
m_domain = std::make_unique<Domain>(Domain::fromPDDL(m_context));
{
BOOST_ASSERT(m_domain);
if (m_domain->isDeclared())
throw utils::ParserException(m_context.parser, "PDDL description may not contain two domains");
m_domain->readPDDL();
}
else if (sectionIdentifier == "problem")
m_problem = std::make_unique<Problem>(Problem::fromPDDL(m_context));
{
BOOST_ASSERT(m_problem);
if (m_problem->isDeclared())
throw utils::ParserException(m_context.parser, "PDDL description may currently not contain two problems");
m_problem->readPDDL();
}
else
throw utils::ParserException(m_context.parser, "Unknown PDDL section \"" + sectionIdentifier + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::checkConsistency()
{
m_domain->checkConsistency();
m_problem->checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -23,37 +23,41 @@ namespace pddl
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain::Domain(Context &context)
: m_context(context)
: m_context(context),
m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain Domain::fromPDDL(Context &context)
void Domain::readPDDL()
{
Domain domain(context);
m_name = m_context.parser.parseIdentifier(isIdentifier);
domain.m_name = context.parser.parseIdentifier(isIdentifier);
std::cout << "Parsing domain " << m_name << std::endl;
std::cout << "Parsing domain " << domain.m_name << std::endl;
context.parser.expect<std::string>(")");
m_context.parser.expect<std::string>(")");
while (true)
{
context.parser.skipWhiteSpace();
m_context.parser.skipWhiteSpace();
if (context.parser.currentCharacter() == ')')
if (m_context.parser.currentCharacter() == ')')
break;
domain.parseSection();
parseSection();
}
domain.computeDerivedRequirements();
computeDerivedRequirements();
domain.checkConsistency();
m_isDeclared = true;
}
return domain;
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Domain::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -72,30 +76,58 @@ const Requirements &Domain::requirements() const
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PrimitiveTypes &Domain::types()
{
return m_primitiveTypes;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PrimitiveTypes &Domain::types() const
{
return m_context.primitiveTypes;
return m_primitiveTypes;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Domain::constants()
{
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Domain::constants() const
{
return m_context.constants;
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PredicateDeclarations &Domain::predicates()
{
return m_predicateDeclarations;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PredicateDeclarations &Domain::predicates() const
{
return m_context.predicateDeclarations;
return m_predicateDeclarations;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<std::unique_ptr<Action>> &Domain::actions()
{
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<std::unique_ptr<Action>> &Domain::actions() const
{
return m_context.actions;
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -242,7 +274,7 @@ void Domain::parseTypeSection()
if (m_context.parser.currentCharacter() == '(')
throw utils::ParserException(m_context.parser, "Only primitive types are allowed in type section");
expressions::PrimitiveType::parseTypedDeclaration(m_context);
expressions::PrimitiveType::parseTypedDeclaration(m_context, *this);
m_context.parser.skipWhiteSpace();
}
@ -259,7 +291,7 @@ void Domain::parseConstantSection()
// Store constants
while (m_context.parser.currentCharacter() != ')')
{
expressions::Constant::parseTypedDeclaration(m_context, m_context.constants);
expressions::Constant::parseTypedDeclaration(m_context, *this);
m_context.parser.skipWhiteSpace();
}
@ -276,7 +308,7 @@ void Domain::parsePredicateSection()
// Store predicates and their arguments
while (m_context.parser.currentCharacter() != ')')
{
expressions::PredicateDeclaration::parse(m_context);
expressions::PredicateDeclaration::parse(m_context, *this);
m_context.parser.skipWhiteSpace();
}
@ -290,7 +322,7 @@ void Domain::parseActionSection()
{
m_context.parser.skipWhiteSpace();
Action::parseDeclaration(m_context);
Action::parseDeclaration(m_context, *this);
m_context.parser.expect<std::string>(")");
}
@ -300,7 +332,7 @@ void Domain::parseActionSection()
void Domain::checkConsistency()
{
// Verify that typing requirement is correctly declared if used
if (!m_context.primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing))
if (!m_primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing))
{
throw ConsistencyException("Domain contains typing information but does not declare typing requirement");
@ -308,7 +340,7 @@ void Domain::checkConsistency()
}
// Verify that all used types have been declared
std::for_each(m_context.primitiveTypes.cbegin(), m_context.primitiveTypes.cend(),
std::for_each(m_primitiveTypes.cbegin(), m_primitiveTypes.cend(),
[&](const auto &type)
{
if (!type->isDeclared())
@ -316,7 +348,7 @@ void Domain::checkConsistency()
});
// Verify that all used constants have been declared
std::for_each(m_context.constants.cbegin(), m_context.constants.cend(),
std::for_each(m_constants.cbegin(), m_constants.cend(),
[&](const auto &constant)
{
if (!constant->isDeclared())
@ -327,7 +359,7 @@ void Domain::checkConsistency()
});
// Verify that all used predicates have been declared
std::for_each(m_context.predicateDeclarations.cbegin(), m_context.predicateDeclarations.cend(),
std::for_each(m_predicateDeclarations.cbegin(), m_predicateDeclarations.cend(),
[&](const auto &predicate)
{
if (!predicate->isDeclared())

View File

@ -1,6 +1,8 @@
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Imply.h>
@ -23,15 +25,16 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier,
Context &context, const expressions::Variables &parameters);
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier, Context &context,
ExpressionContext &expressionContext);
ExpressionPointer parseEffectBodyExpressionContent(const std::string &expressionIdentifier,
Context &context, const expressions::Variables &parameters);
ExpressionPointer parsePredicate(Context &context, const expressions::Variables &parameters);
Context &context, ExpressionContext &expressionContext);
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
void throwUnsupported(const utils::Parser &parser, const std::string &expressionIdentifier)
[[noreturn]] void throwUnsupported(const utils::Parser &parser,
const std::string &expressionIdentifier)
{
throw utils::ParserException(parser, "Expression type \"" + expressionIdentifier + "\" currently unsupported in this context");
}
@ -39,7 +42,7 @@ void throwUnsupported(const utils::Parser &parser, const std::string &expression
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePreconditionExpression(Context &context,
const expressions::Variables &parameters)
ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
@ -49,7 +52,7 @@ ExpressionPointer parsePreconditionExpression(Context &context,
if (expressionIdentifier == "and")
{
expression = expressions::And::parse(context, parameters,
expression = expressions::And::parse(context, expressionContext,
parsePreconditionExpression);
}
else if (expressionIdentifier == "forall"
@ -58,7 +61,7 @@ ExpressionPointer parsePreconditionExpression(Context &context,
throwUnsupported(context.parser, expressionIdentifier);
}
else
expression = parseExpressionContent(expressionIdentifier, context, parameters);
expression = parseExpressionContent(expressionIdentifier, context, expressionContext);
context.parser.expect<std::string>(")");
@ -67,13 +70,13 @@ ExpressionPointer parsePreconditionExpression(Context &context,
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpression(Context &context, const expressions::Variables &parameters)
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
const auto expressionIdentifier = context.parser.parseIdentifier(isIdentifier);
auto expression = parseExpressionContent(expressionIdentifier, context, parameters);
auto expression = parseExpressionContent(expressionIdentifier, context, expressionContext);
context.parser.expect<std::string>(")");
@ -82,22 +85,22 @@ ExpressionPointer parseExpression(Context &context, const expressions::Variables
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier,
Context &context, const expressions::Variables &parameters)
ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier, Context &context,
ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();
if (expressionIdentifier == "and")
return expressions::And::parse(context, parameters, parseExpression);
return expressions::And::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "or")
return expressions::Or::parse(context, parameters, parseExpression);
return expressions::Or::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "not")
return expressions::Not::parse(context, parameters, parseExpression);
return expressions::Not::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "imply")
return expressions::Imply::parse(context, parameters, parseExpression);
return expressions::Imply::parse(context, expressionContext, parseExpression);
if (expressionIdentifier == "exists"
|| expressionIdentifier == "forall"
@ -116,23 +119,25 @@ ExpressionPointer parseExpressionContent(const std::string &expressionIdentifier
throwUnsupported(context.parser, expressionIdentifier);
}
auto &predicateDeclarations = expressionContext.domain.predicates();
// Check if predicate with that name exists
const auto match = std::find_if(context.predicateDeclarations.cbegin(), context.predicateDeclarations.cend(),
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == expressionIdentifier;
});
// If predicate exists, parse it
if (match != context.predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, parameters);
if (match != predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, expressionContext);
throw utils::ParserException(context.parser, "Expression \"" + expressionIdentifier + "\" not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectExpression(Context &context, const expressions::Variables &parameters)
ExpressionPointer parseEffectExpression(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
@ -141,14 +146,14 @@ ExpressionPointer parseEffectExpression(Context &context, const expressions::Var
ExpressionPointer expression;
if (expressionIdentifier == "and")
expression = expressions::And::parse(context, parameters, parseEffectExpression);
expression = expressions::And::parse(context, expressionContext, parseEffectExpression);
else if (expressionIdentifier == "forall"
|| expressionIdentifier == "when")
{
throwUnsupported(context.parser, expressionIdentifier);
}
else
expression = parseEffectBodyExpressionContent(expressionIdentifier, context, parameters);
expression = parseEffectBodyExpressionContent(expressionIdentifier, context, expressionContext);
context.parser.expect<std::string>(")");
@ -158,12 +163,12 @@ ExpressionPointer parseEffectExpression(Context &context, const expressions::Var
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectBodyExpressionContent(const std::string &expressionIdentifier,
Context &context, const expressions::Variables &parameters)
Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if (expressionIdentifier == "not")
return expressions::Not::parse(context, parameters, parsePredicate);
return expressions::Not::parse(context, expressionContext, parsePredicate);
if (expressionIdentifier == "="
|| expressionIdentifier == "assign"
@ -175,23 +180,25 @@ ExpressionPointer parseEffectBodyExpressionContent(const std::string &expression
throwUnsupported(context.parser, expressionIdentifier);
}
const auto &predicateDeclarations = expressionContext.domain.predicates();
// Check if predicate with that name exists
const auto match = std::find_if(context.predicateDeclarations.cbegin(), context.predicateDeclarations.cend(),
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == expressionIdentifier;
});
// If predicate exists, parse it
if (match != context.predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, parameters);
if (match != predicateDeclarations.cend())
return expressions::Predicate::parse(expressionIdentifier, context, expressionContext);
throw utils::ParserException(context.parser, "Expression \"" + expressionIdentifier + "\" not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePredicate(Context &context, const expressions::Variables &parameters)
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
{
context.parser.expect<std::string>("(");
@ -199,18 +206,20 @@ ExpressionPointer parsePredicate(Context &context, const expressions::Variables
ExpressionPointer expression;
const auto &predicateDeclarations = expressionContext.domain.predicates();
// Check if predicate with that name exists
const auto match = std::find_if(context.predicateDeclarations.cbegin(), context.predicateDeclarations.cend(),
const auto match = std::find_if(predicateDeclarations.cbegin(), predicateDeclarations.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
// If predicate exists, parse it
if (match == context.predicateDeclarations.cend())
if (match == predicateDeclarations.cend())
throw utils::ParserException(context.parser, "Unknown predicate \"" + predicateName + "\"");
expression = expressions::Predicate::parse(predicateName, context, parameters);
expression = expressions::Predicate::parse(predicateName, context, expressionContext);
context.parser.expect<std::string>(")");

View File

@ -3,7 +3,9 @@
#include <algorithm>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
@ -16,38 +18,57 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem::Problem(Context &context)
: m_context(context)
Problem::Problem(Context &context, Domain &domain)
: m_context(context),
m_domain(domain),
m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem Problem::fromPDDL(Context &context)
void Problem::readPDDL()
{
Problem problem(context);
m_name = m_context.parser.parseIdentifier(isIdentifier);
problem.m_name = context.parser.parseIdentifier(isIdentifier);
std::cout << "Parsing problem " << m_name << std::endl;
std::cout << "Parsing problem " << problem.m_name << std::endl;
context.parser.expect<std::string>(")");
m_context.parser.expect<std::string>(")");
while (true)
{
context.parser.skipWhiteSpace();
m_context.parser.skipWhiteSpace();
if (context.parser.currentCharacter() == ')')
if (m_context.parser.currentCharacter() == ')')
break;
problem.parseSection();
parseSection();
}
problem.computeDerivedRequirements();
computeDerivedRequirements();
problem.checkConsistency();
m_isDeclared = true;
}
return problem;
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Problem::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain &Problem::domain()
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Domain &Problem::domain() const
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -66,6 +87,20 @@ const Requirements &Problem::requirements() const
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Problem::objects()
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Problem::objects() const
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseSection()
{
m_context.parser.expect<std::string>("(");
@ -203,7 +238,7 @@ void Problem::parseObjectSection()
// Store constants
while (m_context.parser.currentCharacter() != ')')
{
expressions::Constant::parseTypedDeclaration(m_context);
//expressions::Constant::parseTypedDeclaration(m_context);
m_context.parser.skipWhiteSpace();
}

View File

@ -5,7 +5,10 @@
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
@ -50,7 +53,21 @@ ConstantPointer Constant::parseDeclaration(Context &context)
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Constants &constants)
void Constant::parseTypedDeclaration(Context &context, Domain &domain)
{
parseTypedDeclaration(context, domain, domain.constants());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Problem &problem)
{
parseTypedDeclaration(context, problem.domain(), problem.objects());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants &constants)
{
// Parse and store constant
constants.emplace_back(parseDeclaration(context));
@ -67,7 +84,7 @@ void Constant::parseTypedDeclaration(Context &context, Constants &constants)
return;
// If existing, parse and store parent type
auto *type = PrimitiveType::parseExisting(context);
auto *type = PrimitiveType::parseAndFindOrCreate(context, domain);
// Assign parent type to all types that were previously flagged
std::for_each(constants.begin(), constants.end(),
@ -83,21 +100,42 @@ void Constant::parseTypedDeclaration(Context &context, Constants &constants)
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseExisting(Context &context)
Constant *Constant::parseAndFind(Context &context, const ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();
const auto constantName = context.parser.parseIdentifier(isIdentifier);
auto *constant = parseAndFind(constantName, expressionContext.domain.constants());
if (constant)
return constant;
if (expressionContext.problem)
{
constant = parseAndFind(constantName, expressionContext.problem->objects());
if (constant)
return constant;
}
throw utils::ParserException(context.parser, "Constant \"" + constantName + "\" used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(const std::string &constantName, const Constants &constants)
{
// TODO: use hash map
const auto match = std::find_if(context.constants.cbegin(), context.constants.cend(),
const auto match = std::find_if(constants.cbegin(), constants.cend(),
[&](const auto &constant)
{
return constant->name() == constantName;
});
const auto constantExists = (match != context.constants.cend());
const auto constantExists = (match != constants.cend());
if (!constantExists)
throw utils::ParserException(context.parser, "Constant \"" + constantName + "\" used but never declared");
return nullptr;
return match->get();
}

View File

@ -1,8 +1,10 @@
#include <plasp/pddl/expressions/Type.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{

View File

@ -1,6 +1,8 @@
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Constant.h>
@ -27,7 +29,8 @@ Predicate::Predicate()
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(std::string name, Context &context, const Variables &parameters)
PredicatePointer Predicate::parse(std::string name, Context &context,
ExpressionContext &expressionContext)
{
auto predicate = std::make_unique<Predicate>(Predicate());
@ -41,14 +44,14 @@ PredicatePointer Predicate::parse(std::string name, Context &context, const Vari
// Parse variables
if (context.parser.currentCharacter() == '?')
{
const auto *variable = Variable::parseExisting(context, parameters);
const auto *variable = Variable::parseAndFind(context, expressionContext);
auto variableReference = std::make_unique<Reference<Variable>>(variable);
predicate->m_arguments.emplace_back(std::move(variableReference));
}
// Parse constants
else
{
const auto *constant = Constant::parseExisting(context);
const auto *constant = Constant::parseAndFind(context, expressionContext);
auto constantReference = std::make_unique<Reference<Constant>>(constant);
predicate->m_arguments.emplace_back(std::move(constantReference));
}

View File

@ -1,6 +1,8 @@
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Constant.h>
@ -27,7 +29,7 @@ PredicateDeclaration::PredicateDeclaration()
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::parse(Context &context)
void PredicateDeclaration::parse(Context &context, Domain &domain)
{
context.parser.expect<std::string>("(");
@ -40,18 +42,19 @@ void PredicateDeclaration::parse(Context &context)
context.parser.skipWhiteSpace();
ExpressionContext expressionContext(domain, predicate->m_parameters);
// Parse arguments
while (context.parser.currentCharacter() != ')')
{
expressions::Variable::parseTypedDeclaration(context, predicate->m_arguments);
expressions::Variable::parseTypedDeclaration(context, expressionContext);
context.parser.skipWhiteSpace();
}
context.parser.expect<std::string>(")");
// Store new predicate
context.predicateDeclarations.emplace_back(std::move(predicate));
domain.predicates().emplace_back(std::move(predicate));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -86,7 +89,7 @@ const std::string &PredicateDeclaration::name() const
const Variables &PredicateDeclaration::arguments() const
{
return m_arguments;
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -5,6 +5,8 @@
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
namespace plasp
@ -21,65 +23,61 @@ namespace expressions
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType()
: m_isDirty{false},
: m_isDirty{true},
m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType *PrimitiveType::create(std::string name, Context &context)
PrimitiveType::PrimitiveType(std::string name)
: m_isDirty{true},
m_isDeclared{false},
m_name{name}
{
// Create new primitive type if not already existing
auto type = std::make_unique<PrimitiveType>(PrimitiveType());
type->m_name = name;
BOOST_ASSERT(!type->m_name.empty());
// Flag type for potentially upcoming parent type declaration
type->setDirty();
// TODO: Store constant in hash map
context.primitiveTypes.emplace_back(std::move(type));
return context.primitiveTypes.back().get();
BOOST_ASSERT(!m_name.empty());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType *PrimitiveType::parseDeclaration(Context &context)
void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
context.parser.skipWhiteSpace();
const auto typeName = context.parser.parseIdentifier(isIdentifier);
// TODO: use hash map
const auto match = std::find_if(context.primitiveTypes.cbegin(), context.primitiveTypes.cend(),
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
// Return existing primitive type
if (match != context.primitiveTypes.cend())
if (match != types.cend())
{
auto *type = match->get();
type->setDirty();
return type;
return;
}
return create(typeName, context);
types.emplace_back(std::make_unique<PrimitiveType>(typeName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::parseTypedDeclaration(Context &context)
void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
// Parse and store type
auto *type = parseDeclaration(context);
parseDeclaration(context, domain);
auto *type = types.back().get();
// Flag type as correctly declared in the types section
type->setDeclared();
@ -91,7 +89,7 @@ void PrimitiveType::parseTypedDeclaration(Context &context)
return;
// If existing, parse and store parent type
auto *parentType = parseExisting(context);
auto *parentType = parseAndFindOrCreate(context, domain);
parentType->setDirty(false);
@ -99,7 +97,7 @@ void PrimitiveType::parseTypedDeclaration(Context &context)
parentType->setDeclared();
// Assign parent type to all types that were previously flagged
std::for_each(context.primitiveTypes.begin(), context.primitiveTypes.end(),
std::for_each(types.begin(), types.end(),
[&](auto &childType)
{
if (!childType->isDirty())
@ -112,8 +110,10 @@ void PrimitiveType::parseTypedDeclaration(Context &context)
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType *PrimitiveType::parseExisting(Context &context)
PrimitiveType *PrimitiveType::parseAndFindOrCreate(Context &context, Domain &domain)
{
auto &types = domain.types();
context.parser.skipWhiteSpace();
const auto typeName = context.parser.parseIdentifier(isIdentifier);
@ -121,19 +121,22 @@ PrimitiveType *PrimitiveType::parseExisting(Context &context)
BOOST_ASSERT(!typeName.empty());
// TODO: use hash map
const auto match = std::find_if(context.primitiveTypes.cbegin(), context.primitiveTypes.cend(),
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
if (match == context.primitiveTypes.cend())
if (match == types.cend())
{
// Primitive type "object" is implicitly declared
if (typeName != "object")
context.logger.parserWarning(context.parser, "Primitive type \"" + typeName + "\" used but never declared");
return create(typeName, context);
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
types.back()->setDeclared();
return types.back().get();
}
auto *type = match->get();

View File

@ -1,6 +1,8 @@
#include <plasp/pddl/expressions/Type.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Reference.h>
namespace plasp
@ -16,9 +18,9 @@ namespace expressions
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExistingPrimitiveType(Context &context, const Variables &parameters)
ExpressionPointer parseExistingPrimitiveType(Context &context, ExpressionContext &expressionContext)
{
auto primitiveType = PrimitiveType::parseExisting(context);
auto *primitiveType = PrimitiveType::parseAndFindOrCreate(context, expressionContext.domain);
return std::make_unique<Reference<PrimitiveType>>(primitiveType);
}

View File

@ -2,10 +2,14 @@
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/ExpressionVisitor.h>
#include <plasp/pddl/Identifier.h>
#include <plasp/pddl/expressions/Either.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Type.h>
#include <plasp/utils/ParserException.h>
@ -29,7 +33,7 @@ Variable::Variable()
////////////////////////////////////////////////////////////////////////////////////////////////////
VariablePointer Variable::parseDeclaration(Context &context)
void Variable::parseDeclaration(Context &context, Variables &parameters)
{
context.parser.skipWhiteSpace();
@ -42,17 +46,19 @@ VariablePointer Variable::parseDeclaration(Context &context)
// Flag variable for potentially upcoming type declaration
variable->setDirty();
return variable;
parameters.emplace_back(std::move(variable));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclaration(Context &context, Variables &parameters)
void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expressionContext)
{
// Parse and store variable itself
parameters.emplace_back(parseDeclaration(context));
auto &variables = expressionContext.parameters;
auto &parameter = parameters.back();
// Parse and store variable itself
parseDeclaration(context, variables);
auto &variable = variables.back();
context.parser.skipWhiteSpace();
@ -66,14 +72,14 @@ void Variable::parseTypedDeclaration(Context &context, Variables &parameters)
[&](const auto *type)
{
// Set the argument type for all previously flagged arguments
std::for_each(parameters.begin(), parameters.end(),
[&](auto &parameter)
std::for_each(variables.begin(), variables.end(),
[&](auto &variable)
{
if (!parameter->isDirty())
if (!variable->isDirty())
return;
parameter->setType(type);
parameter->setDirty(false);
variable->setType(type);
variable->setDirty(false);
});
};
@ -85,23 +91,23 @@ void Variable::parseTypedDeclaration(Context &context, Variables &parameters)
context.parser.expect<std::string>("(");
context.parser.expect<std::string>("either");
parameter->m_eitherExpression = Either::parse(context, parameters, parseExistingPrimitiveType);
variable->m_eitherExpression = Either::parse(context, expressionContext, parseExistingPrimitiveType);
context.parser.expect<std::string>(")");
setType(parameter->m_eitherExpression.get());
setType(variable->m_eitherExpression.get());
return;
}
// Parse primitive type
const auto *type = PrimitiveType::parseExisting(context);
const auto *type = PrimitiveType::parseAndFindOrCreate(context, expressionContext.domain);
setType(type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variable *Variable::parseExisting(Context &context, const Variables &variables)
const Variable *Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();
@ -109,6 +115,8 @@ const Variable *Variable::parseExisting(Context &context, const Variables &varia
const auto variableName = context.parser.parseIdentifier(isIdentifier);
const auto &variables = expressionContext.parameters;
const auto match = std::find_if(variables.cbegin(), variables.cend(),
[&](const auto &variable)
{
@ -116,7 +124,7 @@ const Variable *Variable::parseExisting(Context &context, const Variables &varia
});
if (match == variables.cend())
throw utils::ParserException(context.parser, "Variable \"" + variableName + "\" used but never declared");
throw utils::ParserException(context.parser, "Parameter \"" + variableName + "\" used but never declared");
return match->get();
}