diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.cpp index 7a880a5b..d69e9d4d 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.cpp @@ -9,7 +9,7 @@ SequenceReorder::SequenceReorder() AddLabeledMatchers(CommandsCommonMatchers::Typename(this), CommandsCommonMatchers::LABEL_TYPENAME); AddMatchers({ - create.Keyword("reorder"), + create.Keyword("reorder").Capture(CAPTURE_START), create.Optional(create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE)), create.Char(':'), create.Optional(create.And({ @@ -22,6 +22,84 @@ SequenceReorder::SequenceReorder() }); } +StructureInformation* SequenceReorder::GetType(CommandsParserState* state, SequenceResult& result) +{ + if (result.HasNextCapture(CAPTURE_TYPE)) + { + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE); + StructureInformation* information; + std::vector memberChain; + + if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), information, memberChain)) + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + + if (memberChain.empty()) + return information; + + auto* lastMember = memberChain.back(); + + if (lastMember->m_type == nullptr) + throw ParsingException(typeNameToken.GetPos(), "Member type must either be struct or union"); + + return lastMember->m_type; + } + + if (state->GetInUse() != nullptr) + return state->GetInUse(); + + throw ParsingException(result.NextCapture(CAPTURE_START).GetPos(), "No type is used. Therefore one needs to be specified directly."); +} + void SequenceReorder::ProcessMatch(CommandsParserState* state, SequenceResult& result) const { + auto* information = GetType(state, result); + auto findFirst = result.PeekAndRemoveIfTag(TAG_FIND_FIRST) == TAG_FIND_FIRST; + + std::string firstVariableName; + if(findFirst) + firstVariableName = result.NextCapture(CAPTURE_ENTRY).IdentifierValue(); + + std::vector> newMembers; + std::list> oldMembers; + + for (auto& oldMember : information->m_ordered_members) + oldMembers.emplace_back(std::move(oldMember)); + + while(result.HasNextCapture(CAPTURE_ENTRY)) + { + const auto& entryToken = result.NextCapture(CAPTURE_ENTRY); + const auto& nextVariableName = entryToken.IdentifierValue(); + auto foundEntry = false; + + for(auto i = oldMembers.begin(); i != oldMembers.end(); ++i) + { + if(i->get()->m_member->m_name == nextVariableName) + { + newMembers.emplace_back(std::move(*i)); + oldMembers.erase(i); + foundEntry = true; + break; + } + } + + if (!foundEntry) + throw ParsingException(entryToken.GetPos(), "Could not find member with specified name"); + } + + information->m_ordered_members.clear(); + + while(findFirst && !oldMembers.empty()) + { + if (oldMembers.front()->m_member->m_name == firstVariableName) + findFirst = false; + + information->m_ordered_members.push_back(std::move(oldMembers.front())); + oldMembers.pop_front(); + } + + for (auto& newMember : newMembers) + information->m_ordered_members.push_back(std::move(newMember)); + + for (auto& oldMember : oldMembers) + information->m_ordered_members.emplace_back(std::move(oldMember)); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.h index 69025476..c26fd14f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceReorder.h @@ -6,8 +6,11 @@ class SequenceReorder final : public CommandsParser::sequence_t { static constexpr auto TAG_FIND_FIRST = 1; - static constexpr auto CAPTURE_TYPE = 1; - static constexpr auto CAPTURE_ENTRY = 2; + static constexpr auto CAPTURE_START = 1; + static constexpr auto CAPTURE_TYPE = 2; + static constexpr auto CAPTURE_ENTRY = 3; + + static StructureInformation* GetType(CommandsParserState* state, SequenceResult& result); protected: void ProcessMatch(CommandsParserState* state, SequenceResult& result) const override;