Refactored error handling.

This commit is contained in:
Patrick Lühne 2017-05-31 18:03:19 +02:00
parent aea640a624
commit 0d8b1e94da
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
11 changed files with 224 additions and 142 deletions

View File

@ -43,10 +43,10 @@ ast::Comparison::Operator translate(Clingo::AST::ComparisonOperator comparisonOp
struct BodyTermTranslateVisitor struct BodyTermTranslateVisitor
{ {
// TODO: refactor // 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) 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()) if (function.arguments.empty())
{ {
@ -73,7 +73,7 @@ struct BodyTermTranslateVisitor
for (size_t i = 0; i < function.arguments.size(); i++) for (size_t i = 0; i < function.arguments.size(); i++)
{ {
auto &argument = function.arguments[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(); variableStack.pop();
@ -93,11 +93,11 @@ struct BodyTermTranslateVisitor
} }
template<class T> 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>()); 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; return std::experimental::nullopt;
} }
}; };
@ -106,22 +106,22 @@ struct BodyTermTranslateVisitor
struct BodyLiteralTranslateVisitor 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); 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 // 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 // Comparisons should never have a sign, because these are converted to positive comparisons by clingo
if (literal.sign != Clingo::AST::Sign::None) 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); const auto operator_ = translate(comparison.comparison);
@ -132,17 +132,17 @@ struct BodyLiteralTranslateVisitor
ast::And conjunction; ast::And conjunction;
conjunction.arguments.reserve(3); 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[0].get()), translate(comparison.left, 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[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()))); 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)); return ast::Formula::make<ast::Exists>(std::move(parameters), std::move(conjunction));
} }
template<class T> 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; return std::experimental::nullopt;
} }
}; };
@ -151,18 +151,18 @@ struct BodyLiteralTranslateVisitor
struct BodyBodyLiteralTranslateVisitor 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) 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> 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; return std::experimental::nullopt;
} }
}; };

102
include/anthem/Exception.h Normal file
View 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

View File

@ -5,6 +5,7 @@
#include <experimental/optional> #include <experimental/optional>
#include <anthem/AST.h> #include <anthem/AST.h>
#include <anthem/Exception.h>
#include <anthem/RuleContext.h> #include <anthem/RuleContext.h>
#include <anthem/Utils.h> #include <anthem/Utils.h>
#include <anthem/output/Formatting.h> #include <anthem/output/Formatting.h>
@ -24,10 +25,10 @@ namespace anthem
struct TermCollectFunctionTermsVisitor 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) 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()); ruleContext.headTerms.reserve(ruleContext.headTerms.size() + function.arguments.size());
@ -36,9 +37,9 @@ struct TermCollectFunctionTermsVisitor
} }
template<class T> 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 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> 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 // TODO: rename, because not only terms are collected anymore
struct HeadLiteralCollectFunctionTermsVisitor 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; 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(); ruleContext.numberOfHeadLiterals = disjunction.elements.size();
for (const auto &conditionalLiteral : disjunction.elements) for (const auto &conditionalLiteral : disjunction.elements)
{ {
if (!conditionalLiteral.condition.empty()) 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.isChoiceRule = true;
ruleContext.numberOfHeadLiterals = aggregate.elements.size(); ruleContext.numberOfHeadLiterals = aggregate.elements.size();
if (aggregate.left_guard || aggregate.right_guard) 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) for (const auto &conditionalLiteral : aggregate.elements)
{ {
if (!conditionalLiteral.condition.empty()) 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> 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 struct FunctionTermTranslateVisitor
{ {
// TODO: check correctness // 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) if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context); throw TranslationException(term.location, "external functions currently unsupported");
std::vector<ast::Term> arguments; std::vector<ast::Term> arguments;
arguments.reserve(function.arguments.size()); arguments.reserve(function.arguments.size());
@ -133,9 +134,9 @@ struct FunctionTermTranslateVisitor
} }
template<class T> 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; return std::experimental::nullopt;
} }
}; };
@ -144,20 +145,20 @@ struct FunctionTermTranslateVisitor
struct LiteralTranslateVisitor 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); 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> 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; return std::experimental::nullopt;
} }
}; };
@ -166,12 +167,12 @@ struct LiteralTranslateVisitor
struct HeadLiteralTranslateToConsequentVisitor 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) 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) if (literal.sign == Clingo::AST::Sign::None)
return translatedLiteral; return translatedLiteral;
@ -182,7 +183,7 @@ struct HeadLiteralTranslateToConsequentVisitor
return ast::Formula::make<ast::Not>(std::move(translatedLiteral.value())); 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; std::vector<ast::Formula> arguments;
arguments.reserve(disjunction.elements.size()); arguments.reserve(disjunction.elements.size());
@ -190,12 +191,12 @@ struct HeadLiteralTranslateToConsequentVisitor
for (const auto &conditionalLiteral : disjunction.elements) for (const auto &conditionalLiteral : disjunction.elements)
{ {
if (!conditionalLiteral.condition.empty()) 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) 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())); arguments.emplace_back(std::move(argument.value()));
} }
@ -203,18 +204,18 @@ struct HeadLiteralTranslateToConsequentVisitor
return ast::Formula::make<ast::Or>(std::move(arguments)); 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) 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 translateConditionalLiteral =
[&](const auto &conditionalLiteral) [&](const auto &conditionalLiteral)
{ {
if (!conditionalLiteral.condition.empty()) 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) if (aggregate.elements.size() == 1)
@ -228,7 +229,7 @@ struct HeadLiteralTranslateToConsequentVisitor
auto argument = translateConditionalLiteral(conditionalLiteral); auto argument = translateConditionalLiteral(conditionalLiteral);
if (!argument) 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())); arguments.emplace_back(std::move(argument.value()));
} }
@ -237,9 +238,9 @@ struct HeadLiteralTranslateToConsequentVisitor
} }
template<class T> 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; return std::experimental::nullopt;
} }
}; };

