mirror of
				https://github.com/Laupetin/OpenAssetTools.git
				synced 2025-10-30 18:17:15 +00:00 
			
		
		
		
	Properly handle tabs in pragma directives and other precompiler statements
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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); | ||||
| }; | ||||
|   | ||||
| @@ -157,22 +157,30 @@ std::vector<std::string> 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<char>::length(DEFINE_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(DEFINE_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, DEFINE_DIRECTIVE, std::char_traits<char>::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<char>::length(UNDEF_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(UNDEF_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, UNDEF_DIRECTIVE, std::char_traits<char>::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<char>::length(IFDEF_DIRECTIVE))) | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(IFDEF_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, IFDEF_DIRECTIVE, std::char_traits<char>::length(IFDEF_DIRECTIVE))) | ||||
|     { | ||||
|         if (!MatchString(line, directivePosition, IFNDEF_DIRECTIVE, std::char_traits<char>::length(IFNDEF_DIRECTIVE))) | ||||
|         if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(IFNDEF_DIRECTIVE) | ||||
|             || !MatchString(line, currentPos, IFNDEF_DIRECTIVE, std::char_traits<char>::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<char>::length(ELSE_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(ELSE_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, ELSE_DIRECTIVE, std::char_traits<char>::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<char>::length(ENDIF_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(ENDIF_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, ENDIF_DIRECTIVE, std::char_traits<char>::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) | ||||
|   | ||||
| @@ -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<std::string> 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<std::string>& parameterValues); | ||||
|   | ||||
| @@ -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<char>::length(INCLUDE_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPos; | ||||
|  | ||||
|     if (directiveEndPos - directiveStartPos != std::char_traits<char>::length(INCLUDE_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, INCLUDE_DIRECTIVE, std::char_traits<char>::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<int>(directivePosition)), INCLUDE_QUOTES_ERROR); | ||||
|     if (!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd)) | ||||
|         throw ParsingException(TokenPos(line.m_filename, line.m_line_number, static_cast<int>(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<char>::length(PRAGMA_ONCE_DIRECTIVE))) | ||||
|     auto currentPos = directiveStartPos; | ||||
|  | ||||
|     if(directiveEndPos - directiveStartPos != std::char_traits<char>::length(PRAGMA_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, PRAGMA_DIRECTIVE, std::char_traits<char>::length(PRAGMA_DIRECTIVE))) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (!SkipWhitespace(line, currentPos)) | ||||
|         return false; | ||||
|  | ||||
|     if (!MatchString(line, currentPos, ONCE_PRAGMA_COMMAND, std::char_traits<char>::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() | ||||
|   | ||||
| @@ -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<std::string> 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: | ||||
|   | ||||
| @@ -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<char>::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<char>::length(PUSH_KEYWORD))) | ||||
|         isPush = true; | ||||
|     else if (MatchNextString(line, directivePosition, POP_KEYWORD, std::char_traits<char>::length(POP_KEYWORD))) | ||||
|         isPush = false; | ||||
|     else | ||||
|         throw ParsingException(CreatePos(line, directivePosition), "Unknown pack directive command."); | ||||
|  | ||||
|     if(isPush) | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(PRAGMA_DIRECTIVE) | ||||
|         || !MatchString(line, currentPosition, PRAGMA_DIRECTIVE, std::char_traits<char>::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<char>::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<char>::length(PUSH_KEYWORD))) | ||||
|         isPush = true; | ||||
|     else if (MatchNextString(line, currentPosition, POP_KEYWORD, std::char_traits<char>::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() | ||||
|   | ||||
| @@ -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<int> 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: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user