From e19f526d8bb144aeeb53dd86ecd3e418322c7a8e Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 1 Nov 2021 14:36:53 +0100 Subject: [PATCH] Properly handle tabs in pragma directives and other precompiler statements --- .../Impl/AbstractDirectiveStreamProxy.cpp | 22 +++- .../Impl/AbstractDirectiveStreamProxy.h | 2 +- .../Parsing/Impl/DefinesStreamProxy.cpp | 113 +++++++++++------- src/Parser/Parsing/Impl/DefinesStreamProxy.h | 18 +-- .../Parsing/Impl/IncludingStreamProxy.cpp | 42 +++++-- .../Parsing/Impl/IncludingStreamProxy.h | 11 +- .../Impl/PackDefinitionStreamProxy.cpp | 69 ++++++----- .../Parsing/Impl/PackDefinitionStreamProxy.h | 5 +- 8 files changed, 178 insertions(+), 104 deletions(-) diff --git a/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.cpp b/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.cpp index 28fb79a5..617849f4 100644 --- a/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.cpp @@ -94,17 +94,29 @@ bool AbstractDirectiveStreamProxy::MatchNextString(const ParserLine& line, unsig return SkipWhitespace(line, position) && MatchString(line, position, str, len); } -bool AbstractDirectiveStreamProxy::FindDirective(const ParserLine& line, unsigned& directivePosition) +bool AbstractDirectiveStreamProxy::FindDirective(const ParserLine& line, unsigned& directiveStartPosition, unsigned& directiveEndPos) { - directivePosition = 0; - for (; directivePosition < line.m_line.size(); directivePosition++) + directiveStartPosition = 0; + for (; directiveStartPosition < line.m_line.size(); directiveStartPosition++) { - const auto c = line.m_line[directivePosition]; + const auto c = line.m_line[directiveStartPosition]; if (isspace(c)) continue; - return c == '#'; + if (c != '#') + continue; + + directiveEndPos = directiveStartPosition + 1; + for(; directiveEndPos < line.m_line.size(); directiveEndPos++) + { + const auto c2 = line.m_line[directiveEndPos]; + + if (isspace(c2)) + break; + } + + return true; } return false; diff --git a/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.h b/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.h index 40cacd1d..513f2f06 100644 --- a/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.h +++ b/src/Parser/Parsing/Impl/AbstractDirectiveStreamProxy.h @@ -18,5 +18,5 @@ protected: 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); + static bool FindDirective(const ParserLine& line, unsigned& directiveStartPosition, unsigned& directiveEndPos); }; diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index b90f48cd..bc49c260 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -157,22 +157,30 @@ std::vector DefinesStreamProxy::MatchDefineParameters(const ParserL return parameters; } -bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, unsigned directivePosition) +bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { - if (!MatchString(line, directivePosition, DEFINE_DIRECTIVE, std::char_traits::length(DEFINE_DIRECTIVE))) + auto currentPos = directiveStartPosition; + + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(DEFINE_DIRECTIVE) + || !MatchString(line, currentPos, DEFINE_DIRECTIVE, std::char_traits::length(DEFINE_DIRECTIVE))) + { return false; + } - const auto nameStartPos = directivePosition; - if (!ExtractIdentifier(line, directivePosition)) - throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name."); + if (!SkipWhitespace(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot define without a name."); - const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos); + const auto nameStartPos = currentPos; + if (!ExtractIdentifier(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot define without a name."); - const auto parameters = MatchDefineParameters(line, directivePosition); + const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos); + + const auto parameters = MatchDefineParameters(line, currentPos); std::string value; - if (directivePosition < line.m_line.size()) - value = line.m_line.substr(directivePosition + 1); + if (currentPos < line.m_line.size()) + value = line.m_line.substr(currentPos + 1); Define define(name, value); define.IdentifyParameters(parameters); @@ -181,19 +189,24 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, unsigned d return true; } -bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, unsigned directivePosition) +bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { - if (!MatchString(line, directivePosition, UNDEF_DIRECTIVE, std::char_traits::length(UNDEF_DIRECTIVE))) + auto currentPos = directiveStartPosition; + + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(UNDEF_DIRECTIVE) + || !MatchString(line, currentPos, UNDEF_DIRECTIVE, std::char_traits::length(UNDEF_DIRECTIVE))) + { return false; + } - if (!SkipWhitespace(line, directivePosition)) - throw ParsingException(CreatePos(line, directivePosition), "Cannot undef without a name."); + if (!SkipWhitespace(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot undef without a name."); - const auto nameStartPos = directivePosition; - if (!ExtractIdentifier(line, directivePosition)) - throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name."); + const auto nameStartPos = currentPos; + if (!ExtractIdentifier(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot undef without a name."); - const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos); + const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos); const auto entry = m_defines.find(name); if (entry != m_defines.end()) @@ -202,13 +215,19 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, unsigned di return true; } -bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, unsigned directivePosition) +bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { + auto currentPos = directiveStartPosition; + auto reverse = false; - if (!MatchString(line, directivePosition, IFDEF_DIRECTIVE, std::char_traits::length(IFDEF_DIRECTIVE))) + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(IFDEF_DIRECTIVE) + || !MatchString(line, currentPos, IFDEF_DIRECTIVE, std::char_traits::length(IFDEF_DIRECTIVE))) { - if (!MatchString(line, directivePosition, IFNDEF_DIRECTIVE, std::char_traits::length(IFNDEF_DIRECTIVE))) + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(IFNDEF_DIRECTIVE) + || !MatchString(line, currentPos, IFNDEF_DIRECTIVE, std::char_traits::length(IFNDEF_DIRECTIVE))) + { return false; + } reverse = true; } @@ -219,14 +238,14 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, unsigned di return true; } - if (!SkipWhitespace(line, directivePosition)) - throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name."); + if (!SkipWhitespace(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot ifdef without a name."); - const auto nameStartPos = directivePosition; - if (!ExtractIdentifier(line, directivePosition)) - throw ParsingException(CreatePos(line, directivePosition), "Cannot ifdef without a name."); + const auto nameStartPos = currentPos; + if (!ExtractIdentifier(line, currentPos)) + throw ParsingException(CreatePos(line, currentPos), "Cannot ifdef without a name."); - const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos); + const auto name = line.m_line.substr(nameStartPos, currentPos - nameStartPos); const auto entry = m_defines.find(name); if (entry != m_defines.end()) @@ -237,10 +256,15 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, unsigned di return true; } -bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, unsigned directivePosition) +bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { - if (!MatchString(line, directivePosition, ELSE_DIRECTIVE, std::char_traits::length(ELSE_DIRECTIVE))) + auto currentPos = directiveStartPosition; + + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(ELSE_DIRECTIVE) + || !MatchString(line, currentPos, ELSE_DIRECTIVE, std::char_traits::length(ELSE_DIRECTIVE))) + { return false; + } if (m_ignore_depth > 0) return true; @@ -248,15 +272,20 @@ bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, unsigned dir if (!m_modes.empty()) m_modes.top() = !m_modes.top(); else - throw ParsingException(CreatePos(line, directivePosition), "Cannot use else without ifdef"); + throw ParsingException(CreatePos(line, currentPos), "Cannot use else without ifdef"); return true; } -bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, unsigned directivePosition) +bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { - if (!MatchString(line, directivePosition, ENDIF_DIRECTIVE, std::char_traits::length(ENDIF_DIRECTIVE))) + auto currentPos = directiveStartPosition; + + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(ENDIF_DIRECTIVE) + || !MatchString(line, currentPos, ENDIF_DIRECTIVE, std::char_traits::length(ENDIF_DIRECTIVE))) + { return false; + } if (m_ignore_depth > 0) { @@ -267,30 +296,31 @@ bool DefinesStreamProxy::MatchEndifDirective(const ParserLine& line, unsigned di if (!m_modes.empty()) m_modes.pop(); else - throw ParsingException(CreatePos(line, directivePosition), "Cannot use endif without ifdef"); + throw ParsingException(CreatePos(line, currentPos), "Cannot use endif without ifdef"); return true; } bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) { - unsigned directivePos; + unsigned directiveStartPos; + unsigned directiveEndPos; - if (!FindDirective(line, directivePos)) + if (!FindDirective(line, directiveStartPos, directiveEndPos)) return false; - directivePos++; + directiveStartPos++; if (m_modes.empty() || m_modes.top() == true) { - if (MatchDefineDirective(line, directivePos) - || MatchUndefDirective(line, directivePos)) + if (MatchDefineDirective(line, directiveStartPos, directiveEndPos) + || MatchUndefDirective(line, directiveStartPos, directiveEndPos)) return true; } - return MatchIfdefDirective(line, directivePos) - || MatchElseDirective(line, directivePos) - || MatchEndifDirective(line, directivePos); + return MatchIfdefDirective(line, directiveStartPos, directiveEndPos) + || MatchElseDirective(line, directiveStartPos, directiveEndPos) + || MatchEndifDirective(line, directiveStartPos, directiveEndPos); } bool DefinesStreamProxy::FindDefineForWord(const ParserLine& line, const unsigned wordStart, const unsigned wordEnd, Define*& value) @@ -427,7 +457,8 @@ void DefinesStreamProxy::ExpandDefines(ParserLine& line) } defineIterations++; - } while (usesDefines); + } + while (usesDefines); } void DefinesStreamProxy::AddDefine(Define define) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index 307d6c07..df8cc835 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -8,10 +8,10 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy { - static constexpr const char* DEFINE_DIRECTIVE = "define "; - static constexpr const char* UNDEF_DIRECTIVE = "undef "; - static constexpr const char* IFDEF_DIRECTIVE = "ifdef "; - static constexpr const char* IFNDEF_DIRECTIVE = "ifndef "; + static constexpr const char* DEFINE_DIRECTIVE = "define"; + static constexpr const char* UNDEF_DIRECTIVE = "undef"; + static constexpr const char* IFDEF_DIRECTIVE = "ifdef"; + static constexpr const char* IFNDEF_DIRECTIVE = "ifndef"; static constexpr const char* ELSE_DIRECTIVE = "else"; static constexpr const char* ENDIF_DIRECTIVE = "endif"; @@ -48,11 +48,11 @@ private: unsigned m_ignore_depth; static std::vector MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); - _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directivePosition); - _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directivePosition); - _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directivePosition); - _NODISCARD bool MatchElseDirective(const ParserLine& line, unsigned directivePosition); - _NODISCARD bool MatchEndifDirective(const ParserLine& line, unsigned directivePosition); + _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); + _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); + _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); + _NODISCARD bool MatchElseDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); + _NODISCARD bool MatchEndifDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchDirectives(const ParserLine& line); static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector& parameterValues); diff --git a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp index d8110a1d..d70a52fd 100644 --- a/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/IncludingStreamProxy.cpp @@ -57,18 +57,23 @@ bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const return false; } -bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, unsigned directivePosition) const +bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, const unsigned directiveStartPos, const unsigned directiveEndPos) const { - if (!MatchString(line, directivePosition, INCLUDE_DIRECTIVE, std::char_traits::length(INCLUDE_DIRECTIVE))) + auto currentPos = directiveStartPos; + + if (directiveEndPos - directiveStartPos != std::char_traits::length(INCLUDE_DIRECTIVE) + || !MatchString(line, currentPos, INCLUDE_DIRECTIVE, std::char_traits::length(INCLUDE_DIRECTIVE))) + { return false; + } unsigned filenameStart, filenameEnd; - if (!ExtractIncludeFilename(line, directivePosition, filenameStart, filenameEnd)) - throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast(directivePosition)), INCLUDE_QUOTES_ERROR); + if (!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd)) + throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast(currentPos)), INCLUDE_QUOTES_ERROR); if (filenameEnd <= filenameStart) - throw ParsingException(CreatePos(line, directivePosition), "No filename specified"); + throw ParsingException(CreatePos(line, currentPos), "No filename specified"); const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart); @@ -76,15 +81,26 @@ bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line, unsigne { std::ostringstream errorStr; errorStr << "Could not include file \"" << filename << "\""; - throw ParsingException(CreatePos(line, directivePosition), errorStr.str()); + throw ParsingException(CreatePos(line, currentPos), errorStr.str()); } return true; } -bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, unsigned directivePosition) +bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, const unsigned directiveStartPos, const unsigned directiveEndPos) { - if(!MatchString(line, directivePosition, PRAGMA_ONCE_DIRECTIVE, std::char_traits::length(PRAGMA_ONCE_DIRECTIVE))) + auto currentPos = directiveStartPos; + + if(directiveEndPos - directiveStartPos != std::char_traits::length(PRAGMA_DIRECTIVE) + || !MatchString(line, currentPos, PRAGMA_DIRECTIVE, std::char_traits::length(PRAGMA_DIRECTIVE))) + { + return false; + } + + if (!SkipWhitespace(line, currentPos)) + return false; + + if (!MatchString(line, currentPos, ONCE_PRAGMA_COMMAND, std::char_traits::length(ONCE_PRAGMA_COMMAND))) return false; const auto absolutePath = absolute(fs::path(line.m_filename.get())); @@ -101,14 +117,14 @@ bool IncludingStreamProxy::MatchPragmaOnceDirective(const ParserLine& line, unsi bool IncludingStreamProxy::MatchDirectives(const ParserLine& line) { - unsigned directivePos; + unsigned directiveStartPos, directiveEndPos; - if (!FindDirective(line, directivePos)) + if (!FindDirective(line, directiveStartPos, directiveEndPos)) return false; - directivePos++; - return MatchIncludeDirective(line, directivePos) - || MatchPragmaOnceDirective(line, directivePos); + directiveStartPos++; + return MatchIncludeDirective(line, directiveStartPos, directiveEndPos) + || MatchPragmaOnceDirective(line, directiveStartPos, directiveEndPos); } ParserLine IncludingStreamProxy::NextLine() diff --git a/src/Parser/Parsing/Impl/IncludingStreamProxy.h b/src/Parser/Parsing/Impl/IncludingStreamProxy.h index b8c9a3a4..d1f22cc8 100644 --- a/src/Parser/Parsing/Impl/IncludingStreamProxy.h +++ b/src/Parser/Parsing/Impl/IncludingStreamProxy.h @@ -8,15 +8,16 @@ class IncludingStreamProxy final : public AbstractDirectiveStreamProxy { static constexpr const char* INCLUDE_QUOTES_ERROR = "Invalid include directive. Expected \"\" or <>"; - static constexpr const char* INCLUDE_DIRECTIVE = "include "; - static constexpr const char* PRAGMA_ONCE_DIRECTIVE = "pragma once"; + static constexpr const char* INCLUDE_DIRECTIVE = "include"; + static constexpr const char* PRAGMA_DIRECTIVE = "pragma"; + static constexpr const char* ONCE_PRAGMA_COMMAND = "once"; IParserLineStream* const m_stream; std::set m_included_files; - _NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition); - _NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directivePosition) const; - _NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directivePosition); + _NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& directiveStartPos, unsigned& filenameEndPos); + _NODISCARD bool MatchIncludeDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos) const; + _NODISCARD bool MatchPragmaOnceDirective(const ParserLine& line, unsigned directiveStartPos, unsigned directiveEndPos); _NODISCARD bool MatchDirectives(const ParserLine& line); public: diff --git a/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.cpp b/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.cpp index 8bb67127..85bfc424 100644 --- a/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.cpp @@ -7,37 +7,50 @@ PackDefinitionStreamProxy::PackDefinitionStreamProxy(IParserLineStream* stream) { } -bool PackDefinitionStreamProxy::MatchPackDirective(const ParserLine& line, unsigned directivePosition) +bool PackDefinitionStreamProxy::MatchPackDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) { auto packValue = 0; + auto currentPosition = directiveStartPosition; - if (!MatchString(line, directivePosition, PRAGMA_PACK_DIRECTIVE, std::char_traits::length(PRAGMA_PACK_DIRECTIVE))) - return false; - - if (!MatchNextCharacter(line, directivePosition, '(')) - throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive."); - - bool isPush; - if (MatchNextString(line, directivePosition, PUSH_KEYWORD, std::char_traits::length(PUSH_KEYWORD))) - isPush = true; - else if (MatchNextString(line, directivePosition, POP_KEYWORD, std::char_traits::length(POP_KEYWORD))) - isPush = false; - else - throw ParsingException(CreatePos(line, directivePosition), "Unknown pack directive command."); - - if(isPush) + if (directiveEndPosition - directiveStartPosition != std::char_traits::length(PRAGMA_DIRECTIVE) + || !MatchString(line, currentPosition, PRAGMA_DIRECTIVE, std::char_traits::length(PRAGMA_DIRECTIVE))) { - if (!MatchNextCharacter(line, directivePosition, ',')) - throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive."); - - if (!ExtractInteger(line, directivePosition, packValue)) - throw ParsingException(CreatePos(line, directivePosition), "Invalid pack value."); + return false; } - if (!MatchNextCharacter(line, directivePosition, ')')) - throw ParsingException(CreatePos(line, directivePosition), "Invalid pack directive."); + if (!SkipWhitespace(line, currentPosition)) + return false; - if(isPush) + if (!MatchString(line, currentPosition, PACK_PRAGMA_COMMAND, std::char_traits::length(PACK_PRAGMA_COMMAND))) + return false; + + if (!SkipWhitespace(line, currentPosition)) + throw ParsingException(CreatePos(line, currentPosition), "Invalid pack directive."); + + if (!MatchNextCharacter(line, currentPosition, '(')) + throw ParsingException(CreatePos(line, currentPosition), "Invalid pack directive."); + + bool isPush; + if (MatchNextString(line, currentPosition, PUSH_KEYWORD, std::char_traits::length(PUSH_KEYWORD))) + isPush = true; + else if (MatchNextString(line, currentPosition, POP_KEYWORD, std::char_traits::length(POP_KEYWORD))) + isPush = false; + else + throw ParsingException(CreatePos(line, currentPosition), "Unknown pack directive command."); + + if (isPush) + { + if (!MatchNextCharacter(line, currentPosition, ',')) + throw ParsingException(CreatePos(line, currentPosition), "Invalid pack directive."); + + if (!ExtractInteger(line, currentPosition, packValue)) + throw ParsingException(CreatePos(line, currentPosition), "Invalid pack value."); + } + + if (!MatchNextCharacter(line, currentPosition, ')')) + throw ParsingException(CreatePos(line, currentPosition), "Invalid pack directive."); + + if (isPush) m_current_pack.push(packValue); else if (!m_current_pack.empty()) m_current_pack.pop(); @@ -47,13 +60,13 @@ bool PackDefinitionStreamProxy::MatchPackDirective(const ParserLine& line, unsig bool PackDefinitionStreamProxy::MatchDirectives(const ParserLine& line) { - unsigned directivePos; + unsigned directiveStartPos, directiveEndPos; - if (!FindDirective(line, directivePos)) + if (!FindDirective(line, directiveStartPos, directiveEndPos)) return false; - directivePos++; - return MatchPackDirective(line, directivePos); + directiveStartPos++; + return MatchPackDirective(line, directiveStartPos, directiveEndPos); } ParserLine PackDefinitionStreamProxy::NextLine() diff --git a/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.h b/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.h index ded7249e..06404a0f 100644 --- a/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.h +++ b/src/Parser/Parsing/Impl/PackDefinitionStreamProxy.h @@ -12,14 +12,15 @@ public: static constexpr int DEFAULT_PACK = 8; private: - static constexpr const char* PRAGMA_PACK_DIRECTIVE = "pragma pack"; + static constexpr const char* PRAGMA_DIRECTIVE = "pragma"; + static constexpr const char* PACK_PRAGMA_COMMAND = "pack"; static constexpr const char* PUSH_KEYWORD = "push"; static constexpr const char* POP_KEYWORD = "pop"; IParserLineStream* const m_stream; std::stack m_current_pack; - _NODISCARD bool MatchPackDirective(const ParserLine& line, unsigned directivePosition); + _NODISCARD bool MatchPackDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); _NODISCARD bool MatchDirectives(const ParserLine& line); public: