diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp index c0b19d27..3266be2f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp @@ -103,9 +103,9 @@ static constexpr int TAG_EVALUATION = std::numeric_limits::max() - 9; static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits::max() - 10; static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits::max() - 1; -static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits::max() - 1; -static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits::max() - 2; -static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits::max() - 3; +static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits::max() - 2; +static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits::max() - 3; +static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits::max() - 4; std::unique_ptr CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier) { diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.cpp index 555bb048..5844fdd1 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.cpp @@ -1,5 +1,7 @@ #include "SequenceCount.h" +#include "Domain/Definition/ArrayDeclarationModifier.h" +#include "Domain/Definition/PointerDeclarationModifier.h" #include "Parsing/Commands/Matcher/CommandsMatcherFactory.h" #include "Parsing/Commands/Matcher/CommandsCommonMatchers.h" @@ -11,16 +13,116 @@ SequenceCount::SequenceCount() AddLabeledMatchers(CommandsCommonMatchers::Evaluation(this), CommandsCommonMatchers::LABEL_EVALUATION); AddLabeledMatchers(CommandsCommonMatchers::ArrayDef(this), CommandsCommonMatchers::LABEL_ARRAY_DEF); AddMatchers({ - create.Keyword("set"), + create.Keyword("set").Capture(CAPTURE_START), create.Keyword("count"), create.OptionalLoop(create.Char('*').Tag(TAG_POINTER_RESOLVE)), create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE), create.OptionalLoop(create.Label(CommandsCommonMatchers::LABEL_ARRAY_DEF).Capture(CAPTURE_ARRAY_INDEX)), - create.Label(CommandsCommonMatchers::LABEL_EVALUATION).Capture(CAPTURE_EVALUATION), + create.Label(CommandsCommonMatchers::LABEL_EVALUATION), create.Char(';') }); } +void SequenceCount::SetCountByArrayIndex(CommandsParserState* state, SequenceResult& result, MemberInformation* member, PointerDeclarationModifier* pointer, + std::unique_ptr evaluation) +{ + std::vector arraySizes; + std::vector depthSize; + for (const auto& modifier : member->m_member->m_type_declaration->m_declaration_modifiers) + { + if (modifier->GetType() == DeclarationModifierType::ARRAY) + arraySizes.push_back(dynamic_cast(modifier.get())->m_size); + } + + depthSize.resize(arraySizes.size()); + auto currentDepthSize = 1u; + for (auto i = arraySizes.size(); i > 0; i--) + { + if(i < arraySizes.size()) + currentDepthSize *= arraySizes[i]; + depthSize[i - 1] = currentDepthSize; + } + + if (pointer->m_count_evaluation_by_array_index.empty()) + { + auto neededCapacity = 0u; + for (auto arraySize : arraySizes) + { + if (neededCapacity == 0) + neededCapacity = arraySize; + else + neededCapacity *= arraySize; + } + pointer->m_count_evaluation_by_array_index.resize(neededCapacity); + } + + auto currentIndex = 0u; + auto currentIndexOffset = 0u; + while (result.HasNextCapture(CAPTURE_ARRAY_INDEX) && currentIndexOffset < depthSize.size()) + { + const auto& arrayIndexToken = result.NextCapture(CAPTURE_ARRAY_INDEX); + if (arrayIndexToken.m_type == CommandsParserValueType::INTEGER) + { + currentIndex += depthSize[currentIndexOffset++] * arrayIndexToken.IntegerValue(); + } + else + { + auto* enumEntry = state->GetRepository()->GetEnumMemberByName(arrayIndexToken.IdentifierValue()); + if (enumEntry == nullptr) + throw ParsingException(arrayIndexToken.GetPos(), "Unknown enum entry"); + + currentIndex += depthSize[currentIndexOffset++] * enumEntry->m_value; + } + } + + pointer->m_count_evaluation_by_array_index[currentIndex] = std::move(evaluation); +} + void SequenceCount::ProcessMatch(CommandsParserState* state, SequenceResult& result) const { + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE); + + StructureInformation* type; + std::vector memberChain; + if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), type, memberChain)) + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + + if (memberChain.empty()) + throw ParsingException(typeNameToken.GetPos(), "Conditions can only be set on members and not for types"); + + auto resolve = 0u; + while (result.PeekAndRemoveIfTag(TAG_POINTER_RESOLVE) == TAG_POINTER_RESOLVE) + resolve++; + + auto* lastMember = memberChain.back(); + PointerDeclarationModifier* pointer = nullptr; + for (const auto& modifier : lastMember->m_member->m_type_declaration->m_declaration_modifiers) + { + if (modifier->GetType() == DeclarationModifierType::POINTER) + { + if (resolve > 0) + { + resolve--; + } + else + { + pointer = dynamic_cast(modifier.get()); + break; + } + } + } + + if (pointer == nullptr) + throw ParsingException(result.NextCapture(CAPTURE_START).GetPos(), "No matching pointer modifier found"); + + auto countEvaluation = CommandsCommonMatchers::ProcessEvaluation(state, result, type); + + if (!result.HasNextCapture(CAPTURE_ARRAY_INDEX)) + { + pointer->m_count_evaluation = std::move(countEvaluation); + } + else + { + SetCountByArrayIndex(state, result, lastMember, pointer, std::move(countEvaluation)); + } } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.h index 3cc16f01..dafa4981 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceCount.h @@ -1,14 +1,18 @@ #pragma once +#include "Domain/Definition/PointerDeclarationModifier.h" #include "Parsing/Commands/Impl/CommandsParser.h" class SequenceCount final : public CommandsParser::sequence_t { static constexpr auto TAG_POINTER_RESOLVE = 1; - static constexpr auto CAPTURE_TYPE = 1; - static constexpr auto CAPTURE_ARRAY_INDEX = 2; - static constexpr auto CAPTURE_EVALUATION = 3; + static constexpr auto CAPTURE_START = 1; + static constexpr auto CAPTURE_TYPE = 2; + static constexpr auto CAPTURE_ARRAY_INDEX = 3; + + static void SetCountByArrayIndex(CommandsParserState* state, SequenceResult& result, MemberInformation* member, PointerDeclarationModifier* pointer, + std::unique_ptr evaluation); protected: void ProcessMatch(CommandsParserState* state, SequenceResult& result) const override;