diff --git a/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.cpp b/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.cpp index ca7020d7..39af7a47 100644 --- a/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.cpp +++ b/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.cpp @@ -18,6 +18,30 @@ CommonStructuredDataDefType::CommonStructuredDataDefType(const CommonStructuredD { } +bool operator<(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs) +{ + if (lhs.m_category < rhs.m_category) + return true; + if (rhs.m_category < lhs.m_category) + return false; + return lhs.m_info.type_index < rhs.m_info.type_index; +} + +bool operator<=(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs) +{ + return !(rhs < lhs); +} + +bool operator>(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs) +{ + return rhs < lhs; +} + +bool operator>=(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs) +{ + return !(lhs < rhs); +} + CommonStructuredDataDefIndexedArray::CommonStructuredDataDefIndexedArray() : m_array_size(0u) { @@ -29,6 +53,30 @@ CommonStructuredDataDefIndexedArray::CommonStructuredDataDefIndexedArray(const C { } +bool operator<(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs) +{ + if (lhs.m_array_type < rhs.m_array_type) + return true; + if (rhs.m_array_type < lhs.m_array_type) + return false; + return lhs.m_array_size < rhs.m_array_size; +} + +bool operator<=(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs) +{ + return !(rhs < lhs); +} + +bool operator>(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs) +{ + return rhs < lhs; +} + +bool operator>=(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs) +{ + return !(lhs < rhs); +} + CommonStructuredDataDefEnumedArray::CommonStructuredDataDefEnumedArray() : m_enum_index(0u) { @@ -39,3 +87,27 @@ CommonStructuredDataDefEnumedArray::CommonStructuredDataDefEnumedArray(const Com m_enum_index(enumIndex) { } + +bool operator<(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs) +{ + if (lhs.m_array_type < rhs.m_array_type) + return true; + if (rhs.m_array_type < lhs.m_array_type) + return false; + return lhs.m_enum_index < rhs.m_enum_index; +} + +bool operator<=(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs) +{ + return !(rhs < lhs); +} + +bool operator>(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs) +{ + return rhs < lhs; +} + +bool operator>=(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs) +{ + return !(lhs < rhs); +} diff --git a/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.h b/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.h index 8f91972d..140ad7b7 100644 --- a/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.h +++ b/src/ObjLoading/Parsing/StructuredDataDef/Domain/CommonStructuredDataDefTypes.h @@ -8,9 +8,9 @@ enum class CommonStructuredDataDefTypeCategory INT, BYTE, BOOL, - STRING, FLOAT, SHORT, + STRING, ENUM, STRUCT, INDEXED_ARRAY, @@ -31,6 +31,11 @@ struct CommonStructuredDataDefType CommonStructuredDataDefType(); explicit CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory category); CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory category, size_t extraInfo); + + friend bool operator<(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs); + friend bool operator<=(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs); + friend bool operator>(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs); + friend bool operator>=(const CommonStructuredDataDefType& lhs, const CommonStructuredDataDefType& rhs); }; struct CommonStructuredDataDefIndexedArray @@ -40,6 +45,11 @@ struct CommonStructuredDataDefIndexedArray CommonStructuredDataDefIndexedArray(); CommonStructuredDataDefIndexedArray(CommonStructuredDataDefType type, size_t arraySize); + + friend bool operator<(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs); + friend bool operator<=(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs); + friend bool operator>(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs); + friend bool operator>=(const CommonStructuredDataDefIndexedArray& lhs, const CommonStructuredDataDefIndexedArray& rhs); }; struct CommonStructuredDataDefEnumedArray @@ -49,4 +59,9 @@ struct CommonStructuredDataDefEnumedArray CommonStructuredDataDefEnumedArray(); CommonStructuredDataDefEnumedArray(CommonStructuredDataDefType type, size_t enumIndex); + + friend bool operator<(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs); + friend bool operator<=(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs); + friend bool operator>(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs); + friend bool operator>=(const CommonStructuredDataDefEnumedArray& lhs, const CommonStructuredDataDefEnumedArray& rhs); }; \ No newline at end of file diff --git a/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefDefScopeSequences.cpp b/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefDefScopeSequences.cpp index 87f0fcf8..10013315 100644 --- a/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefDefScopeSequences.cpp +++ b/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefDefScopeSequences.cpp @@ -27,6 +27,7 @@ namespace sdd::def_scope_sequences auto newEnum = std::make_unique(result.NextCapture(CAPTURE_NAME).IdentifierValue()); state->m_current_enum = newEnum.get(); + state->m_def_types_by_name.emplace(newEnum->m_name, CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::ENUM, state->m_current_def->m_enums.size())); state->m_current_def->m_enums.emplace_back(std::move(newEnum)); } }; @@ -53,8 +54,15 @@ namespace sdd::def_scope_sequences assert(state->m_current_def); auto newStruct = std::make_unique(result.NextCapture(CAPTURE_NAME).IdentifierValue()); - state->m_current_struct = newStruct.get(); + 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, CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::STRUCT, newStructIndex)); state->m_current_def->m_structs.emplace_back(std::move(newStruct)); + + if(newStructPtr->m_name == "root") + state->m_current_def->m_root_type = CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::STRUCT, newStructIndex); } }; @@ -79,6 +87,9 @@ namespace sdd::def_scope_sequences assert(state->m_current_struct == nullptr); state->m_current_def = nullptr; + state->m_def_types_by_name.clear(); + state->m_def_indexed_arrays.clear(); + state->m_def_enumed_arrays.clear(); } }; } @@ -94,6 +105,7 @@ StructuredDataDefDefScopeSequences::StructuredDataDefDefScopeSequences(std::vect void StructuredDataDefDefScopeSequences::AddSequences() const { + AddSequence(std::make_unique()); AddSequence(std::make_unique()); AddSequence(std::make_unique()); } diff --git a/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefStructScopeSequences.cpp b/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefStructScopeSequences.cpp index 4af736ec..0b23142e 100644 --- a/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefStructScopeSequences.cpp +++ b/src/ObjLoading/Parsing/StructuredDataDef/Sequence/StructuredDataDefStructScopeSequences.cpp @@ -4,30 +4,194 @@ namespace sdd::struct_scope_sequences { - class SequenceVersion final : public StructuredDataDefParser::sequence_t + class SequenceStructEntry final : public StructuredDataDefParser::sequence_t { - static constexpr auto CAPTURE_VERSION = 1; + 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 TAG_ARRAY = 8; + static constexpr auto TAG_ARRAY_INDEX = 9; + static constexpr auto TAG_ARRAY_ENUM = 10; + + 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 constexpr auto CAPTURE_ARRAY_ENUM = 5; + + static std::unique_ptr 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 ArrayMatchers(const SimpleMatcherFactory& create) + { + return create.And({ + create.Char('['), + create.Or({ + create.Integer().Tag(TAG_ARRAY_INDEX).Capture(CAPTURE_ARRAY_SIZE), + create.Identifier().Tag(TAG_ARRAY_ENUM).Capture(CAPTURE_ARRAY_ENUM) + }), + create.Char(']') + }).Tag(TAG_ARRAY); + } public: - SequenceVersion() + SequenceStructEntry() { const SimpleMatcherFactory create(this); AddMatchers({ - create.Keyword("version"), - create.Integer().Capture(CAPTURE_VERSION), - create.Char('{') - }); + TypeMatchers(create), + create.Identifier().Capture(CAPTURE_ENTRY_NAME), + create.OptionalLoop(ArrayMatchers(create)), + create.Char(';') + }); + } + + private: + static CommonStructuredDataDefType ProcessType(StructuredDataDefParserState* state, SequenceResult& result) + { + const auto typeTag = result.NextTag(); + + switch (typeTag) + { + case TAG_TYPE_INT: + return CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::INT); + case TAG_TYPE_BYTE: + return CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::BYTE); + case TAG_TYPE_BOOL: + return CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::BOOL); + case TAG_TYPE_FLOAT: + return CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::FLOAT); + case TAG_TYPE_SHORT: + return CommonStructuredDataDefType(CommonStructuredDataDefTypeCategory::SHORT); + case TAG_TYPE_STRING: + { + 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"); + + return {CommonStructuredDataDefTypeCategory::STRING, static_cast(stringLength)}; + } + case TAG_TYPE_NAMED: + { + 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"); + + return existingType->second; + } + default: + throw ParsingException(TokenPos(), "Invalid Tag for Type @ ProcessType!!!"); + } + } + + static CommonStructuredDataDefType ProcessArray(StructuredDataDefParserState* state, SequenceResult& result, CommonStructuredDataDefType currentType) + { + const auto arrayTag = result.NextTag(); + + if (arrayTag == TAG_ARRAY_INDEX) + { + const auto& arraySizeToken = result.NextCapture(CAPTURE_ARRAY_SIZE); + const auto arraySize = arraySizeToken.IntegerValue(); + + if (arraySize <= 0) + throw ParsingException(arraySizeToken.GetPos(), "Array size must be greater than zero"); + + const CommonStructuredDataDefIndexedArray indexedArray(currentType, arraySize); + + const auto existingIndexedArray = state->m_def_indexed_arrays.find(indexedArray); + if (existingIndexedArray != state->m_def_indexed_arrays.end()) + return {CommonStructuredDataDefTypeCategory::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 {CommonStructuredDataDefTypeCategory::INDEXED_ARRAY, newIndexedArrayIndex}; + } + + if (arrayTag == TAG_ARRAY_ENUM) + { + const auto& enumNameToken = result.NextCapture(CAPTURE_ARRAY_ENUM); + const auto enumName = enumNameToken.IdentifierValue(); + + const auto existingType = state->m_def_types_by_name.find(enumName); + if (existingType == state->m_def_types_by_name.end()) + throw ParsingException(enumNameToken.GetPos(), "No type defined under this name"); + if (existingType->second.m_category != CommonStructuredDataDefTypeCategory::ENUM) + throw ParsingException(enumNameToken.GetPos(), "Type for enumed array must be an enum"); + + const CommonStructuredDataDefEnumedArray 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 {CommonStructuredDataDefTypeCategory::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 {CommonStructuredDataDefTypeCategory::ENUM_ARRAY, newEnumedArrayIndex}; + } + + throw ParsingException(TokenPos(), "Invalid Tag for Array @ ProcessArray!!!"); } protected: void ProcessMatch(StructuredDataDefParserState* state, SequenceResult& result) const override { - auto newDef = std::make_unique(); - newDef->m_version = result.NextCapture(CAPTURE_VERSION).IntegerValue(); + assert(state->m_current_def != nullptr); + assert(state->m_current_struct != nullptr); - state->m_current_def = newDef.get(); - state->m_defs.emplace_back(std::move(newDef)); + auto currentType = ProcessType(state, result); + + while (result.PeekAndRemoveIfTag(TAG_ARRAY) == TAG_ARRAY) + currentType = ProcessArray(state, result, currentType); + + // TODO: Calculate offset + state->m_current_struct->m_entries.emplace_back(result.NextCapture(CAPTURE_ENTRY_NAME).IdentifierValue(), currentType, 0); + } + }; + + 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& result) const override + { + assert(state->m_current_struct != nullptr); + + state->m_current_struct = nullptr; } }; } @@ -43,5 +207,6 @@ StructuredDataDefStructScopeSequences::StructuredDataDefStructScopeSequences(std void StructuredDataDefStructScopeSequences::AddSequences() const { - AddSequence(std::make_unique()); + AddSequence(std::make_unique()); + AddSequence(std::make_unique()); } diff --git a/src/ObjLoading/Parsing/StructuredDataDef/StructuredDataDefParserState.h b/src/ObjLoading/Parsing/StructuredDataDef/StructuredDataDefParserState.h index ca6d3c2a..f4d2f10e 100644 --- a/src/ObjLoading/Parsing/StructuredDataDef/StructuredDataDefParserState.h +++ b/src/ObjLoading/Parsing/StructuredDataDef/StructuredDataDefParserState.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -15,6 +16,10 @@ namespace sdd CommonStructuredDataDefEnum* m_current_enum; CommonStructuredDataDefStruct* m_current_struct; + std::map m_def_types_by_name; + std::map m_def_indexed_arrays; + std::map m_def_enumed_arrays; + StructuredDataDefParserState(); }; }