Made Parser seekable for easier maintenance.
This commit is contained in:
parent
27e76fc035
commit
eea3272c56
@ -28,7 +28,7 @@ class Description
|
||||
const Domain &domain() const;
|
||||
|
||||
private:
|
||||
Description(std::istream &istream);
|
||||
Description();
|
||||
|
||||
void parseContent();
|
||||
void parseSection();
|
||||
|
@ -47,6 +47,8 @@ class Description
|
||||
private:
|
||||
Description();
|
||||
|
||||
void parseContent(utils::Parser &parser);
|
||||
|
||||
void parseVersionSection(utils::Parser &parser) const;
|
||||
void parseMetricSection(utils::Parser &parser);
|
||||
void parseVariablesSection(utils::Parser &parser);
|
||||
|
@ -23,7 +23,7 @@ class Logger
|
||||
|
||||
void setPedantic(bool isPedantic = true);
|
||||
|
||||
void parserWarning(const Parser &parser, const std::string &text);
|
||||
void parserWarning(const Parser &parser, const std::string &message);
|
||||
|
||||
private:
|
||||
bool m_isPedantic;
|
||||
|
@ -3,8 +3,11 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace utils
|
||||
@ -19,22 +22,39 @@ namespace utils
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
explicit Parser(std::istream &istream);
|
||||
using Position = std::stringstream::pos_type;
|
||||
|
||||
void setFileName(std::string fileName);
|
||||
const std::string &fileName() const;
|
||||
struct Coordinate
|
||||
{
|
||||
std::string sectionName;
|
||||
size_t row;
|
||||
size_t column;
|
||||
};
|
||||
|
||||
void resetPosition();
|
||||
struct StreamDelimiter
|
||||
{
|
||||
Position position;
|
||||
std::string sectionName;
|
||||
};
|
||||
|
||||
size_t row() const;
|
||||
size_t column() const;
|
||||
public:
|
||||
explicit Parser();
|
||||
explicit Parser(std::string streamName, std::istream &istream);
|
||||
|
||||
void readStream(std::string streamName, std::istream &istream);
|
||||
void readFile(const boost::filesystem::path &path);
|
||||
|
||||
void reset();
|
||||
void seek(Position position);
|
||||
Position position() const;
|
||||
Coordinate coordinate() const;
|
||||
|
||||
void setCaseSensitive(bool isCaseInsensitive = true);
|
||||
|
||||
char currentCharacter() const;
|
||||
void advance();
|
||||
bool advanceIf(char expectedCharacter);
|
||||
bool atEndOfFile() const;
|
||||
bool atEndOfStream() const;
|
||||
|
||||
template<typename Type>
|
||||
Type parse();
|
||||
@ -64,16 +84,11 @@ class Parser
|
||||
|
||||
uint64_t parseIntegerBody();
|
||||
|
||||
std::istream &m_istream;
|
||||
std::string m_fileName;
|
||||
std::istreambuf_iterator<char> m_position;
|
||||
mutable std::stringstream m_stream;
|
||||
|
||||
size_t m_row;
|
||||
size_t m_column;
|
||||
std::vector<StreamDelimiter> m_streamDelimiters;
|
||||
|
||||
bool m_isCaseSensitive;
|
||||
|
||||
bool m_atEndOfFile;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -116,7 +131,7 @@ void Parser::skipWhiteSpace(WhiteSpacePredicate whiteSpacePredicate)
|
||||
{
|
||||
checkStream();
|
||||
|
||||
while (!atEndOfFile() && whiteSpacePredicate(currentCharacter()))
|
||||
while (!atEndOfStream() && whiteSpacePredicate(currentCharacter()))
|
||||
advance();
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,10 @@ class ParserException: public std::exception
|
||||
}
|
||||
|
||||
explicit ParserException(const utils::Parser &parser, const std::string &message)
|
||||
: m_message{parser.fileName() + ":" + std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + " " + message}
|
||||
{
|
||||
const auto coordinate = parser.coordinate();
|
||||
|
||||
m_message = coordinate.sectionName + ":" + std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) + " " + message;
|
||||
}
|
||||
|
||||
~ParserException() throw()
|
||||
|
@ -31,8 +31,10 @@ class ParserWarning: public std::exception
|
||||
}
|
||||
|
||||
explicit ParserWarning(const utils::Parser &parser, const std::string &message)
|
||||
: m_message{parser.fileName() + ":" + std::to_string(parser.row()) + ":" + std::to_string(parser.column()) + " " + message}
|
||||
{
|
||||
const auto coordinate = parser.coordinate();
|
||||
|
||||
m_message = coordinate.sectionName + ":" + std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) + " " + message;
|
||||
}
|
||||
|
||||
~ParserWarning() throw()
|
||||
|
@ -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>("(");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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");
|
||||
|
||||
// Don’t 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();
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
TEST(UtilsTests, ParseSimple)
|
||||
{
|
||||
std::stringstream s("identifier 5 \n-51\t 0 1 expected unexpected");
|
||||
plasp::utils::Parser p(s);
|
||||
plasp::utils::Parser p("input", s);
|
||||
|
||||
ASSERT_EQ(p.parse<std::string>(), "identifier");
|
||||
ASSERT_EQ(p.parse<size_t>(), 5u);
|
||||
@ -19,6 +19,8 @@ TEST(UtilsTests, ParseSimple)
|
||||
|
||||
ASSERT_NO_THROW(p.expect<std::string>("expected"));
|
||||
ASSERT_THROW(p.expect<std::string>("expected"), plasp::utils::ParserException);
|
||||
|
||||
// TODO: test case-insensitive input
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -26,7 +28,7 @@ TEST(UtilsTests, ParseSimple)
|
||||
TEST(UtilsTests, ParseUnsignedNumbers)
|
||||
{
|
||||
std::stringstream s("100 200 -300 -400");
|
||||
plasp::utils::Parser p(s);
|
||||
plasp::utils::Parser p("input", s);
|
||||
|
||||
ASSERT_EQ(p.parse<int>(), 100);
|
||||
ASSERT_EQ(p.parse<size_t>(), 200u);
|
||||
@ -39,13 +41,13 @@ TEST(UtilsTests, ParseUnsignedNumbers)
|
||||
TEST(UtilsTests, ParseEndOfFile)
|
||||
{
|
||||
std::stringstream s1("test");
|
||||
plasp::utils::Parser p1(s1);
|
||||
plasp::utils::Parser p1("input", s1);
|
||||
|
||||
ASSERT_NO_THROW(p1.expect<std::string>("test"));
|
||||
ASSERT_THROW(p1.parse<std::string>(), plasp::utils::ParserException);
|
||||
|
||||
std::stringstream s2("test1 test2 test3");
|
||||
plasp::utils::Parser p2(s2);
|
||||
plasp::utils::Parser p2("input", s2);
|
||||
|
||||
ASSERT_NO_THROW(p2.expect<std::string>("test1"));
|
||||
ASSERT_NO_THROW(p2.expect<std::string>("test2"));
|
||||
@ -53,13 +55,13 @@ TEST(UtilsTests, ParseEndOfFile)
|
||||
ASSERT_THROW(p2.parse<std::string>(), plasp::utils::ParserException);
|
||||
|
||||
std::stringstream s3("-127");
|
||||
plasp::utils::Parser p3(s3);
|
||||
plasp::utils::Parser p3("input", s3);
|
||||
|
||||
p3.expect<int>(-127);
|
||||
ASSERT_THROW(p3.parse<int>(), plasp::utils::ParserException);
|
||||
|
||||
std::stringstream s4("128 -1023 -4095");
|
||||
plasp::utils::Parser p4(s4);
|
||||
plasp::utils::Parser p4("input", s4);
|
||||
|
||||
ASSERT_NO_THROW(p4.expect<size_t>(128));
|
||||
ASSERT_NO_THROW(p4.expect<int>(-1023));
|
||||
@ -67,13 +69,13 @@ TEST(UtilsTests, ParseEndOfFile)
|
||||
ASSERT_THROW(p4.parse<int>(), plasp::utils::ParserException);
|
||||
|
||||
std::stringstream s5("0");
|
||||
plasp::utils::Parser p5(s5);
|
||||
plasp::utils::Parser p5("input", s5);
|
||||
|
||||
p5.expect<bool>(false);
|
||||
ASSERT_THROW(p5.parse<bool>(), plasp::utils::ParserException);
|
||||
|
||||
std::stringstream s6("0 1 0");
|
||||
plasp::utils::Parser p6(s6);
|
||||
plasp::utils::Parser p6("input", s6);
|
||||
|
||||
ASSERT_NO_THROW(p6.expect<bool>(false));
|
||||
ASSERT_NO_THROW(p6.expect<bool>(true));
|
||||
@ -86,74 +88,90 @@ TEST(UtilsTests, ParseEndOfFile)
|
||||
TEST(UtilsTests, ParserPosition)
|
||||
{
|
||||
std::stringstream s("123 \n4\ntest1\n test2\ntest3 \ntest4\n\n\n\n");
|
||||
plasp::utils::Parser p(s);
|
||||
plasp::utils::Parser p("input", s);
|
||||
|
||||
ASSERT_EQ(p.row(), 1u);
|
||||
ASSERT_EQ(p.column(), 1u);
|
||||
plasp::utils::Parser::Coordinate c;
|
||||
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 1u);
|
||||
ASSERT_EQ(c.column, 1u);
|
||||
ASSERT_EQ(p.currentCharacter(), '1');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_EQ(p.row(), 1u);
|
||||
ASSERT_EQ(p.column(), 2u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 1u);
|
||||
ASSERT_EQ(c.column, 2u);
|
||||
ASSERT_EQ(p.currentCharacter(), '2');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_EQ(p.row(), 1u);
|
||||
ASSERT_EQ(p.column(), 3u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 1u);
|
||||
ASSERT_EQ(c.column, 3u);
|
||||
ASSERT_EQ(p.currentCharacter(), '3');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_EQ(p.row(), 1u);
|
||||
ASSERT_EQ(p.column(), 4u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 1u);
|
||||
ASSERT_EQ(c.column, 4u);
|
||||
ASSERT_EQ(p.currentCharacter(), ' ');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_EQ(p.row(), 1u);
|
||||
ASSERT_EQ(p.column(), 5u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 1u);
|
||||
ASSERT_EQ(c.column, 5u);
|
||||
ASSERT_EQ(p.currentCharacter(), '\n');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_EQ(p.row(), 2u);
|
||||
ASSERT_EQ(p.column(), 1u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 2u);
|
||||
ASSERT_EQ(c.column, 1u);
|
||||
ASSERT_EQ(p.currentCharacter(), '4');
|
||||
|
||||
ASSERT_NO_THROW(p.advance());
|
||||
|
||||
ASSERT_NO_THROW(p.expect<std::string>("test1"));
|
||||
|
||||
ASSERT_EQ(p.row(), 3u);
|
||||
ASSERT_EQ(p.column(), 6u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 3u);
|
||||
ASSERT_EQ(c.column, 6u);
|
||||
|
||||
ASSERT_NO_THROW(p.expect<std::string>("test2"));
|
||||
|
||||
ASSERT_EQ(p.row(), 4u);
|
||||
ASSERT_EQ(p.column(), 7u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 4u);
|
||||
ASSERT_EQ(c.column, 7u);
|
||||
|
||||
ASSERT_NO_THROW(p.expect<std::string>("test3"));
|
||||
|
||||
ASSERT_EQ(p.row(), 5u);
|
||||
ASSERT_EQ(p.column(), 6u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 5u);
|
||||
ASSERT_EQ(c.column, 6u);
|
||||
|
||||
ASSERT_NO_THROW(p.skipLine());
|
||||
|
||||
ASSERT_EQ(p.row(), 6u);
|
||||
ASSERT_EQ(p.column(), 1u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 6u);
|
||||
ASSERT_EQ(c.column, 1u);
|
||||
|
||||
ASSERT_NO_THROW(p.skipLine());
|
||||
|
||||
ASSERT_EQ(p.row(), 7u);
|
||||
ASSERT_EQ(p.column(), 1u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 7u);
|
||||
ASSERT_EQ(c.column, 1u);
|
||||
|
||||
ASSERT_NO_THROW(p.skipWhiteSpace());
|
||||
|
||||
ASSERT_TRUE(p.atEndOfFile());
|
||||
ASSERT_EQ(p.row(), 10u);
|
||||
ASSERT_EQ(p.column(), 1u);
|
||||
c = p.coordinate();
|
||||
ASSERT_EQ(c.row, 10u);
|
||||
ASSERT_EQ(c.column, 1u);
|
||||
ASSERT_TRUE(p.atEndOfStream());
|
||||
|
||||
// TODO: test parser with multiple sections
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Reference in New Issue
Block a user