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

@@ -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;