Restructure StreamProxies to use common basis for matching directives

This commit is contained in:
Jan 2021-02-14 10:26:18 +01:00
parent e277de4517
commit efa39a8ac3
10 changed files with 244 additions and 115 deletions

View File

@ -0,0 +1,111 @@
#include "AbstractDirectiveStreamProxy.h"
TokenPos AbstractDirectiveStreamProxy::CreatePos(const ParserLine& line, const unsigned position)
{
return TokenPos(line.m_filename.get(), line.m_line_number, static_cast<int>(position + 1));
}
bool AbstractDirectiveStreamProxy::SkipWhitespace(const ParserLine& line, unsigned& position)
{
while(true)
{
if (position >= line.m_line.size())
return false;
if (isspace(line.m_line[position]))
position++;
else
break;
}
return true;
}
bool AbstractDirectiveStreamProxy::ExtractInteger(const ParserLine& line, unsigned& position, int& value)
{
if (position >= line.m_line.size())
return false;
const auto* startPosition = &line.m_line[position];
char* endPosition;
value = strtol(startPosition, &endPosition, 0);
const auto len = endPosition - startPosition;
if(len > 0)
{
position += len;
return true;
}
return false;
}
bool AbstractDirectiveStreamProxy::ExtractIdentifier(const ParserLine& line, unsigned& position)
{
auto firstChar = true;
while (true)
{
if (position >= line.m_line.size())
return !firstChar;
const auto c = line.m_line[position];
if (isalpha(c)
|| c == '_'
|| firstChar && isdigit(c))
{
position++;
}
else
return !firstChar;
firstChar = false;
}
}
bool AbstractDirectiveStreamProxy::MatchCharacter(const ParserLine& line, unsigned& position, char c)
{
if (position < line.m_line.size() && line.m_line[position] == c)
{
position++;
return true;
}
return false;
}
bool AbstractDirectiveStreamProxy::MatchNextCharacter(const ParserLine& line, unsigned& position, char c)
{
return SkipWhitespace(line, position) && MatchCharacter(line, position, c);
}
bool AbstractDirectiveStreamProxy::MatchString(const ParserLine& line, unsigned& position, const char* str, unsigned len)
{
if (line.m_line.compare(position, len, str) == 0)
{
position += len;
return true;
}
return false;
}
bool AbstractDirectiveStreamProxy::MatchNextString(const ParserLine& line, unsigned& position, const char* str, unsigned len)
{
return SkipWhitespace(line, position) && MatchString(line, position, str, len);
}
bool AbstractDirectiveStreamProxy::FindDirective(const ParserLine& line, unsigned& directivePosition)
{
directivePosition = 0;
for (; directivePosition < line.m_line.size(); directivePosition++)
{
const auto c = line.m_line[directivePosition];
if (isspace(c))
continue;
return c == '#';
}
return false;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "Parsing/IParserLineStream.h"
#include "Parsing/TokenPos.h"
class AbstractDirectiveStreamProxy : public IParserLineStream
{
protected:
AbstractDirectiveStreamProxy() = default;
static TokenPos CreatePos(const ParserLine& line, unsigned position);
static bool SkipWhitespace(const ParserLine& line, unsigned& position);
static bool ExtractInteger(const ParserLine& line, unsigned& position, int& value);
static bool ExtractIdentifier(const ParserLine& line, unsigned& position);
static bool MatchCharacter(const ParserLine& line, unsigned& position, char c);
static bool MatchNextCharacter(const ParserLine& line, unsigned& position, char c);
static bool MatchString(const ParserLine& line, unsigned& position, const char* str, unsigned len);
static bool MatchNextString(const ParserLine& line, unsigned& position, const char* str, unsigned len);
static bool FindDirective(const ParserLine& line, unsigned& directivePosition);
};

View File

@ -11,67 +11,37 @@ DefinesStreamProxy::DefinesStreamProxy(IParserLineStream* stream)
{ {
} }
bool DefinesStreamProxy::FindDirective(const ParserLine& line, unsigned& directivePosition) bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, unsigned directivePosition)
{ {
directivePosition = 0; if (!MatchString(line, directivePosition, DEFINE_DIRECTIVE, std::char_traits<char>::length(DEFINE_DIRECTIVE)))
for (; directivePosition < line.m_line.size(); directivePosition++)
{
const auto c = line.m_line[directivePosition];
if (isspace(c))
continue;
return c == '#';
}
return false;
}
bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsigned directivePosition)
{
constexpr auto directiveLength = std::char_traits<char>::length(DEFINE_DIRECTIVE);
if (line.m_line.compare(directivePosition + 1, directiveLength, DEFINE_DIRECTIVE) != 0)
return false; return false;
const auto nameStartPos = directivePosition + directiveLength + 1; const auto nameStartPos = directivePosition;
auto nameEndPos = nameStartPos; if (!ExtractIdentifier(line, directivePosition))
for (; nameEndPos < line.m_line.size(); nameEndPos++) throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name.");
{
if (isspace(line.m_line[nameEndPos]))
break;
}
if (nameStartPos == nameEndPos) const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos);
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(nameStartPos + 1)), "Defines need a name.");
const auto name = line.m_line.substr(nameStartPos, nameEndPos - nameStartPos);
std::string value; std::string value;
if (nameEndPos < line.m_line.size()) if (directivePosition < line.m_line.size())
value = line.m_line.substr(nameEndPos + 1); value = line.m_line.substr(directivePosition + 1);
m_defines[name] = value; m_defines[name] = value;
return true; return true;
} }
bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsigned directivePosition) bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, unsigned directivePosition)
{ {
constexpr auto directiveLength = std::char_traits<char>::length(UNDEF_DIRECTIVE); if (!MatchString(line, directivePosition, UNDEF_DIRECTIVE, std::char_traits<char>::length(UNDEF_DIRECTIVE)))
if (line.m_line.compare(directivePosition + 1, directiveLength, UNDEF_DIRECTIVE) != 0)
return false; return false;
const auto nameStartPos = directivePosition + directiveLength + 1; if (!SkipWhitespace(line, directivePosition))
auto nameEndPos = nameStartPos; throw ParsingException(CreatePos(line, directivePosition), "Cannot undef without a name.");
for (; nameEndPos < line.m_line.size(); nameEndPos++)
{
if (isspace(line.m_line[nameEndPos]))
break;
}
if (nameStartPos == nameEndPos) const auto nameStartPos = directivePosition;
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(nameStartPos + 1)), "Cannot undef without a name."); if (!ExtractIdentifier(line, directivePosition))
throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name.");
const auto name = line.m_line.substr(nameStartPos, nameEndPos - nameStartPos); const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos);
const auto entry = m_defines.find(name); const auto entry = m_defines.find(name);
if (entry != m_defines.end()) if (entry != m_defines.end())
@ -80,18 +50,14 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig
return true; return true;
} }
bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsigned directivePosition) bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, unsigned directivePosition)
{ {
constexpr auto directiveLengthIfdef = std::char_traits<char>::length(IFDEF_DIRECTIVE);
constexpr auto directiveLengthIfndef = std::char_traits<char>::length(IFNDEF_DIRECTIVE);
auto len = directiveLengthIfdef;
auto reverse = false; auto reverse = false;
if (line.m_line.compare(directivePosition + 1, directiveLengthIfdef, IFDEF_DIRECTIVE) != 0) if(!MatchString(line, directivePosition, IFDEF_DIRECTIVE, std::char_traits<char>::length(IFDEF_DIRECTIVE)))
{ {
if (line.m_line.compare(directivePosition + 1, directiveLengthIfndef, IFNDEF_DIRECTIVE) != 0) if (!MatchString(line, directivePosition, IFNDEF_DIRECTIVE, std::char_traits<char>::length(IFNDEF_DIRECTIVE)))
return false; return false;
len = directiveLengthIfndef;
reverse = true; reverse = true;
} }
@ -101,18 +67,14 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig
return true; return true;
} }
const auto nameStartPos = directivePosition + len + 1; if (!SkipWhitespace(line, directivePosition))
auto nameEndPos = nameStartPos; throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name.");
for (; nameEndPos < line.m_line.size(); nameEndPos++)
{
if (isspace(line.m_line[nameEndPos]))
break;
}
if (nameStartPos == nameEndPos) const auto nameStartPos = directivePosition;
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(nameStartPos + 1)), "Cannot ifdef without a name."); if(!ExtractIdentifier(line, directivePosition))
throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name.");
const auto name = line.m_line.substr(nameStartPos, nameEndPos - nameStartPos); const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos);
const auto entry = m_defines.find(name); const auto entry = m_defines.find(name);
if (entry != m_defines.end()) if (entry != m_defines.end())
@ -123,10 +85,9 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig
return true; return true;
} }
bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, const unsigned directivePosition) bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, unsigned directivePosition)
{ {
constexpr auto directiveLength = std::char_traits<char>::length(ELSE_DIRECTIVE); if (!MatchString(line, directivePosition, ELSE_DIRECTIVE, std::char_traits<char>::length(ELSE_DIRECTIVE)))
if (line.m_line.compare(directivePosition + 1, directiveLength, ELSE_DIRECTIVE) != 0)
return false; return false;
if (m_ignore_depth > 0) if (m_ignore_depth > 0)
@ -135,15 +96,14 @@ bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, const unsign
if (!m_modes.empty()) if (!m_modes.empty())
m_modes.top() = !m_modes.top(); m_modes.top() = !m_modes.top();
else else
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(directivePosition + 1)), "Cannot use else without ifdef"); throw ParsingException(CreatePos(line, directivePosition), "Cannot use else without ifdef");
return true; return true;
} }
bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsigned directivePosition) bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, unsigned directivePosition)
{ {
constexpr auto directiveLength = std::char_traits<char>::length(ENDIF_DIRECTIVE); if (!MatchString(line, directivePosition, ENDIF_DIRECTIVE, std::char_traits<char>::length(ENDIF_DIRECTIVE)))
if (line.m_line.compare(directivePosition + 1, directiveLength, ENDIF_DIRECTIVE) != 0)
return false; return false;
if (m_ignore_depth > 0) if (m_ignore_depth > 0)
@ -155,7 +115,7 @@ bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsig
if (!m_modes.empty()) if (!m_modes.empty())
m_modes.pop(); m_modes.pop();
else else
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(directivePosition + 1)), "Cannot use endif without ifdef"); throw ParsingException(CreatePos(line, directivePosition), "Cannot use endif without ifdef");
return true; return true;
} }
@ -167,9 +127,16 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line)
if (!FindDirective(line, directivePos)) if (!FindDirective(line, directivePos))
return false; return false;
return MatchDefineDirective(line, directivePos) directivePos++;
|| MatchUndefDirective(line, directivePos)
|| MatchIfdefDirective(line, directivePos) if(m_modes.empty() || m_modes.top() == true)
{
if (MatchDefineDirective(line, directivePos)
|| MatchUndefDirective(line, directivePos))
return true;
}
return MatchIfdefDirective(line, directivePos)
|| MatchElseDirective(line, directivePos) || MatchElseDirective(line, directivePos)
|| MatchEndifDirective(line, directivePos); || MatchEndifDirective(line, directivePos);
} }

