Refactoring of Parser class with std::istreambuf_iterator.
This commit is contained in:
parent
8d879344f2
commit
4d984d32c3
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
|
|
||||||
// Don’t skip whitespace
|
// Don’t 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();
|
||||||
|
Reference in New Issue
Block a user