Started implementing colored output.

This commit is contained in:
Patrick Lühne 2016-06-14 12:47:39 +02:00
parent e0dd9833a3
commit 342a346fce
22 changed files with 238 additions and 62 deletions

View File

@ -66,14 +66,6 @@ int main(int argc, char **argv)
return EXIT_SUCCESS;
}
const auto handleException =
[&](const auto &messagePrefix, const auto &exception)
{
std::cerr << messagePrefix << ": " << exception.what() << std::endl << std::endl;
printHelp();
exit(EXIT_FAILURE);
};
try
{
plasp::utils::Parser parser;
@ -108,7 +100,9 @@ int main(int argc, char **argv)
if (language == plasp::Language::Type::Unknown)
{
std::cerr << "Error: Unknown input language" << std::endl << std::endl;
plasp::utils::Logger logger;
logger.exception("error", "unknown input language");
std::cout << std::endl;
printHelp();
return EXIT_FAILURE;
}
@ -137,19 +131,27 @@ int main(int argc, char **argv)
}
catch (const plasp::utils::ParserException &e)
{
handleException("Parser error", e);
plasp::utils::Logger logger;
logger.parserException(e.coordinate(), e.message());
return EXIT_FAILURE;
}
catch (const plasp::utils::ParserWarning &e)
{
handleException("Parser warning", e);
plasp::utils::Logger logger;
logger.parserException(e.coordinate(), e.message());
return EXIT_FAILURE;
}
catch (const plasp::utils::TranslatorException &e)
{
handleException("Translation error", e);
plasp::utils::Logger logger;
logger.exception("translation error", e.what());
return EXIT_FAILURE;
}
catch (const std::exception &e)
{
handleException("Error", e);
plasp::utils::Logger logger;
logger.exception("unexpected error", e.what());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;

View File

@ -71,7 +71,7 @@ std::unique_ptr<Derived> NAry<Derived>::parse(Context &context,
}
if (expression->m_arguments.empty())
context.logger.parserWarning(context.parser, "\"" + Derived::Identifier + "\" expressions should not be empty");
context.logger.parserWarning(context.parser, "" + Derived::Identifier + " expressions should not be empty");
parser.expect<std::string>(")");

View File

@ -0,0 +1,81 @@
#ifndef __PLASP__UTILS__FORMATTING_H
#define __PLASP__UTILS__FORMATTING_H
#include <iostream>
#include <unistd.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Formatting
//
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class Color
{
Black = 0,
Red = 1,
Green = 2,
Yellow = 3,
Blue = 4,
Magenta = 5,
Cyan = 6,
White = 7
};
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class FontWeight
{
Normal = 0,
Bold = 1
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Format
{
Format(Color color, FontWeight fontWeight = FontWeight::Normal)
: color{color},
fontWeight{fontWeight}
{
}
Color color;
FontWeight fontWeight;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &ostream, const Format &format)
{
const auto fontWeightCode = static_cast<size_t>(format.fontWeight);
const auto colorCode = 30 + static_cast<size_t>(format.color);
return (ostream << "\033[" << fontWeightCode << ";" << colorCode << "m");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
class ResetFormat
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &ostream, const ResetFormat &)
{
return (ostream << "\033[0m");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -4,6 +4,7 @@
#include <string>
#include <plasp/utils/Parser.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
@ -37,6 +38,8 @@ class Logger
void setWarningLevel(WarningLevel warningLevel);
void exception(const std::string &errorType, const std::string &message);
void parserException(const Parser::Coordinate &coordinate, const std::string &message);
void parserWarning(const Parser &parser, const std::string &message);
private:

View File

@ -31,10 +31,11 @@ class ParserException: public std::exception
}
explicit ParserException(const utils::Parser &parser, const std::string &message)
: m_coordinate{parser.coordinate()},
m_message{message},
m_plainMessage{m_coordinate.sectionName + ":" + std::to_string(m_coordinate.row)
+ ":" + std::to_string(m_coordinate.column) + " " + m_message}
{
const auto coordinate = parser.coordinate();
m_message = coordinate.sectionName + ":" + std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) + " " + message;
}
~ParserException() throw()
@ -43,14 +44,23 @@ class ParserException: public std::exception
const char *what() const throw()
{
if (m_message.empty())
return "Unspecified parser error";
return m_plainMessage.c_str();
}
return m_message.c_str();
const Parser::Coordinate &coordinate() const
{
return m_coordinate;
}
const std::string &message() const
{
return m_message;
}
private:
Parser::Coordinate m_coordinate;
std::string m_message;
std::string m_plainMessage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -31,10 +31,11 @@ class ParserWarning: public std::exception
}
explicit ParserWarning(const utils::Parser &parser, const std::string &message)
: m_coordinate{parser.coordinate()},
m_message{message},
m_plainMessage{m_coordinate.sectionName + ":" + std::to_string(m_coordinate.row)
+ ":" + std::to_string(m_coordinate.column) + " " + m_message}
{
const auto coordinate = parser.coordinate();
m_message = coordinate.sectionName + ":" + std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) + " " + message;
}
~ParserWarning() throw()
@ -43,14 +44,23 @@ class ParserWarning: public std::exception
const char *what() const throw()
{
if (m_message.empty())
return "Unspecified parser warning";
return m_plainMessage.c_str();
}
return m_message.c_str();
const Parser::Coordinate &coordinate() const
{
return m_coordinate;
}
const std::string &message() const
{
return m_message;
}
private:
Parser::Coordinate m_coordinate;
std::string m_message;
std::string m_plainMessage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -188,7 +188,7 @@ void Description::findSections()
else
{
const auto sectionIdentifier = parser.parse<std::string>();
throw utils::ParserException(parser, "Unknown PDDL section \"" + sectionIdentifier + "\"");
throw utils::ParserException(parser, "Unknown PDDL section " + sectionIdentifier + "");
}
m_context.parser.skipWhiteSpace();

