Refactored error handling.
This commit is contained in:
parent
aea640a624
commit
0d8b1e94da
@ -43,10 +43,10 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp
|
||||
struct BodyTermTranslateVisitor
|
||||
{
|
||||
// TODO: refactor
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Literal &literal, const Clingo::AST::Term &, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
{
|
||||
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
|
||||
throwErrorAtLocation(literal.location, "double-negated literals currently unsupported", context);
|
||||
throw TranslationException(literal.location, "double-negated literals currently unsupported");
|
||||
|
||||
if (function.arguments.empty())
|
||||
{
|
||||
@ -73,7 +73,7 @@ struct BodyTermTranslateVisitor
|
||||
for (size_t i = 0; i < function.arguments.size(); i++)
|
||||
{
|
||||
auto &argument = function.arguments[i];
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[i].get()), translate(argument, context, ruleContext, variableStack)));
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[i].get()), translate(argument, ruleContext, variableStack)));
|
||||
}
|
||||
|
||||
variableStack.pop();
|
||||
@ -93,11 +93,11 @@ struct BodyTermTranslateVisitor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, Context &context, RuleContext &, ast::VariableStack &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &, const Clingo::AST::Term &term, RuleContext &, ast::VariableStack &)
|
||||
{
|
||||
assert(!term.data.is<Clingo::AST::Function>());
|
||||
|
||||
throwErrorAtLocation(term.location, "term currently unsupported in this context, expected function", context);
|
||||
throw TranslationException(term.location, "term currently unsupported in this context, expected function");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
@ -106,22 +106,22 @@ struct BodyTermTranslateVisitor
|
||||
|
||||
struct BodyLiteralTranslateVisitor
|
||||
{
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, ast::VariableStack &)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, RuleContext &, ast::VariableStack &)
|
||||
{
|
||||
return ast::Formula::make<ast::Boolean>(boolean.value);
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &literal, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
{
|
||||
return term.data.accept(BodyTermTranslateVisitor(), literal, term, context, ruleContext, variableStack);
|
||||
return term.data.accept(BodyTermTranslateVisitor(), literal, term, ruleContext, variableStack);
|
||||
}
|
||||
|
||||
// TODO: refactor
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Comparison &comparison, const Clingo::AST::Literal &literal, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
{
|
||||
// Comparisons should never have a sign, because these are converted to positive comparisons by clingo
|
||||
if (literal.sign != Clingo::AST::Sign::None)
|
||||
throwErrorAtLocation(literal.location, "negated comparisons currently unsupported", context);
|
||||
throw TranslationException(literal.location, "negated comparisons currently unsupported");
|
||||
|
||||
const auto operator_ = translate(comparison.comparison);
|
||||
|
||||
@ -132,17 +132,17 @@ struct BodyLiteralTranslateVisitor
|
||||
|
||||
ast::And conjunction;
|
||||
conjunction.arguments.reserve(3);
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[0].get()), translate(comparison.left, context, ruleContext, variableStack)));
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[1].get()), translate(comparison.right, context, ruleContext, variableStack)));
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[0].get()), translate(comparison.left, ruleContext, variableStack)));
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::In>(ast::Variable(parameters[1].get()), translate(comparison.right, ruleContext, variableStack)));
|
||||
conjunction.arguments.emplace_back(ast::Formula::make<ast::Comparison>(operator_, ast::Variable(parameters[0].get()), ast::Variable(parameters[1].get())));
|
||||
|
||||
return ast::Formula::make<ast::Exists>(std::move(parameters), std::move(conjunction));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, ast::VariableStack &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, RuleContext &, ast::VariableStack &)
|
||||
{
|
||||
throwErrorAtLocation(literal.location, "literal currently unsupported in this context, expected function or term", context);
|
||||
throw TranslationException(literal.location, "literal currently unsupported in this context, expected function or term");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
@ -151,18 +151,18 @@ struct BodyLiteralTranslateVisitor
|
||||
|
||||
struct BodyBodyLiteralTranslateVisitor
|
||||
{
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::BodyLiteral &bodyLiteral, RuleContext &ruleContext, ast::VariableStack &variableStack)
|
||||
{
|
||||
if (bodyLiteral.sign != Clingo::AST::Sign::None)
|
||||
throwErrorAtLocation(bodyLiteral.location, "only positive body literals supported currently", context);
|
||||
throw TranslationException(bodyLiteral.location, "only positive body literals supported currently");
|
||||
|
||||
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, context, ruleContext, variableStack);
|
||||
return literal.data.accept(BodyLiteralTranslateVisitor(), literal, ruleContext, variableStack);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, Context &context, RuleContext &, ast::VariableStack &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::BodyLiteral &bodyLiteral, RuleContext &, ast::VariableStack &)
|
||||
{
|
||||
throwErrorAtLocation(bodyLiteral.location, "body literal currently unsupported in this context, expected literal", context);
|
||||
throw TranslationException(bodyLiteral.location, "body literal currently unsupported in this context, expected literal");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
|
102
include/anthem/Exception.h
Normal file
102
include/anthem/Exception.h
Normal file
@ -0,0 +1,102 @@
|
||||
#ifndef __ANTHEM__EXCEPTION_H
|
||||
#define __ANTHEM__EXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include <anthem/Location.h>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Exception
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: implement stream operators to modify message
|
||||
class Exception: public std::exception
|
||||
{
|
||||
public:
|
||||
Exception() = delete;
|
||||
Exception(const Exception &other) = delete;
|
||||
Exception &operator=(const Exception &other) = delete;
|
||||
Exception(Exception &&other) = default;
|
||||
Exception &operator=(Exception &&other) = default;
|
||||
|
||||
explicit Exception(const Location &location)
|
||||
: Exception(location, "unspecified error")
|
||||
{
|
||||
}
|
||||
|
||||
explicit Exception(const Location &location, const char *message)
|
||||
: Exception(location, static_cast<std::string>(message))
|
||||
{
|
||||
}
|
||||
|
||||
explicit Exception(const Location &location, const std::string &message)
|
||||
: m_location{location},
|
||||
m_message{message},
|
||||
// TODO: refactor
|
||||
m_plainMessage{std::string(m_location.sectionStart) + ":" + std::to_string(m_location.rowStart)
|
||||
+ ":" + std::to_string(m_location.columnStart) + " " + m_message}
|
||||
{
|
||||
}
|
||||
|
||||
~Exception() noexcept = default;
|
||||
|
||||
const char *what() const noexcept
|
||||
{
|
||||
return m_plainMessage.c_str();
|
||||
}
|
||||
|
||||
const Location &location() const
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
const std::string &message() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
private:
|
||||
Location m_location;
|
||||
std::string m_message;
|
||||
std::string m_plainMessage;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LogicException : public Exception
|
||||
{
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TranslationException : public Exception
|
||||
{
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SimplificationException : public Exception
|
||||
{
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CompletionException : public Exception
|
||||
{
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -5,6 +5,7 @@
|
||||
#include <experimental/optional>
|
||||
|
||||
#include <anthem/AST.h>
|
||||
#include <anthem/Exception.h>
|
||||
#include <anthem/RuleContext.h>
|
||||
#include <anthem/Utils.h>
|
||||
#include <anthem/output/Formatting.h>
|
||||
@ -24,10 +25,10 @@ namespace anthem
|
||||
|
||||
struct TermCollectFunctionTermsVisitor
|
||||
{
|
||||
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext)
|
||||
void visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext)
|
||||
{
|
||||
if (function.external)
|
||||
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
|
||||
throw LogicException(term.location, "external functions currently unsupported");
|
||||
|
||||
ruleContext.headTerms.reserve(ruleContext.headTerms.size() + function.arguments.size());
|
||||
|
||||
@ -36,9 +37,9 @@ struct TermCollectFunctionTermsVisitor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &)
|
||||
void visit(const T &, const Clingo::AST::Term &term, RuleContext &)
|
||||
{
|
||||
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
|
||||
throw LogicException(term.location, "term currently unsupported in this function expected");
|
||||
}
|
||||
};
|
||||
|
||||
@ -46,19 +47,19 @@ struct TermCollectFunctionTermsVisitor
|
||||
|
||||
struct LiteralCollectFunctionTermsVisitor
|
||||
{
|
||||
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, Context &, RuleContext &)
|
||||
void visit(const Clingo::AST::Boolean &, const Clingo::AST::Literal &, RuleContext &)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext)
|
||||
void visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, RuleContext &ruleContext)
|
||||
{
|
||||
term.data.accept(TermCollectFunctionTermsVisitor(), term, context, ruleContext);
|
||||
term.data.accept(TermCollectFunctionTermsVisitor(), term, ruleContext);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &)
|
||||
void visit(const T &, const Clingo::AST::Literal &literal, RuleContext &)
|
||||
{
|
||||
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
|
||||
throw LogicException(literal.location, "only disjunctions of literals allowed as head literals");
|
||||
}
|
||||
};
|
||||
|
||||
@ -67,47 +68,47 @@ struct LiteralCollectFunctionTermsVisitor
|
||||
// TODO: rename, because not only terms are collected anymore
|
||||
struct HeadLiteralCollectFunctionTermsVisitor
|
||||
{
|
||||
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext)
|
||||
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, RuleContext &ruleContext)
|
||||
{
|
||||
ruleContext.numberOfHeadLiterals = 1;
|
||||
|
||||
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context, ruleContext);
|
||||
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, ruleContext);
|
||||
}
|
||||
|
||||
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
|
||||
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext)
|
||||
{
|
||||
ruleContext.numberOfHeadLiterals = disjunction.elements.size();
|
||||
|
||||
for (const auto &conditionalLiteral : disjunction.elements)
|
||||
{
|
||||
if (!conditionalLiteral.condition.empty())
|
||||
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
|
||||
throw LogicException(headLiteral.location, "conditional head literals currently unsupported");
|
||||
|
||||
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
|
||||
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, ruleContext);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext)
|
||||
void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext)
|
||||
{
|
||||
ruleContext.isChoiceRule = true;
|
||||
ruleContext.numberOfHeadLiterals = aggregate.elements.size();
|
||||
|
||||
if (aggregate.left_guard || aggregate.right_guard)
|
||||
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards currently unsupported", context);
|
||||
throw LogicException(headLiteral.location, "aggregates with left or right guards currently unsupported");
|
||||
|
||||
for (const auto &conditionalLiteral : aggregate.elements)
|
||||
{
|
||||
if (!conditionalLiteral.condition.empty())
|
||||
throwErrorAtLocation(headLiteral.location, "conditional literals in aggregates currently unsupported", context);
|
||||
throw LogicException(headLiteral.location, "conditional literals in aggregates currently unsupported");
|
||||
|
||||
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context, ruleContext);
|
||||
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, ruleContext);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &)
|
||||
void visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &)
|
||||
{
|
||||
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
|
||||
throw LogicException(headLiteral.location, "head literal currently unsupported in this expected literal, disjunction, or aggregate");
|
||||
}
|
||||
};
|
||||
|
||||
@ -118,10 +119,10 @@ struct HeadLiteralCollectFunctionTermsVisitor
|
||||
struct FunctionTermTranslateVisitor
|
||||
{
|
||||
// TODO: check correctness
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
{
|
||||
if (function.external)
|
||||
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
|
||||
throw TranslationException(term.location, "external functions currently unsupported");
|
||||
|
||||
std::vector<ast::Term> arguments;
|
||||
arguments.reserve(function.arguments.size());
|
||||
@ -133,9 +134,9 @@ struct FunctionTermTranslateVisitor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, Context &context, RuleContext &, size_t &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Term &term, RuleContext &, size_t &)
|
||||
{
|
||||
throwErrorAtLocation(term.location, "term currently unsupported in this context, function expected", context);
|
||||
throw TranslationException(term.location, "term currently unsupported in this function expected");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
@ -144,20 +145,20 @@ struct FunctionTermTranslateVisitor
|
||||
|
||||
struct LiteralTranslateVisitor
|
||||
{
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, Context &, RuleContext &, size_t &)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Boolean &boolean, const Clingo::AST::Literal &, RuleContext &, size_t &)
|
||||
{
|
||||
return ast::Formula::make<ast::Boolean>(boolean.value);
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Term &term, const Clingo::AST::Literal &, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
{
|
||||
return term.data.accept(FunctionTermTranslateVisitor(), term, context, ruleContext, headVariableIndex);
|
||||
return term.data.accept(FunctionTermTranslateVisitor(), term, ruleContext, headVariableIndex);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, Context &context, RuleContext &, size_t &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::Literal &literal, RuleContext &, size_t &)
|
||||
{
|
||||
throwErrorAtLocation(literal.location, "only disjunctions of literals allowed as head literals", context);
|
||||
throw TranslationException(literal.location, "only disjunctions of literals allowed as head literals");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
@ -166,12 +167,12 @@ struct LiteralTranslateVisitor
|
||||
|
||||
struct HeadLiteralTranslateToConsequentVisitor
|
||||
{
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
{
|
||||
if (literal.sign == Clingo::AST::Sign::DoubleNegation)
|
||||
throwErrorAtLocation(literal.location, "double-negated head literals currently unsupported", context);
|
||||
throw TranslationException(literal.location, "double-negated head literals currently unsupported");
|
||||
|
||||
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, context, ruleContext, headVariableIndex);
|
||||
auto translatedLiteral = literal.data.accept(LiteralTranslateVisitor(), literal, ruleContext, headVariableIndex);
|
||||
|
||||
if (literal.sign == Clingo::AST::Sign::None)
|
||||
return translatedLiteral;
|
||||
@ -182,7 +183,7 @@ struct HeadLiteralTranslateToConsequentVisitor
|
||||
return ast::Formula::make<ast::Not>(std::move(translatedLiteral.value()));
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
{
|
||||
std::vector<ast::Formula> arguments;
|
||||
arguments.reserve(disjunction.elements.size());
|
||||
@ -190,12 +191,12 @@ struct HeadLiteralTranslateToConsequentVisitor
|
||||
for (const auto &conditionalLiteral : disjunction.elements)
|
||||
{
|
||||
if (!conditionalLiteral.condition.empty())
|
||||
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
|
||||
throw TranslationException(headLiteral.location, "conditional head literals currently unsupported");
|
||||
|
||||
auto argument = visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
|
||||
auto argument = visit(conditionalLiteral.literal, headLiteral, ruleContext, headVariableIndex);
|
||||
|
||||
if (!argument)
|
||||
throwErrorAtLocation(headLiteral.location, "could not parse argument", context);
|
||||
throw TranslationException(headLiteral.location, "could not parse argument");
|
||||
|
||||
arguments.emplace_back(std::move(argument.value()));
|
||||
}
|
||||
@ -203,18 +204,18 @@ struct HeadLiteralTranslateToConsequentVisitor
|
||||
return ast::Formula::make<ast::Or>(std::move(arguments));
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
std::experimental::optional<ast::Formula> visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &ruleContext, size_t &headVariableIndex)
|
||||
{
|
||||
if (aggregate.left_guard || aggregate.right_guard)
|
||||
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards currently unsupported", context);
|
||||
throw TranslationException(headLiteral.location, "aggregates with left or right guards currently unsupported");
|
||||
|
||||
const auto translateConditionalLiteral =
|
||||
[&](const auto &conditionalLiteral)
|
||||
{
|
||||
if (!conditionalLiteral.condition.empty())
|
||||
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
|
||||
throw TranslationException(headLiteral.location, "conditional head literals currently unsupported");
|
||||
|
||||
return this->visit(conditionalLiteral.literal, headLiteral, context, ruleContext, headVariableIndex);
|
||||
return this->visit(conditionalLiteral.literal, headLiteral, ruleContext, headVariableIndex);
|
||||
};
|
||||
|
||||
if (aggregate.elements.size() == 1)
|
||||
@ -228,7 +229,7 @@ struct HeadLiteralTranslateToConsequentVisitor
|
||||
auto argument = translateConditionalLiteral(conditionalLiteral);
|
||||
|
||||
if (!argument)
|
||||
throwErrorAtLocation(headLiteral.location, "could not parse argument", context);
|
||||
throw TranslationException(headLiteral.location, "could not parse argument");
|
||||
|
||||
arguments.emplace_back(std::move(argument.value()));
|
||||
}
|
||||
@ -237,9 +238,9 @@ struct HeadLiteralTranslateToConsequentVisitor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, Context &context, RuleContext &, size_t &)
|
||||
std::experimental::optional<ast::Formula> visit(const T &, const Clingo::AST::HeadLiteral &headLiteral, RuleContext &, size_t &)
|
||||
{
|
||||
throwErrorAtLocation(headLiteral.location, "head literal currently unsupported in this context, expected literal, disjunction, or aggregate", context);
|
||||
throw TranslationException(headLiteral.location, "head literal currently unsupported in this expected literal, disjunction, or aggregate");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <clingo.hh>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
namespace input
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -16,6 +16,23 @@ namespace input
|
||||
|
||||
struct Location
|
||||
{
|
||||
Location() = default;
|
||||
|
||||
Location(const Clingo::Location &clingoLocation)
|
||||
: sectionStart{clingoLocation.begin_file()},
|
||||
sectionEnd{clingoLocation.end_file()},
|
||||
rowStart{clingoLocation.begin_line()},
|
||||
rowEnd{clingoLocation.end_line()},
|
||||
columnStart{clingoLocation.begin_column()},
|
||||
columnEnd{clingoLocation.end_column()}
|
||||
{
|
||||
}
|
||||
|
||||
Location(const Location &other) = default;
|
||||
Location &operator=(const Location &other) = default;
|
||||
Location(Location &&other) = default;
|
||||
Location &operator=(Location &&other) = default;
|
||||
|
||||
const char *sectionStart = nullptr;
|
||||
const char *sectionEnd = nullptr;
|
||||
|
||||
@ -28,7 +45,6 @@ struct Location
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -42,17 +42,17 @@ struct StatementVisitor
|
||||
context.logger.log(output::Priority::Debug) << "[program] " << program.name;
|
||||
|
||||
if (!program.parameters.empty())
|
||||
throwErrorAtLocation(statement.location, "program parameters currently unsupported", context);
|
||||
throw LogicException(statement.location, "program parameters currently unsupported");
|
||||
}
|
||||
|
||||
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::ScopedFormula> &scopedFormulas, Context &context)
|
||||
void visit(const Clingo::AST::Rule &rule, const Clingo::AST::Statement &, std::vector<ast::ScopedFormula> &scopedFormulas, Context &)
|
||||
{
|
||||
RuleContext ruleContext;
|
||||
ast::VariableStack variableStack;
|
||||
variableStack.push(&ruleContext.freeVariables);
|
||||
|
||||
// Collect all head terms
|
||||
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, context, ruleContext);
|
||||
rule.head.data.accept(HeadLiteralCollectFunctionTermsVisitor(), rule.head, ruleContext);
|
||||
|
||||
// Create new variable declarations for the head terms
|
||||
ruleContext.headVariablesStartIndex = ruleContext.freeVariables.size();
|
||||
@ -68,16 +68,12 @@ struct StatementVisitor
|
||||
|
||||
// Compute consequent
|
||||
auto headVariableIndex = ruleContext.headVariablesStartIndex;
|
||||
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, context, ruleContext, headVariableIndex);
|
||||
auto consequent = rule.head.data.accept(HeadLiteralTranslateToConsequentVisitor(), rule.head, ruleContext, headVariableIndex);
|
||||
|
||||
assert(ruleContext.headTerms.size() == headVariableIndex - ruleContext.headVariablesStartIndex);
|
||||
|
||||
if (!consequent)
|
||||
{
|
||||
// TODO: think about throwing an exception instead
|
||||
context.logger.log(output::Priority::Error) << "could not translate formula consequent";
|
||||
return;
|
||||
}
|
||||
throw TranslationException(rule.head.location, "could not translate formula consequent");
|
||||
|
||||
// Generate auxiliary variables replacing the head atom’s arguments
|
||||
for (auto i = ruleContext.headTerms.cbegin(); i != ruleContext.headTerms.cend(); i++)
|
||||
@ -86,7 +82,7 @@ struct StatementVisitor
|
||||
|
||||
const auto auxiliaryHeadVariableID = ruleContext.headVariablesStartIndex + i - ruleContext.headTerms.cbegin();
|
||||
auto element = ast::Variable(ruleContext.freeVariables[auxiliaryHeadVariableID].get());
|
||||
auto set = translate(headTerm, context, ruleContext, variableStack);
|
||||
auto set = translate(headTerm, ruleContext, variableStack);
|
||||
auto in = ast::In(std::move(element), std::move(set));
|
||||
|
||||
antecedent.arguments.emplace_back(std::move(in));
|
||||
@ -97,10 +93,10 @@ struct StatementVisitor
|
||||
{
|
||||
const auto &bodyLiteral = *i;
|
||||
|
||||
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, context, ruleContext, variableStack);
|
||||
auto argument = bodyLiteral.data.accept(BodyBodyLiteralTranslateVisitor(), bodyLiteral, ruleContext, variableStack);
|
||||
|
||||
if (!argument)
|
||||
throwErrorAtLocation(bodyLiteral.location, "could not translate body literal", context);
|
||||
throw TranslationException(bodyLiteral.location, "could not translate body literal");
|
||||
|
||||
antecedent.arguments.emplace_back(std::move(argument.value()));
|
||||
}
|
||||
@ -155,9 +151,9 @@ struct StatementVisitor
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &context)
|
||||
void visit(const T &, const Clingo::AST::Statement &statement, std::vector<ast::ScopedFormula> &, Context &)
|
||||
{
|
||||
throwErrorAtLocation(statement.location, "statement currently unsupported, expected rule", context);
|
||||
throw LogicException(statement.location, "statement currently unsupported, expected rule");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <anthem/AST.h>
|
||||
#include <anthem/ASTUtils.h>
|
||||
#include <anthem/Exception.h>
|
||||
#include <anthem/RuleContext.h>
|
||||
#include <anthem/Utils.h>
|
||||
#include <anthem/output/Formatting.h>
|
||||
@ -18,7 +19,7 @@ namespace anthem
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOperator, const Clingo::AST::Term &term, Context &context)
|
||||
ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOperator, const Clingo::AST::Term &term)
|
||||
{
|
||||
switch (binaryOperator)
|
||||
{
|
||||
@ -33,7 +34,7 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
|
||||
case Clingo::AST::BinaryOperator::Modulo:
|
||||
return ast::BinaryOperation::Operator::Modulo;
|
||||
default:
|
||||
throwErrorAtLocation(term.location, "“binary operation” terms currently unsupported", context);
|
||||
throw TranslationException(term.location, "“binary operation” terms currently unsupported");
|
||||
}
|
||||
|
||||
return ast::BinaryOperation::Operator::Plus;
|
||||
@ -41,13 +42,13 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack);
|
||||
ast::Term translate(const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TermTranslateVisitor
|
||||
{
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::Symbol &symbol, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
switch (symbol.type())
|
||||
{
|
||||
@ -68,10 +69,10 @@ struct TermTranslateVisitor
|
||||
|
||||
for (const auto &argument : symbol.arguments())
|
||||
{
|
||||
auto translatedArgument = visit(argument, term, context, ruleContext, variableStack);
|
||||
auto translatedArgument = visit(argument, term, ruleContext, variableStack);
|
||||
|
||||
if (!translatedArgument)
|
||||
throwErrorAtLocation(term.location, "could not translate argument", context);
|
||||
throw TranslationException(term.location, "could not translate argument");
|
||||
|
||||
functionRaw.arguments.emplace_back(std::move(translatedArgument.value()));
|
||||
}
|
||||
@ -83,7 +84,7 @@ struct TermTranslateVisitor
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, Context &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Variable &variable, const Clingo::AST::Term &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
const auto matchingVariableDeclaration = variableStack.findUserVariableDeclaration(variable.name);
|
||||
const auto isAnonymousVariable = (strcmp(variable.name, "_") == 0);
|
||||
@ -99,58 +100,58 @@ struct TermTranslateVisitor
|
||||
return ast::Term::make<ast::Variable>(ruleContext.freeVariables.back().get());
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, RuleContext &, const ast::VariableStack &)
|
||||
{
|
||||
throwErrorAtLocation(term.location, "“unary operation” terms currently unsupported", context);
|
||||
throw TranslationException(term.location, "“unary operation” terms currently unsupported");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
const auto operator_ = translate(binaryOperation.binary_operator, term, context);
|
||||
auto left = translate(binaryOperation.left, context, ruleContext, variableStack);
|
||||
auto right = translate(binaryOperation.right, context, ruleContext, variableStack);
|
||||
const auto operator_ = translate(binaryOperation.binary_operator, term);
|
||||
auto left = translate(binaryOperation.left, ruleContext, variableStack);
|
||||
auto right = translate(binaryOperation.right, ruleContext, variableStack);
|
||||
|
||||
return ast::Term::make<ast::BinaryOperation>(operator_, std::move(left), std::move(right));
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
auto left = translate(interval.left, context, ruleContext, variableStack);
|
||||
auto right = translate(interval.right, context, ruleContext, variableStack);
|
||||
auto left = translate(interval.left, ruleContext, variableStack);
|
||||
auto right = translate(interval.right, ruleContext, variableStack);
|
||||
|
||||
return ast::Term::make<ast::Interval>(std::move(left), std::move(right));
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Function &function, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
if (function.external)
|
||||
throwErrorAtLocation(term.location, "external functions currently unsupported", context);
|
||||
throw TranslationException(term.location, "external functions currently unsupported");
|
||||
|
||||
std::vector<ast::Term> arguments;
|
||||
arguments.reserve(function.arguments.size());
|
||||
|
||||
for (const auto &argument : function.arguments)
|
||||
arguments.emplace_back(translate(argument, context, ruleContext, variableStack));
|
||||
arguments.emplace_back(translate(argument, ruleContext, variableStack));
|
||||
|
||||
return ast::Term::make<ast::Function>(function.name, std::move(arguments));
|
||||
}
|
||||
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, Context &context, RuleContext &, const ast::VariableStack &)
|
||||
std::experimental::optional<ast::Term> visit(const Clingo::AST::Pool &, const Clingo::AST::Term &term, RuleContext &, const ast::VariableStack &)
|
||||
{
|
||||
throwErrorAtLocation(term.location, "“pool” terms currently unsupported", context);
|
||||
throw TranslationException(term.location, "“pool” terms currently unsupported");
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Term translate(const Clingo::AST::Term &term, Context &context, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
ast::Term translate(const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, context, ruleContext, variableStack);
|
||||
auto translatedTerm = term.data.accept(TermTranslateVisitor(), term, ruleContext, variableStack);
|
||||
|
||||
if (!translatedTerm)
|
||||
throwErrorAtLocation(term.location, "could not translate term", context);
|
||||
throw TranslationException(term.location, "could not translate term");
|
||||
|
||||
return std::move(translatedTerm.value());
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <clingo.hh>
|
||||
|
||||
#include <anthem/Context.h>
|
||||
#include <anthem/input/Location.h>
|
||||
#include <anthem/Location.h>
|
||||
|
||||
namespace anthem
|
||||
{
|
||||
@ -17,34 +17,6 @@ namespace anthem
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T1, class T2>
|
||||
T1 location_cast(const T2 &location);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
inline input::Location location_cast(const Clingo::Location &location)
|
||||
{
|
||||
return {location.begin_file(), location.end_file(), location.begin_line(), location.end_line(),
|
||||
location.begin_column(), location.end_column()};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: refactor
|
||||
inline void throwErrorAtLocation(const Clingo::Location &clingoLocation, const char *errorMessage,
|
||||
Context &context)
|
||||
{
|
||||
const auto location = location_cast<input::Location>(clingoLocation);
|
||||
|
||||
// TODO: think about removing this to avoid double error messages
|
||||
context.logger.log(output::Priority::Error, location) << errorMessage;
|
||||
|
||||
throw std::runtime_error(errorMessage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isPrefix(const char *prefix, const char *string)
|
||||
{
|
||||
const auto prefixLength = std::strlen(prefix);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <anthem/input/Location.h>
|
||||
#include <anthem/Location.h>
|
||||
#include <anthem/output/ColorStream.h>
|
||||
#include <anthem/output/FormatScope.h>
|
||||
#include <anthem/output/Priority.h>
|
||||
@ -34,7 +34,7 @@ class Logger
|
||||
void setColorPolicy(ColorStream::ColorPolicy colorPolicy);
|
||||
|
||||
FormatScope log(Priority priority);
|
||||
FormatScope log(Priority priority, const input::Location &location);
|
||||
FormatScope log(Priority priority, const Location &location);
|
||||
|
||||
private:
|
||||
ColorStream m_outputStream;
|
||||
|
@ -3,9 +3,6 @@ set(target anthem)
|
||||
file(GLOB core_sources "anthem/*.cpp")
|
||||
file(GLOB core_headers "../include/anthem/*.h")
|
||||
|
||||
file(GLOB input_sources "anthem/input/*.cpp")
|
||||
file(GLOB input_headers "../include/anthem/input/*.h")
|
||||
|
||||
file(GLOB output_sources "anthem/output/*.cpp")
|
||||
file(GLOB output_headers "../include/anthem/output/*.h")
|
||||
|
||||
@ -13,9 +10,6 @@ set(sources
|
||||
${core_sources}
|
||||
${core_headers}
|
||||
|
||||
${input_sources}
|
||||
${input_headers}
|
||||
|
||||
${output_sources}
|
||||
${output_headers}
|
||||
)
|
||||
|
@ -110,7 +110,7 @@ FormatScope Logger::log(Priority priority)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FormatScope Logger::log(Priority priority, const input::Location &location)
|
||||
FormatScope Logger::log(Priority priority, const Location &location)
|
||||
{
|
||||
const auto priorityID = static_cast<int>(priority);
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
std::stringstream errors;
|
||||
|
||||
anthem::output::Logger logger(output, errors);
|
||||
anthem::Context context = {logger, {}};
|
||||
anthem::Context context(std::move(logger));
|
||||
context.simplify = true;
|
||||
context.complete = true;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user