View File

@ -3,9 +3,10 @@
#include <unordered_map> #include <unordered_map>
#include <stack> #include <stack>
#include "AbstractDirectiveStreamProxy.h"
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
class DefinesStreamProxy final : public IParserLineStream class DefinesStreamProxy final : public AbstractDirectiveStreamProxy
{ {
static constexpr const char* DEFINE_DIRECTIVE = "define "; static constexpr const char* DEFINE_DIRECTIVE = "define ";
static constexpr const char* UNDEF_DIRECTIVE = "undef "; static constexpr const char* UNDEF_DIRECTIVE = "undef ";
@ -14,12 +15,11 @@ class DefinesStreamProxy final : public IParserLineStream
static constexpr const char* ELSE_DIRECTIVE = "else"; static constexpr const char* ELSE_DIRECTIVE = "else";
static constexpr const char* ENDIF_DIRECTIVE = "endif"; static constexpr const char* ENDIF_DIRECTIVE = "endif";
std::unordered_map<std::string, std::string> m_defines;
IParserLineStream* const m_stream; IParserLineStream* const m_stream;
std::unordered_map<std::string, std::string> m_defines;
std::stack<bool> m_modes; std::stack<bool> m_modes;
unsigned m_ignore_depth; unsigned m_ignore_depth;
_NODISCARD static bool FindDirective(const ParserLine& line, unsigned& directivePosition);
_NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directivePosition); _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directivePosition);
_NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directivePosition); _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directivePosition);
_NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directivePosition); _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directivePosition);

