mirror of
				https://github.com/Laupetin/OpenAssetTools.git
				synced 2025-10-30 18:17:15 +00:00 
			
		
		
		
	Add support for defineproxy if directive parsing
This commit is contained in:
		| @@ -317,8 +317,9 @@ public: | ||||
|         { | ||||
|             m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount); | ||||
|             const auto& firstToken = m_token_cache.front(); | ||||
|             while (m_line_cache.front().m_line_number != firstToken.GetPos().m_line | ||||
|                 || *m_line_cache.front().m_filename != firstToken.GetPos().m_filename.get()) | ||||
|             while (!m_line_cache.empty() | ||||
|                 && (m_line_cache.front().m_line_number != firstToken.GetPos().m_line | ||||
|                     || *m_line_cache.front().m_filename != firstToken.GetPos().m_filename.get())) | ||||
|             { | ||||
|                 m_line_cache.pop_front(); | ||||
|                 m_line_index--; | ||||
|   | ||||
| @@ -0,0 +1,16 @@ | ||||
| #include "DefinesIfDirectiveExpressionSequence.h" | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
| #include "DefinesIfExpressionMatchers.h" | ||||
|  | ||||
| DefinesIfDirectiveExpressionSequence::DefinesIfDirectiveExpressionSequence() | ||||
| { | ||||
|     const SimpleMatcherFactory create(this); | ||||
|     AddLabeledMatchers(DefinesIfExpressionMatchers().Expression(this), SimpleExpressionMatchers::LABEL_EXPRESSION); | ||||
|     AddMatchers(create.Label(SimpleExpressionMatchers::LABEL_EXPRESSION)); | ||||
| } | ||||
|  | ||||
| void DefinesIfDirectiveExpressionSequence::ProcessMatch(DefinesIfDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const | ||||
| { | ||||
|     state->m_expression = DefinesIfExpressionMatchers(state).ProcessExpression(result); | ||||
| } | ||||
| @@ -0,0 +1,13 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "DefinesIfDirectiveParser.h" | ||||
| #include "DefinesIfDirectiveParsingState.h" | ||||
|  | ||||
| class DefinesIfDirectiveExpressionSequence final : public DefinesIfDirectiveParser::sequence_t | ||||
| { | ||||
| public: | ||||
|     DefinesIfDirectiveExpressionSequence(); | ||||
|  | ||||
| protected: | ||||
|     void ProcessMatch(DefinesIfDirectiveParsingState* state, SequenceResult<SimpleParserValue>& result) const override; | ||||
| }; | ||||
							
								
								
									
										22
									
								
								src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #include "DefinesIfDirectiveParser.h" | ||||
|  | ||||
| #include "DefinesIfDirectiveExpressionSequence.h" | ||||
|  | ||||
| DefinesIfDirectiveParser::DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer, const std::map<std::string, DefinesStreamProxy::Define>& defines) | ||||
|     : AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>(lexer, std::make_unique<DefinesIfDirectiveParsingState>(defines)) | ||||
| { | ||||
| } | ||||
|  | ||||
| const std::vector<AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>::sequence_t*>& DefinesIfDirectiveParser::GetTestsForState() | ||||
| { | ||||
|     static std::vector<sequence_t*> sequences | ||||
|     { | ||||
|         new DefinesIfDirectiveExpressionSequence() | ||||
|     }; | ||||
|     return sequences; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ISimpleExpression> DefinesIfDirectiveParser::GetParsedExpression() const | ||||
| { | ||||
|     return std::move(m_state->m_expression); | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/Parser/Parsing/Impl/Defines/DefinesIfDirectiveParser.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "DefinesIfDirectiveParsingState.h" | ||||
| #include "Parsing/Impl/AbstractParser.h" | ||||
| #include "Parsing/Simple/SimpleParserValue.h" | ||||
|  | ||||
| class DefinesIfDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState> | ||||
| { | ||||
| public: | ||||
|     DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer, const std::map<std::string, DefinesStreamProxy::Define>& defines); | ||||
|  | ||||
| protected: | ||||
|     const std::vector<sequence_t*>& GetTestsForState() override; | ||||
|  | ||||
| public: | ||||
|     _NODISCARD std::unique_ptr<ISimpleExpression> GetParsedExpression() const; | ||||
| }; | ||||
| @@ -0,0 +1,6 @@ | ||||
| #include "DefinesIfDirectiveParsingState.h" | ||||
|  | ||||
| DefinesIfDirectiveParsingState::DefinesIfDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines) | ||||
|     : m_defines(defines) | ||||
| { | ||||
| } | ||||
| @@ -0,0 +1,16 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
| #include <memory> | ||||
|  | ||||
| #include "Parsing/Impl/DefinesStreamProxy.h" | ||||
| #include "Parsing/Simple/Expression/ISimpleExpression.h" | ||||
|  | ||||
| class DefinesIfDirectiveParsingState | ||||
| { | ||||
| public: | ||||
|     const std::map<std::string, DefinesStreamProxy::Define>& m_defines; | ||||
|     std::unique_ptr<ISimpleExpression> m_expression; | ||||
|  | ||||
|     explicit DefinesIfDirectiveParsingState(const std::map<std::string, DefinesStreamProxy::Define>& defines); | ||||
| }; | ||||
| @@ -0,0 +1,37 @@ | ||||
| #include "DefinesIfExpressionMatchers.h" | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| DefinesIfExpressionMatchers::DefinesIfExpressionMatchers() | ||||
|     : DefinesIfExpressionMatchers(nullptr) | ||||
| { | ||||
| } | ||||
|  | ||||
| DefinesIfExpressionMatchers::DefinesIfExpressionMatchers(const DefinesIfDirectiveParsingState* state) | ||||
|     : SimpleExpressionMatchers(false, false, true, true), | ||||
|       m_state(state) | ||||
| { | ||||
| } | ||||
|  | ||||
| std::unique_ptr<SimpleExpressionMatchers::matcher_t> DefinesIfExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const | ||||
| { | ||||
|     const SimpleMatcherFactory create(labelSupplier); | ||||
|  | ||||
|     return create.And({ | ||||
|         create.Keyword("defined"), | ||||
|         create.Char('('), | ||||
|         create.Identifier().Capture(CAPTURE_DEFINE_NAME), | ||||
|         create.Char(')'), | ||||
|     }); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ISimpleExpression> DefinesIfExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const | ||||
| { | ||||
|     const auto& defineCapture = result.NextCapture(CAPTURE_DEFINE_NAME); | ||||
|  | ||||
|     assert(m_state); | ||||
|     if(m_state && m_state->m_defines.find(defineCapture.IdentifierValue()) != m_state->m_defines.end()) | ||||
|         return std::make_unique<SimpleExpressionValue>(1); | ||||
|  | ||||
|     return std::make_unique<SimpleExpressionValue>(0); | ||||
| } | ||||
| @@ -0,0 +1,21 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "DefinesIfDirectiveParsingState.h" | ||||
| #include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" | ||||
|  | ||||
| class DefinesIfExpressionMatchers final : public SimpleExpressionMatchers | ||||
| { | ||||
|     static constexpr auto CAPTURE_DEFINE_NAME = CAPTURE_OFFSET_EXPRESSION_EXT + 1; | ||||
|  | ||||
|     const DefinesIfDirectiveParsingState* m_state; | ||||
|  | ||||
| protected: | ||||
|     std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override; | ||||
|     std::unique_ptr<ISimpleExpression> ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const override; | ||||
|  | ||||
| public: | ||||
|     DefinesIfExpressionMatchers(); | ||||
|     explicit DefinesIfExpressionMatchers(const DefinesIfDirectiveParsingState* state); | ||||
| }; | ||||
| @@ -3,52 +3,15 @@ | ||||
| #include <sstream> | ||||
| #include <utility> | ||||
|  | ||||
| #include "Utils/ClassUtils.h" | ||||
| #include "AbstractParser.h" | ||||
| #include "ParserSingleInputStream.h" | ||||
| #include "Defines/DefinesIfDirectiveParser.h" | ||||
| #include "Parsing/ParsingException.h" | ||||
| #include "Parsing/Simple/SimpleLexer.h" | ||||
| #include "Parsing/Simple/Expression/ISimpleExpression.h" | ||||
|  | ||||
| class DefinesIfDirectiveParsingState | ||||
| { | ||||
| public: | ||||
|     std::unique_ptr<ISimpleExpression> m_expression; | ||||
| }; | ||||
|  | ||||
| class DefinesIfDirectiveParser final : public AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState> | ||||
| { | ||||
| protected: | ||||
|     explicit DefinesIfDirectiveParser(ILexer<SimpleParserValue>* lexer) | ||||
|         : AbstractParser<SimpleParserValue, DefinesIfDirectiveParsingState>(lexer, std::make_unique<DefinesIfDirectiveParsingState>()) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     const std::vector<sequence_t*>& GetTestsForState() override | ||||
|     { | ||||
|         static std::vector<sequence_t*> sequences | ||||
|         { | ||||
|         }; | ||||
|         return sequences; | ||||
|     } | ||||
|  | ||||
| public: | ||||
|     static bool EvaluateIfDirective(std::map<std::string, DefinesStreamProxy::Define>& defines, const std::string& value) | ||||
|     { | ||||
|         std::istringstream ss(value); | ||||
|         ParserSingleInputStream inputStream(ss, ""); | ||||
|         SimpleLexer::Config config{}; | ||||
|         config.m_emit_new_line_tokens = false; | ||||
|         config.m_read_numbers = true; | ||||
|         config.m_read_strings = false; | ||||
|         SimpleLexer lexer(&inputStream, std::move(config)); | ||||
|         DefinesIfDirectiveParser parser(&lexer); | ||||
|         if (!parser.Parse()) | ||||
|             return false; | ||||
|  | ||||
|         const auto& expression = parser.m_state->m_expression; | ||||
|         return expression->IsStatic() && expression->Evaluate().IsTruthy(); | ||||
|     } | ||||
| }; | ||||
| #include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| DefinesStreamProxy::DefineParameterPosition::DefineParameterPosition() | ||||
|     : m_parameter_index(0u), | ||||
| @@ -315,6 +278,101 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ISimpleExpression> DefinesStreamProxy::ParseIfExpression(const std::string& expressionString) const | ||||
| { | ||||
|     std::istringstream ss(expressionString); | ||||
|     ParserSingleInputStream inputStream(ss, "#if expression"); | ||||
|  | ||||
|     SimpleLexer::Config lexerConfig; | ||||
|     lexerConfig.m_emit_new_line_tokens = false; | ||||
|     lexerConfig.m_read_numbers = true; | ||||
|     lexerConfig.m_read_strings = false; | ||||
|     SimpleExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig); | ||||
|  | ||||
|     SimpleLexer lexer(&inputStream, std::move(lexerConfig)); | ||||
|     DefinesIfDirectiveParser parser(&lexer, m_defines); | ||||
|  | ||||
|     if (!parser.Parse()) | ||||
|         return nullptr; | ||||
|  | ||||
|     return parser.GetParsedExpression(); | ||||
| } | ||||
|  | ||||
| bool DefinesStreamProxy::MatchIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) | ||||
| { | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(IF_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, IF_DIRECTIVE, std::char_traits<char>::length(IF_DIRECTIVE))) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (!m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK) | ||||
|     { | ||||
|         m_ignore_depth++; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     if (!SkipWhitespace(line, currentPos)) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot if without an expression."); | ||||
|  | ||||
|     const auto expressionString = line.m_line.substr(currentPos, line.m_line.size() - currentPos); | ||||
|  | ||||
|     if (expressionString.empty()) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot if without an expression."); | ||||
|  | ||||
|     const auto expression = ParseIfExpression(expressionString); | ||||
|     if (!expression) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Failed to parse if expression"); | ||||
|  | ||||
|     m_modes.push(expression->Evaluate().IsTruthy() ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool DefinesStreamProxy::MatchElIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) | ||||
| { | ||||
|     auto currentPos = directiveStartPosition; | ||||
|  | ||||
|     if (directiveEndPosition - directiveStartPosition != std::char_traits<char>::length(ELIF_DIRECTIVE) | ||||
|         || !MatchString(line, currentPos, ELIF_DIRECTIVE, std::char_traits<char>::length(ELIF_DIRECTIVE))) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     if (m_ignore_depth > 0) | ||||
|         return true; | ||||
|  | ||||
|     if (m_modes.empty()) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot use elif without if"); | ||||
|  | ||||
|     if (m_modes.top() == BlockMode::BLOCK_BLOCKED) | ||||
|         return true; | ||||
|  | ||||
|     if(m_modes.top() == BlockMode::IN_BLOCK) | ||||
|     { | ||||
|         m_modes.top() = BlockMode::BLOCK_BLOCKED; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     if (!SkipWhitespace(line, currentPos)) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot elif without an expression."); | ||||
|  | ||||
|     const auto expressionString = line.m_line.substr(currentPos, line.m_line.size() - currentPos); | ||||
|  | ||||
|     if (expressionString.empty()) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot elif without an expression."); | ||||
|  | ||||
|     const auto expression = ParseIfExpression(expressionString); | ||||
|     if (!expression) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Failed to parse elif expression"); | ||||
|  | ||||
|     m_modes.top() = expression->Evaluate().IsTruthy() ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) | ||||
| { | ||||
|     auto currentPos = directiveStartPosition; | ||||
| @@ -332,7 +390,7 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig | ||||
|         reverse = true; | ||||
|     } | ||||
|  | ||||
|     if (!m_modes.empty() && !m_modes.top()) | ||||
|     if (!m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK) | ||||
|     { | ||||
|         m_ignore_depth++; | ||||
|         return true; | ||||
| @@ -349,9 +407,9 @@ bool DefinesStreamProxy::MatchIfdefDirective(const ParserLine& line, const unsig | ||||
|     const auto entry = m_defines.find(name); | ||||
|  | ||||
|     if (entry != m_defines.end()) | ||||
|         m_modes.push(!reverse); | ||||
|         m_modes.push(!reverse ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK); | ||||
|     else | ||||
|         m_modes.push(reverse); | ||||
|         m_modes.push(reverse ? BlockMode::IN_BLOCK : BlockMode::NOT_IN_BLOCK); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
| @@ -369,11 +427,11 @@ bool DefinesStreamProxy::MatchElseDirective(const ParserLine& line, const unsign | ||||
|     if (m_ignore_depth > 0) | ||||
|         return true; | ||||
|  | ||||
|     if (!m_modes.empty()) | ||||
|         m_modes.top() = !m_modes.top(); | ||||
|     else | ||||
|     if (m_modes.empty()) | ||||
|         throw ParsingException(CreatePos(line, currentPos), "Cannot use else without ifdef"); | ||||
|  | ||||
|     m_modes.top() = m_modes.top() == BlockMode::NOT_IN_BLOCK ? BlockMode::IN_BLOCK : BlockMode::BLOCK_BLOCKED; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| @@ -411,7 +469,7 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) | ||||
|  | ||||
|     directiveStartPos++; | ||||
|  | ||||
|     if (m_modes.empty() || m_modes.top() == true) | ||||
|     if (m_modes.empty() || m_modes.top() == BlockMode::IN_BLOCK) | ||||
|     { | ||||
|         if (MatchDefineDirective(line, directiveStartPos, directiveEndPos) | ||||
|             || MatchUndefDirective(line, directiveStartPos, directiveEndPos)) | ||||
| @@ -419,6 +477,8 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) | ||||
|     } | ||||
|  | ||||
|     return MatchIfdefDirective(line, directiveStartPos, directiveEndPos) | ||||
|         || MatchIfDirective(line, directiveStartPos, directiveEndPos) | ||||
|         || MatchElIfDirective(line, directiveStartPos, directiveEndPos) | ||||
|         || MatchElseDirective(line, directiveStartPos, directiveEndPos) | ||||
|         || MatchEndifDirective(line, directiveStartPos, directiveEndPos); | ||||
| } | ||||
| @@ -583,7 +643,7 @@ ParserLine DefinesStreamProxy::NextLine() | ||||
|         ContinueDefine(line); | ||||
|         line.m_line.clear(); | ||||
|     } | ||||
|     else if (MatchDirectives(line) || !m_modes.empty() && !m_modes.top()) | ||||
|     else if (MatchDirectives(line) || !m_modes.empty() && m_modes.top() != BlockMode::IN_BLOCK) | ||||
|     { | ||||
|         line.m_line.clear(); | ||||
|     } | ||||
|   | ||||
| @@ -6,11 +6,14 @@ | ||||
|  | ||||
| #include "AbstractDirectiveStreamProxy.h" | ||||
| #include "Parsing/IParserLineStream.h" | ||||
| #include "Parsing/Simple/Expression/ISimpleExpression.h" | ||||
|  | ||||
| class DefinesStreamProxy final : public AbstractDirectiveStreamProxy | ||||
| { | ||||
|     static constexpr const char* DEFINE_DIRECTIVE = "define"; | ||||
|     static constexpr const char* UNDEF_DIRECTIVE = "undef"; | ||||
|     static constexpr const char* IF_DIRECTIVE = "if"; | ||||
|     static constexpr const char* ELIF_DIRECTIVE = "elif"; | ||||
|     static constexpr const char* IFDEF_DIRECTIVE = "ifdef"; | ||||
|     static constexpr const char* IFNDEF_DIRECTIVE = "ifndef"; | ||||
|     static constexpr const char* ELSE_DIRECTIVE = "else"; | ||||
| @@ -43,9 +46,16 @@ public: | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|     enum class BlockMode | ||||
|     { | ||||
|         NOT_IN_BLOCK, | ||||
|         IN_BLOCK, | ||||
|         BLOCK_BLOCKED | ||||
|     }; | ||||
|  | ||||
|     IParserLineStream* const m_stream; | ||||
|     std::map<std::string, Define> m_defines; | ||||
|     std::stack<bool> m_modes; | ||||
|     std::stack<BlockMode> m_modes; | ||||
|     unsigned m_ignore_depth; | ||||
|  | ||||
|     bool m_in_define; | ||||
| @@ -56,8 +66,11 @@ private: | ||||
|     static int GetLineEndEscapePos(const ParserLine& line); | ||||
|     static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); | ||||
|     void ContinueDefine(const ParserLine& line); | ||||
|     _NODISCARD std::unique_ptr<ISimpleExpression> ParseIfExpression(const std::string& expressionString) const; | ||||
|     _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); | ||||
|     _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); | ||||
|     _NODISCARD bool MatchIfDirective(const ParserLine& line, unsigned directiveStartPosition, unsigned directiveEndPosition); | ||||
|     _NODISCARD bool MatchElIfDirective(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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user