View File

@ -54,7 +54,7 @@ void Domain::findSections()
if (unique && sectionPosition != -1)
{
parser.seek(value);
throw utils::ParserException(parser, "Only one \":" + sectionName + "\" section allowed");
throw utils::ParserException(parser, "Only one :" + sectionName + " section allowed");
}
sectionPosition = value;
@ -95,7 +95,7 @@ void Domain::findSections()
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");
m_context.logger.parserWarning(parser, "Section type " + sectionIdentifier + " currently unsupported");
parser.seek(sectionIdentifierPosition);
}
@ -104,7 +104,7 @@ void Domain::findSections()
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(m_context.parser, "Unknown domain section \"" + sectionIdentifier + "\"");
throw utils::ParserException(m_context.parser, "Unknown domain section " + sectionIdentifier + "");
}
// Skip section for now and parse it later
@ -280,7 +280,7 @@ void Domain::checkRequirement(Requirement::Type requirementType) const
if (hasRequirement(requirementType))
return;
throw ConsistencyException("Requirement \"" + Requirement(requirementType).toPDDL() + "\" used but never declared");
throw ConsistencyException("Requirement " + Requirement(requirementType).toPDDL() + " used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -114,7 +114,7 @@ ExpressionPointer parseExpression(Context &context, ExpressionContext &expressio
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(context.parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
throw utils::ParserException(context.parser, "Expression type " + expressionIdentifier + " unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -186,7 +186,7 @@ ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(context.parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
throw utils::ParserException(context.parser, "Expression type " + expressionIdentifier + " unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -59,7 +59,7 @@ std::unique_ptr<InitialState> InitialState::parseDeclaration(Context &context,
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(parser, "Expression type \"" + expressionIdentifier + "\" unknown or not allowed in this context");
throw utils::ParserException(parser, "Expression type " + expressionIdentifier + " unknown or not allowed in this context");
};
parser.skipWhiteSpace();

View File

@ -53,7 +53,7 @@ void Problem::findSections()
if (unique && sectionPosition != -1)
{
parser.seek(value);
throw utils::ParserException(parser, "Only one \":" + sectionName + "\" section allowed");
throw utils::ParserException(parser, "Only one :" + sectionName + " section allowed");
}
sectionPosition = value;
@ -89,7 +89,7 @@ void Problem::findSections()
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.parserWarning(parser, "Section type \"" + sectionIdentifier + "\" currently unsupported");
m_context.logger.parserWarning(parser, "Section type " + sectionIdentifier + " currently unsupported");
parser.seek(sectionIdentifierPosition);
}
@ -98,7 +98,7 @@ void Problem::findSections()
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
throw utils::ParserException(m_context.parser, "Unknown problem section " + sectionIdentifier + "");
}
// Skip section for now and parse it later
@ -204,7 +204,7 @@ void Problem::parseDomainSection()
const auto domainName = parser.parseIdentifier(isIdentifier);
if (m_domain.name() != domainName)
throw utils::ParserException(parser, "Domains do not match (\"" + m_domain.name() + "\" and \"" + domainName + "\")");
throw utils::ParserException(parser, "Domains do not match (" + m_domain.name() + "” and “" + domainName + ")");
parser.expect<std::string>(")");
}
@ -261,7 +261,7 @@ void Problem::checkRequirement(Requirement::Type requirementType) const
if (hasRequirement(requirementType))
return;
throw ConsistencyException("Requirement \"" + Requirement(requirementType).toPDDL() + "\" used but never declared");
throw ConsistencyException("Requirement " + Requirement(requirementType).toPDDL() + " used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -89,12 +89,12 @@ Requirement Requirement::parse(Context &context)
const auto match = requirementTypesToPDDL.right.find(requirementName);
if (match == requirementTypesToPDDL.right.end())
throw utils::ParserException(context.parser, "Unknown PDDL requirement \"" + requirementName + "\"");
throw utils::ParserException(context.parser, "Unknown PDDL requirement " + requirementName + "");
const auto requirementType = match->second;
if (requirementType == Requirement::Type::GoalUtilities)
context.logger.parserWarning(context.parser, "Requirement \"goal-utilities\" is not part of the PDDL 3.1 specification");
context.logger.parserWarning(context.parser, "Requirement “goal-utilities” is not part of the PDDL 3.1 specification");
return Requirement(match->second);
}