View File

@ -20,7 +20,7 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const
while (isspace(line.m_line[currentPos])) while (isspace(line.m_line[currentPos]))
{ {
if (currentPos++ >= line.m_line.size()) if (currentPos++ >= line.m_line.size())
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR); throw ParsingException(CreatePos(line, currentPos - 1), INCLUDE_QUOTES_ERROR);
} }
if (line.m_line[currentPos] == '"') if (line.m_line[currentPos] == '"')
@ -28,7 +28,7 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const
else if (line.m_line[currentPos] == '<') else if (line.m_line[currentPos] == '<')
isDoubleQuotes = false; isDoubleQuotes = false;
else else
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR); throw ParsingException(CreatePos(line, currentPos - 1), INCLUDE_QUOTES_ERROR);
filenameStartPosition = ++currentPos; filenameStartPosition = ++currentPos;
filenameEndPosition = 0; filenameEndPosition = 0;
@ -40,7 +40,7 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const
if (c == '"') if (c == '"')
{ {
if (!isDoubleQuotes) if (!isDoubleQuotes)
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), ""); throw ParsingException(CreatePos(line, currentPos - 1), "");
filenameEndPosition = currentPos; filenameEndPosition = currentPos;
return true; return true;
} }
@ -48,7 +48,7 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const
if (c == '>') if (c == '>')
{ {
if (isDoubleQuotes) if (isDoubleQuotes)
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR); throw ParsingException(CreatePos(line, currentPos - 1), INCLUDE_QUOTES_ERROR);
filenameEndPosition = currentPos; filenameEndPosition = currentPos;
return true; return true;
} }
@ -57,20 +57,18 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const
return false; return false;
} }
bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const unsigned directivePosition) const bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, unsigned directivePosition) const
{ {
constexpr auto directiveLength = std::char_traits<char>::length(INCLUDE_DIRECTIVE); if (!MatchString(line, directivePosition, INCLUDE_DIRECTIVE, std::char_traits<char>::length(INCLUDE_DIRECTIVE)))
if (line.m_line.compare(directivePosition + 1, directiveLength, INCLUDE_DIRECTIVE) != 0)
return false; return false;
const auto currentPos = directivePosition + directiveLength + 1;
unsigned filenameStart, filenameEnd; unsigned filenameStart, filenameEnd;
if (!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd)) if (!ExtractIncludeFilename(line, directivePosition, filenameStart, filenameEnd))
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR); throw ParsingException(TokenPos(line.m_filename, line.m_line_number, directivePosition), INCLUDE_QUOTES_ERROR);
if (filenameEnd <= filenameStart) if (filenameEnd <= filenameStart)
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), "No filename specified"); throw ParsingException(CreatePos(line, directivePosition), "No filename specified");
const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart); const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart);
@ -78,16 +76,15 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const u
{ {
std::ostringstream errorStr; std::ostringstream errorStr;
errorStr << "Could not include file \"" << filename << "\""; errorStr << "Could not include file \"" << filename << "\"";
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), errorStr.str()); throw ParsingException(CreatePos(line, directivePosition), errorStr.str());
} }
return true; return true;
} }
bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, const unsigned directivePosition) bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, unsigned directivePosition)
{ {
constexpr auto directiveLength = std::char_traits<char>::length(PRAGMA_ONCE_DIRECTIVE); if(!MatchString(line, directivePosition, PRAGMA_ONCE_DIRECTIVE, std::char_traits<char>::length(PRAGMA_ONCE_DIRECTIVE)))
if (line.m_line.compare(directivePosition + 1, directiveLength, PRAGMA_ONCE_DIRECTIVE) != 0)
return false; return false;
const auto absolutePath = absolute(fs::path(line.m_filename.get())); const auto absolutePath = absolute(fs::path(line.m_filename.get()));
@ -102,22 +99,6 @@ bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, cons
return true; return true;
} }
bool IncludingStreamProxy::FindDirective(const ParserLine& line, unsigned& directivePosition)
{
directivePosition = 0;
for (; directivePosition < line.m_line.size(); directivePosition++)
{
const auto c = line.m_line[directivePosition];
if (isspace(c))
continue;
return c == '#';
}
return false;
}
bool IncludingStreamProxy::MatchDirectives(const ParserLine& line) bool IncludingStreamProxy::MatchDirectives(const ParserLine& line)
{ {
unsigned directivePos; unsigned directivePos;
@ -125,6 +106,7 @@ bool IncludingStreamProxy::MatchDirectives(const ParserLine& line)
if (!FindDirective(line, directivePos)) if (!FindDirective(line, directivePos))
return false; return false;
directivePos++;
return MatchIncludeDirective(line, directivePos) return MatchIncludeDirective(line, directivePos)
|| MatchPragmaOnceDirective(line, directivePos); || MatchPragmaOnceDirective(line, directivePos);
} }

