From a36d1c430aa1d2cc48fc01dd94d37886d1b9c9b4 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 6 Sep 2022 20:52:52 +0200 Subject: [PATCH] Use SimpleExpressionInterpreter in DefinesStreamProxy and expand defines and defined expressions before parsing --- raw/iw4/techniques/technique_test.technique | 0 .../technique_test.technique.template | 15 ---- .../DefinesDirectiveExpressionSequence.cpp | 16 ---- .../DefinesDirectiveExpressionSequence.h | 13 --- .../Impl/Defines/DefinesDirectiveParser.cpp | 22 ----- .../Impl/Defines/DefinesDirectiveParser.h | 17 ---- .../Defines/DefinesDirectiveParsingState.cpp | 6 -- .../Defines/DefinesDirectiveParsingState.h | 16 ---- .../Defines/DefinesExpressionMatchers.cpp | 37 -------- .../Impl/Defines/DefinesExpressionMatchers.h | 21 ----- .../Parsing/Impl/DefinesStreamProxy.cpp | 86 ++++++++++++++----- src/Parser/Parsing/Impl/DefinesStreamProxy.h | 14 +-- .../Templating/TemplatingStreamProxy.cpp | 11 +-- 13 files changed, 77 insertions(+), 197 deletions(-) delete mode 100644 raw/iw4/techniques/technique_test.technique delete mode 100644 raw/iw4/techniques/technique_test.technique.template delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.cpp delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.h delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.cpp delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.h delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.cpp delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.h delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.cpp delete mode 100644 src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.h diff --git a/raw/iw4/techniques/technique_test.technique b/raw/iw4/techniques/technique_test.technique deleted file mode 100644 index e69de29b..00000000 diff --git a/raw/iw4/techniques/technique_test.technique.template b/raw/iw4/techniques/technique_test.technique.template deleted file mode 100644 index 291ce561..00000000 --- a/raw/iw4/techniques/technique_test.technique.template +++ /dev/null @@ -1,15 +0,0 @@ -#pragma options TEST(asdf, bla) -#pragma switch TEST_SWITCH - -#ifdef TEST_SWITCH -#define SVAL "1" -#else -#define SVAL "0" -#endif - -#pragma filename "lemao_" + TEST + SVAL + ".txt" - -HAHA TEST -#ifdef TEST_SWITCH -kekw -#endif \ No newline at end of file diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.cpp b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.cpp deleted file mode 100644 index 26c8bc53..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "DefinesDirectiveExpressionSequence.h" - -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" -#include "DefinesExpressionMatchers.h" - -DefinesDirectiveExpressionSequence::DefinesDirectiveExpressionSequence() -{ - const SimpleMatcherFactory create(this); - AddLabeledMatchers(DefinesExpressionMatchers().Expression(this), SimpleExpressionMatchers::LABEL_EXPRESSION); - AddMatchers(create.Label(SimpleExpressionMatchers::LABEL_EXPRESSION)); -} - -void DefinesDirectiveExpressionSequence::ProcessMatch(DefinesDirectiveParsingState* state, SequenceResult& result) const -{ - state->m_expression = DefinesExpressionMatchers(state).ProcessExpression(result); -} diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.h b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.h deleted file mode 100644 index 24f156c7..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveExpressionSequence.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "DefinesDirectiveParser.h" -#include "DefinesDirectiveParsingState.h" - -class DefinesDirectiveExpressionSequence final : public DefinesDirectiveParser::sequence_t -{ -public: - DefinesDirectiveExpressionSequence(); - -protected: - void ProcessMatch(DefinesDirectiveParsingState* state, SequenceResult& result) const override; -}; diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.cpp b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.cpp deleted file mode 100644 index b0491132..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "DefinesDirectiveParser.h" - -#include "DefinesDirectiveExpressionSequence.h" - -DefinesDirectiveParser::DefinesDirectiveParser(ILexer* lexer, const std::map& defines) - : AbstractParser(lexer, std::make_unique(defines)) -{ -} - -const std::vector::sequence_t*>& DefinesDirectiveParser::GetTestsForState() -{ - static std::vector sequences - { - new DefinesDirectiveExpressionSequence() - }; - return sequences; -} - -std::unique_ptr DefinesDirectiveParser::GetParsedExpression() const -{ - return std::move(m_state->m_expression); -} diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.h b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.h deleted file mode 100644 index 8fb72f30..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParser.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include "DefinesDirectiveParsingState.h" -#include "Parsing/Impl/AbstractParser.h" -#include "Parsing/Simple/SimpleParserValue.h" - -class DefinesDirectiveParser final : public AbstractParser -{ -public: - DefinesDirectiveParser(ILexer* lexer, const std::map& defines); - -protected: - const std::vector& GetTestsForState() override; - -public: - _NODISCARD std::unique_ptr GetParsedExpression() const; -}; diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.cpp b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.cpp deleted file mode 100644 index 469eef39..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "DefinesDirectiveParsingState.h" - -DefinesDirectiveParsingState::DefinesDirectiveParsingState(const std::map& defines) - : m_defines(defines) -{ -} diff --git a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.h b/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.h deleted file mode 100644 index 1b04aa1a..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesDirectiveParsingState.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include - -#include "Parsing/Impl/DefinesStreamProxy.h" -#include "Parsing/Simple/Expression/ISimpleExpression.h" - -class DefinesDirectiveParsingState -{ -public: - const std::map& m_defines; - std::unique_ptr m_expression; - - explicit DefinesDirectiveParsingState(const std::map& defines); -}; diff --git a/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.cpp b/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.cpp deleted file mode 100644 index dd88914b..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "DefinesExpressionMatchers.h" - -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" - -DefinesExpressionMatchers::DefinesExpressionMatchers() - : DefinesExpressionMatchers(nullptr) -{ -} - -DefinesExpressionMatchers::DefinesExpressionMatchers(const DefinesDirectiveParsingState* state) - : SimpleExpressionMatchers(true, false, true, true, false), - m_state(state) -{ -} - -std::unique_ptr DefinesExpressionMatchers::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 DefinesExpressionMatchers::ProcessOperandExtension(SequenceResult& 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(1); - - return std::make_unique(0); -} diff --git a/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.h b/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.h deleted file mode 100644 index 8ccc384a..00000000 --- a/src/Parser/Parsing/Impl/Defines/DefinesExpressionMatchers.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#include "DefinesDirectiveParsingState.h" -#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" - -class DefinesExpressionMatchers final : public SimpleExpressionMatchers -{ - static constexpr auto CAPTURE_DEFINE_NAME = CAPTURE_OFFSET_EXPRESSION_EXT + 1; - - const DefinesDirectiveParsingState* m_state; - -protected: - std::unique_ptr ParseOperandExtension(const supplier_t* labelSupplier) const override; - std::unique_ptr ProcessOperandExtension(SequenceResult& result) const override; - -public: - DefinesExpressionMatchers(); - explicit DefinesExpressionMatchers(const DefinesDirectiveParsingState* state); -}; diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index d36f3c28..513f7049 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -1,13 +1,14 @@ #include "DefinesStreamProxy.h" +#include #include #include #include "Utils/ClassUtils.h" #include "AbstractParser.h" #include "ParserSingleInputStream.h" -#include "Defines/DefinesDirectiveParser.h" #include "Parsing/ParsingException.h" +#include "Parsing/Simple/SimpleExpressionInterpreter.h" #include "Parsing/Simple/SimpleLexer.h" #include "Parsing/Simple/Expression/ISimpleExpression.h" #include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" @@ -34,7 +35,7 @@ DefinesStreamProxy::Define::Define(std::string name, std::string value) { } -std::string DefinesStreamProxy::Define::Render(const std::vector& parameterValues) +std::string DefinesStreamProxy::Define::Render(const std::vector& parameterValues) const { if (parameterValues.empty() || m_parameter_positions.empty()) return m_value; @@ -279,25 +280,17 @@ bool DefinesStreamProxy::MatchUndefDirective(const ParserLine& line, const unsig return true; } -std::unique_ptr DefinesStreamProxy::ParseExpression(const std::string& expressionString) const +std::unique_ptr DefinesStreamProxy::ParseExpression(std::string expressionString) const { - std::istringstream ss(expressionString); + ParserLine pseudoLine(nullptr, 1, std::move(expressionString)); + ExpandDefinedExpressions(pseudoLine); + ExpandDefines(pseudoLine); + + std::istringstream ss(pseudoLine.m_line); ParserSingleInputStream inputStream(ss, "defines directive expression"); - SimpleLexer::Config lexerConfig; - lexerConfig.m_emit_new_line_tokens = false; - lexerConfig.m_read_integer_numbers = true; - lexerConfig.m_read_floating_point_numbers = true; - lexerConfig.m_read_strings = true; - SimpleExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig); - - SimpleLexer lexer(&inputStream, std::move(lexerConfig)); - DefinesDirectiveParser parser(&lexer, m_defines); - - if (!parser.Parse()) - return nullptr; - - return parser.GetParsedExpression(); + const SimpleExpressionInterpreter expressionInterpreter(&inputStream); + return expressionInterpreter.Evaluate(); } bool DefinesStreamProxy::MatchIfDirective(const ParserLine& line, const unsigned directiveStartPosition, const unsigned directiveEndPosition) @@ -485,7 +478,7 @@ bool DefinesStreamProxy::MatchDirectives(const ParserLine& line) || MatchEndifDirective(line, directiveStartPos, directiveEndPos); } -bool DefinesStreamProxy::FindDefineForWord(const ParserLine& line, const unsigned wordStart, const unsigned wordEnd, Define*& value) +bool DefinesStreamProxy::FindDefineForWord(const ParserLine& line, const unsigned wordStart, const unsigned wordEnd, const Define*& value) const { const std::string word(line.m_line, wordStart, wordEnd - wordStart); const auto foundEntry = m_defines.find(word); @@ -560,7 +553,58 @@ void DefinesStreamProxy::ExtractParametersFromDefineUsage(const ParserLine& line } } -void DefinesStreamProxy::ExpandDefines(ParserLine& line) +bool DefinesStreamProxy::MatchDefinedExpression(const ParserLine& line, unsigned& pos, std::string& definitionName) +{ + unsigned currentPos = pos; + + if (!MatchNextCharacter(line, currentPos, '(')) + return false; + + const auto nameStartPos = currentPos; + if (!ExtractIdentifier(line, currentPos)) + return false; + + const auto nameEndPos = currentPos; + if (!MatchNextCharacter(line, currentPos, ')')) + return false; + + pos = currentPos; + definitionName = line.m_line.substr(nameStartPos, nameEndPos - nameStartPos); + return true; +} + +void DefinesStreamProxy::ExpandDefinedExpressions(ParserLine& line) const +{ + auto currentPos = 0u; + + while (true) + { + const auto definedPos = line.m_line.find(DEFINED_KEYWORD, currentPos); + if (definedPos == std::string::npos) + break; + + currentPos = definedPos; + + if (definedPos > 0 && !isspace(line.m_line[definedPos - 1])) + { + currentPos += std::char_traits::length(DEFINED_KEYWORD); + continue; + } + + auto definitionEndPos = currentPos + std::char_traits::length(DEFINED_KEYWORD); + std::string definitionName; + if (!MatchDefinedExpression(line, definitionEndPos, definitionName)) + { + currentPos += std::char_traits::length(DEFINED_KEYWORD); + continue; + } + + const auto entry = m_defines.find(definitionName); + line.m_line.replace(currentPos, definitionEndPos - currentPos, entry != m_defines.end() ? "1" : "0"); + } +} + +void DefinesStreamProxy::ExpandDefines(ParserLine& line) const { bool usesDefines; auto defineIterations = 0u; @@ -575,7 +619,7 @@ void DefinesStreamProxy::ExpandDefines(ParserLine& line) auto wordStart = 0u; auto lastWordEnd = 0u; auto inWord = false; - Define* value; + const Define* value; std::ostringstream str; for (auto i = 0u; i < line.m_line.size(); i++) diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index 6a93ac36..f4b29735 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -18,6 +18,7 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy static constexpr const char* IFNDEF_DIRECTIVE = "ifndef"; static constexpr const char* ELSE_DIRECTIVE = "else"; static constexpr const char* ENDIF_DIRECTIVE = "endif"; + static constexpr const char* DEFINED_KEYWORD = "defined"; static constexpr auto MAX_DEFINE_ITERATIONS = 128u; @@ -42,7 +43,7 @@ public: Define(); Define(std::string name, std::string value); void IdentifyParameters(const std::vector& parameterNames); - std::string Render(const std::vector& parameterValues); + _NODISCARD std::string Render(const std::vector& parameterValues) const; }; private: @@ -77,17 +78,20 @@ private: _NODISCARD bool MatchDirectives(const ParserLine& line); static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector& parameterValues); - bool FindDefineForWord(const ParserLine& line, unsigned wordStart, unsigned wordEnd, Define*& value); + bool FindDefineForWord(const ParserLine& line, unsigned wordStart, unsigned wordEnd, const Define*& value) const; + + static bool MatchDefinedExpression(const ParserLine& line, unsigned& pos, std::string& definitionName); + void ExpandDefinedExpressions(ParserLine& line) const; public: - DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false); + explicit DefinesStreamProxy(IParserLineStream* stream, bool skipDirectiveLines = false); void AddDefine(Define define); void Undefine(const std::string& name); - void ExpandDefines(ParserLine& line); + void ExpandDefines(ParserLine& line) const; - _NODISCARD std::unique_ptr ParseExpression(const std::string& expressionString) const; + _NODISCARD std::unique_ptr ParseExpression(std::string expressionString) const; ParserLine NextLine() override; bool IncludeFile(const std::string& filename) override; diff --git a/src/RawTemplater/Templating/TemplatingStreamProxy.cpp b/src/RawTemplater/Templating/TemplatingStreamProxy.cpp index 8d1b5b55..b3725f08 100644 --- a/src/RawTemplater/Templating/TemplatingStreamProxy.cpp +++ b/src/RawTemplater/Templating/TemplatingStreamProxy.cpp @@ -91,10 +91,8 @@ bool TemplatingStreamProxy::MatchOptionsDirective(const ParserLine& line, const const auto optionStartPosition = currentPosition; if (!ExtractIdentifier(line, currentPosition)) throw ParsingException(CreatePos(line, currentPosition), "Invalid options directive."); - - std::ostringstream optionValueBuilder; - optionValueBuilder << '"' << line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition) << '"'; - options.emplace_back(optionValueBuilder.str()); + + options.emplace_back(line.m_line.substr(optionStartPosition, currentPosition - optionStartPosition)); firstArg = false; } @@ -126,10 +124,7 @@ bool TemplatingStreamProxy::MatchFilenameDirective(const ParserLine& line, const if (expressionString.empty()) throw ParsingException(CreatePos(line, currentPosition), "Cannot pragma filename without an expression."); - ParserLine expressionStringAsLine(line.m_filename, line.m_line_number, expressionString); - m_defines_proxy->ExpandDefines(expressionStringAsLine); - - const auto expression = m_defines_proxy->ParseExpression(expressionStringAsLine.m_line); + const auto expression = m_defines_proxy->ParseExpression(expressionString); if (!expression) throw ParsingException(CreatePos(line, currentPosition), "Failed to parse pragma filename expression");