View File

@ -3,10 +3,10 @@
#include <cstdlib> #include <cstdlib>
#include <clingo.hh>
namespace anthem namespace anthem
{ {
namespace input
{
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// //
@ -16,6 +16,23 @@ namespace input
struct Location 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 *sectionStart = nullptr;
const char *sectionEnd = nullptr; const char *sectionEnd = nullptr;
@ -28,7 +45,6 @@ struct Location
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
}
} }
#endif #endif

View File

@ -42,17 +42,17 @@ struct StatementVisitor
context.logger.log(output::Priority::Debug) << "[program] " << program.name; context.logger.log(output::Priority::Debug) << "[program] " << program.name;
if (!program.parameters.empty()) 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; RuleContext ruleContext;
ast::VariableStack variableStack; ast::VariableStack variableStack;
variableStack.push(&ruleContext.freeVariables); variableStack.push(&ruleContext.freeVariables);
// Collect all head terms // 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 // Create new variable declarations for the head terms
ruleContext.headVariablesStartIndex = ruleContext.freeVariables.size(); ruleContext.headVariablesStartIndex = ruleContext.freeVariables.size();
@ -68,16 +68,12 @@ struct StatementVisitor
// Compute consequent // Compute consequent
auto headVariableIndex = ruleContext.headVariablesStartIndex; 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); assert(ruleContext.headTerms.size() == headVariableIndex - ruleContext.headVariablesStartIndex);
if (!consequent) if (!consequent)
{ throw TranslationException(rule.head.location, "could not translate formula consequent");
// TODO: think about throwing an exception instead
context.logger.log(output::Priority::Error) << "could not translate formula consequent";
return;
}
// Generate auxiliary variables replacing the head atoms arguments // Generate auxiliary variables replacing the head atoms arguments
for (auto i = ruleContext.headTerms.cbegin(); i != ruleContext.headTerms.cend(); i++) 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(); const auto auxiliaryHeadVariableID = ruleContext.headVariablesStartIndex + i - ruleContext.headTerms.cbegin();
auto element = ast::Variable(ruleContext.freeVariables[auxiliaryHeadVariableID].get()); 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)); auto in = ast::In(std::move(element), std::move(set));
antecedent.arguments.emplace_back(std::move(in)); antecedent.arguments.emplace_back(std::move(in));
@ -97,10 +93,10 @@ struct StatementVisitor
{ {
const auto &bodyLiteral = *i; 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) 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())); antecedent.arguments.emplace_back(std::move(argument.value()));
} }
@ -155,9 +151,9 @@ struct StatementVisitor
} }
template<class T> 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");
} }
}; };

View File