View File

@ -2,9 +2,10 @@
#include <set> #include <set>
#include "AbstractDirectiveStreamProxy.h"
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
class IncludingStreamProxy final : public IParserLineStream class IncludingStreamProxy final : public AbstractDirectiveStreamProxy
{ {
static constexpr const char* INCLUDE_QUOTES_ERROR = "Invalid include directive. Expected \"\" or <>"; static constexpr const char* INCLUDE_QUOTES_ERROR = "Invalid include directive. Expected \"\" or <>";
static constexpr const char* INCLUDE_DIRECTIVE = "include "; static constexpr const char* INCLUDE_DIRECTIVE = "include ";
@ -13,11 +14,9 @@ class IncludingStreamProxy final : public IParserLineStream
IParserLineStream* const m_stream; IParserLineStream* const m_stream;
std::set<std::string> m_included_files; std::set<std::string> m_included_files;
_NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition); _NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition);
_NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directivePosition) const; _NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directivePosition) const;
_NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directivePosition); _NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directivePosition);
_NODISCARD static bool FindDirective(const ParserLine& line, unsigned& directivePosition);
_NODISCARD bool MatchDirectives(const ParserLine& line); _NODISCARD bool MatchDirectives(const ParserLine& line);
public: public:

View File

@ -294,4 +294,48 @@ namespace test::parsing::impl::defines_stream_proxy
REQUIRE(proxy.Eof()); REQUIRE(proxy.Eof());
} }
TEST_CASE("DefinesStreamProxy: Ensure defines in disabled block are ignored", "[parsing][parsingstream]")
{
const std::vector<std::string> lines
{
"#ifdef LOLO",
"#define hello world",
"#endif",
"hello"
};
MockParserLineStream mockStream(lines);
DefinesStreamProxy proxy(&mockStream);
ExpectLine(&proxy, 1, "");
ExpectLine(&proxy, 2, "");
ExpectLine(&proxy, 3, "");
ExpectLine(&proxy, 4, "hello");
REQUIRE(proxy.Eof());
}
TEST_CASE("DefinesStreamProxy: Ensure undefs in disabled block are ignored", "[parsing][parsingstream]")
{
const std::vector<std::string> lines
{
"#define hello world",
"#ifdef LOLO",
"#undef hello",
"#endif",
"hello"
};
MockParserLineStream mockStream(lines);
DefinesStreamProxy proxy(&mockStream);
ExpectLine(&proxy, 1, "");
ExpectLine(&proxy, 2, "");
ExpectLine(&proxy, 3, "");
ExpectLine(&proxy, 4, "");
ExpectLine(&proxy, 5, "world");
REQUIRE(proxy.Eof());
}
} }

View File

@ -13,7 +13,6 @@ class MockLexer final : public ILexer<TokenType>
static_assert(std::is_base_of<IParserValue, TokenType>::value); static_assert(std::is_base_of<IParserValue, TokenType>::value);
std::vector<TokenType> m_tokens; std::vector<TokenType> m_tokens;
//std::vector<HeaderParserValue> m_tokens;
TokenType m_eof; TokenType m_eof;
int m_pop_count; int m_pop_count;
@ -58,4 +57,9 @@ public:
{ {
return m_pop_count; return m_pop_count;
} }
_NODISCARD ParserLine GetLineForPos(const TokenPos& pos) const override
{
return ParserLine();
}
}; };