From 38f3d7d10eb8fe27f519d510ea05b330fe22647d Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 24 Nov 2021 17:44:14 +0100 Subject: [PATCH] Move Menu Expression to Simple Namespace to have generic configurable expressions --- .../Menu/Matcher/MenuCommonMatchers.cpp | 306 ----------------- .../Parsing/Menu/Matcher/MenuCommonMatchers.h | 37 -- .../Menu/Matcher/MenuExpressionMatchers.cpp | 49 +++ .../Menu/Matcher/MenuExpressionMatchers.h | 18 + src/ObjLoading/Parsing/Menu/MenuFileLexing.h | 22 -- .../Parsing/Menu/MenuFileReader.cpp | 15 +- .../EventHandlerSetScopeSequences.cpp | 30 +- .../GenericExpressionPropertySequence.cpp | 16 +- .../Menu/Sequence/MenuScopeSequences.cpp | 2 +- .../Parsing/Impl/DefinesStreamProxy.cpp | 45 +++ src/Parser/Parsing/Impl/DefinesStreamProxy.h | 4 +- .../Parsing/Matcher/AbstractMatcherFactory.h | 12 + src/Parser/Parsing/Matcher/MatcherFalse.h | 23 ++ src/Parser/Parsing/Matcher/MatcherTrue.h | 23 ++ .../SimpleExpressionBinaryOperation.cpp | 23 +- .../SimpleExpressionBinaryOperation.h | 3 +- .../Expression/SimpleExpressionMatchers.cpp | 316 ++++++++++++++++++ .../Expression/SimpleExpressionMatchers.h | 65 ++++ .../SimpleExpressionUnaryOperation.cpp | 12 +- .../SimpleExpressionUnaryOperation.h | 3 +- .../Simple/Matcher/SimpleMatcherFactory.h | 2 +- 21 files changed, 619 insertions(+), 407 deletions(-) delete mode 100644 src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp delete mode 100644 src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h create mode 100644 src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp create mode 100644 src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h delete mode 100644 src/ObjLoading/Parsing/Menu/MenuFileLexing.h create mode 100644 src/Parser/Parsing/Matcher/MatcherFalse.h create mode 100644 src/Parser/Parsing/Matcher/MatcherTrue.h create mode 100644 src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp create mode 100644 src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h diff --git a/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp b/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp deleted file mode 100644 index c1158c2d..00000000 --- a/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#include "MenuCommonMatchers.h" - -#include - -#include "MenuMatcherFactory.h" -#include "Parsing/Menu/MenuFileLexing.h" -#include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h" -#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h" -#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h" - -using namespace menu; - -static constexpr int TAG_OPERAND = std::numeric_limits::max() - 1; -static constexpr int TAG_EXPRESSION_UNARY_OPERATION = std::numeric_limits::max() - 2; -static constexpr int TAG_EXPRESSION_FUNCTION_CALL = std::numeric_limits::max() - 3; -static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = std::numeric_limits::max() - 4; -static constexpr int TAG_EXPRESSION_PARENTHESIS = std::numeric_limits::max() - 5; -static constexpr int TAG_EXPRESSION_PARENTHESIS_END = std::numeric_limits::max() - 6; -static constexpr int TAG_EXPRESSION = std::numeric_limits::max() - 7; -static constexpr int TAG_EXPRESSION_BINARY_OPERATION = std::numeric_limits::max() - 8; - -static constexpr int CAPTURE_OPERAND = std::numeric_limits::max() - 1; -static constexpr int CAPTURE_UNARY_OPERATION_TYPE = std::numeric_limits::max() - 2; -static constexpr int CAPTURE_BINARY_OPERATION_TYPE = std::numeric_limits::max() - 3; -static constexpr int CAPTURE_FUNCTION_NAME = std::numeric_limits::max() - 4; - -std::unique_ptr MenuCommonMatchers::ProcessExpressionInParenthesis(MenuFileParserState* state, SequenceResult& result) -{ - auto processedEvaluation = ProcessExpression(state, result); - - if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_PARENTHESIS_END) != TAG_EXPRESSION_PARENTHESIS_END) - throw ParsingException(TokenPos(), "Expected parenthesis end tag @ ExpressionInParenthesis"); - - return processedEvaluation; -} - -std::unique_ptr MenuCommonMatchers::ProcessOperand(MenuFileParserState* state, SequenceResult& result) -{ - const auto& operandToken = result.NextCapture(CAPTURE_OPERAND); - - switch (operandToken.m_type) - { - case SimpleParserValueType::INTEGER: - return std::make_unique(operandToken.IntegerValue()); - case SimpleParserValueType::FLOATING_POINT: - return std::make_unique(operandToken.FloatingPointValue()); - case SimpleParserValueType::STRING: - return std::make_unique(operandToken.StringValue()); - case SimpleParserValueType::IDENTIFIER: - return std::make_unique(operandToken.IdentifierValue()); - default: - throw ParsingException(TokenPos(), "Unknown operand type @ Operand"); - } -} - -std::unique_ptr MenuCommonMatchers::ProcessFunctionCall(MenuFileParserState* state, SequenceResult& result) -{ - auto functionCall = std::make_unique(result.NextCapture(CAPTURE_FUNCTION_NAME).IdentifierValue()); - - while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END) - { - functionCall->m_args.emplace_back(ProcessExpression(state, result)); - } - - return std::move(functionCall); -} - -std::unique_ptr MenuCommonMatchers::ProcessExpression(MenuFileParserState* state, SequenceResult& result) -{ - if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION) - return nullptr; - - std::vector> operands; - std::list> operators; - - while (true) - { - std::unique_ptr firstStatementPart; - std::vector unaryOperations; - auto nextTag = result.NextTag(); - - while (nextTag == TAG_EXPRESSION_UNARY_OPERATION) - { - unaryOperations.push_back(result.NextCapture(CAPTURE_UNARY_OPERATION_TYPE).IntegerValue()); - nextTag = result.NextTag(); - } - - switch (nextTag) - { - case TAG_EXPRESSION_PARENTHESIS: - firstStatementPart = ProcessExpressionInParenthesis(state, result); - break; - - case TAG_EXPRESSION_FUNCTION_CALL: - firstStatementPart = ProcessFunctionCall(state, result); - break; - - case TAG_OPERAND: - firstStatementPart = ProcessOperand(state, result); - break; - - default: - throw ParsingException(TokenPos(), "Invalid followup tag @ Expression"); - } - - for (auto i = unaryOperations.size(); i > 0; i--) - { - const auto operationIndex = unaryOperations[i - 1]; - if (operationIndex < 0 || operationIndex >= static_cast(SimpleUnaryOperationId::COUNT)) - throw ParsingException(TokenPos(), "Invalid unary operation id @ Expression"); - firstStatementPart = std::make_unique(SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[operationIndex], - std::move(firstStatementPart)); - } - - operands.emplace_back(std::move(firstStatementPart)); - - if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_BINARY_OPERATION) == TAG_EXPRESSION_BINARY_OPERATION) - { - const auto operationIndex = result.NextCapture(CAPTURE_BINARY_OPERATION_TYPE).IntegerValue(); - if (operationIndex < 0 || operationIndex >= static_cast(SimpleBinaryOperationId::COUNT)) - throw ParsingException(TokenPos(), "Invalid binary operation id @ Expression"); - - operators.emplace_back(operators.size(), SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[operationIndex]); - } - else - break; - - if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION) - throw ParsingException(TokenPos(), "Expected EvaluationTag @ Evaluation"); - } - - operators.sort([](const std::pair& p1, const std::pair& p2) - { - if (p1.second->m_precedence != p2.second->m_precedence) - return p1.second->m_precedence > p2.second->m_precedence; - - return p1.first > p2.first; - }); - - while (!operators.empty()) - { - const auto [operatorIndex, operatorType] = operators.back(); - - auto operation = std::make_unique(operatorType, std::move(operands[operatorIndex]), std::move(operands[operatorIndex + 1])); - operands.erase(operands.begin() + static_cast(operatorIndex)); - operands[operatorIndex] = std::move(operation); - - operators.pop_back(); - - for (auto& [opIndex, _] : operators) - { - if (opIndex > operatorIndex) - opIndex--; - } - } - - return std::move(operands.front()); -} - -std::unique_ptr MenuCommonMatchers::ParseOperand(const supplier_t* labelSupplier) -{ - const MenuMatcherFactory create(labelSupplier); - - return create.Or({ - create.Integer(), - create.FloatingPoint(), - create.String(), - create.Identifier(), - }).Tag(TAG_OPERAND).Capture(CAPTURE_OPERAND); -} - -std::unique_ptr MenuCommonMatchers::ParseBinaryOperationType(const supplier_t* labelSupplier) -{ - const MenuMatcherFactory create(labelSupplier); - - return create.Or({ - create.Char('+').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::ADD)); - }), - create.Char('-').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::SUBTRACT)); - }), - create.Char('*').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::MULTIPLY)); - }), - create.Char('/').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::DIVIDE)); - }), - create.Char('%').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::REMAINDER)); - }), - create.Char('&').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::BITWISE_AND)); - }), - create.Char('|').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::BITWISE_OR)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::SHIFT_LEFT)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::SHIFT_LEFT)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::SHIFT_RIGHT)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::SHIFT_RIGHT)); - }), - create.Char('>').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::GREATER_THAN)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::GREATER_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::GREATER_EQUAL_THAN)); - }), - create.Char('<').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::LESS_THAN)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::LESS_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::LESS_EQUAL_THAN)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::EQUALS)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::EQUALS)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::NOT_EQUAL)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::NOT_EQUAL)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::LOGICAL_AND)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::AND)); - }), - create.MultiChar(static_cast(MenuFileLexing::MultiChar::LOGICAL_OR)).Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleBinaryOperationId::OR)); - }), - }).Capture(CAPTURE_BINARY_OPERATION_TYPE); -} - -std::unique_ptr MenuCommonMatchers::ParseFunctionCall(const supplier_t* labelSupplier) -{ - const MenuMatcherFactory create(labelSupplier); - - return create.And({ - create.Identifier().Capture(CAPTURE_FUNCTION_NAME), - create.Char('('), - create.Optional(create.And({ - create.Label(LABEL_EXPRESSION), - create.OptionalLoop(create.And({ - create.Char(','), - create.Label(LABEL_EXPRESSION) - })), - })), - create.Char(')').Tag(TAG_EXPRESSION_FUNCTION_CALL_END) - }).Tag(TAG_EXPRESSION_FUNCTION_CALL); -} - -std::unique_ptr MenuCommonMatchers::ParseUnaryOperationType(const supplier_t* labelSupplier) -{ - const MenuMatcherFactory create(labelSupplier); - - return create.Or({ - create.Char('!').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleUnaryOperationId::NOT)); - }), - create.Char('~').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleUnaryOperationId::BITWISE_NOT)); - }), - create.Char('-').Transform([](const MenuMatcherFactory::token_list_t& values) - { - return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(SimpleUnaryOperationId::NEGATIVE)); - }), - }).Tag(TAG_EXPRESSION_UNARY_OPERATION).Capture(CAPTURE_UNARY_OPERATION_TYPE); -} - -std::unique_ptr MenuCommonMatchers::Expression(const supplier_t* labelSupplier) -{ - const MenuMatcherFactory create(labelSupplier); - - return create.And({ - create.OptionalLoop(ParseUnaryOperationType(labelSupplier)), - create.Or({ - create.And({ - create.Char('('), - create.Label(LABEL_EXPRESSION), - create.Char(')').Tag(TAG_EXPRESSION_PARENTHESIS_END) - }).Tag(TAG_EXPRESSION_PARENTHESIS), - ParseFunctionCall(labelSupplier), - ParseOperand(labelSupplier) - }), - create.Optional(create.And({ - ParseBinaryOperationType(labelSupplier), - create.Label(LABEL_EXPRESSION) - }).Tag(TAG_EXPRESSION_BINARY_OPERATION)) - }).Tag(TAG_EXPRESSION); -} diff --git a/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h b/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h deleted file mode 100644 index 6d90151b..00000000 --- a/src/ObjLoading/Parsing/Menu/Matcher/MenuCommonMatchers.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include - -#include "Parsing/Matcher/AbstractMatcher.h" -#include "Parsing/Matcher/MatcherLabel.h" -#include "Parsing/Menu/MenuFileParser.h" -#include "Parsing/Simple/Expression/ISimpleExpression.h" -#include "Parsing/Sequence/SequenceResult.h" -#include "Parsing/Simple/SimpleParserValue.h" - -namespace menu -{ - class MenuCommonMatchers - { - public: - using matcher_t = MenuFileParser::sequence_t::matcher_t; - typedef IMatcherForLabelSupplier supplier_t; - - static constexpr int LABEL_EXPRESSION = std::numeric_limits::max() - 1; - - private: - static std::unique_ptr ParseBinaryOperationType(const supplier_t* labelSupplier); - static std::unique_ptr ParseOperand(const supplier_t* labelSupplier); - static std::unique_ptr ParseFunctionCall(const supplier_t* labelSupplier); - static std::unique_ptr ParseUnaryOperationType(const supplier_t* labelSupplier); - - static std::unique_ptr ProcessExpressionInParenthesis(MenuFileParserState* state, SequenceResult& result); - static std::unique_ptr ProcessOperand(MenuFileParserState* state, SequenceResult& result); - static std::unique_ptr ProcessFunctionCall(MenuFileParserState* state, SequenceResult& result); - - public: - static std::unique_ptr Expression(const supplier_t* labelSupplier); - static std::unique_ptr ProcessExpression(MenuFileParserState* state, SequenceResult& result); - }; -} diff --git a/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp new file mode 100644 index 00000000..e6063ecb --- /dev/null +++ b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.cpp @@ -0,0 +1,49 @@ +#include "MenuExpressionMatchers.h" + +#include "MenuMatcherFactory.h" +#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h" + +using namespace menu; + +static constexpr int TAG_EXPRESSION_FUNCTION_CALL = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION_EXT + 1; +static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION_EXT + 2; + +static constexpr int CAPTURE_FUNCTION_NAME = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1; + + +MenuExpressionMatchers::MenuExpressionMatchers() + : SimpleExpressionMatchers(true, true, true, true) +{ +} + +std::unique_ptr MenuExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const +{ + const MenuMatcherFactory create(labelSupplier); + + return create.Or({ + create.And({ + create.Identifier().Capture(CAPTURE_FUNCTION_NAME), + create.Char('('), + create.Optional(create.And({ + create.Label(LABEL_EXPRESSION), + create.OptionalLoop(create.And({ + create.Char(','), + create.Label(LABEL_EXPRESSION) + })), + })), + create.Char(')').Tag(TAG_EXPRESSION_FUNCTION_CALL_END) + }).Tag(TAG_EXPRESSION_FUNCTION_CALL) + }); +} + +std::unique_ptr MenuExpressionMatchers::ProcessOperandExtension(SequenceResult& result) const +{ + auto functionCall = std::make_unique(result.NextCapture(CAPTURE_FUNCTION_NAME).IdentifierValue()); + + while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END) + { + functionCall->m_args.emplace_back(ProcessExpression(result)); + } + + return std::move(functionCall); +} \ No newline at end of file diff --git a/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h new file mode 100644 index 00000000..ab59cfd6 --- /dev/null +++ b/src/ObjLoading/Parsing/Menu/Matcher/MenuExpressionMatchers.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" + +namespace menu +{ + class MenuExpressionMatchers final : public SimpleExpressionMatchers + { + public: + MenuExpressionMatchers(); + + protected: + std::unique_ptr ParseOperandExtension(const supplier_t* labelSupplier) const override; + std::unique_ptr ProcessOperandExtension(SequenceResult& result) const override; + }; +} diff --git a/src/ObjLoading/Parsing/Menu/MenuFileLexing.h b/src/ObjLoading/Parsing/Menu/MenuFileLexing.h deleted file mode 100644 index cd925301..00000000 --- a/src/ObjLoading/Parsing/Menu/MenuFileLexing.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -namespace menu -{ - class MenuFileLexing - { - public: - enum class MultiChar - { - SHIFT_LEFT, - SHIFT_RIGHT, - GREATER_EQUAL, - LESS_EQUAL, - EQUALS, - NOT_EQUAL, - LOGICAL_AND, - LOGICAL_OR - }; - - MenuFileLexing() = delete; - }; -} \ No newline at end of file diff --git a/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp b/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp index adbcc41f..daf61c62 100644 --- a/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp +++ b/src/ObjLoading/Parsing/Menu/MenuFileReader.cpp @@ -1,7 +1,7 @@ #include "MenuFileReader.h" -#include "MenuFileLexing.h" #include "MenuFileParser.h" +#include "Matcher/MenuExpressionMatchers.h" #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/DefinesStreamProxy.h" #include "Parsing/Impl/IncludingStreamProxy.h" @@ -123,18 +123,9 @@ std::unique_ptr MenuFileReader::ReadMenuFile() lexerConfig.m_emit_new_line_tokens = false; lexerConfig.m_read_strings = true; lexerConfig.m_read_numbers = true; - lexerConfig.m_multi_character_tokens = std::vector({ - {static_cast(MenuFileLexing::MultiChar::SHIFT_LEFT), "<<"}, - {static_cast(MenuFileLexing::MultiChar::SHIFT_RIGHT), ">>"}, - {static_cast(MenuFileLexing::MultiChar::GREATER_EQUAL), ">="}, - {static_cast(MenuFileLexing::MultiChar::LESS_EQUAL), "<="}, - {static_cast(MenuFileLexing::MultiChar::EQUALS), "=="}, - {static_cast(MenuFileLexing::MultiChar::NOT_EQUAL), "!="}, - {static_cast(MenuFileLexing::MultiChar::LOGICAL_AND), "&&"}, - {static_cast(MenuFileLexing::MultiChar::LOGICAL_OR), "||"}, - }); - const auto lexer = std::make_unique(m_stream, std::move(lexerConfig)); + MenuExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig); + const auto lexer = std::make_unique(m_stream, std::move(lexerConfig)); const auto parser = std::make_unique(lexer.get(), m_feature_level); if (!parser->Parse()) diff --git a/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp index 5325bbb8..c65ce61f 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/EventHandlerSetScopeSequences.cpp @@ -7,7 +7,7 @@ #include "Generic/GenericStringPropertySequence.h" #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h" #include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h" -#include "Parsing/Menu/Matcher/MenuCommonMatchers.h" +#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h" #include "Parsing/Menu/Matcher/MenuMatcherFactory.h" #include "Parsing/Menu/Matcher/MenuMatcherScriptInt.h" #include "Parsing/Menu/Matcher/MenuMatcherScriptNumeric.h" @@ -326,8 +326,9 @@ namespace menu::event_handler_set_scope_sequences SequenceSetLocalVar() { const ScriptMatcherFactory create(this); + const MenuExpressionMatchers expressionMatchers; - AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION); + AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Or({ @@ -337,7 +338,7 @@ namespace menu::event_handler_set_scope_sequences create.ScriptKeyword("setLocalVarString").Tag(TAG_STRING) }), create.ScriptText().Capture(CAPTURE_VAR_NAME), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Optional(create.Char(';')) }); } @@ -420,10 +421,12 @@ namespace menu::event_handler_set_scope_sequences protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { + const MenuExpressionMatchers expressionMatchers; + const auto typeTag = static_cast(result.NextTag()); const auto& varNameToken = result.NextCapture(CAPTURE_VAR_NAME); const auto& varName = MenuMatcherFactory::TokenTextValue(varNameToken); - auto expression = MenuCommonMatchers::ProcessExpression(state, result); + auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(varNameToken.GetPos(), "No expression"); @@ -443,13 +446,14 @@ namespace menu::event_handler_set_scope_sequences SequenceIf() { const ScriptMatcherFactory create(this); + const MenuExpressionMatchers expressionMatchers; - AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION); + AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Keyword("if").Capture(CAPTURE_KEYWORD), create.Char('('), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Char(')'), create.Char('{') }); @@ -458,7 +462,8 @@ namespace menu::event_handler_set_scope_sequences protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { - auto expression = MenuCommonMatchers::ProcessExpression(state, result); + const MenuExpressionMatchers expressionMatchers; + auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression"); @@ -485,14 +490,15 @@ namespace menu::event_handler_set_scope_sequences SequenceElseIf() { const ScriptMatcherFactory create(this); + const MenuExpressionMatchers expressionMatchers; - AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION); + AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Char('}'), create.Keyword("elseif").Capture(CAPTURE_KEYWORD), create.Char('('), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Char(')'), create.Char('{') }); @@ -501,7 +507,8 @@ namespace menu::event_handler_set_scope_sequences protected: void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override { - auto expression = MenuCommonMatchers::ProcessExpression(state, result); + const MenuExpressionMatchers expressionMatchers; + auto expression = expressionMatchers.ProcessExpression(result); if (!expression) throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression"); @@ -539,8 +546,9 @@ namespace menu::event_handler_set_scope_sequences SequenceElse() { const ScriptMatcherFactory create(this); + const MenuExpressionMatchers expressionMatchers; - AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION); + AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); AddMatchers({ create.Char('}'), diff --git a/src/ObjLoading/Parsing/Menu/Sequence/Generic/GenericExpressionPropertySequence.cpp b/src/ObjLoading/Parsing/Menu/Sequence/Generic/GenericExpressionPropertySequence.cpp index 3082f03f..e10049f0 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/Generic/GenericExpressionPropertySequence.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/Generic/GenericExpressionPropertySequence.cpp @@ -2,7 +2,7 @@ #include -#include "Parsing/Menu/Matcher/MenuCommonMatchers.h" +#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h" #include "Parsing/Menu/Matcher/MenuMatcherFactory.h" using namespace menu; @@ -10,7 +10,8 @@ using namespace menu; GenericExpressionPropertySequence::GenericExpressionPropertySequence(callback_t setCallback) : m_set_callback(std::move(setCallback)) { - AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION); + const MenuExpressionMatchers expressionMatchers; + AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION); } std::unique_ptr GenericExpressionPropertySequence::WithKeyword(std::string keyword, callback_t setCallback) @@ -20,7 +21,7 @@ std::unique_ptr GenericExpressionPropertySequ const MenuMatcherFactory create(result.get()); result->AddMatchers({ create.KeywordIgnoreCase(std::move(keyword)).Capture(CAPTURE_FIRST_TOKEN), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Optional(create.Char(';')) }); @@ -38,7 +39,7 @@ std::unique_ptr GenericExpressionPropertySequ result->AddMatchers({ create.And(std::move(keywordMatchers)).Capture(CAPTURE_FIRST_TOKEN), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Optional(create.Char(';')) }); @@ -56,10 +57,10 @@ std::unique_ptr GenericExpressionPropertySequ create.And({ create.KeywordIgnoreCase("when"), create.Char('('), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION), + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION), create.Char(')') }), - create.Label(MenuCommonMatchers::LABEL_EXPRESSION) + create.Label(MenuExpressionMatchers::LABEL_EXPRESSION) }), create.Optional(create.Char(';')) }); @@ -71,7 +72,8 @@ void GenericExpressionPropertySequence::ProcessMatch(MenuFileParserState* state, { if (m_set_callback) { - auto expression = MenuCommonMatchers::ProcessExpression(state, result); + const MenuExpressionMatchers expressionMatchers; + auto expression = expressionMatchers.ProcessExpression(result); m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(expression)); } } diff --git a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp index e6c21d32..ef7a119d 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp @@ -12,7 +12,7 @@ #include "Generic/GenericStringPropertySequence.h" #include "Parsing/Menu/Matcher/MenuMatcherFactory.h" #include "Parsing/Menu/Domain/CommonMenuTypes.h" -#include "Parsing/Menu/Matcher/MenuCommonMatchers.h" +#include "Parsing/Menu/Matcher/MenuExpressionMatchers.h" using namespace menu; diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp index adca5d70..45d63e9a 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.cpp @@ -3,7 +3,52 @@ #include #include +#include "AbstractParser.h" +#include "ParserSingleInputStream.h" #include "Parsing/ParsingException.h" +#include "Parsing/Simple/SimpleLexer.h" +#include "Parsing/Simple/Expression/ISimpleExpression.h" + +class DefinesIfDirectiveParsingState +{ +public: + std::unique_ptr m_expression; +}; + +class DefinesIfDirectiveParser final : public AbstractParser +{ +protected: + explicit DefinesIfDirectiveParser(ILexer* lexer) + : AbstractParser(lexer, std::make_unique()) + { + } + + const std::vector& GetTestsForState() override + { + static std::vector sequences + { + }; + return sequences; + } + +public: + static bool EvaluateIfDirective(std::map& 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(); + } +}; DefinesStreamProxy::DefineParameterPosition::DefineParameterPosition() : m_parameter_index(0u), diff --git a/src/Parser/Parsing/Impl/DefinesStreamProxy.h b/src/Parser/Parsing/Impl/DefinesStreamProxy.h index a840e5bb..221b5faf 100644 --- a/src/Parser/Parsing/Impl/DefinesStreamProxy.h +++ b/src/Parser/Parsing/Impl/DefinesStreamProxy.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -44,7 +44,7 @@ public: private: IParserLineStream* const m_stream; - std::unordered_map m_defines; + std::map m_defines; std::stack m_modes; unsigned m_ignore_depth; diff --git a/src/Parser/Parsing/Matcher/AbstractMatcherFactory.h b/src/Parser/Parsing/Matcher/AbstractMatcherFactory.h index e6f5c03f..39535cc4 100644 --- a/src/Parser/Parsing/Matcher/AbstractMatcherFactory.h +++ b/src/Parser/Parsing/Matcher/AbstractMatcherFactory.h @@ -7,6 +7,8 @@ #include "MatcherAnd.h" #include "MatcherLabel.h" #include "MatcherLoop.h" +#include "MatcherFalse.h" +#include "MatcherTrue.h" #include "MatcherOptional.h" #include "MatcherOr.h" #include "Parsing/IParserValue.h" @@ -85,6 +87,16 @@ public: { } + _NODISCARD MatcherFactoryWrapper False() const + { + return MatcherFactoryWrapper(std::make_unique>()); + } + + _NODISCARD MatcherFactoryWrapper True() const + { + return MatcherFactoryWrapper(std::make_unique>()); + } + _NODISCARD MatcherFactoryWrapper And(std::initializer_list>>> matchers) const { return MatcherFactoryWrapper(std::make_unique>(matchers)); diff --git a/src/Parser/Parsing/Matcher/MatcherFalse.h b/src/Parser/Parsing/Matcher/MatcherFalse.h new file mode 100644 index 00000000..3834c223 --- /dev/null +++ b/src/Parser/Parsing/Matcher/MatcherFalse.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherFalse final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override + { + return MatcherResult::NoMatch(); + } + +public: + MatcherFalse() + = default; +}; diff --git a/src/Parser/Parsing/Matcher/MatcherTrue.h b/src/Parser/Parsing/Matcher/MatcherTrue.h new file mode 100644 index 00000000..7dd6375c --- /dev/null +++ b/src/Parser/Parsing/Matcher/MatcherTrue.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "Parsing/IParserValue.h" +#include "AbstractMatcher.h" + +template +class MatcherTrue final : public AbstractMatcher +{ + // TokenType must inherit IParserValue + static_assert(std::is_base_of::value); + +protected: + MatcherResult CanMatch(ILexer* lexer, unsigned tokenOffset) override + { + return MatcherResult::Match(0); + } + +public: + MatcherTrue() + = default; +}; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp index 7120b30f..032459df 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.cpp @@ -3,14 +3,17 @@ #include #include -SimpleExpressionBinaryOperationType::SimpleExpressionBinaryOperationType(std::string syntax, const SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction) - : m_syntax(std::move(syntax)), +SimpleExpressionBinaryOperationType::SimpleExpressionBinaryOperationType(const SimpleBinaryOperationId id, std::string syntax, const SimpleOperationPrecedence precedence, + evaluation_function_t evaluationFunction) + : m_id(id), + m_syntax(std::move(syntax)), m_precedence(precedence), m_evaluation_function(std::move(evaluationFunction)) { } const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_ADD( + SimpleBinaryOperationId::ADD, "+", SimpleOperationPrecedence::ADDITION_SUBTRACTION, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -48,6 +51,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SUBTRACT( + SimpleBinaryOperationId::SUBTRACT, "-", SimpleOperationPrecedence::ADDITION_SUBTRACTION, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -72,6 +76,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_MULTIPLY( + SimpleBinaryOperationId::MULTIPLY, "*", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -96,6 +101,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_DIVIDE( + SimpleBinaryOperationId::DIVIDE, "/", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -120,6 +126,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_REMAINDER( + SimpleBinaryOperationId::REMAINDER, "%", SimpleOperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -132,6 +139,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_AND( + SimpleBinaryOperationId::BITWISE_AND, "&", SimpleOperationPrecedence::BITWISE_AND, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -144,6 +152,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_BITWISE_OR( + SimpleBinaryOperationId::BITWISE_OR, "|", SimpleOperationPrecedence::BITWISE_OR, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -156,6 +165,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_LEFT( + SimpleBinaryOperationId::SHIFT_LEFT, "<<", SimpleOperationPrecedence::BITWISE_SHIFT, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -168,6 +178,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_SHIFT_RIGHT( + SimpleBinaryOperationId::SHIFT_RIGHT, ">>", SimpleOperationPrecedence::BITWISE_SHIFT, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -180,6 +191,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_THAN( + SimpleBinaryOperationId::GREATER_THAN, ">", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -207,6 +219,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_GREATER_EQUAL_THAN( + SimpleBinaryOperationId::GREATER_EQUAL_THAN, ">=", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -234,6 +247,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_THAN( + SimpleBinaryOperationId::LESS_THAN, "<", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -261,6 +275,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_LESS_EQUAL_THAN( + SimpleBinaryOperationId::LESS_EQUAL_THAN, "<=", SimpleOperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -288,6 +303,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_EQUALS( + SimpleBinaryOperationId::EQUALS, "==", SimpleOperationPrecedence::RELATIONAL_EQUALS, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -325,6 +341,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_NOT_EQUAL( + SimpleBinaryOperationId::NOT_EQUAL, "!=", SimpleOperationPrecedence::RELATIONAL_EQUALS, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -362,6 +379,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_AND( + SimpleBinaryOperationId::AND, "&&", SimpleOperationPrecedence::LOGICAL_AND, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue @@ -373,6 +391,7 @@ const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::O ); const SimpleExpressionBinaryOperationType SimpleExpressionBinaryOperationType::OPERATION_OR( + SimpleBinaryOperationId::OR, "||", SimpleOperationPrecedence::LOGICAL_OR, [](const SimpleExpressionValue& operand1, const SimpleExpressionValue& operand2) -> SimpleExpressionValue diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h index 90eefe1f..44446a45 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h @@ -49,12 +49,13 @@ class SimpleExpressionBinaryOperationType public: using evaluation_function_t = std::function; + SimpleBinaryOperationId m_id; std::string m_syntax; SimpleOperationPrecedence m_precedence; evaluation_function_t m_evaluation_function; private: - SimpleExpressionBinaryOperationType(std::string syntax, SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction); + SimpleExpressionBinaryOperationType(SimpleBinaryOperationId id, std::string syntax, SimpleOperationPrecedence precedence, evaluation_function_t evaluationFunction); public: static const SimpleExpressionBinaryOperationType OPERATION_ADD; diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp new file mode 100644 index 00000000..244bb4fe --- /dev/null +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.cpp @@ -0,0 +1,316 @@ +#include "SimpleExpressionMatchers.h" + +#include + +#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" +#include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h" +#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h" + +static constexpr int TAG_EXPRESSION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 1; +static constexpr int TAG_OPERAND = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 2; +static constexpr int TAG_UNARY_OPERATION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 3; +static constexpr int TAG_PARENTHESIS = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 4; +static constexpr int TAG_PARENTHESIS_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 5; +static constexpr int TAG_BINARY_OPERATION = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 6; +static constexpr int TAG_OPERAND_EXT = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 7; +static constexpr int TAG_OPERAND_EXT_END = SimpleExpressionMatchers::TAG_OFFSET_EXPRESSION + 8; + +static constexpr int CAPTURE_OPERAND = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 1; +static constexpr int CAPTURE_UNARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 2; +static constexpr int CAPTURE_BINARY_OPERATION_TYPE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION + 3; + +SimpleExpressionMatchers::SimpleExpressionMatchers() + : SimpleExpressionMatchers(true, true, true, true) +{ +} + +SimpleExpressionMatchers::SimpleExpressionMatchers(const bool enableStringOperands, const bool enableIdentifierOperands, const bool enableFloatingPointOperands, const bool enableIntOperands) + : m_enable_string_operands(enableStringOperands), + m_enable_identifier_operands(enableIdentifierOperands), + m_enable_floating_point_operands(enableFloatingPointOperands), + m_enable_int_operands(enableIntOperands) +{ +} + +SimpleExpressionMatchers::~SimpleExpressionMatchers() += default; + +void SimpleExpressionMatchers::ApplyTokensToLexerConfig(SimpleLexer::Config& lexerConfig) +{ + for (const auto* unaryOperation : SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES) + { + if (unaryOperation->m_syntax.size() <= 1) + continue; + + lexerConfig.m_multi_character_tokens.emplace_back(MULTI_TOKEN_OFFSET_UNARY + static_cast(unaryOperation->m_id), unaryOperation->m_syntax); + } + + for (const auto* binaryOperation : SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES) + { + if (binaryOperation->m_syntax.size() <= 1) + continue; + + lexerConfig.m_multi_character_tokens.emplace_back(MULTI_TOKEN_OFFSET_BINARY + static_cast(binaryOperation->m_id), binaryOperation->m_syntax); + } +} + +std::vector SimpleExpressionMatchers::EnabledUnaryOperations() const +{ + return std::vector(&SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[0], + &SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[std::extent_v]); +} + +std::vector SimpleExpressionMatchers::EnabledBinaryOperations() const +{ + return std::vector(&SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[0], + &SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[std::extent_v]); +} + +std::unique_ptr SimpleExpressionMatchers::ProcessExpressionInParenthesis(SequenceResult& result) const +{ + auto processedEvaluation = ProcessExpression(result); + + if (result.PeekAndRemoveIfTag(TAG_PARENTHESIS_END) != TAG_PARENTHESIS_END) + throw ParsingException(TokenPos(), "Expected parenthesis end tag @ ExpressionInParenthesis"); + + return processedEvaluation; +} + +std::unique_ptr SimpleExpressionMatchers::ProcessOperand(SequenceResult& result) const +{ + const auto& operandToken = result.NextCapture(CAPTURE_OPERAND); + + switch (operandToken.m_type) + { + case SimpleParserValueType::INTEGER: + return std::make_unique(operandToken.IntegerValue()); + case SimpleParserValueType::FLOATING_POINT: + return std::make_unique(operandToken.FloatingPointValue()); + case SimpleParserValueType::STRING: + return std::make_unique(operandToken.StringValue()); + case SimpleParserValueType::IDENTIFIER: + return std::make_unique(operandToken.IdentifierValue()); + default: + throw ParsingException(TokenPos(), "Unknown operand type @ Operand"); + } +} + +std::unique_ptr SimpleExpressionMatchers::ProcessOperandExtension(SequenceResult& result) const +{ + return nullptr; +} + +std::unique_ptr SimpleExpressionMatchers::ProcessExpression(SequenceResult& result) const +{ + if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION) + return nullptr; + + std::vector> operands; + std::list> operators; + + while (true) + { + std::unique_ptr firstStatementPart; + std::vector unaryOperations; + auto nextTag = result.NextTag(); + + while (nextTag == TAG_UNARY_OPERATION) + { + unaryOperations.push_back(result.NextCapture(CAPTURE_UNARY_OPERATION_TYPE).IntegerValue()); + nextTag = result.NextTag(); + } + + switch (nextTag) + { + case TAG_PARENTHESIS: + firstStatementPart = ProcessExpressionInParenthesis(result); + break; + + case TAG_OPERAND: + firstStatementPart = ProcessOperand(result); + break; + + case TAG_OPERAND_EXT: + firstStatementPart = ProcessOperandExtension(result); + if (result.PeekAndRemoveIfTag(TAG_OPERAND_EXT_END) != TAG_OPERAND_EXT_END) + throw ParsingException(TokenPos(), "Unclosed operand extension @ Expression"); + break; + + default: + throw ParsingException(TokenPos(), "Invalid followup tag @ Expression"); + } + + for (auto i = unaryOperations.size(); i > 0; i--) + { + const auto operationIndex = unaryOperations[i - 1]; + if (operationIndex < 0 || operationIndex >= static_cast(SimpleUnaryOperationId::COUNT)) + throw ParsingException(TokenPos(), "Invalid unary operation id @ Expression"); + firstStatementPart = std::make_unique(SimpleExpressionUnaryOperationType::ALL_OPERATION_TYPES[operationIndex], + std::move(firstStatementPart)); + } + + operands.emplace_back(std::move(firstStatementPart)); + + if (result.PeekAndRemoveIfTag(TAG_BINARY_OPERATION) == TAG_BINARY_OPERATION) + { + const auto operationIndex = result.NextCapture(CAPTURE_BINARY_OPERATION_TYPE).IntegerValue(); + if (operationIndex < 0 || operationIndex >= static_cast(SimpleBinaryOperationId::COUNT)) + throw ParsingException(TokenPos(), "Invalid binary operation id @ Expression"); + + operators.emplace_back(operators.size(), SimpleExpressionBinaryOperationType::ALL_OPERATION_TYPES[operationIndex]); + } + else + break; + + if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) != TAG_EXPRESSION) + throw ParsingException(TokenPos(), "Expected EvaluationTag @ Evaluation"); + } + + operators.sort([](const std::pair& p1, const std::pair& p2) + { + if (p1.second->m_precedence != p2.second->m_precedence) + return p1.second->m_precedence > p2.second->m_precedence; + + return p1.first > p2.first; + }); + + while (!operators.empty()) + { + const auto& [operatorIndex, operatorType] = operators.back(); + + auto operation = std::make_unique(operatorType, std::move(operands[operatorIndex]), std::move(operands[operatorIndex + 1])); + operands.erase(operands.begin() + static_cast(operatorIndex)); + operands[operatorIndex] = std::move(operation); + + operators.pop_back(); + + for (auto& [opIndex, _] : operators) + { + if (opIndex > operatorIndex) + opIndex--; + } + } + + return std::move(operands.front()); +} + +std::unique_ptr SimpleExpressionMatchers::ParseOperand(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + std::vector> operandMatchers; + operandMatchers.reserve(4); + + if (m_enable_string_operands) + operandMatchers.emplace_back(create.String()); + + if (m_enable_identifier_operands) + operandMatchers.emplace_back(create.Identifier()); + + if (m_enable_floating_point_operands) + operandMatchers.emplace_back(create.FloatingPoint()); + + if (m_enable_int_operands) + operandMatchers.emplace_back(create.Integer()); + + return create.Or(std::move(operandMatchers)).Tag(TAG_OPERAND).Capture(CAPTURE_OPERAND); +} + +std::unique_ptr SimpleExpressionMatchers::ParseBinaryOperationType(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + const auto enabledBinaryOperations = EnabledBinaryOperations(); + std::vector> binaryOperationsMatchers; + binaryOperationsMatchers.reserve(enabledBinaryOperations.size()); + + for (const auto* enabledBinaryOperation : enabledBinaryOperations) + { + if (enabledBinaryOperation->m_syntax.size() > 1) + { + binaryOperationsMatchers.emplace_back( + create.MultiChar(MULTI_TOKEN_OFFSET_BINARY + static_cast(enabledBinaryOperation->m_id)) + .Transform([enabledBinaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledBinaryOperation->m_id)); + })); + } + else if (!enabledBinaryOperation->m_syntax.empty()) + { + binaryOperationsMatchers.emplace_back( + create.Char(enabledBinaryOperation->m_syntax[0]) + .Transform([enabledBinaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledBinaryOperation->m_id)); + })); + } + } + + return create.Or(std::move(binaryOperationsMatchers)).Capture(CAPTURE_BINARY_OPERATION_TYPE); +} + +std::unique_ptr SimpleExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + return create.False(); +} + +std::unique_ptr SimpleExpressionMatchers::ParseUnaryOperationType(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + const auto enabledUnaryOperations = EnabledUnaryOperations(); + std::vector> unaryOperationsMatchers; + unaryOperationsMatchers.reserve(enabledUnaryOperations.size()); + + for (const auto* enabledUnaryOperation : enabledUnaryOperations) + { + if (enabledUnaryOperation->m_syntax.size() > 1) + { + unaryOperationsMatchers.emplace_back( + create.MultiChar(MULTI_TOKEN_OFFSET_UNARY + static_cast(enabledUnaryOperation->m_id)) + .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); + })); + } + else if (!enabledUnaryOperation->m_syntax.empty()) + { + unaryOperationsMatchers.emplace_back( + create.Char(enabledUnaryOperation->m_syntax[0]) + .Transform([enabledUnaryOperation](const SimpleMatcherFactory::token_list_t& values) + { + return SimpleParserValue::Integer(values[0].get().GetPos(), static_cast(enabledUnaryOperation->m_id)); + })); + } + } + + return create.Or(std::move(unaryOperationsMatchers)).Tag(TAG_UNARY_OPERATION).Capture(CAPTURE_UNARY_OPERATION_TYPE); +} + +std::unique_ptr SimpleExpressionMatchers::Expression(const supplier_t* labelSupplier) const +{ + const SimpleMatcherFactory create(labelSupplier); + + return create.And({ + create.OptionalLoop(ParseUnaryOperationType(labelSupplier)), + create.Or({ + create.And({ + create.Char('('), + create.Label(LABEL_EXPRESSION), + create.Char(')').Tag(TAG_PARENTHESIS_END) + }).Tag(TAG_PARENTHESIS), + create.And({ + create.True().Tag(TAG_OPERAND_EXT), + ParseOperandExtension(labelSupplier), + create.True().Tag(TAG_OPERAND_EXT_END) + }), + ParseOperand(labelSupplier) + }), + create.Optional(create.And({ + ParseBinaryOperationType(labelSupplier), + create.Label(LABEL_EXPRESSION) + }).Tag(TAG_BINARY_OPERATION)) + }).Tag(TAG_EXPRESSION); +} diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h new file mode 100644 index 00000000..5d9cb3f2 --- /dev/null +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionMatchers.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include "SimpleExpressionBinaryOperation.h" +#include "SimpleExpressionUnaryOperation.h" +#include "Utils/ClassUtils.h" +#include "Parsing/Matcher/AbstractMatcher.h" +#include "Parsing/Matcher/MatcherLabel.h" +#include "Parsing/Simple/Expression/ISimpleExpression.h" +#include "Parsing/Sequence/SequenceResult.h" +#include "Parsing/Simple/SimpleParserValue.h" +#include + +class SimpleExpressionMatchers +{ +public: + using matcher_t = AbstractMatcher; + typedef IMatcherForLabelSupplier supplier_t; + + static constexpr auto CAPTURE_OFFSET_EXPRESSION = 7000; + static constexpr auto TAG_OFFSET_EXPRESSION = 7000; + static constexpr auto CAPTURE_OFFSET_EXPRESSION_EXT = 8000; + static constexpr auto TAG_OFFSET_EXPRESSION_EXT = 8000; + static constexpr auto LABEL_EXPRESSION = 7000; + static constexpr auto MULTI_TOKEN_OFFSET_UNARY = 700; + static constexpr auto MULTI_TOKEN_OFFSET_BINARY = 720; + +private: + bool m_enable_string_operands; + bool m_enable_identifier_operands; + bool m_enable_floating_point_operands; + bool m_enable_int_operands; + +public: + SimpleExpressionMatchers(); + virtual ~SimpleExpressionMatchers(); + SimpleExpressionMatchers(const SimpleExpressionMatchers& other) = default; + SimpleExpressionMatchers(SimpleExpressionMatchers&& other) noexcept = default; + SimpleExpressionMatchers& operator=(const SimpleExpressionMatchers& other) = default; + SimpleExpressionMatchers& operator=(SimpleExpressionMatchers&& other) noexcept = default; + +protected: + SimpleExpressionMatchers(bool enableStringOperands, bool enableIdentifierOperands, bool enableFloatingPointOperands, bool enableIntOperands); + + virtual std::unique_ptr ParseOperandExtension(const supplier_t* labelSupplier) const; + virtual std::unique_ptr ProcessOperandExtension(SequenceResult& result) const; + + _NODISCARD virtual std::vector EnabledUnaryOperations() const; + _NODISCARD virtual std::vector EnabledBinaryOperations() const; + +private: + std::unique_ptr ParseBinaryOperationType(const supplier_t* labelSupplier) const; + std::unique_ptr ParseOperand(const supplier_t* labelSupplier) const; + std::unique_ptr ParseUnaryOperationType(const supplier_t* labelSupplier) const; + + std::unique_ptr ProcessExpressionInParenthesis(SequenceResult& result) const; + std::unique_ptr ProcessOperand(SequenceResult& result) const; + +public: + std::unique_ptr Expression(const supplier_t* labelSupplier) const; + std::unique_ptr ProcessExpression(SequenceResult& result) const; + + virtual void ApplyTokensToLexerConfig(SimpleLexer::Config& lexerConfig); +}; \ No newline at end of file diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp index 05ece031..2041f1ce 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.cpp @@ -4,13 +4,15 @@ #include "SimpleExpressionBinaryOperation.h" -SimpleExpressionUnaryOperationType::SimpleExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction) - : m_syntax(std::move(syntax)), +SimpleExpressionUnaryOperationType::SimpleExpressionUnaryOperationType(const SimpleUnaryOperationId id, std::string syntax, evaluation_function_t evaluationFunction) + : m_id(id), + m_syntax(std::move(syntax)), m_evaluation_function(std::move(evaluationFunction)) { } const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_NOT( + SimpleUnaryOperationId::NOT, "!", [](const SimpleExpressionValue& operand) -> SimpleExpressionValue { @@ -19,10 +21,11 @@ const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPE ); const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_BITWISE_NOT( + SimpleUnaryOperationId::BITWISE_NOT, "~", [](const SimpleExpressionValue& operand) -> SimpleExpressionValue { - if(operand.m_type == SimpleExpressionValue::Type::INT) + if (operand.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(~operand.m_int_value); return SimpleExpressionValue(0); @@ -30,10 +33,11 @@ const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPE ); const SimpleExpressionUnaryOperationType SimpleExpressionUnaryOperationType::OPERATION_NEGATIVE( + SimpleUnaryOperationId::NEGATIVE, "-", [](const SimpleExpressionValue& operand) -> SimpleExpressionValue { - if(operand.m_type == SimpleExpressionValue::Type::INT) + if (operand.m_type == SimpleExpressionValue::Type::INT) return SimpleExpressionValue(-operand.m_int_value); if (operand.m_type == SimpleExpressionValue::Type::DOUBLE) return SimpleExpressionValue(-operand.m_double_value); diff --git a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h index 771a7e0d..bfbe0302 100644 --- a/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h +++ b/src/Parser/Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h @@ -21,11 +21,12 @@ class SimpleExpressionUnaryOperationType public: using evaluation_function_t = std::function; + SimpleUnaryOperationId m_id; std::string m_syntax; evaluation_function_t m_evaluation_function; private: - SimpleExpressionUnaryOperationType(std::string syntax, evaluation_function_t evaluationFunction); + SimpleExpressionUnaryOperationType(SimpleUnaryOperationId id, std::string syntax, evaluation_function_t evaluationFunction); public: static const SimpleExpressionUnaryOperationType OPERATION_NOT; diff --git a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h index 8abd31b4..c5a801f5 100644 --- a/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h +++ b/src/Parser/Parsing/Simple/Matcher/SimpleMatcherFactory.h @@ -9,7 +9,7 @@ class SimpleMatcherFactory : public AbstractMatcherFactory { public: explicit SimpleMatcherFactory(const IMatcherForLabelSupplier* labelSupplier); - + _NODISCARD MatcherFactoryWrapper Type(SimpleParserValueType type) const; _NODISCARD MatcherFactoryWrapper Keyword(std::string value) const; _NODISCARD MatcherFactoryWrapper KeywordIgnoreCase(std::string value) const;