mirror of
				https://github.com/Laupetin/OpenAssetTools.git
				synced 2025-10-30 18:17:15 +00:00 
			
		
		
		
	Move StructuredDataDef Parsing to new package
This commit is contained in:
		| @@ -0,0 +1,157 @@ | ||||
| #include "StructuredDataDefScopeSequences.h" | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| namespace sdd::def_scope_sequences | ||||
| { | ||||
|     class SequenceEnum final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_NAME = 1; | ||||
|         static constexpr auto CAPTURE_RESERVED_COUNT = 2; | ||||
|  | ||||
|     public: | ||||
|         SequenceEnum() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Keyword("enum"), | ||||
|                 create.Optional(create.And({ | ||||
|                     create.Char('('), | ||||
|                     create.Integer().Capture(CAPTURE_RESERVED_COUNT), | ||||
|                     create.Char(')') | ||||
|                 })), | ||||
|                 create.Identifier().Capture(CAPTURE_NAME), | ||||
|                 create.Char('{') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_def); | ||||
|  | ||||
|             auto newEnum = std::make_unique<CommonStructuredDataEnum>(result.NextCapture(CAPTURE_NAME).IdentifierValue()); | ||||
|             if (result.HasNextCapture(CAPTURE_RESERVED_COUNT)) | ||||
|             { | ||||
|                 const auto& reservedCountToken = result.NextCapture(CAPTURE_RESERVED_COUNT); | ||||
|                 newEnum->m_reserved_entry_count = reservedCountToken.IntegerValue(); | ||||
|  | ||||
|                 if (newEnum->m_reserved_entry_count <= 0) | ||||
|                     throw ParsingException(reservedCountToken.GetPos(), "Reserved enum entry count must be greater than zero"); | ||||
|             } | ||||
|  | ||||
|             state->m_current_enum = newEnum.get(); | ||||
|             state->m_def_types_by_name.emplace(newEnum->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::ENUM, state->m_current_def->m_enums.size())); | ||||
|             state->m_current_def->m_enums.emplace_back(std::move(newEnum)); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     class SequenceStruct final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_NAME = 1; | ||||
|  | ||||
|     public: | ||||
|         SequenceStruct() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Keyword("struct"), | ||||
|                 create.Identifier().Capture(CAPTURE_NAME), | ||||
|                 create.Char('{') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_def); | ||||
|  | ||||
|             auto newStruct = std::make_unique<CommonStructuredDataStruct>(result.NextCapture(CAPTURE_NAME).IdentifierValue()); | ||||
|             auto* newStructPtr = newStruct.get(); | ||||
|             const auto newStructIndex = state->m_current_def->m_structs.size(); | ||||
|  | ||||
|             state->m_current_struct = newStructPtr; | ||||
|             state->m_def_types_by_name.emplace(newStruct->m_name, CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex)); | ||||
|             state->m_current_def->m_structs.emplace_back(std::move(newStruct)); | ||||
|             state->m_current_struct_offset_in_bits = 0; | ||||
|  | ||||
|             if (newStructPtr->m_name == "root") | ||||
|             { | ||||
|                 state->m_current_struct_offset_in_bits = 64u; | ||||
|                 state->m_current_def->m_root_type = CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, newStructIndex); | ||||
|             } | ||||
|             else | ||||
|                 state->m_current_struct_offset_in_bits = 0; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     class SequenceCloseScope final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_NAME = 1; | ||||
|  | ||||
|     public: | ||||
|         SequenceCloseScope() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Char('}') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         static void CreateDefaultStructWhenNoStructsSpecified(const StructuredDataDefParserState* state) | ||||
|         { | ||||
|             if (state->m_current_def->m_structs.empty()) | ||||
|             { | ||||
|                 state->m_current_def->m_structs.emplace_back(std::make_unique<CommonStructuredDataStruct>()); | ||||
|                 state->m_current_def->m_root_type = CommonStructuredDataType(CommonStructuredDataTypeCategory::STRUCT, 0u); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static void SetDefSizeFromRootStruct(const StructuredDataDefParserState* state) | ||||
|         { | ||||
|             if (state->m_current_def->m_root_type.m_category == CommonStructuredDataTypeCategory::STRUCT | ||||
|                 && state->m_current_def->m_root_type.m_info.type_index < state->m_current_def->m_structs.size()) | ||||
|             { | ||||
|                 const auto* _struct = state->m_current_def->m_structs[state->m_current_def->m_root_type.m_info.type_index].get(); | ||||
|                 state->m_current_def->m_size_in_byte = _struct->m_size_in_byte; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_enum == nullptr); | ||||
|             assert(state->m_current_struct == nullptr); | ||||
|  | ||||
|             CreateDefaultStructWhenNoStructsSpecified(state); | ||||
|             SetDefSizeFromRootStruct(state); | ||||
|  | ||||
|             // TODO: Calculate checksum here | ||||
|  | ||||
|             state->m_current_def = nullptr; | ||||
|             state->m_def_types_by_name.clear(); | ||||
|             state->m_def_indexed_arrays.clear(); | ||||
|             state->m_def_enumed_arrays.clear(); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| using namespace sdd; | ||||
| using namespace def_scope_sequences; | ||||
|  | ||||
| StructuredDataDefScopeSequences::StructuredDataDefScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, | ||||
|                                                                        std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|     : AbstractScopeSequenceHolder(allSequences, scopeSequences) | ||||
| { | ||||
| } | ||||
|  | ||||
| void StructuredDataDefScopeSequences::AddSequences() const | ||||
| { | ||||
|     AddSequence(std::make_unique<SequenceCloseScope>()); | ||||
|     AddSequence(std::make_unique<SequenceEnum>()); | ||||
|     AddSequence(std::make_unique<SequenceStruct>()); | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Parsing/Sequence/AbstractScopeSequenceHolder.h" | ||||
| #include "StructuredDataDef/Parsing/StructuredDataDefParser.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataDefScopeSequences final : AbstractScopeSequenceHolder<StructuredDataDefParser> | ||||
|     { | ||||
|     public: | ||||
|         StructuredDataDefScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences); | ||||
|  | ||||
|         void AddSequences() const; | ||||
|     }; | ||||
| } | ||||
| @@ -0,0 +1,81 @@ | ||||
| #include "StructuredDataEnumScopeSequences.h" | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| namespace sdd::enum_scope_sequences | ||||
| { | ||||
|     class SequenceEnumEntry final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_ENTRY_VALUE = 1; | ||||
|  | ||||
|     public: | ||||
|         SequenceEnumEntry() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.String().Capture(CAPTURE_ENTRY_VALUE), | ||||
|                 create.Or({ | ||||
|                     create.Char(','), | ||||
|                     create.Char('}').NoConsume() | ||||
|                 }) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_enum); | ||||
|  | ||||
|             const auto& entryValueToken = result.NextCapture(CAPTURE_ENTRY_VALUE); | ||||
|             if (state->m_current_enum->m_reserved_entry_count > 0 && static_cast<size_t>(state->m_current_enum->m_reserved_entry_count) <= state->m_current_enum->m_entries.size()) | ||||
|                 throw ParsingException(entryValueToken.GetPos(), "Enum entry count exceeds reserved count"); | ||||
|  | ||||
|             state->m_current_enum->m_entries.emplace_back(entryValueToken.StringValue(), state->m_current_enum->m_entries.size()); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     class SequenceCloseEnum final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|     public: | ||||
|         SequenceCloseEnum() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Char('}'), | ||||
|                 create.Optional(create.Char(';')) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_enum != nullptr); | ||||
|  | ||||
|             std::sort(state->m_current_enum->m_entries.begin(), state->m_current_enum->m_entries.end(), [](const CommonStructuredDataEnumEntry& e1, const CommonStructuredDataEnumEntry& e2) | ||||
|             { | ||||
|                 return e1.m_name < e2.m_name; | ||||
|             }); | ||||
|  | ||||
|             state->m_current_enum = nullptr; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| using namespace sdd; | ||||
| using namespace enum_scope_sequences; | ||||
|  | ||||
| StructuredDataEnumScopeSequences::StructuredDataEnumScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, | ||||
|                                                                          std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|     : AbstractScopeSequenceHolder(allSequences, scopeSequences) | ||||
| { | ||||
| } | ||||
|  | ||||
| void StructuredDataEnumScopeSequences::AddSequences() const | ||||
| { | ||||
|     AddSequence(std::make_unique<SequenceCloseEnum>()); | ||||
|     AddSequence(std::make_unique<SequenceEnumEntry>()); | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Parsing/Sequence/AbstractScopeSequenceHolder.h" | ||||
| #include "StructuredDataDef/Parsing/StructuredDataDefParser.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataEnumScopeSequences final : AbstractScopeSequenceHolder<StructuredDataDefParser> | ||||
|     { | ||||
|     public: | ||||
|         StructuredDataEnumScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences); | ||||
|  | ||||
|         void AddSequences() const; | ||||
|     }; | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| #include "StructuredDataNoScopeSequences.h" | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| namespace sdd::no_scope_sequences | ||||
| { | ||||
|     class SequenceVersion final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_VERSION = 1; | ||||
|  | ||||
|     public: | ||||
|         SequenceVersion() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Keyword("version"), | ||||
|                 create.Integer().Capture(CAPTURE_VERSION), | ||||
|                 create.Char('{') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             auto newDef = std::make_unique<CommonStructuredDataDef>(result.NextCapture(CAPTURE_VERSION).IntegerValue()); | ||||
|             state->m_current_def = newDef.get(); | ||||
|             state->m_defs.emplace_back(std::move(newDef)); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| using namespace sdd; | ||||
| using namespace no_scope_sequences; | ||||
|  | ||||
| StructuredDataNoScopeSequences::StructuredDataNoScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, | ||||
|                                                                      std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|     : AbstractScopeSequenceHolder(allSequences, scopeSequences) | ||||
| { | ||||
| } | ||||
|  | ||||
| void StructuredDataNoScopeSequences::AddSequences() const | ||||
| { | ||||
|     AddSequence(std::make_unique<SequenceVersion>()); | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Parsing/Sequence/AbstractScopeSequenceHolder.h" | ||||
| #include "StructuredDataDef/Parsing/StructuredDataDefParser.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataNoScopeSequences final : AbstractScopeSequenceHolder<StructuredDataDefParser> | ||||
|     { | ||||
|     public: | ||||
|         StructuredDataNoScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences); | ||||
|  | ||||
|         void AddSequences() const; | ||||
|     }; | ||||
| } | ||||
| @@ -0,0 +1,307 @@ | ||||
| #include "StructuredDataStructScopeSequences.h" | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" | ||||
|  | ||||
| namespace sdd::struct_scope_sequences | ||||
| { | ||||
|     class SequenceStructEntry final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto TAG_TYPE_INT = 1; | ||||
|         static constexpr auto TAG_TYPE_BYTE = 2; | ||||
|         static constexpr auto TAG_TYPE_BOOL = 3; | ||||
|         static constexpr auto TAG_TYPE_FLOAT = 4; | ||||
|         static constexpr auto TAG_TYPE_SHORT = 5; | ||||
|         static constexpr auto TAG_TYPE_STRING = 6; | ||||
|         static constexpr auto TAG_TYPE_NAMED = 7; | ||||
|  | ||||
|         static constexpr auto CAPTURE_STRING_LENGTH = 1; | ||||
|         static constexpr auto CAPTURE_TYPE_NAME = 2; | ||||
|         static constexpr auto CAPTURE_ENTRY_NAME = 3; | ||||
|         static constexpr auto CAPTURE_ARRAY_SIZE = 4; | ||||
|  | ||||
|         static std::unique_ptr<matcher_t> TypeMatchers(const SimpleMatcherFactory& create) | ||||
|         { | ||||
|             return create.Or({ | ||||
|                 create.Keyword("int").Tag(TAG_TYPE_INT), | ||||
|                 create.Keyword("byte").Tag(TAG_TYPE_BYTE), | ||||
|                 create.Keyword("bool").Tag(TAG_TYPE_BOOL), | ||||
|                 create.Keyword("float").Tag(TAG_TYPE_FLOAT), | ||||
|                 create.Keyword("short").Tag(TAG_TYPE_SHORT), | ||||
|                 create.And({ | ||||
|                     create.Keyword("string"), | ||||
|                     create.Char('('), | ||||
|                     create.Integer().Capture(CAPTURE_STRING_LENGTH), | ||||
|                     create.Char(')') | ||||
|                 }).Tag(TAG_TYPE_STRING), | ||||
|                 create.Identifier().Tag(TAG_TYPE_NAMED).Capture(CAPTURE_TYPE_NAME) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         static std::unique_ptr<matcher_t> ArrayMatchers(const SimpleMatcherFactory& create) | ||||
|         { | ||||
|             return create.And({ | ||||
|                 create.Char('['), | ||||
|                 create.Or({ | ||||
|                     create.Integer().Capture(CAPTURE_ARRAY_SIZE), | ||||
|                     create.Identifier().Capture(CAPTURE_ARRAY_SIZE) | ||||
|                 }), | ||||
|                 create.Char(']') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     public: | ||||
|         SequenceStructEntry() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 TypeMatchers(create), | ||||
|                 create.Identifier().Capture(CAPTURE_ENTRY_NAME), | ||||
|                 create.OptionalLoop(ArrayMatchers(create)), | ||||
|                 create.Char(';') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         static CommonStructuredDataType ProcessType(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result, size_t& currentSize, size_t& currentBitAlign) | ||||
|         { | ||||
|             const auto typeTag = result.NextTag(); | ||||
|  | ||||
|             switch (typeTag) | ||||
|             { | ||||
|             case TAG_TYPE_INT: | ||||
|                 currentSize = 32; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::INT); | ||||
|             case TAG_TYPE_BYTE: | ||||
|                 currentSize = 8; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::BYTE); | ||||
|             case TAG_TYPE_BOOL: | ||||
|                 currentSize = 1; | ||||
|                 currentBitAlign = 0; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::BOOL); | ||||
|             case TAG_TYPE_FLOAT: | ||||
|                 currentSize = 32; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::FLOAT); | ||||
|             case TAG_TYPE_SHORT: | ||||
|                 currentSize = 16; | ||||
|                 currentBitAlign = 8; | ||||
|                 return CommonStructuredDataType(CommonStructuredDataTypeCategory::SHORT); | ||||
|             case TAG_TYPE_STRING: | ||||
|                 { | ||||
|                     currentBitAlign = 8; | ||||
|                     const auto& stringLengthToken = result.NextCapture(CAPTURE_STRING_LENGTH); | ||||
|                     const auto stringLength = stringLengthToken.IntegerValue(); | ||||
|  | ||||
|                     if (stringLength <= 0) | ||||
|                         throw ParsingException(stringLengthToken.GetPos(), "String length must be greater than zero"); | ||||
|  | ||||
|                     currentSize = stringLength * 8; | ||||
|                     return {CommonStructuredDataTypeCategory::STRING, static_cast<size_t>(stringLength)}; | ||||
|                 } | ||||
|             case TAG_TYPE_NAMED: | ||||
|                 { | ||||
|                     currentBitAlign = 8; | ||||
|                     const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE_NAME); | ||||
|                     const auto typeName = typeNameToken.IdentifierValue(); | ||||
|  | ||||
|                     const auto existingType = state->m_def_types_by_name.find(typeName); | ||||
|                     if (existingType == state->m_def_types_by_name.end()) | ||||
|                         throw ParsingException(typeNameToken.GetPos(), "No type defined under this name"); | ||||
|  | ||||
|                     if (existingType->second.m_category == CommonStructuredDataTypeCategory::STRUCT) | ||||
|                     { | ||||
|                         assert(existingType->second.m_info.type_index < state->m_current_def->m_structs.size()); | ||||
|                         const auto* _struct = state->m_current_def->m_structs[existingType->second.m_info.type_index].get(); | ||||
|                         currentSize = _struct->m_size_in_byte * 8; | ||||
|                     } | ||||
|                     else if (existingType->second.m_category == CommonStructuredDataTypeCategory::ENUM) | ||||
|                     { | ||||
|                         assert(existingType->second.m_info.type_index < state->m_current_def->m_enums.size()); | ||||
|                         currentSize = 16; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         assert(false); | ||||
|                         currentSize = 0; | ||||
|                     } | ||||
|  | ||||
|                     return existingType->second; | ||||
|                 } | ||||
|             default: | ||||
|                 throw ParsingException(TokenPos(), "Invalid Tag for Type @ ProcessType!!!"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         static CommonStructuredDataType ProcessArray(StructuredDataDefParserState* state, const SimpleParserValue& arrayToken, const CommonStructuredDataType currentType, | ||||
|                                                      size_t& currentSize, size_t& currentBitAlign) | ||||
|         { | ||||
|             currentBitAlign = 8; | ||||
|  | ||||
|             if (arrayToken.m_type == SimpleParserValueType::INTEGER) | ||||
|             { | ||||
|                 const auto arrayElementCount = arrayToken.IntegerValue(); | ||||
|  | ||||
|                 if (arrayElementCount <= 0) | ||||
|                     throw ParsingException(arrayToken.GetPos(), "Array size must be greater than zero"); | ||||
|  | ||||
|                 currentSize *= arrayElementCount; | ||||
|  | ||||
|                 const CommonStructuredDataIndexedArray indexedArray(currentType, arrayElementCount); | ||||
|  | ||||
|                 const auto existingIndexedArray = state->m_def_indexed_arrays.find(indexedArray); | ||||
|                 if (existingIndexedArray != state->m_def_indexed_arrays.end()) | ||||
|                     return {CommonStructuredDataTypeCategory::INDEXED_ARRAY, existingIndexedArray->second}; | ||||
|  | ||||
|                 const auto newIndexedArrayIndex = state->m_current_def->m_indexed_arrays.size(); | ||||
|                 state->m_current_def->m_indexed_arrays.push_back(indexedArray); | ||||
|                 return {CommonStructuredDataTypeCategory::INDEXED_ARRAY, newIndexedArrayIndex}; | ||||
|             } | ||||
|  | ||||
|             if (arrayToken.m_type == SimpleParserValueType::IDENTIFIER) | ||||
|             { | ||||
|                 const auto enumName = arrayToken.IdentifierValue(); | ||||
|  | ||||
|                 const auto existingType = state->m_def_types_by_name.find(enumName); | ||||
|                 if (existingType == state->m_def_types_by_name.end()) | ||||
|                     throw ParsingException(arrayToken.GetPos(), "No type defined under this name"); | ||||
|                 if (existingType->second.m_category != CommonStructuredDataTypeCategory::ENUM) | ||||
|                     throw ParsingException(arrayToken.GetPos(), "Type for enumed array must be an enum"); | ||||
|  | ||||
|                 assert(existingType->second.m_info.type_index < state->m_current_def->m_enums.size()); | ||||
|                 const auto* _enum = state->m_current_def->m_enums[existingType->second.m_info.type_index].get(); | ||||
|  | ||||
|                 const auto enumElementCount = _enum->ElementCount(); | ||||
|                 assert(enumElementCount > 0); | ||||
|                 currentSize *= enumElementCount; | ||||
|  | ||||
|                 const CommonStructuredDataEnumedArray enumedArray(currentType, existingType->second.m_info.type_index); | ||||
|  | ||||
|                 const auto existingEnumedArray = state->m_def_enumed_arrays.find(enumedArray); | ||||
|                 if (existingEnumedArray != state->m_def_enumed_arrays.end()) | ||||
|                     return {CommonStructuredDataTypeCategory::ENUM_ARRAY, existingEnumedArray->second}; | ||||
|  | ||||
|                 const auto newEnumedArrayIndex = state->m_current_def->m_enumed_arrays.size(); | ||||
|                 state->m_current_def->m_enumed_arrays.push_back(enumedArray); | ||||
|                 return {CommonStructuredDataTypeCategory::ENUM_ARRAY, newEnumedArrayIndex}; | ||||
|             } | ||||
|  | ||||
|             throw ParsingException(arrayToken.GetPos(), "Invalid Token for Array @ ProcessArray!!!"); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_def != nullptr); | ||||
|             assert(state->m_current_struct != nullptr); | ||||
|  | ||||
|             size_t currentSize = 0; | ||||
|             size_t currentAlign = 0; | ||||
|             auto currentType = ProcessType(state, result, currentSize, currentAlign); | ||||
|  | ||||
|             std::vector<std::reference_wrapper<const SimpleParserValue>> arrayTokens; | ||||
|             while (result.HasNextCapture(CAPTURE_ARRAY_SIZE)) | ||||
|                 arrayTokens.emplace_back(result.NextCapture(CAPTURE_ARRAY_SIZE)); | ||||
|  | ||||
|             for (auto i = arrayTokens.rbegin(); i != arrayTokens.rend(); ++i) | ||||
|                 currentType = ProcessArray(state, i->get(), currentType, currentSize, currentAlign); | ||||
|  | ||||
|             if (currentAlign > 0) | ||||
|                 state->m_current_struct_offset_in_bits = (state->m_current_struct_offset_in_bits + currentAlign - 1) / currentAlign * currentAlign; | ||||
|  | ||||
|             state->m_current_struct->m_properties.emplace_back(result.NextCapture(CAPTURE_ENTRY_NAME).IdentifierValue(), currentType, state->m_current_struct_offset_in_bits); | ||||
|             state->m_current_struct_offset_in_bits += currentSize; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     class SequencePadding final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|         static constexpr auto CAPTURE_PADDING_VALUE = 1; | ||||
|  | ||||
|     public: | ||||
|         SequencePadding() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Keyword("pad"), | ||||
|                 create.Char('('), | ||||
|                 create.Integer().Capture(CAPTURE_PADDING_VALUE), | ||||
|                 create.Char(')'), | ||||
|                 create.Char(';') | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             const auto& paddingValueToken = result.NextCapture(CAPTURE_PADDING_VALUE); | ||||
|             const auto paddingValue = paddingValueToken.IntegerValue(); | ||||
|  | ||||
|             if (paddingValue <= 0) | ||||
|                 throw ParsingException(paddingValueToken.GetPos(), "Padding value must be greater than 0"); | ||||
|  | ||||
|             // Align to next byte | ||||
|             state->m_current_struct_offset_in_bits = (state->m_current_struct_offset_in_bits + 7) / 8 * 8; | ||||
|  | ||||
|             // Add padding value to current size | ||||
|             state->m_current_struct_offset_in_bits += static_cast<size_t>(paddingValue); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     class SequenceCloseStruct final : public StructuredDataDefParser::sequence_t | ||||
|     { | ||||
|     public: | ||||
|         SequenceCloseStruct() | ||||
|         { | ||||
|             const SimpleMatcherFactory create(this); | ||||
|  | ||||
|             AddMatchers({ | ||||
|                 create.Char('}'), | ||||
|                 create.Optional(create.Char(';')) | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|     protected: | ||||
|         void ProcessMatch(StructuredDataDefParserState* state, SequenceResult<SimpleParserValue>& result) const override | ||||
|         { | ||||
|             assert(state->m_current_struct != nullptr); | ||||
|  | ||||
|             // Set the size of the finalized struct | ||||
|             if (!state->m_current_struct->m_properties.empty()) | ||||
|                 state->m_current_struct->m_size_in_byte = (state->m_current_struct_offset_in_bits + 7) / 8; | ||||
|             else | ||||
|                 state->m_current_struct->m_size_in_byte = 0u; | ||||
|  | ||||
|             state->m_current_struct_offset_in_bits = 0u; | ||||
|  | ||||
|             // Sort the entries of the struct alphabetically | ||||
|             std::sort(state->m_current_struct->m_properties.begin(), state->m_current_struct->m_properties.end(), | ||||
|                       [](const CommonStructuredDataStructProperty& e1, const CommonStructuredDataStructProperty& e2) | ||||
|                       { | ||||
|                           return e1.m_name < e2.m_name; | ||||
|                       }); | ||||
|             state->m_current_struct = nullptr; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| using namespace sdd; | ||||
| using namespace struct_scope_sequences; | ||||
|  | ||||
| StructuredDataStructScopeSequences::StructuredDataStructScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, | ||||
|                                                                        std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences) | ||||
|     : AbstractScopeSequenceHolder(allSequences, scopeSequences) | ||||
| { | ||||
| } | ||||
|  | ||||
| void StructuredDataStructScopeSequences::AddSequences() const | ||||
| { | ||||
|     AddSequence(std::make_unique<SequenceCloseStruct>()); | ||||
|     AddSequence(std::make_unique<SequencePadding>()); | ||||
|     AddSequence(std::make_unique<SequenceStructEntry>()); | ||||
| } | ||||
| @@ -0,0 +1,15 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Parsing/Sequence/AbstractScopeSequenceHolder.h" | ||||
| #include "StructuredDataDef/Parsing/StructuredDataDefParser.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataStructScopeSequences final : AbstractScopeSequenceHolder<StructuredDataDefParser> | ||||
|     { | ||||
|     public: | ||||
|         StructuredDataStructScopeSequences(std::vector<std::unique_ptr<StructuredDataDefParser::sequence_t>>& allSequences, std::vector<StructuredDataDefParser::sequence_t*>& scopeSequences); | ||||
|  | ||||
|         void AddSequences() const; | ||||
|     }; | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| #include "StructuredDataDefParser.h" | ||||
|  | ||||
| #include "Sequence/StructuredDataDefScopeSequences.h" | ||||
| #include "Sequence/StructuredDataEnumScopeSequences.h" | ||||
| #include "Sequence/StructuredDataNoScopeSequences.h" | ||||
| #include "Sequence/StructuredDataStructScopeSequences.h" | ||||
|  | ||||
| using namespace sdd; | ||||
|  | ||||
| StructuredDataDefParser::StructuredDataDefParser(SimpleLexer* lexer) | ||||
|     : AbstractParser(lexer, std::make_unique<StructuredDataDefParserState>()) | ||||
| { | ||||
|     CreateSequenceCollections(); | ||||
| } | ||||
|  | ||||
| void StructuredDataDefParser::CreateSequenceCollections() | ||||
| { | ||||
|     m_all_tests.clear(); | ||||
|     m_no_scope_tests.clear(); | ||||
|     m_def_tests.clear(); | ||||
|     m_enum_tests.clear(); | ||||
|     m_struct_tests.clear(); | ||||
|  | ||||
|     const StructuredDataNoScopeSequences noScopeSequences(m_all_tests, m_no_scope_tests); | ||||
|     noScopeSequences.AddSequences(); | ||||
|  | ||||
|     const StructuredDataDefScopeSequences defScopeSequences(m_all_tests, m_def_tests); | ||||
|     defScopeSequences.AddSequences(); | ||||
|  | ||||
|     const StructuredDataEnumScopeSequences enumScopeSequences(m_all_tests, m_enum_tests); | ||||
|     enumScopeSequences.AddSequences(); | ||||
|  | ||||
|     const StructuredDataStructScopeSequences structScopeSequences(m_all_tests, m_struct_tests); | ||||
|     structScopeSequences.AddSequences(); | ||||
| } | ||||
|  | ||||
| const std::vector<StructuredDataDefParser::sequence_t*>& StructuredDataDefParser::GetTestsForState() | ||||
| { | ||||
|     if (!m_state->m_current_def) | ||||
|         return m_no_scope_tests; | ||||
|  | ||||
|     if (m_state->m_current_enum) | ||||
|         return m_enum_tests; | ||||
|  | ||||
|     if (m_state->m_current_struct) | ||||
|         return m_struct_tests; | ||||
|  | ||||
|     return m_def_tests; | ||||
| } | ||||
|  | ||||
| std::vector<std::unique_ptr<CommonStructuredDataDef>> StructuredDataDefParser::GetDefs() const | ||||
| { | ||||
|     return std::move(m_state->m_defs); | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "Utils/ClassUtils.h" | ||||
| #include "StructuredDataDefParserState.h" | ||||
| #include "StructuredDataDef/CommonStructuredDataDef.h" | ||||
| #include "Parsing/Simple/SimpleLexer.h" | ||||
| #include "Parsing/Simple/SimpleParserValue.h" | ||||
| #include "Parsing/Impl/AbstractParser.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataDefParser final : public AbstractParser<SimpleParserValue, StructuredDataDefParserState> | ||||
|     { | ||||
|         std::vector<std::unique_ptr<sequence_t>> m_all_tests; | ||||
|         std::vector<sequence_t*> m_no_scope_tests; | ||||
|         std::vector<sequence_t*> m_def_tests; | ||||
|         std::vector<sequence_t*> m_enum_tests; | ||||
|         std::vector<sequence_t*> m_struct_tests; | ||||
|          | ||||
|         void CreateSequenceCollections(); | ||||
|  | ||||
|     protected: | ||||
|         const std::vector<sequence_t*>& GetTestsForState() override; | ||||
|  | ||||
|     public: | ||||
|         explicit StructuredDataDefParser(SimpleLexer* lexer); | ||||
|         _NODISCARD std::vector<std::unique_ptr<CommonStructuredDataDef>> GetDefs() const; | ||||
|     }; | ||||
| } | ||||
| @@ -0,0 +1,11 @@ | ||||
| #include "StructuredDataDefParserState.h" | ||||
|  | ||||
| using namespace sdd; | ||||
|  | ||||
| StructuredDataDefParserState::StructuredDataDefParserState() | ||||
|     : m_current_def(nullptr), | ||||
|       m_current_enum(nullptr), | ||||
|       m_current_struct(nullptr), | ||||
|       m_current_struct_offset_in_bits(0u) | ||||
| { | ||||
| } | ||||
| @@ -0,0 +1,28 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <map> | ||||
| #include <memory> | ||||
| #include <vector> | ||||
| #include <cstddef> | ||||
|  | ||||
| #include "StructuredDataDef/CommonStructuredDataDef.h" | ||||
|  | ||||
| namespace sdd | ||||
| { | ||||
|     class StructuredDataDefParserState | ||||
|     { | ||||
|     public: | ||||
|         std::vector<std::unique_ptr<CommonStructuredDataDef>> m_defs; | ||||
|  | ||||
|         CommonStructuredDataDef* m_current_def; | ||||
|         CommonStructuredDataEnum* m_current_enum; | ||||
|         CommonStructuredDataStruct* m_current_struct; | ||||
|         size_t m_current_struct_offset_in_bits; | ||||
|  | ||||
|         std::map<std::string, CommonStructuredDataType> m_def_types_by_name; | ||||
|         std::map<CommonStructuredDataIndexedArray, size_t> m_def_indexed_arrays; | ||||
|         std::map<CommonStructuredDataEnumedArray, size_t> m_def_enumed_arrays; | ||||
|  | ||||
|         StructuredDataDefParserState(); | ||||
|     }; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user