View File

@ -225,7 +225,7 @@ void TranslatorASP::translateActions() const
else
{
if (precondition.expressionType() != Expression::Type::And)
throw utils::TranslatorException("Only \"and\" expressions and (negated) predicates supported as action preconditions currently");
throw utils::TranslatorException("Only “and” expressions and (negated) predicates supported as action preconditions currently");
const auto &andExpression = dynamic_cast<const expressions::And &>(precondition);
@ -251,7 +251,7 @@ void TranslatorASP::translateActions() const
else
{
if (effect.expressionType() != Expression::Type::And)
throw utils::TranslatorException("Only \"and\" expressions and (negated) predicates supported as action effects currently");
throw utils::TranslatorException("Only “and” expressions and (negated) predicates supported as action effects currently");
const auto &andExpression = dynamic_cast<const expressions::And &>(effect);

View File

@ -156,7 +156,7 @@ Constant *Constant::parseAndFind(Context &context, const Domain &domain)
if (constant != nullptr)
return constant;
throw utils::ParserException(context.parser, "Constant \"" + constantName + "\" used but never declared");
throw utils::ParserException(context.parser, "Constant " + constantName + " used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -177,7 +177,7 @@ Constant *Constant::parseAndFind(Context &context, const Problem &problem)
if (constant)
return constant;
throw utils::ParserException(context.parser, "Constant \"" + constantName + "\" used but never declared");
throw utils::ParserException(context.parser, "Constant " + constantName + " used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -122,11 +122,11 @@ PrimitiveType *PrimitiveType::parseAndFind(Context &context, Domain &domain)
// Only "object" is allowed as an implicit type
if (typeName == "object" || typeName == "objects")
{
context.logger.parserWarning(context.parser, "Primitive type \"" + typeName + "\" should be declared");
context.logger.parserWarning(context.parser, "Primitive type " + typeName + " should be declared");
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
}
else
throw utils::ParserException(context.parser, "Type \"" + typeName + "\" used but never declared");
throw utils::ParserException(context.parser, "Type " + typeName + " used but never declared");
return types.back().get();
}

View File

@ -26,7 +26,7 @@ UnsupportedPointer Unsupported::parse(Context &context)
expression->m_type = parser.parseIdentifier(isIdentifier);
context.logger.parserWarning(context.parser, "Expression type \"" + expression->m_type + "\" currently unsupported in this context");
context.logger.parserWarning(context.parser, "Expression type " + expression->m_type + " currently unsupported in this context");
skipSection(parser);

View File

@ -52,7 +52,7 @@ void Variable::parseDeclaration(Context &context, Variables &parameters)
});
if (match != parameters.cend())
throw utils::ParserException(context.parser, "Variable \"" + variable->m_name + "\" already declared in this scope");
throw utils::ParserException(context.parser, "Variable " + variable->m_name + " already declared in this scope");
// Flag variable for potentially upcoming type declaration
variable->setDirty();
@ -154,7 +154,7 @@ const Variable *Variable::parseAndFind(Context &context, const ExpressionContext
});
if (match == variables.cend())
throw utils::ParserException(context.parser, "Parameter \"" + variableName + "\" used but never declared");
throw utils::ParserException(context.parser, "Parameter " + variableName + " used but never declared");
return match->get();
}

