diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.h index d914a46a..eba3c274 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.h @@ -5,10 +5,11 @@ #include "IHeaderBlock.h" #include "IHeaderBlockNameHolder.h" #include "IHeaderBlockVariableDefining.h" +#include "IHeaderBlockVariableHolder.h" #include "Domain/Definition/StructDefinition.h" #include "Domain/Definition/Variable.h" -class HeaderBlockStruct final : public IHeaderBlock, public IHeaderBlockNameHolder, public IHeaderBlockVariableDefining +class HeaderBlockStruct final : public IHeaderBlock, public IHeaderBlockNameHolder, public IHeaderBlockVariableDefining, public IHeaderBlockVariableHolder { std::string m_namespace; std::string m_type_name; @@ -32,7 +33,7 @@ public: void OnClose(HeaderParserState* state) override; void OnChildBlockClose(HeaderParserState* state, IHeaderBlock* block) override; - void AddVariable(std::shared_ptr variable); + void AddVariable(std::shared_ptr variable) override; void SetCustomAlignment(int alignment); void Inherit(const StructDefinition* parentStruct); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.h index edcbd25f..3fc53fd7 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.h @@ -3,8 +3,9 @@ #include "IHeaderBlock.h" #include "IHeaderBlockNameHolder.h" #include "IHeaderBlockVariableDefining.h" +#include "IHeaderBlockVariableHolder.h" -class HeaderBlockUnion final : public IHeaderBlock, public IHeaderBlockNameHolder, public IHeaderBlockVariableDefining +class HeaderBlockUnion final : public IHeaderBlock, public IHeaderBlockNameHolder, public IHeaderBlockVariableDefining, public IHeaderBlockVariableHolder { std::string m_namespace; std::string m_type_name; @@ -28,7 +29,7 @@ public: void OnClose(HeaderParserState* state) override; void OnChildBlockClose(HeaderParserState* state, IHeaderBlock* block) override; - void AddVariable(std::shared_ptr variable); + void AddVariable(std::shared_ptr variable) override; void SetCustomAlignment(int alignment); void Inherit(const StructDefinition* parentStruct); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/IHeaderBlockVariableHolder.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/IHeaderBlockVariableHolder.h new file mode 100644 index 00000000..86141f4c --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/IHeaderBlockVariableHolder.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +#include "Domain/Definition/Variable.h" + +class IHeaderBlockVariableHolder +{ +public: + IHeaderBlockVariableHolder() = default; + virtual ~IHeaderBlockVariableHolder() = default; + IHeaderBlockVariableHolder(const IHeaderBlockVariableHolder& other) = default; + IHeaderBlockVariableHolder(IHeaderBlockVariableHolder&& other) noexcept = default; + IHeaderBlockVariableHolder& operator=(const IHeaderBlockVariableHolder& other) = default; + IHeaderBlockVariableHolder& operator=(IHeaderBlockVariableHolder&& other) noexcept = default; + + virtual void AddVariable(std::shared_ptr variable) = 0; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp index 5dfb2730..4204f0ef 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceTypedef.cpp @@ -1,6 +1,5 @@ #include "SequenceTypedef.h" - #include "Domain/Definition/ArrayDeclarationModifier.h" #include "Domain/Definition/PointerDeclarationModifier.h" #include "Parsing/Header/Matcher/HeaderMatcherFactory.h" diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp index 0071b4b5..712b5c94 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.cpp @@ -1,5 +1,8 @@ #include "SequenceVariable.h" +#include "Domain/Definition/ArrayDeclarationModifier.h" +#include "Domain/Definition/PointerDeclarationModifier.h" +#include "Parsing/Header/Block/IHeaderBlockVariableHolder.h" #include "Parsing/Header/Matcher/HeaderMatcherFactory.h" #include "Parsing/Header/Matcher/HeaderCommonMatchers.h" @@ -38,11 +41,80 @@ SequenceVariable::SequenceVariable() }, LABEL_POINTER_TO_ARRAY); AddMatchers(create.Or({ - create.Label(LABEL_ARRAY_OF_POINTERS), - create.Label(LABEL_POINTER_TO_ARRAY) + create.Label(LABEL_ARRAY_OF_POINTERS).Tag(TAG_ARRAY_OF_POINTERS), + create.Label(LABEL_POINTER_TO_ARRAY).Tag(TAG_POINTER_TO_ARRAY) })); } +void SequenceVariable::AddPointerDeclarationModifiers(SequenceResult& result, TypeDeclaration* typeDeclaration) const +{ + while (result.PeekAndRemoveIfTag(TAG_POINTER) == TAG_POINTER) + typeDeclaration->m_declaration_modifiers.emplace_back(std::make_unique()); +} + +void SequenceVariable::AddArrayDeclarationModifiers(HeaderParserState* state, SequenceResult& result, TypeDeclaration* typeDeclaration) const +{ + while (result.HasNextCapture(CAPTURE_ARRAY)) + { + const auto& arrayToken = result.NextCapture(CAPTURE_ARRAY); + + if (arrayToken.m_type == HeaderParserValueType::INTEGER) + { + typeDeclaration->m_declaration_modifiers.emplace_back(std::make_unique(arrayToken.IntegerValue())); + } + else + { + auto* enumMember = state->FindEnumMember(arrayToken.IdentifierValue()); + + if (enumMember == nullptr) + throw ParsingException(arrayToken.GetPos(), "Unknown enum member"); + + typeDeclaration->m_declaration_modifiers.emplace_back(std::make_unique(enumMember->m_value)); + } + } +} + void SequenceVariable::ProcessMatch(HeaderParserState* state, SequenceResult& result) const { + auto* variableHolder = dynamic_cast(state->GetBlock()); + if (variableHolder == nullptr) + throw ParsingException(TokenPos(), "Defining variable in non VariableHolder block"); + + const auto modeTag = result.NextTag(); + assert(modeTag == TAG_ARRAY_OF_POINTERS || modeTag == TAG_POINTER_TO_ARRAY); + + const auto name = result.NextCapture(CAPTURE_NAME).IdentifierValue(); + + const auto& typenameToken = result.NextCapture(CAPTURE_TYPE); + const auto* type = state->FindType(typenameToken.TypeNameValue()); + if (type == nullptr && !state->m_namespace.IsEmpty()) + { + const auto fullTypename = NamespaceBuilder::Combine(state->m_namespace.ToString(), typenameToken.TypeNameValue()); + type = state->FindType(fullTypename); + } + if (type == nullptr) + throw ParsingException(typenameToken.GetPos(), "Unknown type"); + + auto variable = std::make_shared(name, std::make_unique(type)); + variable->m_type_declaration->m_is_const = result.PeekAndRemoveIfTag(TAG_CONST) == TAG_CONST; + + if (result.HasNextCapture(CAPTURE_ALIGN)) + { + const auto& alignToken = result.NextCapture(CAPTURE_ALIGN); + variable->m_alignment_override = static_cast(alignToken.IntegerValue()); + variable->m_has_alignment_override = true; + } + + if (modeTag == TAG_ARRAY_OF_POINTERS) + { + AddArrayDeclarationModifiers(state, result, variable->m_type_declaration.get()); + AddPointerDeclarationModifiers(result, variable->m_type_declaration.get()); + } + else + { + AddPointerDeclarationModifiers(result, variable->m_type_declaration.get()); + AddArrayDeclarationModifiers(state, result, variable->m_type_declaration.get()); + } + + variableHolder->AddVariable(std::move(variable)); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h index 55145d01..70a5986f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Sequence/SequenceVariable.h @@ -21,6 +21,9 @@ class SequenceVariable final : public HeaderParser::sequence_t static constexpr auto LABEL_ARRAY_OF_POINTERS = 1; static constexpr auto LABEL_POINTER_TO_ARRAY = 2; + void AddPointerDeclarationModifiers(SequenceResult& result, TypeDeclaration* typeDeclaration) const; + void AddArrayDeclarationModifiers(HeaderParserState* state, SequenceResult& result, TypeDeclaration* typeDeclaration) const; + protected: void ProcessMatch(HeaderParserState* state, SequenceResult& result) const override; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h index 44ab5fca..f6e4d797 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Matcher/AbstractMatcher.h @@ -68,7 +68,7 @@ public: return result; if (m_tag_id != NO_ID) - result.m_tags.push_back(m_tag_id); + result.m_tags.insert(result.m_tags.begin(), m_tag_id); if (m_transform_func) { diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Header/Sequence/SequenceNamespaceTests.cpp b/test/ZoneCodeGeneratorLibTests/Parsing/Header/Sequence/SequenceNamespaceTests.cpp index fc671188..919b7055 100644 --- a/test/ZoneCodeGeneratorLibTests/Parsing/Header/Sequence/SequenceNamespaceTests.cpp +++ b/test/ZoneCodeGeneratorLibTests/Parsing/Header/Sequence/SequenceNamespaceTests.cpp @@ -2,6 +2,7 @@ #include "Parsing/Header/Sequence/SequenceNamespace.h" #include "Parsing/Mock/MockLexer.h" +#include "Parsing/Mock/MockPackValueSupplier.h" namespace test::parsing::header::sequence::sequence_namespace { @@ -15,8 +16,9 @@ namespace test::parsing::header::sequence::sequence_namespace HeaderParserValue::Character(pos, '{') }, HeaderParserValue::EndOfFile(pos))); + const auto packValueSupplier = std::make_unique(); const auto sequence = std::make_unique(); - const auto state = std::make_unique(); + const auto state = std::make_unique(packValueSupplier.get()); unsigned consumedTokenCount; auto result = sequence->MatchSequence(lexer.get(), state.get(), consumedTokenCount); diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.cpp b/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.cpp new file mode 100644 index 00000000..a839dec9 --- /dev/null +++ b/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.cpp @@ -0,0 +1,8 @@ +#include "MockPackValueSupplier.h" + +#include "Parsing/Impl/PackDefinitionStreamProxy.h" + +int MockPackValueSupplier::GetCurrentPack() const +{ + return PackDefinitionStreamProxy::DEFAULT_PACK; +} diff --git a/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.h b/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.h new file mode 100644 index 00000000..adcb0114 --- /dev/null +++ b/test/ZoneCodeGeneratorLibTests/Parsing/Mock/MockPackValueSupplier.h @@ -0,0 +1,10 @@ +#pragma once + +#include "Utils/ClassUtils.h" +#include "Parsing/IPackValueSupplier.h" + +class MockPackValueSupplier final : public IPackValueSupplier +{ +public: + _NODISCARD int GetCurrentPack() const override; +};