Made Parser seekable for easier maintenance.

This commit is contained in:
2016-06-07 18:41:01 +02:00
parent 27e76fc035
commit eea3272c56
11 changed files with 221 additions and 134 deletions

View File

@@ -18,9 +18,8 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Description::Description(std::istream &istream)
: m_parser(istream),
m_context(m_parser),
Description::Description()
: m_context(m_parser),
m_domain{std::make_unique<Domain>(Domain(m_context))},
m_problem{std::make_unique<Problem>(Problem(m_context, *m_domain))}
{
@@ -31,9 +30,9 @@ Description::Description(std::istream &istream)
Description Description::fromStream(std::istream &istream)
{
Description description(istream);
Description description;
description.m_parser.setFileName("std::cin");
description.m_parser.readStream("std::cin", istream);
description.parseContent();
description.checkConsistency();
@@ -47,29 +46,15 @@ Description Description::fromFiles(const std::vector<std::string> &paths)
{
BOOST_ASSERT(!paths.empty());
std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path + "\"");
});
std::ifstream fileStream;
Description description(fileStream);
Description description;
std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
fileStream.close();
fileStream.clear();
fileStream.open(path, std::ios::in);
description.m_parser.setFileName(path);
description.m_parser.resetPosition();
description.parseContent();
description.m_parser.readFile(path);
});
description.parseContent();
description.checkConsistency();
return description;
@@ -92,7 +77,7 @@ void Description::parseContent()
{
m_context.parser.skipWhiteSpace();
if (m_context.parser.atEndOfFile())
if (m_context.parser.atEndOfStream())
return;
m_context.parser.expect<std::string>("(");

View File

@@ -30,18 +30,11 @@ Description::Description()
Description Description::fromStream(std::istream &istream)
{
utils::Parser parser;
parser.readStream("std::cin", istream);
Description description;
utils::Parser parser(istream);
description.parseVersionSection(parser);
description.parseMetricSection(parser);
description.parseVariablesSection(parser);
description.parseMutexSection(parser);
description.parseInitialStateSection(parser);
description.parseGoalSection(parser);
description.parseOperatorSection(parser);
description.parseAxiomSection(parser);
description.parseContent(parser);
return description;
}
@@ -53,9 +46,13 @@ 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() + "\"");
std::ifstream fileStream(path.string(), std::ios::in);
utils::Parser parser;
parser.readFile(path);
return Description::fromStream(fileStream);
Description description;
description.parseContent(parser);
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -146,6 +143,20 @@ bool Description::usesConditionalEffects() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseContent(utils::Parser &parser)
{
parseVersionSection(parser);
parseMetricSection(parser);
parseVariablesSection(parser);
parseMutexSection(parser);
parseInitialStateSection(parser);
parseGoalSection(parser);
parseOperatorSection(parser);
parseAxiomSection(parser);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseVersionSection(utils::Parser &parser) const
{
parser.expect<std::string>("begin_version");

View File

@@ -27,12 +27,16 @@ void Logger::setPedantic(bool isPedantic)
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::parserWarning(const Parser &parser, const std::string &text)
void Logger::parserWarning(const Parser &parser, const std::string &message)
{
if (m_isPedantic)
throw ParserWarning(parser, text);
throw ParserWarning(parser, message);
std::cerr << "Warning: " << parser.fileName() << ":" << parser.row() << ":" << parser.column() << " " << text << std::endl;
const auto coordinate = parser.coordinate();
std::cerr << "Warning: " << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column)
<< " " << message << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,6 +1,7 @@
#include <plasp/utils/Parser.h>
#include <algorithm>
#include <fstream>
#include <boost/assert.hpp>
@@ -21,56 +22,116 @@ const std::istreambuf_iterator<char> Parser::EndOfFile = std::istreambuf_iterato
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Parser(std::istream &istream)
: m_istream(istream),
m_position(m_istream),
m_row{1},
m_column{1},
m_isCaseSensitive{true},
m_atEndOfFile{false}
Parser::Parser()
: m_isCaseSensitive{true}
{
std::setlocale(LC_NUMERIC, "C");
// Dont skip whitespace
istream.exceptions(std::istream::badbit);
m_stream.exceptions(std::istream::badbit);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::setFileName(std::string fileName)
Parser::Parser(std::string streamName, std::istream &istream)
: Parser()
{
m_fileName = fileName;
readStream(streamName, istream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Parser::fileName() const
void Parser::readStream(std::string streamName, std::istream &istream)
{
return m_fileName;
// Store position of new section
const auto position = m_stream.tellp();
m_streamDelimiters.push_back({position, streamName});
m_stream << istream.rdbuf();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::resetPosition()
void Parser::readFile(const boost::filesystem::path &path)
{
m_row = 1;
m_column = 1;
m_atEndOfFile = false;
m_position = std::istreambuf_iterator<char>(m_istream);
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
std::ifstream fileStream(path.string(), std::ios::in);
readStream(path.string(), fileStream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
size_t Parser::row() const
void Parser::reset()
{
return m_row;
m_stream.clear();
seek(std::ios::beg);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
size_t Parser::column() const
void Parser::seek(Position position)
{
return m_column;
m_stream.clear();
m_stream.seekg(position);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Position Parser::position() const
{
return m_stream.tellg();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Coordinate Parser::coordinate() const
{
const auto currentPosition = position();
// Find current section
auto currentFile = std::find_if(m_streamDelimiters.crbegin(), m_streamDelimiters.crend(),
[&](const auto &fileDelimiter)
{
return currentPosition >= fileDelimiter.position;
});
// If the parser is at the end of the stream, still count from the beginning of the last section
if (currentFile == m_streamDelimiters.crend())
currentFile = m_streamDelimiters.crbegin();
// Go back to beginning of section
m_stream.clear();
m_stream.seekg(currentFile->position);
size_t row = 1;
size_t column = 1;
// Compute the coordinate character by character
while (true)
{
if (currentPosition == -1 && atEndOfStream())
break;
else if (currentPosition >= 0 && position() >= currentPosition)
break;
const auto character = currentCharacter();
if (character == '\n')
{
row++;
column = 1;
}
else if (std::isblank(character) || std::isprint(character))
column++;
m_stream.ignore(1);
}
return {currentFile->sectionName, row, column};
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -84,29 +145,27 @@ void Parser::setCaseSensitive(bool isCaseSensitive)
char Parser::currentCharacter() const
{
checkStream();
if (m_isCaseSensitive)
return *m_position;
return m_stream.peek();
return std::tolower(*m_position);
return std::tolower(m_stream.peek());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Parser::atEndOfFile() const
bool Parser::atEndOfStream() const
{
return m_position.equal(EndOfFile);
return position() == -1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::checkStream() const
{
if (atEndOfFile())
if (atEndOfStream())
throw ParserException(*this, "Reading past end of file");
if (m_istream.fail())
if (m_stream.fail())
throw ParserException(*this);
}
@@ -115,18 +174,7 @@ void Parser::checkStream() const
void Parser::advance()
{
checkStream();
const auto character = currentCharacter();
if (character == '\n')
{
m_row++;
m_column = 1;
}
else if (std::isblank(character) || std::isprint(character))
m_column++;
m_position++;
m_stream.ignore(1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -246,7 +294,7 @@ uint64_t Parser::parseIntegerBody()
uint64_t value = 0;
while (!atEndOfFile())
while (!atEndOfStream())
{
const auto character = currentCharacter();