View File

@ -56,7 +56,7 @@ Description Description::fromStream(std::istream &istream)
Description Description::fromFile(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
throw std::runtime_error("File does not exist: " + path.string() + "");
utils::Parser parser;
parser.readFile(path);

View File

@ -74,7 +74,7 @@ Value Value::fromSAS(utils::Parser &parser)
else if (sasSign == "NegatedAtom")
value.m_sign = Value::Sign::Negative;
else
throw utils::ParserException(parser, "Invalid value sign \"" + sasSign + "\"");
throw utils::ParserException(parser, "Invalid value sign " + sasSign + "");
try
{

View File

@ -1,5 +1,6 @@
#include <plasp/utils/Logger.h>
#include <plasp/utils/Formatting.h>
#include <plasp/utils/ParserWarning.h>
namespace plasp
@ -61,6 +62,56 @@ void Logger::setWarningLevel(WarningLevel warningLevel)
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::exception(const std::string &errorType, const std::string &message)
{
if (isatty(STDERR_FILENO))
{
std::cerr
<< Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
else
{
std::cerr
<< "error:"
<< " "
<< message
<< std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::parserException(const Parser::Coordinate &coordinate, const std::string &message)
{
if (isatty(STDERR_FILENO))
{
std::cerr
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " "
<< Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
else
{
std::cerr
<< coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< " "
<< "error:"
<< " "
<< message
<< std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::parserWarning(const Parser &parser, const std::string &message)
{
if (m_warningLevel == WarningLevel::Ignore)
@ -71,9 +122,28 @@ void Logger::parserWarning(const Parser &parser, const std::string &message)
const auto coordinate = parser.coordinate();
std::cerr << "Warning: " << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column)
<< " " << message << std::endl;
if (isatty(STDERR_FILENO))
{
std::cerr
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " "
<< Format(Color::Magenta, FontWeight::Bold) << "warning:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
else
{
std::cerr
<< coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< " "
<< "warning:"
<< " "
<< message
<< std::endl;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -79,7 +79,7 @@ void Parser::readStream(std::string streamName, std::istream &istream)
void Parser::readFile(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
throw std::runtime_error("File does not exist: " + path.string() + "");
std::ifstream fileStream(path.string(), std::ios::in);
@ -310,7 +310,7 @@ template<>
void Parser::expect<std::string>(const std::string &expectedValue)
{
if (!probe<std::string>(expectedValue))
throw ParserException(*this, "Expected \"" + expectedValue + "\"");
throw ParserException(*this, "Expected " + expectedValue + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -344,7 +344,7 @@ template<>
void Parser::expect<char>(const char &expectedValue)
{
if (!probe<char>(expectedValue))
throw ParserException(*this, std::string("Expected \"") + expectedValue + "\"");
throw ParserException(*this, std::string("Expected ") + expectedValue + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -439,7 +439,7 @@ template<>
void Parser::expect<int64_t>(const int64_t &expectedValue)
{
if (!probe<int64_t>(expectedValue))
throw ParserException(*this, "Expected \"" + std::to_string(expectedValue) + "\"");
throw ParserException(*this, "Expected " + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -448,7 +448,7 @@ template<>
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
{
if (!probe<uint64_t>(expectedValue))
throw ParserException(*this, "Expected \"" + std::to_string(expectedValue) + "\"");
throw ParserException(*this, "Expected " + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -523,7 +523,7 @@ void Parser::expect<bool>(const bool &expectedValue)
const auto value = parse<bool>();
if (value != expectedValue)
throw ParserException(*this, "Expected \"" + std::to_string(expectedValue) + "\"");
throw ParserException(*this, "Expected " + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,7 @@ class SASParserTests : public ::testing::Test
std::stringstream outputStream;
if (!fileStream.is_open())
throw std::runtime_error("Could not open file \"" + path + "\"");
throw std::runtime_error("Could not open file " + path + "");
outputStream << fileStream.rdbuf();