mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Restructure StreamProxies to use common basis for matching directives
This commit is contained in:
parent
e277de4517
commit
efa39a8ac3
@ -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;
|
||||||
|
}
|
@ -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);
|
||||||
|
};
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 ";
|
||||||
@ -12,12 +13,10 @@ 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:
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user