Refactoring of Parser class with std::istreambuf_iterator.

This commit is contained in:
Patrick Lühne 2016-05-30 12:54:56 +02:00
parent 8d879344f2
commit 4d984d32c3
2 changed files with 23 additions and 27 deletions

View File

@ -18,16 +18,13 @@ namespace utils
class Parser class Parser
{ {
public:
using CharacterType = unsigned char;
public: public:
explicit Parser(std::istream &istream); explicit Parser(std::istream &istream);
size_t row() const; size_t row() const;
size_t column() const; size_t column() const;
CharacterType currentCharacter() const; char currentCharacter() const;
void advance(); void advance();
bool atEndOfFile() const; bool atEndOfFile() const;
@ -52,17 +49,17 @@ class Parser
std::string getLine(); std::string getLine();
private: private:
static const std::istream_iterator<CharacterType> EndOfFile; static const std::istreambuf_iterator<char> EndOfFile;
private: private:
void checkStream() const; void checkStream() const;
bool advanceIf(CharacterType expectedCharacter); bool advanceIf(char expectedCharacter);
uint64_t parseIntegerBody(); uint64_t parseIntegerBody();
std::istream &m_istream; std::istream &m_istream;
std::istream_iterator<CharacterType> m_position; std::istreambuf_iterator<char> m_position;
size_t m_row; size_t m_row;
size_t m_column; size_t m_column;
@ -81,7 +78,7 @@ std::string Parser::parseIdentifier(CharacterPredicate characterPredicate, White
while (true) while (true)
{ {
const auto character = *m_position; const auto character = currentCharacter();
if (!characterPredicate(character)) if (!characterPredicate(character))
return value; return value;
@ -110,7 +107,7 @@ void Parser::skipWhiteSpace(WhiteSpacePredicate whiteSpacePredicate)
{ {
checkStream(); checkStream();
while (m_position != EndOfFile && whiteSpacePredicate(*m_position)) while (!atEndOfFile() && whiteSpacePredicate(currentCharacter()))
advance(); advance();
} }

View File

@ -17,7 +17,7 @@ namespace utils
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
const std::istream_iterator<Parser::CharacterType> Parser::EndOfFile = std::istream_iterator<Parser::CharacterType>(); const std::istreambuf_iterator<char> Parser::EndOfFile = std::istreambuf_iterator<char>();
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -30,10 +30,9 @@ Parser::Parser(std::istream &istream)
{ {
std::setlocale(LC_NUMERIC, "C"); std::setlocale(LC_NUMERIC, "C");
istream.exceptions(std::istream::badbit);
// Dont skip whitespace // Dont skip whitespace
istream >> std::noskipws; istream >> std::noskipws;
istream.exceptions(std::istream::badbit);
checkStream(); checkStream();
} }
@ -54,7 +53,7 @@ size_t Parser::column() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::CharacterType Parser::currentCharacter() const char Parser::currentCharacter() const
{ {
checkStream(); checkStream();
@ -65,14 +64,14 @@ Parser::CharacterType Parser::currentCharacter() const
bool Parser::atEndOfFile() const bool Parser::atEndOfFile() const
{ {
return m_position == EndOfFile; return m_position.equal(EndOfFile);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::checkStream() const void Parser::checkStream() const
{ {
if (m_position == EndOfFile) if (atEndOfFile())
throw ParserException(m_row, m_column, "Reading past end of file"); throw ParserException(m_row, m_column, "Reading past end of file");
if (m_istream.fail()) if (m_istream.fail())
@ -85,7 +84,7 @@ void Parser::advance()
{ {
checkStream(); checkStream();
const auto character = *m_position; const auto character = currentCharacter();
if (character == '\n') if (character == '\n')
{ {
@ -100,11 +99,11 @@ void Parser::advance()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
bool Parser::advanceIf(CharacterType expectedCharacter) bool Parser::advanceIf(char expectedCharacter)
{ {
checkStream(); checkStream();
if (*m_position != expectedCharacter) if (currentCharacter() != expectedCharacter)
return false; return false;
advance(); advance();
@ -129,7 +128,7 @@ void Parser::skipLine()
{ {
checkStream(); checkStream();
while (*m_position != '\n') while (currentCharacter() != '\n')
advance(); advance();
advance(); advance();
@ -145,7 +144,7 @@ std::string Parser::getLine()
while (true) while (true)
{ {
const auto character = *m_position; const auto character = currentCharacter();
advance(); advance();
@ -171,7 +170,7 @@ std::string Parser::parse<std::string>()
while (true) while (true)
{ {
const auto character = *m_position; const auto character = currentCharacter();
if (std::isspace(character)) if (std::isspace(character))
break; break;
@ -195,10 +194,10 @@ void Parser::expect<std::string>(const std::string &expectedValue)
std::for_each(expectedValue.cbegin(), expectedValue.cend(), std::for_each(expectedValue.cbegin(), expectedValue.cend(),
[&](const auto &expectedCharacter) [&](const auto &expectedCharacter)
{ {
const auto character = *m_position; const auto character = static_cast<char>(this->currentCharacter());
if (character != expectedCharacter) if (character != expectedCharacter)
throw ParserException(m_row, m_column, "Unexpected string, expected " + expectedValue); throw ParserException(m_row, m_column, "Unexpected string, expected " + expectedValue + " (expected " + expectedCharacter + ", got " + character + ")");
this->advance(); this->advance();
}); });
@ -210,14 +209,14 @@ uint64_t Parser::parseIntegerBody()
{ {
checkStream(); checkStream();
if (!std::isdigit(*m_position)) if (!std::isdigit(currentCharacter()))
throw ParserException(m_row, m_column, "Could not parse integer value"); throw ParserException(m_row, m_column, "Could not parse integer value");
uint64_t value = 0; uint64_t value = 0;
while (m_position != std::istream_iterator<CharacterType>()) while (!atEndOfFile())
{ {
const auto character = *m_position; const auto character = currentCharacter();
if (!std::isdigit(character)) if (!std::isdigit(character))
break; break;
@ -252,7 +251,7 @@ uint64_t Parser::parse<uint64_t>()
{ {
skipWhiteSpace(); skipWhiteSpace();
if (*m_position == '-') if (currentCharacter() == '-')
throw ParserException(m_row, m_column, "Expected unsigned integer, got signed one"); throw ParserException(m_row, m_column, "Expected unsigned integer, got signed one");
return parseIntegerBody(); return parseIntegerBody();