@ -5,6 +5,7 @@
#include <anthem/AST.h> #include <anthem/AST.h>
#include <anthem/ASTUtils.h> #include <anthem/ASTUtils.h>
#include <anthem/Exception.h>
#include <anthem/RuleContext.h> #include <anthem/RuleContext.h>
#include <anthem/Utils.h> #include <anthem/Utils.h>
#include <anthem/output/Formatting.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) switch (binaryOperator)
{ {
@ -33,7 +34,7 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
case Clingo::AST::BinaryOperator::Modulo: case Clingo::AST::BinaryOperator::Modulo:
return ast::BinaryOperation::Operator::Modulo; return ast::BinaryOperation::Operator::Modulo;
default: default:
throwErrorAtLocation(term.location, "“binary operation” terms currently unsupported", context); throw TranslationException(term.location, "“binary operation” terms currently unsupported");
} }
return ast::BinaryOperation::Operator::Plus; 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 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()) switch (symbol.type())
{ {
@ -68,10 +69,10 @@ struct TermTranslateVisitor
for (const auto &argument : symbol.arguments()) for (const auto &argument : symbol.arguments())
{ {
auto translatedArgument = visit(argument, term, context, ruleContext, variableStack); auto translatedArgument = visit(argument, term, ruleContext, variableStack);
if (!translatedArgument) 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())); functionRaw.arguments.emplace_back(std::move(translatedArgument.value()));
} }
@ -83,7 +84,7 @@ struct TermTranslateVisitor
return std::experimental::nullopt; 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 matchingVariableDeclaration = variableStack.findUserVariableDeclaration(variable.name);
const auto isAnonymousVariable = (strcmp(variable.name, "_") == 0); const auto isAnonymousVariable = (strcmp(variable.name, "_") == 0);
@ -99,58 +100,58 @@ struct TermTranslateVisitor
return ast::Term::make<ast::Variable>(ruleContext.freeVariables.back().get()); 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; 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); const auto operator_ = translate(binaryOperation.binary_operator, term);
auto left = translate(binaryOperation.left, context, ruleContext, variableStack); auto left = translate(binaryOperation.left, ruleContext, variableStack);
auto right = translate(binaryOperation.right, context, ruleContext, variableStack); auto right = translate(binaryOperation.right, ruleContext, variableStack);
return ast::Term::make<ast::BinaryOperation>(operator_, std::move(left), std::move(right)); 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 left = translate(interval.left, ruleContext, variableStack);
auto right = translate(interval.right, context, ruleContext, variableStack); auto right = translate(interval.right, ruleContext, variableStack);
return ast::Term::make<ast::Interval>(std::move(left), std::move(right)); 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) if (function.external)
throwErrorAtLocation(term.location, "external functions currently unsupported", context); throw TranslationException(term.location, "external functions currently unsupported");
std::vector<ast::Term> arguments; std::vector<ast::Term> arguments;
arguments.reserve(function.arguments.size()); arguments.reserve(function.arguments.size());
for (const auto &argument : function.arguments) 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)); 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; 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) if (!translatedTerm)
throwErrorAtLocation(term.location, "could not translate term", context); throw TranslationException(term.location, "could not translate term");
return std::move(translatedTerm.value()); return std::move(translatedTerm.value());
} }

View File

@ -6,7 +6,7 @@
#include <clingo.hh> #include <clingo.hh>
#include <anthem/Context.h> #include <anthem/Context.h>
#include <anthem/input/Location.h> #include <anthem/Location.h>
namespace anthem 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) inline bool isPrefix(const char *prefix, const char *string)
{ {
const auto prefixLength = std::strlen(prefix); const auto prefixLength = std::strlen(prefix);

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
#include <anthem/input/Location.h> #include <anthem/Location.h>
#include <anthem/output/ColorStream.h> #include <anthem/output/ColorStream.h>
#include <anthem/output/FormatScope.h> #include <anthem/output/FormatScope.h>
#include <anthem/output/Priority.h> #include <anthem/output/Priority.h>
@ -34,7 +34,7 @@ class Logger
void setColorPolicy(ColorStream::ColorPolicy colorPolicy); void setColorPolicy(ColorStream::ColorPolicy colorPolicy);
FormatScope log(Priority priority); FormatScope log(Priority priority);
FormatScope log(Priority priority, const input::Location &location); FormatScope log(Priority priority, const Location &location);
private: private:
ColorStream m_outputStream; ColorStream m_outputStream;

View File

@ -3,9 +3,6 @@ set(target anthem)
file(GLOB core_sources "anthem/*.cpp") file(GLOB core_sources "anthem/*.cpp")
file(GLOB core_headers "../include/anthem/*.h") 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_sources "anthem/output/*.cpp")
file(GLOB output_headers "../include/anthem/output/*.h") file(GLOB output_headers "../include/anthem/output/*.h")
@ -13,9 +10,6 @@ set(sources
${core_sources} ${core_sources}
${core_headers} ${core_headers}
${input_sources}
${input_headers}
${output_sources} ${output_sources}
${output_headers} ${output_headers}
) )

View File

@ -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); const auto priorityID = static_cast<int>(priority);

View File

@ -15,7 +15,7 @@
std::stringstream errors; std::stringstream errors;
anthem::output::Logger logger(output, errors); anthem::output::Logger logger(output, errors);
anthem::Context context = {logger, {}}; anthem::Context context(std::move(logger));
context.simplify = true; context.simplify = true;
context.complete = true; context.complete = true;