mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-09 22:38:06 -05:00
Add Tests for ZCG cpp
This commit is contained in:
@ -0,0 +1,228 @@
|
||||
#include "MemberComputations.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "StructureComputations.h"
|
||||
#include "Domain/Definition/ArrayDeclarationModifier.h"
|
||||
#include "Domain/Definition/PointerDeclarationModifier.h"
|
||||
|
||||
MemberComputations::MemberComputations(const MemberInformation* member)
|
||||
: m_info(member)
|
||||
{
|
||||
assert(m_info != nullptr);
|
||||
}
|
||||
|
||||
bool MemberComputations::ShouldIgnore() const
|
||||
{
|
||||
return m_info->m_condition && m_info->m_condition->IsStatic() && m_info->m_condition->EvaluateNumeric() == 0;
|
||||
}
|
||||
|
||||
bool MemberComputations::ContainsNonEmbeddedReference() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
return std::any_of(declarationModifiers.begin(), declarationModifiers.end(), [](const std::unique_ptr<DeclarationModifier>& modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::POINTER;
|
||||
});
|
||||
}
|
||||
|
||||
bool MemberComputations::ContainsSinglePointerReference() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return false;
|
||||
|
||||
const auto* lastModifier = declarationModifiers[declarationModifiers.size() - 1].get();
|
||||
if (lastModifier->GetType() != DeclarationModifierType::POINTER)
|
||||
return false;
|
||||
|
||||
return !dynamic_cast<const PointerDeclarationModifier*>(lastModifier)->AnyCountEvaluationIsArray();
|
||||
}
|
||||
|
||||
bool MemberComputations::ContainsArrayPointerReference() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return false;
|
||||
|
||||
const auto* lastModifier = declarationModifiers[declarationModifiers.size() - 1].get();
|
||||
if (lastModifier->GetType() != DeclarationModifierType::POINTER)
|
||||
return false;
|
||||
|
||||
return dynamic_cast<const PointerDeclarationModifier*>(lastModifier)->AnyCountEvaluationIsArray();
|
||||
}
|
||||
|
||||
bool MemberComputations::ContainsPointerArrayReference() const
|
||||
{
|
||||
if (!ContainsSinglePointerReference())
|
||||
return false;
|
||||
|
||||
const auto pointerDepth = GetPointerDepth();
|
||||
const auto isArray = IsArray();
|
||||
|
||||
return isArray && pointerDepth == 1 || !isArray && pointerDepth == 2;
|
||||
}
|
||||
|
||||
bool MemberComputations::ContainsArrayReference() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return false;
|
||||
|
||||
const auto* lastModifier = declarationModifiers[declarationModifiers.size() - 1].get();
|
||||
return lastModifier->GetType() == DeclarationModifierType::ARRAY;
|
||||
}
|
||||
|
||||
const IEvaluation* MemberComputations::GetArrayPointerCountEvaluation() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return nullptr;
|
||||
|
||||
const auto* lastModifier = declarationModifiers[declarationModifiers.size() - 1].get();
|
||||
return lastModifier->GetType() == DeclarationModifierType::POINTER
|
||||
? dynamic_cast<const PointerDeclarationModifier*>(lastModifier)->GetCountEvaluation()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsArray() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return false;
|
||||
|
||||
return declarationModifiers[0]->GetType() == DeclarationModifierType::ARRAY;
|
||||
}
|
||||
|
||||
std::vector<int> MemberComputations::GetArraySizes() const
|
||||
{
|
||||
std::vector<int> sizes;
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
for (const auto& declarationModifier : declarationModifiers)
|
||||
{
|
||||
if (declarationModifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
sizes.push_back(dynamic_cast<const ArrayDeclarationModifier*>(declarationModifier.get())->m_size);
|
||||
}
|
||||
|
||||
return sizes;
|
||||
}
|
||||
|
||||
int MemberComputations::GetArrayDimension() const
|
||||
{
|
||||
auto dimension = 0;
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
for (const auto& declarationModifier : declarationModifiers)
|
||||
{
|
||||
if (declarationModifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
dimension++;
|
||||
}
|
||||
|
||||
return dimension;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsPointerToArray() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
return false;
|
||||
|
||||
const auto* lastModifier = declarationModifiers[declarationModifiers.size() - 1].get();
|
||||
if (lastModifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
return false;
|
||||
|
||||
return std::any_of(declarationModifiers.begin(), declarationModifiers.end(), [](const std::unique_ptr<DeclarationModifier>& modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::POINTER;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<int> MemberComputations::GetPointerToArraySizes() const
|
||||
{
|
||||
std::vector<int> sizes;
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
for (const auto& declarationModifier : declarationModifiers)
|
||||
{
|
||||
if (declarationModifier->GetType() == DeclarationModifierType::ARRAY)
|
||||
{
|
||||
sizes.push_back(dynamic_cast<ArrayDeclarationModifier*>(declarationModifier.get())->m_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return sizes;
|
||||
}
|
||||
|
||||
int MemberComputations::GetPointerDepth() const
|
||||
{
|
||||
auto depth = 0;
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
for(const auto& declarationModifier : declarationModifiers)
|
||||
{
|
||||
if (declarationModifier->GetType() == DeclarationModifierType::POINTER)
|
||||
depth++;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsNotInDefaultNormalBlock() const
|
||||
{
|
||||
return m_info->m_fast_file_block != nullptr && !(m_info->m_fast_file_block->m_type == FastFileBlockType::NORMAL && m_info->m_fast_file_block->m_is_default);
|
||||
}
|
||||
|
||||
bool MemberComputations::IsInTempBlock() const
|
||||
{
|
||||
return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::TEMP;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsInRuntimeBlock() const
|
||||
{
|
||||
return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::RUNTIME;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsFirstMember() const
|
||||
{
|
||||
const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers();
|
||||
return !parentUsedMembers.empty() && parentUsedMembers[0] == m_info;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsLastMember() const
|
||||
{
|
||||
const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers();
|
||||
return !parentUsedMembers.empty() && parentUsedMembers[parentUsedMembers.size() - 1] == m_info;
|
||||
}
|
||||
|
||||
bool MemberComputations::HasDynamicArraySize() const
|
||||
{
|
||||
const auto& declarationModifiers = m_info->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
return std::any_of(declarationModifiers.begin(), declarationModifiers.end(), [](const std::unique_ptr<DeclarationModifier>& declarationModifier)
|
||||
{
|
||||
return declarationModifier->GetType() == DeclarationModifierType::ARRAY
|
||||
&& dynamic_cast<ArrayDeclarationModifier*>(declarationModifier.get())->m_dynamic_size_evaluation;
|
||||
});
|
||||
}
|
||||
|
||||
bool MemberComputations::IsDynamicMember() const
|
||||
{
|
||||
if (HasDynamicArraySize())
|
||||
return true;
|
||||
|
||||
return !ContainsNonEmbeddedReference() && m_info->m_type && StructureComputations(m_info->m_type).GetDynamicMember() != nullptr;
|
||||
}
|
||||
|
||||
bool MemberComputations::IsAfterPartialLoad() const
|
||||
{
|
||||
if (IsDynamicMember())
|
||||
return true;
|
||||
|
||||
return m_info->m_parent->m_definition->GetType() == DataDefinitionType::UNION && StructureComputations(m_info->m_parent).GetDynamicMember() != nullptr;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "Domain/Information/MemberInformation.h"
|
||||
|
||||
class MemberComputations
|
||||
{
|
||||
const MemberInformation* const m_info;
|
||||
|
||||
public:
|
||||
explicit MemberComputations(const MemberInformation* member);
|
||||
|
||||
_NODISCARD bool ShouldIgnore() const;
|
||||
_NODISCARD bool ContainsNonEmbeddedReference() const;
|
||||
_NODISCARD bool ContainsSinglePointerReference() const;
|
||||
_NODISCARD bool ContainsArrayPointerReference() const;
|
||||
_NODISCARD bool ContainsPointerArrayReference() const;
|
||||
_NODISCARD bool ContainsArrayReference() const;
|
||||
_NODISCARD const IEvaluation* GetArrayPointerCountEvaluation() const;
|
||||
_NODISCARD bool IsArray() const;
|
||||
_NODISCARD std::vector<int> GetArraySizes() const;
|
||||
_NODISCARD int GetArrayDimension() const;
|
||||
_NODISCARD bool IsPointerToArray() const;
|
||||
_NODISCARD std::vector<int> GetPointerToArraySizes() const;
|
||||
_NODISCARD int GetPointerDepth() const;
|
||||
_NODISCARD bool IsNotInDefaultNormalBlock() const;
|
||||
_NODISCARD bool IsInTempBlock() const;
|
||||
_NODISCARD bool IsInRuntimeBlock() const;
|
||||
_NODISCARD bool IsFirstMember() const;
|
||||
_NODISCARD bool IsLastMember() const;
|
||||
_NODISCARD bool HasDynamicArraySize() const;
|
||||
_NODISCARD bool IsDynamicMember() const;
|
||||
_NODISCARD bool IsAfterPartialLoad() const;
|
||||
};
|
@ -0,0 +1,243 @@
|
||||
#include "MemberDeclarationModifierComputations.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "MemberComputations.h"
|
||||
#include "Domain/Definition/ArrayDeclarationModifier.h"
|
||||
#include "Domain/Definition/PointerDeclarationModifier.h"
|
||||
|
||||
DeclarationModifierComputations::DeclarationModifierComputations(const MemberInformation* member, std::vector<int> modifierIndices)
|
||||
: m_information(member),
|
||||
m_modifier_indices(std::move(modifierIndices))
|
||||
{
|
||||
auto combinedIndex = 0;
|
||||
auto arraySizes = MemberComputations(m_information).GetArraySizes();
|
||||
std::vector<int> sizePerDepth(arraySizes.size());
|
||||
|
||||
auto currentDepthSize = 1;
|
||||
for (int i = arraySizes.size(); i > 0; i--)
|
||||
{
|
||||
sizePerDepth[i - 1] = currentDepthSize;
|
||||
currentDepthSize *= arraySizes[i - 1];
|
||||
}
|
||||
|
||||
auto currentDepth = 0;
|
||||
for (auto modifierIndex : m_modifier_indices)
|
||||
{
|
||||
combinedIndex += sizePerDepth[currentDepth++] * modifierIndex;
|
||||
}
|
||||
|
||||
m_combined_index = combinedIndex;
|
||||
}
|
||||
|
||||
DeclarationModifierComputations::DeclarationModifierComputations(const MemberInformation* member)
|
||||
: m_information(member),
|
||||
m_combined_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
DeclarationModifier* DeclarationModifierComputations::GetDeclarationModifier() const
|
||||
{
|
||||
const auto& declarationModifiers = m_information->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (m_modifier_indices.size() < declarationModifiers.size())
|
||||
return declarationModifiers[m_modifier_indices.size()].get();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DeclarationModifier* DeclarationModifierComputations::GetNextDeclarationModifier() const
|
||||
{
|
||||
const auto& declarationModifiers = m_information->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
if (m_modifier_indices.size() + 1 < declarationModifiers.size())
|
||||
return declarationModifiers[m_modifier_indices.size() + 1].get();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<DeclarationModifier*> DeclarationModifierComputations::GetFollowingDeclarationModifiers() const
|
||||
{
|
||||
std::vector<DeclarationModifier*> following;
|
||||
const auto& declarationModifiers = m_information->m_member->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
if (m_modifier_indices.size() + 1 < declarationModifiers.size())
|
||||
{
|
||||
for (auto i = declarationModifiers.begin() + m_modifier_indices.size() + 1; i != declarationModifiers.end(); ++i)
|
||||
{
|
||||
following.push_back(i->get());
|
||||
}
|
||||
}
|
||||
|
||||
return following;
|
||||
}
|
||||
|
||||
std::vector<int> DeclarationModifierComputations::GetArrayIndices() const
|
||||
{
|
||||
return m_modifier_indices;
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::IsArray() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
return declarationModifier != nullptr && declarationModifier->GetType() == DeclarationModifierType::ARRAY;
|
||||
}
|
||||
|
||||
int DeclarationModifierComputations::GetArraySize() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier != nullptr && declarationModifier->GetType() == DeclarationModifierType::ARRAY)
|
||||
{
|
||||
return dynamic_cast<ArrayDeclarationModifier*>(declarationModifier)->m_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::HasDynamicArrayCount() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier != nullptr && declarationModifier->GetType() == DeclarationModifierType::ARRAY)
|
||||
{
|
||||
return dynamic_cast<ArrayDeclarationModifier*>(declarationModifier)->m_dynamic_count_evaluation != nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const IEvaluation* DeclarationModifierComputations::GetDynamicArrayCountEvaluation() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier != nullptr && declarationModifier->GetType() == DeclarationModifierType::ARRAY)
|
||||
{
|
||||
return dynamic_cast<ArrayDeclarationModifier*>(declarationModifier)->m_dynamic_count_evaluation.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<DeclarationModifierComputations> DeclarationModifierComputations::GetArrayEntries() const
|
||||
{
|
||||
std::vector<DeclarationModifierComputations> arrayEntries;
|
||||
|
||||
const auto arraySize = GetArraySize();
|
||||
for (auto i = 0; i < arraySize; i++)
|
||||
{
|
||||
std::vector<int> childModifierIndices(m_modifier_indices.size() + 1);
|
||||
std::copy(m_modifier_indices.begin(), m_modifier_indices.end(), childModifierIndices.begin());
|
||||
childModifierIndices[childModifierIndices.size() - 1] = i;
|
||||
arrayEntries.push_back(DeclarationModifierComputations(m_information, std::move(childModifierIndices)));
|
||||
}
|
||||
|
||||
return arrayEntries;
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::IsSinglePointer() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
|
||||
if (declarationModifier != nullptr
|
||||
&& declarationModifier->GetType() == DeclarationModifierType::POINTER
|
||||
&& !dynamic_cast<PointerDeclarationModifier*>(declarationModifier)->CountEvaluationIsArray(m_combined_index))
|
||||
{
|
||||
const auto following = GetFollowingDeclarationModifiers();
|
||||
|
||||
return !std::any_of(following.begin(), following.end(), [](const DeclarationModifier* modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::POINTER;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::IsArrayPointer() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
|
||||
if (declarationModifier != nullptr
|
||||
&& declarationModifier->GetType() == DeclarationModifierType::POINTER
|
||||
&& dynamic_cast<PointerDeclarationModifier*>(declarationModifier)->CountEvaluationIsArray(m_combined_index))
|
||||
{
|
||||
const auto following = GetFollowingDeclarationModifiers();
|
||||
|
||||
return !std::any_of(following.begin(), following.end(), [](const DeclarationModifier* modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::POINTER;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const IEvaluation* DeclarationModifierComputations::GetArrayPointerCountEvaluation() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier == nullptr || declarationModifier->GetType() != DeclarationModifierType::POINTER)
|
||||
return nullptr;
|
||||
|
||||
return dynamic_cast<PointerDeclarationModifier*>(declarationModifier)->GetCountEvaluationForArrayIndex(m_combined_index);
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::IsPointerArray() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier == nullptr)
|
||||
return false;
|
||||
|
||||
auto* nextDeclarationModifier = GetNextDeclarationModifier();
|
||||
if (nextDeclarationModifier == nullptr)
|
||||
return false;
|
||||
|
||||
const auto thisDeclModIsArray = declarationModifier->GetType() == DeclarationModifierType::POINTER
|
||||
&& dynamic_cast<PointerDeclarationModifier*>(declarationModifier)->CountEvaluationIsArray(m_combined_index)
|
||||
|| declarationModifier->GetType() == DeclarationModifierType::ARRAY;
|
||||
|
||||
if (!thisDeclModIsArray)
|
||||
return false;
|
||||
|
||||
const auto nextDeclModIsSinglePointer = nextDeclarationModifier->GetType() == DeclarationModifierType::POINTER
|
||||
&& !dynamic_cast<PointerDeclarationModifier*>(nextDeclarationModifier)->AnyCountEvaluationIsArray();
|
||||
|
||||
return nextDeclModIsSinglePointer;
|
||||
}
|
||||
|
||||
const IEvaluation* DeclarationModifierComputations::GetPointerArrayCountEvaluation() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if (declarationModifier->GetType() == DeclarationModifierType::POINTER)
|
||||
{
|
||||
return dynamic_cast<PointerDeclarationModifier*>(declarationModifier)->GetCountEvaluationForArrayIndex(m_combined_index);
|
||||
}
|
||||
|
||||
if (declarationModifier->GetType() == DeclarationModifierType::ARRAY)
|
||||
{
|
||||
auto* arrayDeclarationModifier = dynamic_cast<ArrayDeclarationModifier*>(declarationModifier);
|
||||
return arrayDeclarationModifier->m_dynamic_count_evaluation.get(); // This might be null in which case there is no evaluation but a static size
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DeclarationModifierComputations::IsDynamicArray() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier == nullptr)
|
||||
return false;
|
||||
|
||||
return declarationModifier->GetType() == DeclarationModifierType::ARRAY
|
||||
&& dynamic_cast<ArrayDeclarationModifier*>(declarationModifier)->m_dynamic_size_evaluation != nullptr;
|
||||
}
|
||||
|
||||
const IEvaluation* DeclarationModifierComputations::GetDynamicArraySizeEvaluation() const
|
||||
{
|
||||
auto* declarationModifier = GetDeclarationModifier();
|
||||
if (declarationModifier == nullptr
|
||||
|| declarationModifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
return nullptr;
|
||||
|
||||
return dynamic_cast<ArrayDeclarationModifier*>(declarationModifier)->m_dynamic_size_evaluation.get();
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Domain/Information/MemberInformation.h"
|
||||
#include "Domain/Evaluation/IEvaluation.h"
|
||||
|
||||
class DeclarationModifierComputations
|
||||
{
|
||||
const MemberInformation* const m_information;
|
||||
std::vector<int> m_modifier_indices;
|
||||
int m_combined_index;
|
||||
|
||||
DeclarationModifierComputations(const MemberInformation* member, std::vector<int> modifierIndices);
|
||||
|
||||
public:
|
||||
explicit DeclarationModifierComputations(const MemberInformation* member);
|
||||
|
||||
_NODISCARD DeclarationModifier* GetDeclarationModifier() const;
|
||||
_NODISCARD DeclarationModifier* GetNextDeclarationModifier() const;
|
||||
_NODISCARD std::vector<DeclarationModifier*> GetFollowingDeclarationModifiers() const;
|
||||
_NODISCARD std::vector<int> GetArrayIndices() const;
|
||||
_NODISCARD bool IsArray() const;
|
||||
_NODISCARD int GetArraySize() const;
|
||||
_NODISCARD bool HasDynamicArrayCount() const;
|
||||
_NODISCARD const IEvaluation* GetDynamicArrayCountEvaluation() const;
|
||||
_NODISCARD std::vector<DeclarationModifierComputations> GetArrayEntries() const;
|
||||
_NODISCARD bool IsSinglePointer() const;
|
||||
_NODISCARD bool IsArrayPointer() const;
|
||||
_NODISCARD const IEvaluation* GetArrayPointerCountEvaluation() const;
|
||||
_NODISCARD bool IsPointerArray() const;
|
||||
_NODISCARD const IEvaluation* GetPointerArrayCountEvaluation() const;
|
||||
_NODISCARD bool IsDynamicArray() const;
|
||||
_NODISCARD const IEvaluation* GetDynamicArraySizeEvaluation() const;
|
||||
};
|
@ -0,0 +1,51 @@
|
||||
#include "StructureComputations.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "MemberComputations.h"
|
||||
|
||||
StructureComputations::StructureComputations(const StructureInformation* structure)
|
||||
: m_info(structure)
|
||||
{
|
||||
assert(m_info != nullptr);
|
||||
}
|
||||
|
||||
bool StructureComputations::IsAsset() const
|
||||
{
|
||||
return m_info->m_asset_enum_entry != nullptr;
|
||||
}
|
||||
|
||||
MemberInformation* StructureComputations::GetDynamicMember() const
|
||||
{
|
||||
for (const auto& member : m_info->m_ordered_members)
|
||||
{
|
||||
if (MemberComputations(member.get()).IsDynamicMember())
|
||||
return member.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<MemberInformation*> StructureComputations::GetUsedMembers() const
|
||||
{
|
||||
std::vector<MemberInformation*> members;
|
||||
|
||||
if (m_info->m_definition->GetType() == DataDefinitionType::UNION && GetDynamicMember() != nullptr)
|
||||
{
|
||||
for (const auto& member : m_info->m_ordered_members)
|
||||
{
|
||||
if (!MemberComputations(member.get()).ShouldIgnore())
|
||||
members.push_back(member.get());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& member : m_info->m_ordered_members)
|
||||
{
|
||||
if (!member->m_is_leaf && !MemberComputations(member.get()).ShouldIgnore())
|
||||
members.push_back(member.get());
|
||||
}
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Domain/Information/StructureInformation.h"
|
||||
|
||||
class StructureComputations
|
||||
{
|
||||
const StructureInformation* const m_info;
|
||||
|
||||
public:
|
||||
explicit StructureComputations(const StructureInformation* structure);
|
||||
|
||||
_NODISCARD bool IsAsset() const;
|
||||
_NODISCARD MemberInformation* GetDynamicMember() const;
|
||||
_NODISCARD std::vector<MemberInformation*> GetUsedMembers() const;
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
#include "ArrayDeclarationModifier.h"
|
||||
|
||||
DeclarationModifierType ArrayDeclarationModifier::GetType() const
|
||||
{
|
||||
return DeclarationModifierType::ARRAY;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "DeclarationModifier.h"
|
||||
#include "Domain/Evaluation/IEvaluation.h"
|
||||
|
||||
class ArrayDeclarationModifier final : public DeclarationModifier
|
||||
{
|
||||
public:
|
||||
int m_size;
|
||||
|
||||
/**
|
||||
* \brief The array size is not actually given by \c m_size but instead is dynamic.
|
||||
*/
|
||||
std::unique_ptr<IEvaluation> m_dynamic_size_evaluation;
|
||||
|
||||
/**
|
||||
* \brief The array has a size that is given by \c m_size but only a certain dynamic amount is handled by generated count.
|
||||
*/
|
||||
std::unique_ptr<IEvaluation> m_dynamic_count_evaluation;
|
||||
|
||||
DeclarationModifierType GetType() const override;
|
||||
};
|
@ -0,0 +1,75 @@
|
||||
#include "BaseTypeDefinition.h"
|
||||
|
||||
BaseTypeDefinition::BaseTypeDefinition(std::string name, const unsigned size)
|
||||
: DataDefinition("", std::move(name)),
|
||||
m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
DataDefinitionType BaseTypeDefinition::GetType() const
|
||||
{
|
||||
return DataDefinitionType::BASE_TYPE;
|
||||
}
|
||||
|
||||
unsigned BaseTypeDefinition::GetAlignment()
|
||||
{
|
||||
// Since this type has no members the alignment is always equal to the size.
|
||||
return m_size;
|
||||
}
|
||||
|
||||
unsigned BaseTypeDefinition::GetAlignment() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
bool BaseTypeDefinition::GetForceAlignment()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BaseTypeDefinition::GetForceAlignment() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned BaseTypeDefinition::GetSize()
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
unsigned BaseTypeDefinition::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::FLOAT = new BaseTypeDefinition("float", 4);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::DOUBLE = new BaseTypeDefinition("double", 8);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::BOOL = new BaseTypeDefinition("bool", 1);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::CHAR = new BaseTypeDefinition("char", 1);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::UNSIGNED_CHAR = new BaseTypeDefinition("unsigned char", 1);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::SHORT = new BaseTypeDefinition("short", 2);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::UNSIGNED_SHORT = new BaseTypeDefinition("unsigned short", 2);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::INT = new BaseTypeDefinition("int", 4);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::UNSIGNED_INT = new BaseTypeDefinition("unsigned int", 4);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::LONG = new BaseTypeDefinition("long", 4);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::UNSIGNED_LONG = new BaseTypeDefinition("unsigned long", 4);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::LONG_LONG = new BaseTypeDefinition("long long", 8);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::UNSIGNED_LONG_LONG = new BaseTypeDefinition("unsigned long long", 8);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::VOID = new BaseTypeDefinition("void", 0);
|
||||
const BaseTypeDefinition* const BaseTypeDefinition::ALL_BASE_TYPES[]
|
||||
{
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
BOOL,
|
||||
CHAR,
|
||||
UNSIGNED_CHAR,
|
||||
SHORT,
|
||||
UNSIGNED_SHORT,
|
||||
INT,
|
||||
UNSIGNED_INT,
|
||||
LONG,
|
||||
UNSIGNED_LONG,
|
||||
LONG_LONG,
|
||||
UNSIGNED_LONG_LONG,
|
||||
VOID
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include "DataDefinition.h"
|
||||
|
||||
class BaseTypeDefinition final : public DataDefinition
|
||||
{
|
||||
public:
|
||||
const unsigned m_size;
|
||||
|
||||
private:
|
||||
BaseTypeDefinition(std::string name, unsigned size);
|
||||
|
||||
public:
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
_NODISCARD unsigned GetAlignment() override;
|
||||
_NODISCARD unsigned GetAlignment() const;
|
||||
_NODISCARD bool GetForceAlignment() override;
|
||||
_NODISCARD bool GetForceAlignment() const;
|
||||
_NODISCARD unsigned GetSize() override;
|
||||
_NODISCARD unsigned GetSize() const;
|
||||
|
||||
static const BaseTypeDefinition* const FLOAT;
|
||||
static const BaseTypeDefinition* const DOUBLE;
|
||||
static const BaseTypeDefinition* const BOOL;
|
||||
static const BaseTypeDefinition* const CHAR;
|
||||
static const BaseTypeDefinition* const UNSIGNED_CHAR;
|
||||
static const BaseTypeDefinition* const SHORT;
|
||||
static const BaseTypeDefinition* const UNSIGNED_SHORT;
|
||||
static const BaseTypeDefinition* const INT;
|
||||
static const BaseTypeDefinition* const UNSIGNED_INT;
|
||||
static const BaseTypeDefinition* const LONG;
|
||||
static const BaseTypeDefinition* const UNSIGNED_LONG;
|
||||
static const BaseTypeDefinition* const LONG_LONG;
|
||||
static const BaseTypeDefinition* const UNSIGNED_LONG_LONG;
|
||||
static const BaseTypeDefinition* const VOID;
|
||||
|
||||
static const BaseTypeDefinition* const ALL_BASE_TYPES[];
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
#include "DataDefinition.h"
|
||||
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
#include "Utils/NamespaceBuilder.h"
|
||||
|
||||
DataDefinition::DataDefinition(std::string _namespace, std::string name)
|
||||
: m_namespace(std::move(_namespace)),
|
||||
m_name(std::move(name))
|
||||
{
|
||||
assert(!m_name.empty());
|
||||
}
|
||||
|
||||
std::string DataDefinition::GetFullName() const
|
||||
{
|
||||
return NamespaceBuilder::Combine(m_namespace, m_name);
|
||||
}
|
37
src/ZoneCodeGeneratorLib/Domain/Definition/DataDefinition.h
Normal file
37
src/ZoneCodeGeneratorLib/Domain/Definition/DataDefinition.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
enum class DataDefinitionType
|
||||
{
|
||||
STRUCT,
|
||||
UNION,
|
||||
ENUM,
|
||||
TYPEDEF,
|
||||
BASE_TYPE,
|
||||
FORWARD_DECLARATION
|
||||
};
|
||||
|
||||
class DataDefinition
|
||||
{
|
||||
public:
|
||||
DataDefinition() = default;
|
||||
DataDefinition(std::string _namespace, std::string name);
|
||||
|
||||
virtual ~DataDefinition() = default;
|
||||
DataDefinition(const DataDefinition& other) = default;
|
||||
DataDefinition(DataDefinition&& other) noexcept = default;
|
||||
DataDefinition& operator=(const DataDefinition& other) = default;
|
||||
DataDefinition& operator=(DataDefinition&& other) noexcept = default;
|
||||
|
||||
std::string m_namespace;
|
||||
std::string m_name;
|
||||
|
||||
_NODISCARD virtual DataDefinitionType GetType() const = 0;
|
||||
_NODISCARD virtual unsigned GetAlignment() = 0;
|
||||
_NODISCARD virtual bool GetForceAlignment() = 0;
|
||||
_NODISCARD virtual unsigned GetSize() = 0;
|
||||
|
||||
_NODISCARD std::string GetFullName() const;
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
enum class DeclarationModifierType
|
||||
{
|
||||
POINTER,
|
||||
ARRAY
|
||||
};
|
||||
|
||||
class DeclarationModifier
|
||||
{
|
||||
public:
|
||||
DeclarationModifier() = default;
|
||||
virtual ~DeclarationModifier() = default;
|
||||
|
||||
_NODISCARD virtual DeclarationModifierType GetType() const = 0;
|
||||
};
|
@ -0,0 +1,57 @@
|
||||
#include "DefinitionWithMembers.h"
|
||||
|
||||
DefinitionWithMembers::DefinitionWithMembers(std::string _namespace, std::string name, const unsigned pack)
|
||||
: DataDefinition(std::move(_namespace), std::move(name)),
|
||||
m_flags(0),
|
||||
m_size(0),
|
||||
m_alignment(0),
|
||||
m_has_alignment_override(false),
|
||||
m_anonymous(false),
|
||||
m_pack(pack),
|
||||
m_alignment_override(0)
|
||||
{
|
||||
}
|
||||
|
||||
void DefinitionWithMembers::CalculateAlignment()
|
||||
{
|
||||
if (m_has_alignment_override)
|
||||
{
|
||||
m_flags |= FLAG_ALIGNMENT_FORCED;
|
||||
m_alignment = m_alignment_override;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_alignment = 0;
|
||||
for (const auto& member : m_members)
|
||||
{
|
||||
const auto memberAlignment = member->GetAlignment();
|
||||
if (memberAlignment > m_alignment)
|
||||
m_alignment = memberAlignment;
|
||||
}
|
||||
}
|
||||
m_flags |= FLAG_ALIGNMENT_CALCULATED;
|
||||
}
|
||||
|
||||
unsigned DefinitionWithMembers::GetAlignment()
|
||||
{
|
||||
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
|
||||
CalculateAlignment();
|
||||
|
||||
return m_alignment;
|
||||
}
|
||||
|
||||
bool DefinitionWithMembers::GetForceAlignment()
|
||||
{
|
||||
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
|
||||
CalculateAlignment();
|
||||
|
||||
return m_flags & FLAG_ALIGNMENT_FORCED;
|
||||
}
|
||||
|
||||
unsigned DefinitionWithMembers::GetSize()
|
||||
{
|
||||
if ((m_flags & FLAG_SIZE_CALCULATED) == 0)
|
||||
CalculateSize();
|
||||
|
||||
return m_size;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "DataDefinition.h"
|
||||
#include "Variable.h"
|
||||
|
||||
class DefinitionWithMembers : public DataDefinition
|
||||
{
|
||||
protected:
|
||||
static constexpr int FLAG_SIZE_CALCULATED = 1 << 0;
|
||||
static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1;
|
||||
static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2;
|
||||
|
||||
unsigned m_flags;
|
||||
unsigned m_size;
|
||||
unsigned m_alignment;
|
||||
|
||||
virtual void CalculateSize() = 0;
|
||||
void CalculateAlignment();
|
||||
|
||||
public:
|
||||
bool m_has_alignment_override;
|
||||
bool m_anonymous;
|
||||
|
||||
const unsigned m_pack;
|
||||
unsigned m_alignment_override;
|
||||
|
||||
std::vector<std::unique_ptr<Variable>> m_members;
|
||||
|
||||
DefinitionWithMembers(std::string _namespace, std::string name, unsigned pack);
|
||||
|
||||
_NODISCARD unsigned GetAlignment() override;
|
||||
_NODISCARD bool GetForceAlignment() override;
|
||||
_NODISCARD unsigned GetSize() override;
|
||||
};
|
@ -0,0 +1,35 @@
|
||||
#include "EnumDefinition.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
EnumDefinition::EnumDefinition(std::string _namespace, std::string name, const BaseTypeDefinition* parentType)
|
||||
: DataDefinition(std::move(_namespace), std::move(name)),
|
||||
m_parent_type(parentType)
|
||||
{
|
||||
assert(parentType != nullptr);
|
||||
}
|
||||
|
||||
DataDefinitionType EnumDefinition::GetType() const
|
||||
{
|
||||
return DataDefinitionType::ENUM;
|
||||
}
|
||||
|
||||
unsigned EnumDefinition::GetAlignment()
|
||||
{
|
||||
return m_parent_type->GetAlignment();
|
||||
}
|
||||
|
||||
bool EnumDefinition::GetForceAlignment()
|
||||
{
|
||||
return m_parent_type->GetForceAlignment();
|
||||
}
|
||||
|
||||
unsigned EnumDefinition::GetSize()
|
||||
{
|
||||
return m_parent_type->GetSize();
|
||||
}
|
||||
|
||||
void EnumDefinition::AddEnumMember(EnumMember enumMember)
|
||||
{
|
||||
m_members.emplace_back(std::make_unique<EnumMember>(std::move(enumMember)));
|
||||
}
|
24
src/ZoneCodeGeneratorLib/Domain/Definition/EnumDefinition.h
Normal file
24
src/ZoneCodeGeneratorLib/Domain/Definition/EnumDefinition.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "BaseTypeDefinition.h"
|
||||
#include "DataDefinition.h"
|
||||
#include "EnumMember.h"
|
||||
|
||||
class EnumDefinition final : public DataDefinition
|
||||
{
|
||||
public:
|
||||
const BaseTypeDefinition* m_parent_type;
|
||||
std::vector<std::unique_ptr<EnumMember>> m_members;
|
||||
|
||||
EnumDefinition(std::string _namespace, std::string name, const BaseTypeDefinition* parentType);
|
||||
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
_NODISCARD unsigned GetAlignment() override;
|
||||
_NODISCARD bool GetForceAlignment() override;
|
||||
_NODISCARD unsigned GetSize() override;
|
||||
|
||||
void AddEnumMember(EnumMember enumMember);
|
||||
};
|
12
src/ZoneCodeGeneratorLib/Domain/Definition/EnumMember.cpp
Normal file
12
src/ZoneCodeGeneratorLib/Domain/Definition/EnumMember.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "EnumMember.h"
|
||||
|
||||
EnumMember::EnumMember()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
|
||||
EnumMember::EnumMember(std::string name, const long long value)
|
||||
: m_name(std::move(name)),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
13
src/ZoneCodeGeneratorLib/Domain/Definition/EnumMember.h
Normal file
13
src/ZoneCodeGeneratorLib/Domain/Definition/EnumMember.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class EnumMember
|
||||
{
|
||||
public:
|
||||
std::string m_name;
|
||||
long long m_value;
|
||||
|
||||
EnumMember();
|
||||
EnumMember(std::string name, long long value);
|
||||
};
|
@ -0,0 +1,28 @@
|
||||
#include "ForwardDeclaration.h"
|
||||
|
||||
ForwardDeclaration::ForwardDeclaration(std::string _namespace, std::string name, DataDefinitionType type)
|
||||
: DataDefinition(std::move(_namespace), std::move(name)),
|
||||
m_forwarded_type(type),
|
||||
m_definition(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DataDefinitionType ForwardDeclaration::GetType() const
|
||||
{
|
||||
return DataDefinitionType::FORWARD_DECLARATION;
|
||||
}
|
||||
|
||||
unsigned ForwardDeclaration::GetAlignment()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ForwardDeclaration::GetForceAlignment()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned ForwardDeclaration::GetSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "DataDefinition.h"
|
||||
|
||||
class ForwardDeclaration final : public DataDefinition
|
||||
{
|
||||
public:
|
||||
const DataDefinitionType m_forwarded_type;
|
||||
DataDefinition* m_definition;
|
||||
|
||||
ForwardDeclaration(std::string _namespace, std::string name, DataDefinitionType type);
|
||||
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
_NODISCARD unsigned GetAlignment() override;
|
||||
_NODISCARD bool GetForceAlignment() override;
|
||||
_NODISCARD unsigned GetSize() override;
|
||||
};
|
@ -0,0 +1,72 @@
|
||||
#include "PointerDeclarationModifier.h"
|
||||
|
||||
#include "Domain/Evaluation/OperandStatic.h"
|
||||
|
||||
const IEvaluation* const PointerDeclarationModifier::DEFAULT_COUNT = new OperandStatic(1);
|
||||
|
||||
DeclarationModifierType PointerDeclarationModifier::GetType() const
|
||||
{
|
||||
return DeclarationModifierType::POINTER;
|
||||
}
|
||||
|
||||
const IEvaluation* PointerDeclarationModifier::GetCountEvaluation() const
|
||||
{
|
||||
if (m_count_evaluation)
|
||||
return m_count_evaluation.get();
|
||||
|
||||
return DEFAULT_COUNT;
|
||||
}
|
||||
|
||||
const IEvaluation* PointerDeclarationModifier::GetCountEvaluationForArrayIndex(const int index)
|
||||
{
|
||||
if (index >= 0 && m_count_evaluation_by_array_index.size() > static_cast<unsigned>(index))
|
||||
{
|
||||
return m_count_evaluation_by_array_index[index].get();
|
||||
}
|
||||
|
||||
if (m_count_evaluation)
|
||||
{
|
||||
return m_count_evaluation.get();
|
||||
}
|
||||
|
||||
return DEFAULT_COUNT;
|
||||
}
|
||||
|
||||
bool PointerDeclarationModifier::EvaluationIsArray(const IEvaluation* evaluation)
|
||||
{
|
||||
return !evaluation->IsStatic() || evaluation->EvaluateNumeric() > 1;
|
||||
}
|
||||
|
||||
bool PointerDeclarationModifier::CountEvaluationIsArray() const
|
||||
{
|
||||
if (m_count_evaluation)
|
||||
{
|
||||
return EvaluationIsArray(m_count_evaluation.get());
|
||||
}
|
||||
|
||||
return EvaluationIsArray(DEFAULT_COUNT);
|
||||
}
|
||||
|
||||
bool PointerDeclarationModifier::CountEvaluationIsArray(const int index) const
|
||||
{
|
||||
if(index >= 0 && m_count_evaluation_by_array_index.size() > static_cast<unsigned>(index))
|
||||
{
|
||||
return EvaluationIsArray(m_count_evaluation_by_array_index[index].get());
|
||||
}
|
||||
|
||||
return CountEvaluationIsArray();
|
||||
}
|
||||
|
||||
bool PointerDeclarationModifier::AnyCountEvaluationIsArray() const
|
||||
{
|
||||
if (m_count_evaluation && EvaluationIsArray(m_count_evaluation.get()))
|
||||
return true;
|
||||
|
||||
for(const auto& arrayCountEvaluation : m_count_evaluation_by_array_index)
|
||||
{
|
||||
if (EvaluationIsArray(arrayCountEvaluation.get()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return EvaluationIsArray(DEFAULT_COUNT);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "DeclarationModifier.h"
|
||||
#include "Domain/Evaluation/IEvaluation.h"
|
||||
|
||||
class PointerDeclarationModifier final : public DeclarationModifier
|
||||
{
|
||||
static const IEvaluation* const DEFAULT_COUNT;
|
||||
|
||||
static bool EvaluationIsArray(const IEvaluation* evaluation);
|
||||
|
||||
public:
|
||||
std::unique_ptr<IEvaluation> m_count_evaluation;
|
||||
std::vector<std::unique_ptr<IEvaluation>> m_count_evaluation_by_array_index;
|
||||
|
||||
_NODISCARD DeclarationModifierType GetType() const override;
|
||||
_NODISCARD const IEvaluation* GetCountEvaluation() const;
|
||||
_NODISCARD const IEvaluation* GetCountEvaluationForArrayIndex(int index);
|
||||
|
||||
_NODISCARD bool CountEvaluationIsArray() const;
|
||||
_NODISCARD bool CountEvaluationIsArray(int index) const;
|
||||
_NODISCARD bool AnyCountEvaluationIsArray() const;
|
||||
};
|
@ -0,0 +1,49 @@
|
||||
#include "StructDefinition.h"
|
||||
|
||||
#include "Utils/AlignmentUtils.h"
|
||||
|
||||
void StructDefinition::CalculateSize()
|
||||
{
|
||||
m_size = 0;
|
||||
auto currentBitOffset = 0u;
|
||||
|
||||
for(const auto& member : m_members)
|
||||
{
|
||||
if(member->m_type_declaration->m_has_custom_bit_size)
|
||||
{
|
||||
currentBitOffset += member->m_type_declaration->m_custom_bit_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentBitOffset > 0)
|
||||
{
|
||||
currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u);
|
||||
m_size += currentBitOffset / 8;
|
||||
currentBitOffset = 0;
|
||||
}
|
||||
|
||||
m_size = AlignmentUtils::Align(m_size, member->GetForceAlignment() ? member->GetAlignment() : std::min(member->GetAlignment(), m_pack));
|
||||
m_size += member->m_type_declaration->GetSize();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentBitOffset > 0)
|
||||
{
|
||||
currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u);
|
||||
m_size += currentBitOffset / 8;
|
||||
}
|
||||
|
||||
m_size = AlignmentUtils::Align(m_size, GetAlignment());
|
||||
|
||||
m_flags |= FLAG_SIZE_CALCULATED;
|
||||
}
|
||||
|
||||
StructDefinition::StructDefinition(std::string _namespace, std::string name, const int pack)
|
||||
: DefinitionWithMembers(std::move(_namespace), std::move(name), pack)
|
||||
{
|
||||
}
|
||||
|
||||
DataDefinitionType StructDefinition::GetType() const
|
||||
{
|
||||
return DataDefinitionType::STRUCT;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "DefinitionWithMembers.h"
|
||||
|
||||
class StructDefinition final : public DefinitionWithMembers
|
||||
{
|
||||
protected:
|
||||
void CalculateSize() override;
|
||||
|
||||
public:
|
||||
StructDefinition(std::string _namespace, std::string name, int pack);
|
||||
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
};
|
@ -0,0 +1,90 @@
|
||||
#include "TypeDeclaration.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ArrayDeclarationModifier.h"
|
||||
|
||||
TypeDeclaration::TypeDeclaration(DataDefinition* type)
|
||||
: m_flags(0),
|
||||
m_size(0),
|
||||
m_alignment(0),
|
||||
m_is_const(false),
|
||||
m_has_custom_bit_size(false),
|
||||
m_type(type),
|
||||
m_custom_bit_size(0)
|
||||
{
|
||||
assert(m_type != nullptr);
|
||||
}
|
||||
|
||||
void TypeDeclaration::CalculateSize()
|
||||
{
|
||||
auto currentSize = m_type->GetSize();
|
||||
|
||||
for(auto i = m_declaration_modifiers.size(); i > 0; i--)
|
||||
{
|
||||
const auto& declarationModifier = m_declaration_modifiers[i - 1];
|
||||
|
||||
switch(declarationModifier->GetType())
|
||||
{
|
||||
case DeclarationModifierType::POINTER:
|
||||
currentSize = POINTER_SIZE;
|
||||
break;
|
||||
|
||||
case DeclarationModifierType::ARRAY:
|
||||
currentSize *= dynamic_cast<ArrayDeclarationModifier*>(declarationModifier.get())->m_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_flags |= FLAG_SIZE_CALCULATED;
|
||||
}
|
||||
|
||||
void TypeDeclaration::CalculateAlignment()
|
||||
{
|
||||
auto hasPointerModifier = false;
|
||||
for (const auto& declarationModifier : m_declaration_modifiers)
|
||||
{
|
||||
if (declarationModifier->GetType() == DeclarationModifierType::POINTER)
|
||||
{
|
||||
hasPointerModifier = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPointerModifier)
|
||||
{
|
||||
m_alignment = POINTER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_alignment = m_type->GetAlignment();
|
||||
if (m_type->GetForceAlignment())
|
||||
m_flags |= FLAG_ALIGNMENT_FORCED;
|
||||
}
|
||||
|
||||
m_flags |= FLAG_ALIGNMENT_CALCULATED;
|
||||
}
|
||||
|
||||
unsigned TypeDeclaration::GetSize()
|
||||
{
|
||||
if ((m_flags & FLAG_SIZE_CALCULATED) == 0)
|
||||
CalculateSize();
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
unsigned TypeDeclaration::GetAlignment()
|
||||
{
|
||||
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
|
||||
CalculateAlignment();
|
||||
|
||||
return m_alignment;
|
||||
}
|
||||
|
||||
bool TypeDeclaration::GetForceAlignment()
|
||||
{
|
||||
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
|
||||
CalculateAlignment();
|
||||
|
||||
return m_flags & FLAG_ALIGNMENT_FORCED;
|
||||
}
|
37
src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h
Normal file
37
src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include "DataDefinition.h"
|
||||
#include "DeclarationModifier.h"
|
||||
|
||||
class TypeDeclaration
|
||||
{
|
||||
static constexpr unsigned POINTER_SIZE = sizeof(uint32_t); // TODO: Change this to support 64bit
|
||||
static constexpr int FLAG_SIZE_CALCULATED = 1 << 0;
|
||||
static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1;
|
||||
static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2;
|
||||
|
||||
unsigned m_flags;
|
||||
unsigned m_size;
|
||||
unsigned m_alignment;
|
||||
|
||||
void CalculateSize();
|
||||
void CalculateAlignment();
|
||||
|
||||
public:
|
||||
explicit TypeDeclaration(DataDefinition* type);
|
||||
|
||||
bool m_is_const;
|
||||
bool m_has_custom_bit_size;
|
||||
|
||||
DataDefinition* m_type;
|
||||
unsigned m_custom_bit_size;
|
||||
|
||||
std::vector<std::unique_ptr<DeclarationModifier>> m_declaration_modifiers;
|
||||
|
||||
unsigned GetSize();
|
||||
unsigned GetAlignment();
|
||||
bool GetForceAlignment();
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
#include "TypedefDefinition.h"
|
||||
|
||||
TypedefDefinition::TypedefDefinition(std::string _namespace, std::string name, std::unique_ptr<TypeDeclaration> typeDeclaration)
|
||||
: DataDefinition(std::move(_namespace), std::move(name)),
|
||||
m_has_alignment_override(false),
|
||||
m_alignment_override(0),
|
||||
m_type_declaration(std::move(typeDeclaration))
|
||||
{
|
||||
}
|
||||
|
||||
DataDefinitionType TypedefDefinition::GetType() const
|
||||
{
|
||||
return DataDefinitionType::TYPEDEF;
|
||||
}
|
||||
|
||||
unsigned TypedefDefinition::GetAlignment()
|
||||
{
|
||||
if (m_has_alignment_override)
|
||||
{
|
||||
return m_alignment_override;
|
||||
}
|
||||
return m_type_declaration->GetAlignment();
|
||||
}
|
||||
|
||||
bool TypedefDefinition::GetForceAlignment()
|
||||
{
|
||||
return m_has_alignment_override || m_type_declaration->GetForceAlignment();
|
||||
}
|
||||
|
||||
unsigned TypedefDefinition::GetSize()
|
||||
{
|
||||
return m_type_declaration->GetSize();
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "DataDefinition.h"
|
||||
#include "TypeDeclaration.h"
|
||||
|
||||
class TypedefDefinition final : public DataDefinition
|
||||
{
|
||||
public:
|
||||
bool m_has_alignment_override;
|
||||
unsigned m_alignment_override;
|
||||
std::unique_ptr<TypeDeclaration> m_type_declaration;
|
||||
|
||||
TypedefDefinition(std::string _namespace, std::string name, std::unique_ptr<TypeDeclaration> typeDeclaration);
|
||||
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
_NODISCARD unsigned GetAlignment() override;
|
||||
_NODISCARD bool GetForceAlignment() override;
|
||||
_NODISCARD unsigned GetSize() override;
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
#include "UnionDefinition.h"
|
||||
|
||||
#include "Utils/AlignmentUtils.h"
|
||||
|
||||
void UnionDefinition::CalculateSize()
|
||||
{
|
||||
m_size = 0;
|
||||
|
||||
for(const auto& member : m_members)
|
||||
{
|
||||
const auto memberSize = member->m_type_declaration->GetSize();
|
||||
if (memberSize > m_size)
|
||||
m_size = memberSize;
|
||||
}
|
||||
|
||||
m_size = AlignmentUtils::Align(m_size, GetAlignment());
|
||||
|
||||
m_flags |= FLAG_SIZE_CALCULATED;
|
||||
}
|
||||
|
||||
UnionDefinition::UnionDefinition(std::string _namespace, std::string name, const int pack)
|
||||
: DefinitionWithMembers(std::move(_namespace), std::move(name), pack)
|
||||
{
|
||||
}
|
||||
|
||||
DataDefinitionType UnionDefinition::GetType() const
|
||||
{
|
||||
return DataDefinitionType::UNION;
|
||||
}
|
14
src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.h
Normal file
14
src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "DefinitionWithMembers.h"
|
||||
|
||||
class UnionDefinition final : public DefinitionWithMembers
|
||||
{
|
||||
protected:
|
||||
void CalculateSize() override;
|
||||
|
||||
public:
|
||||
UnionDefinition(std::string _namespace, std::string name, int pack);
|
||||
|
||||
_NODISCARD DataDefinitionType GetType() const override;
|
||||
};
|
14
src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp
Normal file
14
src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "Variable.h"
|
||||
|
||||
unsigned Variable::GetAlignment()
|
||||
{
|
||||
if (m_has_alignment_override)
|
||||
return m_alignment_override;
|
||||
|
||||
return m_type_declaration->GetAlignment();
|
||||
}
|
||||
|
||||
bool Variable::GetForceAlignment()
|
||||
{
|
||||
return m_has_alignment_override || m_type_declaration->GetForceAlignment();
|
||||
}
|
18
src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h
Normal file
18
src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "TypeDeclaration.h"
|
||||
|
||||
class Variable
|
||||
{
|
||||
public:
|
||||
std::string m_name;
|
||||
bool m_has_alignment_override;
|
||||
unsigned m_alignment_override;
|
||||
std::unique_ptr<TypeDeclaration> m_type_declaration;
|
||||
|
||||
unsigned GetAlignment();
|
||||
bool GetForceAlignment();
|
||||
};
|
26
src/ZoneCodeGeneratorLib/Domain/Evaluation/IEvaluation.h
Normal file
26
src/ZoneCodeGeneratorLib/Domain/Evaluation/IEvaluation.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
enum class EvaluationType
|
||||
{
|
||||
OPERAND_DYNAMIC,
|
||||
OPERAND_STATIC,
|
||||
OPERATION
|
||||
};
|
||||
|
||||
class IEvaluation
|
||||
{
|
||||
public:
|
||||
IEvaluation() = default;
|
||||
virtual ~IEvaluation() = default;
|
||||
|
||||
IEvaluation(const IEvaluation& other) = default;
|
||||
IEvaluation(IEvaluation&& other) noexcept = default;
|
||||
IEvaluation& operator=(const IEvaluation& other) = default;
|
||||
IEvaluation& operator=(IEvaluation&& other) noexcept = default;
|
||||
|
||||
_NODISCARD virtual EvaluationType GetType() const = 0;
|
||||
_NODISCARD virtual bool IsStatic() const = 0;
|
||||
_NODISCARD virtual int EvaluateNumeric() const = 0;
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
#include "OperandDynamic.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
OperandDynamic::OperandDynamic(StructureInformation* structure)
|
||||
: m_structure(structure)
|
||||
{
|
||||
}
|
||||
|
||||
EvaluationType OperandDynamic::GetType() const
|
||||
{
|
||||
return EvaluationType::OPERAND_DYNAMIC;
|
||||
}
|
||||
|
||||
bool OperandDynamic::IsStatic() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int OperandDynamic::EvaluateNumeric() const
|
||||
{
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
21
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h
Normal file
21
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "IEvaluation.h"
|
||||
#include "Domain/Information/MemberInformation.h"
|
||||
#include "Domain/Information/StructureInformation.h"
|
||||
|
||||
class OperandDynamic final : public IEvaluation
|
||||
{
|
||||
public:
|
||||
StructureInformation* const m_structure;
|
||||
std::vector<MemberInformation*> m_referenced_member_chain;
|
||||
std::vector<std::unique_ptr<IEvaluation>> m_array_indices;
|
||||
|
||||
explicit OperandDynamic(StructureInformation* structure);
|
||||
|
||||
_NODISCARD EvaluationType GetType() const override;
|
||||
_NODISCARD bool IsStatic() const override;
|
||||
_NODISCARD int EvaluateNumeric() const override;
|
||||
};
|
28
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp
Normal file
28
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "OperandStatic.h"
|
||||
|
||||
OperandStatic::OperandStatic(const int value)
|
||||
: m_value(value),
|
||||
m_enum_member(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
OperandStatic::OperandStatic(const int value, EnumMember* enumMember)
|
||||
: m_value(value),
|
||||
m_enum_member(enumMember)
|
||||
{
|
||||
}
|
||||
|
||||
EvaluationType OperandStatic::GetType() const
|
||||
{
|
||||
return EvaluationType::OPERAND_STATIC;
|
||||
}
|
||||
|
||||
bool OperandStatic::IsStatic() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int OperandStatic::EvaluateNumeric() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
18
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h
Normal file
18
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "IEvaluation.h"
|
||||
#include "Domain/Definition/EnumMember.h"
|
||||
|
||||
class OperandStatic final : public IEvaluation
|
||||
{
|
||||
public:
|
||||
const int m_value;
|
||||
EnumMember* const m_enum_member;
|
||||
|
||||
explicit OperandStatic(int value);
|
||||
OperandStatic(int value, EnumMember* enumMember);
|
||||
|
||||
_NODISCARD EvaluationType GetType() const override;
|
||||
_NODISCARD bool IsStatic() const override;
|
||||
_NODISCARD int EvaluateNumeric() const override;
|
||||
};
|
33
src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp
Normal file
33
src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "Operation.h"
|
||||
|
||||
Operation::Operation(const OperationType* type)
|
||||
: m_operation_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
EvaluationType Operation::GetType() const
|
||||
{
|
||||
return EvaluationType::OPERATION;
|
||||
}
|
||||
|
||||
bool Operation::IsStatic() const
|
||||
{
|
||||
return m_operand1->IsStatic() && m_operand2->IsStatic();
|
||||
}
|
||||
|
||||
int Operation::EvaluateNumeric() const
|
||||
{
|
||||
return m_operation_type->m_evaluation_function(m_operand1->EvaluateNumeric(), m_operand2->EvaluateNumeric());
|
||||
}
|
||||
|
||||
bool Operation::Operand1NeedsParenthesis() const
|
||||
{
|
||||
return m_operand1->GetType() == EvaluationType::OPERATION
|
||||
&& dynamic_cast<Operation*>(m_operand1.get())->m_operation_type->m_precedence > m_operation_type->m_precedence;
|
||||
}
|
||||
|
||||
bool Operation::Operand2NeedsParenthesis() const
|
||||
{
|
||||
return m_operand2->GetType() == EvaluationType::OPERATION
|
||||
&& dynamic_cast<Operation*>(m_operand2.get())->m_operation_type->m_precedence > m_operation_type->m_precedence;
|
||||
}
|
24
src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h
Normal file
24
src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "IEvaluation.h"
|
||||
#include "OperationType.h"
|
||||
|
||||
class Operation final : public IEvaluation
|
||||
{
|
||||
public:
|
||||
const OperationType* const m_operation_type;
|
||||
std::unique_ptr<IEvaluation> m_operand1;
|
||||
std::unique_ptr<IEvaluation> m_operand2;
|
||||
|
||||
explicit Operation(const OperationType* type);
|
||||
|
||||
_NODISCARD EvaluationType GetType() const override;
|
||||
_NODISCARD bool IsStatic() const override;
|
||||
_NODISCARD int EvaluateNumeric() const override;
|
||||
|
||||
_NODISCARD bool Operand1NeedsParenthesis() const;
|
||||
_NODISCARD bool Operand2NeedsParenthesis() const;
|
||||
};
|
139
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp
Normal file
139
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include "OperationType.h"
|
||||
|
||||
OperationType::OperationType(std::string syntax, const OperationPrecedence precedence, std::function<int(int, int)> evaluationFunction)
|
||||
: m_syntax(std::move(syntax)),
|
||||
m_precedence(precedence),
|
||||
m_evaluation_function(std::move(evaluationFunction))
|
||||
{
|
||||
}
|
||||
|
||||
const OperationType* const OperationType::OPERATION_ADD
|
||||
= new OperationType("+", OperationPrecedence::ADDITION_SUBTRACTION, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 + op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_SUBTRACT
|
||||
= new OperationType("-", OperationPrecedence::ADDITION_SUBTRACTION, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 - op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_MULTIPLY
|
||||
= new OperationType("*", OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 * op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_DIVIDE
|
||||
= new OperationType("/", OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 / op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_REMAINDER
|
||||
= new OperationType("%", OperationPrecedence::MULTIPLICATION_DIVISION_REMAINDER, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 % op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_BITWISE_AND
|
||||
= new OperationType("&", OperationPrecedence::BITWISE_AND, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 & op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_BITWISE_XOR
|
||||
= new OperationType("^", OperationPrecedence::BITWISE_XOR, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 ^ op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_BITWISE_OR
|
||||
= new OperationType("|", OperationPrecedence::BITWISE_OR, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 | op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_SHIFT_LEFT
|
||||
= new OperationType("<<", OperationPrecedence::BITWISE_SHIFT, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 << op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_SHIFT_RIGHT
|
||||
= new OperationType(">>", OperationPrecedence::BITWISE_SHIFT, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 >> op2;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_GREATER_THAN
|
||||
= new OperationType(">", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 > op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_GREATER_EQUALS_THAN
|
||||
= new OperationType(">=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 >= op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_LESS_THAN
|
||||
= new OperationType("<", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 < op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_LESS_EQUALS_THAN
|
||||
= new OperationType("<=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 <= op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_EQUALS
|
||||
= new OperationType("==", OperationPrecedence::RELATIONAL_EQUALS, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 == op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_NOT_EQUALS
|
||||
= new OperationType("!=", OperationPrecedence::RELATIONAL_EQUALS, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 != op2 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_AND
|
||||
= new OperationType("&&", OperationPrecedence::LOGICAL_AND, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 > 0 && op2 > 0 ? 1 : 0;
|
||||
});
|
||||
|
||||
const OperationType* const OperationType::OPERATION_OR
|
||||
= new OperationType("||", OperationPrecedence::LOGICAL_OR, [](auto op1, auto op2)
|
||||
{
|
||||
return op1 > 0 || op2 > 0 ? 1 : 0;
|
||||
});
|
||||
|
||||
|
||||
const OperationType* const OperationType::ALL_OPERATION_TYPES[]
|
||||
{
|
||||
OPERATION_ADD,
|
||||
OPERATION_SUBTRACT,
|
||||
OPERATION_MULTIPLY,
|
||||
OPERATION_DIVIDE,
|
||||
OPERATION_REMAINDER,
|
||||
OPERATION_BITWISE_AND,
|
||||
OPERATION_BITWISE_XOR,
|
||||
OPERATION_BITWISE_OR,
|
||||
OPERATION_SHIFT_LEFT,
|
||||
OPERATION_SHIFT_RIGHT,
|
||||
OPERATION_GREATER_THAN,
|
||||
OPERATION_GREATER_EQUALS_THAN,
|
||||
OPERATION_LESS_THAN,
|
||||
OPERATION_LESS_EQUALS_THAN,
|
||||
OPERATION_EQUALS,
|
||||
OPERATION_NOT_EQUALS,
|
||||
OPERATION_AND,
|
||||
OPERATION_OR
|
||||
};
|
52
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h
Normal file
52
src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
// https://en.cppreference.com/w/cpp/language/operator_precedence
|
||||
enum class OperationPrecedence
|
||||
{
|
||||
MULTIPLICATION_DIVISION_REMAINDER = 1,
|
||||
ADDITION_SUBTRACTION = 2,
|
||||
BITWISE_SHIFT = 3,
|
||||
RELATIONAL_GREATER_LESS_THAN = 4,
|
||||
RELATIONAL_EQUALS = 5,
|
||||
BITWISE_AND = 6,
|
||||
BITWISE_XOR = 7,
|
||||
BITWISE_OR = 8,
|
||||
LOGICAL_AND = 9,
|
||||
LOGICAL_OR = 10
|
||||
};
|
||||
|
||||
class OperationType
|
||||
{
|
||||
public:
|
||||
std::string m_syntax;
|
||||
OperationPrecedence m_precedence;
|
||||
std::function<int(int operand1, int operand2)> m_evaluation_function;
|
||||
|
||||
private:
|
||||
OperationType(std::string syntax, OperationPrecedence precedence, std::function<int(int, int)> evaluationFunction);
|
||||
|
||||
public:
|
||||
static const OperationType* const OPERATION_ADD;
|
||||
static const OperationType* const OPERATION_SUBTRACT;
|
||||
static const OperationType* const OPERATION_MULTIPLY;
|
||||
static const OperationType* const OPERATION_DIVIDE;
|
||||
static const OperationType* const OPERATION_REMAINDER;
|
||||
static const OperationType* const OPERATION_BITWISE_AND;
|
||||
static const OperationType* const OPERATION_BITWISE_XOR;
|
||||
static const OperationType* const OPERATION_BITWISE_OR;
|
||||
static const OperationType* const OPERATION_SHIFT_LEFT;
|
||||
static const OperationType* const OPERATION_SHIFT_RIGHT;
|
||||
static const OperationType* const OPERATION_GREATER_THAN;
|
||||
static const OperationType* const OPERATION_GREATER_EQUALS_THAN;
|
||||
static const OperationType* const OPERATION_LESS_THAN;
|
||||
static const OperationType* const OPERATION_LESS_EQUALS_THAN;
|
||||
static const OperationType* const OPERATION_EQUALS;
|
||||
static const OperationType* const OPERATION_NOT_EQUALS;
|
||||
static const OperationType* const OPERATION_AND;
|
||||
static const OperationType* const OPERATION_OR;
|
||||
|
||||
static const OperationType* const ALL_OPERATION_TYPES[];
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
#include "CustomAction.h"
|
||||
|
||||
CustomAction::CustomAction(std::string actionName)
|
||||
: m_action_name(std::move(actionName))
|
||||
{
|
||||
}
|
15
src/ZoneCodeGeneratorLib/Domain/Extension/CustomAction.h
Normal file
15
src/ZoneCodeGeneratorLib/Domain/Extension/CustomAction.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Domain/Definition/DataDefinition.h"
|
||||
|
||||
class CustomAction
|
||||
{
|
||||
public:
|
||||
std::string m_action_name;
|
||||
std::vector<DataDefinition*> m_parameter_types;
|
||||
|
||||
explicit CustomAction(std::string actionName);
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
#include "FastFileBlock.h"
|
||||
|
||||
FastFileBlock::FastFileBlock(std::string name, const unsigned index, const FastFileBlockType type, const bool isDefault)
|
||||
: m_name(std::move(name)),
|
||||
m_index(index),
|
||||
m_type(type),
|
||||
m_is_default(isDefault)
|
||||
{
|
||||
}
|
22
src/ZoneCodeGeneratorLib/Domain/FastFile/FastFileBlock.h
Normal file
22
src/ZoneCodeGeneratorLib/Domain/FastFile/FastFileBlock.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
enum class FastFileBlockType
|
||||
{
|
||||
TEMP,
|
||||
RUNTIME,
|
||||
DELAY,
|
||||
NORMAL
|
||||
};
|
||||
|
||||
class FastFileBlock
|
||||
{
|
||||
public:
|
||||
std::string m_name;
|
||||
unsigned m_index;
|
||||
FastFileBlockType m_type;
|
||||
bool m_is_default;
|
||||
|
||||
FastFileBlock(std::string name, unsigned index, FastFileBlockType type, bool isDefault);
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
#include "MemberInformation.h"
|
||||
|
||||
MemberInformation::MemberInformation(StructureInformation* parent, StructureInformation* type, Variable* member)
|
||||
: m_parent(parent),
|
||||
m_type(type),
|
||||
m_member(member),
|
||||
m_is_string(false),
|
||||
m_is_script_string(false),
|
||||
m_is_reusable(false),
|
||||
m_is_leaf(false),
|
||||
m_fast_file_block(nullptr)
|
||||
{
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "StructureInformation.h"
|
||||
#include "Domain/Definition/Variable.h"
|
||||
#include "Domain/FastFile/FastFileBlock.h"
|
||||
#include "Domain/Evaluation/IEvaluation.h"
|
||||
|
||||
class StructureInformation;
|
||||
class MemberInformation
|
||||
{
|
||||
public:
|
||||
StructureInformation* m_parent;
|
||||
StructureInformation* m_type;
|
||||
Variable* m_member;
|
||||
bool m_is_string;
|
||||
bool m_is_script_string;
|
||||
bool m_is_reusable;
|
||||
bool m_is_leaf;
|
||||
std::unique_ptr<IEvaluation> m_condition;
|
||||
FastFileBlock* m_fast_file_block;
|
||||
|
||||
MemberInformation(StructureInformation* parent, StructureInformation* type, Variable* member);
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
#include "StructureInformation.h"
|
||||
|
||||
StructureInformation::StructureInformation(DefinitionWithMembers* definition)
|
||||
: m_has_non_default_fast_file_align(false),
|
||||
m_custom_fast_file_align(0),
|
||||
m_definition(definition),
|
||||
m_asset_enum_entry(nullptr),
|
||||
m_is_leaf(false),
|
||||
m_non_embedded_reference_exists(false),
|
||||
m_single_pointer_reference_exists(false),
|
||||
m_array_pointer_reference_exists(false),
|
||||
m_array_reference_exists(false),
|
||||
m_reference_from_non_default_normal_block_exists(false),
|
||||
m_post_load_action(nullptr),
|
||||
m_block(nullptr)
|
||||
{
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "MemberInformation.h"
|
||||
#include "Domain/Definition/DefinitionWithMembers.h"
|
||||
#include "Domain/Definition/EnumMember.h"
|
||||
#include "Domain/Extension/CustomAction.h"
|
||||
#include "Domain/FastFile/FastFileBlock.h"
|
||||
|
||||
class MemberInformation;
|
||||
class StructureInformation
|
||||
{
|
||||
public:
|
||||
bool m_has_non_default_fast_file_align;
|
||||
unsigned m_custom_fast_file_align;
|
||||
|
||||
DefinitionWithMembers* const m_definition;
|
||||
EnumMember* m_asset_enum_entry;
|
||||
|
||||
std::vector<StructureInformation*> m_usages;
|
||||
std::vector<std::unique_ptr<MemberInformation>> m_ordered_members;
|
||||
|
||||
bool m_is_leaf;
|
||||
|
||||
bool m_non_embedded_reference_exists;
|
||||
bool m_single_pointer_reference_exists;
|
||||
bool m_array_pointer_reference_exists;
|
||||
bool m_array_reference_exists;
|
||||
bool m_reference_from_non_default_normal_block_exists;
|
||||
|
||||
std::unique_ptr<CustomAction> m_post_load_action;
|
||||
FastFileBlock* m_block;
|
||||
std::vector<MemberInformation*> m_name_chain;
|
||||
|
||||
explicit StructureInformation(DefinitionWithMembers* definition);
|
||||
};
|
0
src/ZoneCodeGeneratorLib/Generating/CodeGenerator.h
Normal file
0
src/ZoneCodeGeneratorLib/Generating/CodeGenerator.h
Normal file
0
src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.cpp
Normal file
0
src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.cpp
Normal file
37
src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h
Normal file
37
src/ZoneCodeGeneratorLib/Parsing/AbstractLexer.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "IParserLineStream.h"
|
||||
|
||||
template <typename TokenType>
|
||||
class AbstractLexer : public ILexer
|
||||
{
|
||||
std::deque<TokenType> m_token_cache;
|
||||
IParserLineStream* const m_stream;
|
||||
|
||||
protected:
|
||||
explicit AbstractLexer(IParserLineStream* stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
virtual TokenType GetNextToken() = 0;
|
||||
|
||||
public:
|
||||
const TokenType& GetToken(int index)
|
||||
{
|
||||
assert(index >= 0);
|
||||
while (index <= m_token_cache.size())
|
||||
m_token_cache.emplace_back(std::move(GetNextToken()));
|
||||
|
||||
return m_token_cache[index];
|
||||
}
|
||||
|
||||
void PopTokens(int amount) override
|
||||
{
|
||||
m_token_cache.erase(m_token_cache.begin(), m_token_cache.begin() + amount);
|
||||
}
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
#include "CommandsFileReader.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
|
||||
: m_args(args),
|
||||
m_filename(std::move(filename))
|
||||
{
|
||||
}
|
||||
|
||||
bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository)
|
||||
{
|
||||
std::cout << "Reading commands file: " << m_filename << std::endl;
|
||||
return true;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ZoneCodeGeneratorArguments.h"
|
||||
#include "Persistence/IDataRepository.h"
|
||||
|
||||
class CommandsFileReader
|
||||
{
|
||||
const ZoneCodeGeneratorArguments* m_args;
|
||||
std::string m_filename;
|
||||
|
||||
public:
|
||||
explicit CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);
|
||||
|
||||
bool ReadCommandsFile(IDataRepository* repository);
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
#include "CommandsLexer.h"
|
||||
|
||||
CommandsLexer::CommandsLexer(IParserLineStream* stream)
|
||||
: AbstractLexer(stream)
|
||||
{
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsLexer::GetNextToken()
|
||||
{
|
||||
return CommandsParserValue::Invalid(TokenPos());
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "CommandsParserValue.h"
|
||||
#include "Parsing/AbstractLexer.h"
|
||||
|
||||
class CommandsLexer final : public AbstractLexer<CommandsParserValue>
|
||||
{
|
||||
protected:
|
||||
CommandsParserValue GetNextToken() override;
|
||||
|
||||
public:
|
||||
explicit CommandsLexer(IParserLineStream* stream);
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
class CommandsParser
|
||||
{
|
||||
|
||||
};
|
@ -0,0 +1,174 @@
|
||||
#include "CommandsParserValue.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
CommandsParserValue CommandsParserValue::Invalid(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::INVALID);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::EndOfFile(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::END_OF_FILE);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::Character(const TokenPos pos, const char c)
|
||||
{
|
||||
CommandsParserValue pv(pos, c);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::ShiftLeft(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::SHIFT_LEFT);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::ShiftRight(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::SHIFT_RIGHT);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::Equals(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::EQUALS);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::NotEqual(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::NOT_EQUAL);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::GreaterEqual(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::GREATER_EQUAL);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::LessEqual(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::LESS_EQUAL);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::LogicalAnd(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::LOGICAL_AND);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::LogicalOr(const TokenPos pos)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::LOGICAL_OR);
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::Integer(const TokenPos pos, const int value)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::INTEGER);
|
||||
pv.m_value.int_value = value;
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::FloatingPoint(const TokenPos pos, const double value)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::FLOATING_POINT);
|
||||
pv.m_value.double_value = value;
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::String(const TokenPos pos, std::string* stringValue)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::STRING);
|
||||
pv.m_value.string_value = stringValue;
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::Identifier(const TokenPos pos, std::string* identifier)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::IDENTIFIER);
|
||||
pv.m_value.string_value = identifier;
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue CommandsParserValue::TypeName(const TokenPos pos, std::string* typeName)
|
||||
{
|
||||
CommandsParserValue pv(pos, CommandsParserValueType::TYPE_NAME);
|
||||
pv.m_value.string_value = typeName;
|
||||
return pv;
|
||||
}
|
||||
|
||||
CommandsParserValue::CommandsParserValue(const TokenPos pos, const int type)
|
||||
: m_pos(pos),
|
||||
m_type(type),
|
||||
m_value()
|
||||
{
|
||||
}
|
||||
|
||||
CommandsParserValue::~CommandsParserValue()
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case CommandsParserValueType::STRING:
|
||||
case CommandsParserValueType::IDENTIFIER:
|
||||
case CommandsParserValueType::TYPE_NAME:
|
||||
delete m_value.string_value;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_value = ValueType();
|
||||
}
|
||||
|
||||
CommandsParserValue::CommandsParserValue(CommandsParserValue&& other) noexcept
|
||||
: m_type(other.m_type),
|
||||
m_value(other.m_value)
|
||||
{
|
||||
other.m_value = ValueType();
|
||||
}
|
||||
|
||||
CommandsParserValue& CommandsParserValue::operator=(CommandsParserValue&& other) noexcept
|
||||
{
|
||||
m_type = other.m_type;
|
||||
m_value = other.m_value;
|
||||
other.m_value = ValueType();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int CommandsParserValue::IntegerValue() const
|
||||
{
|
||||
assert(m_type == CommandsParserValueType::INTEGER);
|
||||
return m_value.int_value;
|
||||
}
|
||||
|
||||
double CommandsParserValue::FloatingPointValue() const
|
||||
{
|
||||
assert(m_type == CommandsParserValueType::FLOATING_POINT);
|
||||
return m_value.double_value;
|
||||
}
|
||||
|
||||
std::string& CommandsParserValue::StringValue() const
|
||||
{
|
||||
assert(m_type == CommandsParserValueType::STRING);
|
||||
return *m_value.string_value;
|
||||
}
|
||||
|
||||
std::string& CommandsParserValue::IdentifierValue() const
|
||||
{
|
||||
assert(m_type == CommandsParserValueType::IDENTIFIER);
|
||||
return *m_value.string_value;
|
||||
}
|
||||
|
||||
std::string& CommandsParserValue::TypeNameValue() const
|
||||
{
|
||||
assert(m_type == CommandsParserValueType::TYPE_NAME);
|
||||
return *m_value.string_value;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Parsing/TokenPos.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
class CommandsParserValueType
|
||||
{
|
||||
CommandsParserValueType() = default;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
FIRST = 0x100,
|
||||
|
||||
// Meta tokens
|
||||
INVALID = FIRST,
|
||||
END_OF_FILE,
|
||||
|
||||
// Symbol tokens
|
||||
SHIFT_LEFT,
|
||||
SHIFT_RIGHT,
|
||||
EQUALS,
|
||||
NOT_EQUAL,
|
||||
GREATER_EQUAL,
|
||||
LESS_EQUAL,
|
||||
LOGICAL_AND,
|
||||
LOGICAL_OR,
|
||||
|
||||
// Generic token types
|
||||
INTEGER,
|
||||
FLOATING_POINT,
|
||||
STRING,
|
||||
IDENTIFIER,
|
||||
|
||||
// Parser created
|
||||
TYPE_NAME,
|
||||
|
||||
// End
|
||||
MAX
|
||||
};
|
||||
};
|
||||
|
||||
class CommandsParserValue
|
||||
{
|
||||
public:
|
||||
TokenPos m_pos;
|
||||
int m_type;
|
||||
union ValueType
|
||||
{
|
||||
int int_value;
|
||||
double double_value;
|
||||
std::string* string_value;
|
||||
} m_value;
|
||||
|
||||
static CommandsParserValue Invalid(TokenPos pos);
|
||||
static CommandsParserValue EndOfFile(TokenPos pos);
|
||||
static CommandsParserValue Character(TokenPos pos, char c);
|
||||
static CommandsParserValue ShiftLeft(TokenPos pos);
|
||||
static CommandsParserValue ShiftRight(TokenPos pos);
|
||||
static CommandsParserValue Equals(TokenPos pos);
|
||||
static CommandsParserValue NotEqual(TokenPos pos);
|
||||
static CommandsParserValue GreaterEqual(TokenPos pos);
|
||||
static CommandsParserValue LessEqual(TokenPos pos);
|
||||
static CommandsParserValue LogicalAnd(TokenPos pos);
|
||||
static CommandsParserValue LogicalOr(TokenPos pos);
|
||||
static CommandsParserValue Integer(TokenPos pos, int value);
|
||||
static CommandsParserValue FloatingPoint(TokenPos pos, double value);
|
||||
static CommandsParserValue String(TokenPos pos, std::string* stringValue);
|
||||
static CommandsParserValue Identifier(TokenPos pos, std::string* identifier);
|
||||
static CommandsParserValue TypeName(TokenPos pos, std::string* typeName);
|
||||
|
||||
private:
|
||||
CommandsParserValue(TokenPos pos, int type);
|
||||
|
||||
public:
|
||||
~CommandsParserValue();
|
||||
CommandsParserValue(const CommandsParserValue& other) = delete;
|
||||
CommandsParserValue(CommandsParserValue&& other) noexcept;
|
||||
CommandsParserValue& operator=(const CommandsParserValue& other) = delete;
|
||||
CommandsParserValue& operator=(CommandsParserValue&& other) noexcept;
|
||||
|
||||
_NODISCARD int IntegerValue() const;
|
||||
_NODISCARD double FloatingPointValue() const;
|
||||
_NODISCARD std::string& StringValue() const;
|
||||
_NODISCARD std::string& IdentifierValue() const;
|
||||
_NODISCARD std::string& TypeNameValue() const;
|
||||
};
|
46
src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp
Normal file
46
src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "HeaderFileReader.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Parsing/Impl/CommentRemovingStreamProxy.h"
|
||||
#include "Parsing/Impl/IncludingStreamProxy.h"
|
||||
#include "Parsing/Impl/ParserFilesystemStream.h"
|
||||
|
||||
HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
|
||||
: m_args(args),
|
||||
m_filename(std::move(filename))
|
||||
{
|
||||
}
|
||||
|
||||
bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) const
|
||||
{
|
||||
std::cout << "Reading header file: " << m_filename << std::endl;
|
||||
|
||||
ParserFilesystemStream stream(m_filename);
|
||||
if(!stream.IsOpen())
|
||||
{
|
||||
std::cout << "Could not open header file" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
IParserLineStream* lineStream = &stream;
|
||||
|
||||
IncludingStreamProxy includeProxy(lineStream);
|
||||
lineStream = &includeProxy;
|
||||
|
||||
CommentRemovingStreamProxy commentProxy(lineStream);
|
||||
lineStream = &commentProxy;
|
||||
|
||||
|
||||
while(true)
|
||||
{
|
||||
auto line = lineStream->NextLine();
|
||||
|
||||
if (line.IsEof())
|
||||
break;
|
||||
|
||||
std::cout << "Line " << line.m_filename << ":" << line.m_line_number << ": " << line.m_line << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
17
src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h
Normal file
17
src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ZoneCodeGeneratorArguments.h"
|
||||
#include "Persistence/IDataRepository.h"
|
||||
|
||||
class HeaderFileReader
|
||||
{
|
||||
const ZoneCodeGeneratorArguments* m_args;
|
||||
std::string m_filename;
|
||||
|
||||
public:
|
||||
HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);
|
||||
|
||||
bool ReadHeaderFile(IDataRepository* repository) const;
|
||||
};
|
15
src/ZoneCodeGeneratorLib/Parsing/ILexer.h
Normal file
15
src/ZoneCodeGeneratorLib/Parsing/ILexer.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
class ILexer
|
||||
{
|
||||
public:
|
||||
|
||||
ILexer() = default;
|
||||
virtual ~ILexer() = default;
|
||||
ILexer(const ILexer& other) = default;
|
||||
ILexer(ILexer&& other) noexcept = default;
|
||||
ILexer& operator=(const ILexer& other) = default;
|
||||
ILexer& operator=(ILexer&& other) noexcept = default;
|
||||
|
||||
virtual void PopTokens(int amount) = 0;
|
||||
};
|
13
src/ZoneCodeGeneratorLib/Parsing/IParserLineStream.cpp
Normal file
13
src/ZoneCodeGeneratorLib/Parsing/IParserLineStream.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "IParserLineStream.h"
|
||||
|
||||
ParserLine::ParserLine(const std::string& filename, const int lineNumber, std::string line)
|
||||
: m_filename(filename),
|
||||
m_line_number(lineNumber),
|
||||
m_line(std::move(line))
|
||||
{
|
||||
}
|
||||
|
||||
bool ParserLine::IsEof() const
|
||||
{
|
||||
return m_line_number <= 0;
|
||||
}
|
34
src/ZoneCodeGeneratorLib/Parsing/IParserLineStream.h
Normal file
34
src/ZoneCodeGeneratorLib/Parsing/IParserLineStream.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
class ParserLine
|
||||
{
|
||||
public:
|
||||
const std::string& m_filename;
|
||||
const int m_line_number;
|
||||
std::string m_line;
|
||||
|
||||
ParserLine(const std::string& filename, int lineNumber, std::string line);
|
||||
|
||||
_NODISCARD bool IsEof() const;
|
||||
};
|
||||
|
||||
class IParserLineStream
|
||||
{
|
||||
public:
|
||||
IParserLineStream() = default;
|
||||
virtual ~IParserLineStream() = default;
|
||||
|
||||
IParserLineStream(const IParserLineStream& other) = default;
|
||||
IParserLineStream(IParserLineStream&& other) noexcept = default;
|
||||
IParserLineStream& operator=(const IParserLineStream& other) = default;
|
||||
IParserLineStream& operator=(IParserLineStream&& other) noexcept = default;
|
||||
|
||||
virtual ParserLine NextLine() = 0;
|
||||
virtual bool IncludeFile(const std::string& filename) = 0;
|
||||
_NODISCARD virtual bool IsOpen() const = 0;
|
||||
_NODISCARD virtual bool Eof() const = 0;
|
||||
};
|
@ -0,0 +1,74 @@
|
||||
#include "CommentRemovingStreamProxy.h"
|
||||
|
||||
CommentRemovingStreamProxy::CommentRemovingStreamProxy(IParserLineStream* stream)
|
||||
: m_stream(stream),
|
||||
m_inside_multi_line_comment(false),
|
||||
m_next_line_is_comment(false)
|
||||
{
|
||||
}
|
||||
|
||||
ParserLine CommentRemovingStreamProxy::NextLine()
|
||||
{
|
||||
auto line = m_stream->NextLine();
|
||||
|
||||
if (m_next_line_is_comment)
|
||||
{
|
||||
m_next_line_is_comment = !line.m_line.empty() && line.m_line[line.m_line.size() - 1] == '\\';
|
||||
return ParserLine(line.m_filename, line.m_line_number, std::string());
|
||||
}
|
||||
|
||||
unsigned multiLineCommentStart = 0;
|
||||
for (auto i = 0u; i < line.m_line.size(); i++)
|
||||
{
|
||||
const auto c = line.m_line[i];
|
||||
|
||||
if (m_inside_multi_line_comment)
|
||||
{
|
||||
if (c == '*' && i + 1 < line.m_line.size() && line.m_line[i + 1] == '/')
|
||||
{
|
||||
line.m_line.erase(multiLineCommentStart, i + 2 - multiLineCommentStart);
|
||||
multiLineCommentStart = 0;
|
||||
m_inside_multi_line_comment = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c == '/' && i + 1 < line.m_line.size())
|
||||
{
|
||||
const auto c1 = line.m_line[i + 1];
|
||||
|
||||
if (c1 == '*')
|
||||
{
|
||||
multiLineCommentStart = i;
|
||||
m_inside_multi_line_comment = true;
|
||||
}
|
||||
else if(c1 == '/')
|
||||
{
|
||||
m_next_line_is_comment = line.m_line[line.m_line.size() - 1] == '\\';
|
||||
line.m_line.erase(i);
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_inside_multi_line_comment)
|
||||
line.m_line.erase(multiLineCommentStart);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool CommentRemovingStreamProxy::IncludeFile(const std::string& filename)
|
||||
{
|
||||
return m_stream->IncludeFile(filename);
|
||||
}
|
||||
|
||||
bool CommentRemovingStreamProxy::IsOpen() const
|
||||
{
|
||||
return m_stream->IsOpen();
|
||||
}
|
||||
|
||||
bool CommentRemovingStreamProxy::Eof() const
|
||||
{
|
||||
return m_stream->Eof();
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class CommentRemovingStreamProxy final : public IParserLineStream
|
||||
{
|
||||
IParserLineStream* const m_stream;
|
||||
bool m_inside_multi_line_comment;
|
||||
bool m_next_line_is_comment;
|
||||
|
||||
public:
|
||||
explicit CommentRemovingStreamProxy(IParserLineStream* stream);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
125
src/ZoneCodeGeneratorLib/Parsing/Impl/IncludingStreamProxy.cpp
Normal file
125
src/ZoneCodeGeneratorLib/Parsing/Impl/IncludingStreamProxy.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include "IncludingStreamProxy.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "Parsing/ParsingException.h"
|
||||
|
||||
IncludingStreamProxy::IncludingStreamProxy(IParserLineStream* stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::FindIncludeDirective(const ParserLine& line, unsigned& includeDirectivePosition)
|
||||
{
|
||||
includeDirectivePosition = 0;
|
||||
for (; includeDirectivePosition < line.m_line.size() - INCLUDE_DIRECTIVE_MINIMUM_TOTAL_LENGTH; includeDirectivePosition++)
|
||||
{
|
||||
const auto c = line.m_line[includeDirectivePosition];
|
||||
|
||||
if (isspace(c))
|
||||
continue;
|
||||
|
||||
if (c != '#')
|
||||
return false;
|
||||
|
||||
if (line.m_line.compare(includeDirectivePosition + 1, INCLUDE_DIRECTIVE_LENGTH, INCLUDE_DIRECTIVE) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::ExtractIncludeFilename(const ParserLine& line, const unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition)
|
||||
{
|
||||
auto currentPos = includeDirectivePosition;
|
||||
bool isDoubleQuotes;
|
||||
if (line.m_line[currentPos] == '"')
|
||||
isDoubleQuotes = true;
|
||||
else if (line.m_line[currentPos] == '<')
|
||||
isDoubleQuotes = false;
|
||||
else
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
|
||||
filenameStartPosition = ++currentPos;
|
||||
filenameEndPosition = 0;
|
||||
|
||||
for (; currentPos < line.m_line.size(); currentPos++)
|
||||
{
|
||||
const auto c = line.m_line[currentPos];
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if (!isDoubleQuotes)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), "");
|
||||
filenameEndPosition = currentPos;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == '>')
|
||||
{
|
||||
if (isDoubleQuotes)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
filenameEndPosition = currentPos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::MatchIncludeDirective(const ParserLine& line) const
|
||||
{
|
||||
unsigned includeDirectivePos;
|
||||
|
||||
if (!FindIncludeDirective(line, includeDirectivePos))
|
||||
return false;
|
||||
|
||||
const auto currentPos = includeDirectivePos + INCLUDE_DIRECTIVE_LENGTH + 1;
|
||||
unsigned filenameStart, filenameEnd;
|
||||
|
||||
if(!ExtractIncludeFilename(line, currentPos, filenameStart, filenameEnd))
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), INCLUDE_QUOTES_ERROR);
|
||||
|
||||
if(filenameEnd <= filenameStart)
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), "No filename specified");
|
||||
|
||||
const auto filename = line.m_line.substr(filenameStart, filenameEnd - filenameStart);
|
||||
|
||||
if(!m_stream->IncludeFile(filename))
|
||||
{
|
||||
std::ostringstream errorStr;
|
||||
errorStr << "Could not include file \"" << filename << "\"";
|
||||
throw ParsingException(TokenPos(line.m_filename, line.m_line_number, currentPos), errorStr.str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ParserLine IncludingStreamProxy::NextLine()
|
||||
{
|
||||
auto line = m_stream->NextLine();
|
||||
|
||||
if (MatchIncludeDirective(line))
|
||||
return m_stream->NextLine();
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::IncludeFile(const std::string& filename)
|
||||
{
|
||||
return m_stream->IncludeFile(filename);
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::IsOpen() const
|
||||
{
|
||||
return m_stream->IsOpen();
|
||||
}
|
||||
|
||||
bool IncludingStreamProxy::Eof() const
|
||||
{
|
||||
return m_stream->Eof();
|
||||
}
|
25
src/ZoneCodeGeneratorLib/Parsing/Impl/IncludingStreamProxy.h
Normal file
25
src/ZoneCodeGeneratorLib/Parsing/Impl/IncludingStreamProxy.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class IncludingStreamProxy final : public IParserLineStream
|
||||
{
|
||||
static constexpr const char* INCLUDE_QUOTES_ERROR = "Invalid include directive. Expected \"\" or <>";
|
||||
static constexpr const char* INCLUDE_DIRECTIVE = "include ";
|
||||
static constexpr int INCLUDE_DIRECTIVE_LENGTH = std::char_traits<char>::length(INCLUDE_DIRECTIVE);
|
||||
static constexpr int INCLUDE_DIRECTIVE_MINIMUM_TOTAL_LENGTH = INCLUDE_DIRECTIVE_LENGTH + 1 + 2; // #=+1 ""=+2
|
||||
|
||||
IParserLineStream* const m_stream;
|
||||
|
||||
_NODISCARD static bool FindIncludeDirective(const ParserLine& line, unsigned& includeDirectivePosition);
|
||||
_NODISCARD static bool ExtractIncludeFilename(const ParserLine& line, unsigned includeDirectivePosition, unsigned& filenameStartPosition, unsigned& filenameEndPosition);
|
||||
_NODISCARD bool MatchIncludeDirective(const ParserLine& line) const;
|
||||
|
||||
public:
|
||||
explicit IncludingStreamProxy(IParserLineStream* stream);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
@ -0,0 +1,94 @@
|
||||
#include "ParserFilesystemStream.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const std::string ParserFilesystemStream::EMPTY_FILE_NAME;
|
||||
|
||||
ParserFilesystemStream::FileInfo::FileInfo(std::string filePath)
|
||||
: m_file_path(std::move(filePath)),
|
||||
m_stream(m_file_path),
|
||||
m_line_number(1)
|
||||
{
|
||||
}
|
||||
|
||||
ParserFilesystemStream::ParserFilesystemStream(std::string path)
|
||||
{
|
||||
m_files.emplace(FileInfo(std::move(path)));
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::IsOpen() const
|
||||
{
|
||||
return !m_files.empty()
|
||||
&& m_files.top().m_stream.is_open();
|
||||
}
|
||||
|
||||
ParserLine ParserFilesystemStream::NextLine()
|
||||
{
|
||||
std::ostringstream str;
|
||||
auto hasLength = false;
|
||||
|
||||
if (m_files.empty())
|
||||
return ParserLine(EMPTY_FILE_NAME, 0, std::string());
|
||||
|
||||
while(!m_files.empty())
|
||||
{
|
||||
auto& fileInfo = m_files.top();
|
||||
|
||||
auto c = fileInfo.m_stream.get();
|
||||
while (c != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\r':
|
||||
c = fileInfo.m_stream.get();
|
||||
if (c == '\n')
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str());
|
||||
str << '\r';
|
||||
hasLength = true;
|
||||
continue;
|
||||
|
||||
case '\n':
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number++, str.str());
|
||||
|
||||
default:
|
||||
str << static_cast<char>(c);
|
||||
hasLength = true;
|
||||
break;
|
||||
}
|
||||
|
||||
c = fileInfo.m_stream.get();
|
||||
}
|
||||
|
||||
if(hasLength)
|
||||
return ParserLine(fileInfo.m_file_path, fileInfo.m_line_number, str.str());
|
||||
m_files.pop();
|
||||
}
|
||||
|
||||
return ParserLine(EMPTY_FILE_NAME, 0, std::string());
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::IncludeFile(const std::string& filename)
|
||||
{
|
||||
if (m_files.empty())
|
||||
return false;
|
||||
|
||||
auto newFilePath = fs::path(m_files.top().m_file_path);
|
||||
newFilePath.remove_filename().concat(filename);
|
||||
|
||||
FileInfo fileInfo(newFilePath.string());
|
||||
|
||||
if (!fileInfo.m_stream.is_open())
|
||||
return false;
|
||||
|
||||
m_files.emplace(std::move(fileInfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserFilesystemStream::Eof() const
|
||||
{
|
||||
return m_files.empty()
|
||||
|| m_files.top().m_stream.eof();
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
#include <fstream>
|
||||
|
||||
#include "Parsing/IParserLineStream.h"
|
||||
|
||||
class ParserFilesystemStream final : public IParserLineStream
|
||||
{
|
||||
static const std::string EMPTY_FILE_NAME;
|
||||
|
||||
class FileInfo
|
||||
{
|
||||
public:
|
||||
std::string m_file_path;
|
||||
std::ifstream m_stream;
|
||||
int m_line_number;
|
||||
|
||||
explicit FileInfo(std::string filePath);
|
||||
};
|
||||
std::stack<FileInfo> m_files;
|
||||
|
||||
public:
|
||||
explicit ParserFilesystemStream(std::string path);
|
||||
|
||||
ParserLine NextLine() override;
|
||||
bool IncludeFile(const std::string& filename) override;
|
||||
_NODISCARD bool IsOpen() const override;
|
||||
_NODISCARD bool Eof() const override;
|
||||
};
|
32
src/ZoneCodeGeneratorLib/Parsing/ParsingException.cpp
Normal file
32
src/ZoneCodeGeneratorLib/Parsing/ParsingException.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "ParsingException.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
ParsingException::ParsingException(const TokenPos position, std::string message)
|
||||
: m_pos(position),
|
||||
m_message(std::move(message))
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << m_pos.m_line << ':' << m_pos.m_column << ' ' << m_message;
|
||||
m_full_message = str.str();
|
||||
}
|
||||
|
||||
TokenPos ParsingException::Position() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
const std::string& ParsingException::Message() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
std::string ParsingException::FullMessage() const
|
||||
{
|
||||
return m_full_message;
|
||||
}
|
||||
|
||||
char const* ParsingException::what() const
|
||||
{
|
||||
return m_full_message.c_str();
|
||||
}
|
22
src/ZoneCodeGeneratorLib/Parsing/ParsingException.h
Normal file
22
src/ZoneCodeGeneratorLib/Parsing/ParsingException.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include "TokenPos.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
class ParsingException final : std::exception
|
||||
{
|
||||
TokenPos m_pos;
|
||||
std::string m_message;
|
||||
std::string m_full_message;
|
||||
|
||||
public:
|
||||
ParsingException(TokenPos position, std::string message);
|
||||
|
||||
_NODISCARD TokenPos Position() const;
|
||||
_NODISCARD const std::string& Message() const;
|
||||
_NODISCARD std::string FullMessage() const;
|
||||
_NODISCARD char const* what() const override;
|
||||
};
|
17
src/ZoneCodeGeneratorLib/Parsing/TokenPos.cpp
Normal file
17
src/ZoneCodeGeneratorLib/Parsing/TokenPos.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "TokenPos.h"
|
||||
|
||||
const std::string TokenPos::EMPTY_FILENAME;
|
||||
|
||||
TokenPos::TokenPos()
|
||||
: m_filename(EMPTY_FILENAME),
|
||||
m_line(1),
|
||||
m_column(1)
|
||||
{
|
||||
}
|
||||
|
||||
TokenPos::TokenPos(const std::string& filename, const int line, const int column)
|
||||
: m_filename(filename),
|
||||
m_line(line),
|
||||
m_column(column)
|
||||
{
|
||||
}
|
16
src/ZoneCodeGeneratorLib/Parsing/TokenPos.h
Normal file
16
src/ZoneCodeGeneratorLib/Parsing/TokenPos.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class TokenPos
|
||||
{
|
||||
static const std::string EMPTY_FILENAME;
|
||||
|
||||
public:
|
||||
const std::string& m_filename;
|
||||
int m_line;
|
||||
int m_column;
|
||||
|
||||
TokenPos();
|
||||
TokenPos(const std::string& filename, int line, int column);
|
||||
};
|
39
src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h
Normal file
39
src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Domain/Definition/EnumDefinition.h"
|
||||
#include "Domain/Definition/StructDefinition.h"
|
||||
#include "Domain/Definition/TypedefDefinition.h"
|
||||
#include "Domain/Definition/UnionDefinition.h"
|
||||
#include "Domain/Information/StructureInformation.h"
|
||||
#include "Domain/FastFile/FastFileBlock.h"
|
||||
|
||||
class IDataRepository
|
||||
{
|
||||
public:
|
||||
IDataRepository() = default;
|
||||
virtual ~IDataRepository() = default;
|
||||
IDataRepository(const IDataRepository& other) = default;
|
||||
IDataRepository(IDataRepository&& other) noexcept = default;
|
||||
IDataRepository& operator=(const IDataRepository& other) = default;
|
||||
IDataRepository& operator=(IDataRepository&& other) noexcept = default;
|
||||
|
||||
virtual void Add(std::unique_ptr<EnumDefinition> enumsDefinition) = 0;
|
||||
virtual void Add(std::unique_ptr<StructDefinition> structDefinition) = 0;
|
||||
virtual void Add(std::unique_ptr<UnionDefinition> unionDefinition) = 0;
|
||||
virtual void Add(std::unique_ptr<TypedefDefinition> typedefDefinition) = 0;
|
||||
virtual void Add(std::unique_ptr<StructureInformation> structureInformation) = 0;
|
||||
virtual void Add(std::unique_ptr<FastFileBlock> fastFileBlock) = 0;
|
||||
|
||||
_NODISCARD virtual const std::vector<EnumDefinition*>& GetAllEnums() const = 0;
|
||||
_NODISCARD virtual const std::vector<StructDefinition*>& GetAllStructs() const = 0;
|
||||
_NODISCARD virtual const std::vector<UnionDefinition*>& GetAllUnions() const = 0;
|
||||
_NODISCARD virtual const std::vector<TypedefDefinition*>& GetAllTypedefs() const = 0;
|
||||
_NODISCARD virtual const std::vector<StructureInformation*>& GetAllStructureInformation() const = 0;
|
||||
_NODISCARD virtual const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const = 0;
|
||||
|
||||
_NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0;
|
||||
_NODISCARD virtual StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const = 0;
|
||||
};
|
@ -0,0 +1,91 @@
|
||||
#include "InMemoryRepository.h"
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<EnumDefinition> enumsDefinition)
|
||||
{
|
||||
auto* raw = enumsDefinition.release();
|
||||
m_enums.push_back(raw);
|
||||
m_data_definitions_by_name[raw->m_name] = raw;
|
||||
}
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<StructDefinition> structDefinition)
|
||||
{
|
||||
auto* raw = structDefinition.release();
|
||||
m_structs.push_back(raw);
|
||||
m_data_definitions_by_name[raw->m_name] = raw;
|
||||
}
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<UnionDefinition> unionDefinition)
|
||||
{
|
||||
auto* raw = unionDefinition.release();
|
||||
m_unions.push_back(raw);
|
||||
m_data_definitions_by_name[raw->m_name] = raw;
|
||||
}
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<TypedefDefinition> typedefDefinition)
|
||||
{
|
||||
auto* raw = typedefDefinition.release();
|
||||
m_typedefs.push_back(raw);
|
||||
m_data_definitions_by_name[raw->m_name] = raw;
|
||||
}
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<StructureInformation> structureInformation)
|
||||
{
|
||||
auto* raw = structureInformation.release();
|
||||
m_structures_information.push_back(raw);
|
||||
m_structure_information_by_definition[raw->m_definition] = raw;
|
||||
}
|
||||
|
||||
void InMemoryRepository::Add(std::unique_ptr<FastFileBlock> fastFileBlock)
|
||||
{
|
||||
m_fast_file_blocks.push_back(fastFileBlock.release());
|
||||
}
|
||||
|
||||
const std::vector<EnumDefinition*>& InMemoryRepository::GetAllEnums() const
|
||||
{
|
||||
return m_enums;
|
||||
}
|
||||
|
||||
const std::vector<StructDefinition*>& InMemoryRepository::GetAllStructs() const
|
||||
{
|
||||
return m_structs;
|
||||
}
|
||||
|
||||
const std::vector<UnionDefinition*>& InMemoryRepository::GetAllUnions() const
|
||||
{
|
||||
return m_unions;
|
||||
}
|
||||
|
||||
const std::vector<TypedefDefinition*>& InMemoryRepository::GetAllTypedefs() const
|
||||
{
|
||||
return m_typedefs;
|
||||
}
|
||||
|
||||
const std::vector<StructureInformation*>& InMemoryRepository::GetAllStructureInformation() const
|
||||
{
|
||||
return m_structures_information;
|
||||
}
|
||||
|
||||
const std::vector<FastFileBlock*>& InMemoryRepository::GetAllFastFileBlocks() const
|
||||
{
|
||||
return m_fast_file_blocks;
|
||||
}
|
||||
|
||||
DataDefinition* InMemoryRepository::GetDataDefinitionByName(const std::string& name) const
|
||||
{
|
||||
const auto foundEntry = m_data_definitions_by_name.find(name);
|
||||
|
||||
if (foundEntry != m_data_definitions_by_name.end())
|
||||
return foundEntry->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StructureInformation* InMemoryRepository::GetInformationFor(DefinitionWithMembers* definitionWithMembers) const
|
||||
{
|
||||
const auto foundEntry = m_structure_information_by_definition.find(definitionWithMembers);
|
||||
|
||||
if (foundEntry != m_structure_information_by_definition.end())
|
||||
return foundEntry->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Persistence/IDataRepository.h"
|
||||
|
||||
class InMemoryRepository final : public IDataRepository
|
||||
{
|
||||
std::vector<EnumDefinition*> m_enums;
|
||||
std::vector<StructDefinition*> m_structs;
|
||||
std::vector<UnionDefinition*> m_unions;
|
||||
std::vector<TypedefDefinition*> m_typedefs;
|
||||
std::vector<StructureInformation*> m_structures_information;
|
||||
std::vector<FastFileBlock*> m_fast_file_blocks;
|
||||
std::map<std::string, DataDefinition*> m_data_definitions_by_name;
|
||||
std::map<DefinitionWithMembers*, StructureInformation*> m_structure_information_by_definition;
|
||||
|
||||
public:
|
||||
void Add(std::unique_ptr<EnumDefinition> enumsDefinition) override;
|
||||
void Add(std::unique_ptr<StructDefinition> structDefinition) override;
|
||||
void Add(std::unique_ptr<UnionDefinition> unionDefinition) override;
|
||||
void Add(std::unique_ptr<TypedefDefinition> typedefDefinition) override;
|
||||
void Add(std::unique_ptr<StructureInformation> structureInformation) override;
|
||||
void Add(std::unique_ptr<FastFileBlock> fastFileBlock) override;
|
||||
|
||||
_NODISCARD const std::vector<EnumDefinition*>& GetAllEnums() const override;
|
||||
_NODISCARD const std::vector<StructDefinition*>& GetAllStructs() const override;
|
||||
_NODISCARD const std::vector<UnionDefinition*>& GetAllUnions() const override;
|
||||
_NODISCARD const std::vector<TypedefDefinition*>& GetAllTypedefs() const override;
|
||||
_NODISCARD const std::vector<StructureInformation*>& GetAllStructureInformation() const override;
|
||||
_NODISCARD const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const override;
|
||||
|
||||
_NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override;
|
||||
_NODISCARD StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const override;
|
||||
};
|
299
src/ZoneCodeGeneratorLib/Printing/PrettyPrinter.cpp
Normal file
299
src/ZoneCodeGeneratorLib/Printing/PrettyPrinter.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
#include "PrettyPrinter.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#include "Domain/Definition/ArrayDeclarationModifier.h"
|
||||
#include "Utils/NamespaceBuilder.h"
|
||||
|
||||
PrettyPrinter::PrettyPrinter(std::ostream& stream, const IDataRepository* repository)
|
||||
: m_stream(stream),
|
||||
m_repository(repository)
|
||||
{
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintSeparator() const
|
||||
{
|
||||
m_stream << std::endl
|
||||
<< "==========================================================================================================" << std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintVariablePointerToArray(Variable* variable) const
|
||||
{
|
||||
const auto& declarationModifiers = variable->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
std::vector<int> arraySize;
|
||||
auto pointerDepth = 0;
|
||||
auto modifierOffset = 0u;
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::POINTER)
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
arraySize.push_back(dynamic_cast<ArrayDeclarationModifier*>(modifier.get())->m_size);
|
||||
}
|
||||
|
||||
m_stream << " " << variable->m_type_declaration->m_type->GetFullName() << '(';
|
||||
for (auto p = 0; p < pointerDepth; p++)
|
||||
m_stream << '*';
|
||||
m_stream << variable->m_name << ")";
|
||||
for (auto size : arraySize)
|
||||
m_stream << '[' << size << ']';
|
||||
m_stream << std::endl;
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintVariableArrayOfPointers(Variable* variable) const
|
||||
{
|
||||
const auto& declarationModifiers = variable->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
std::vector<int> arraySize;
|
||||
auto pointerDepth = 0;
|
||||
auto modifierOffset = 0u;
|
||||
|
||||
for(; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
arraySize.push_back(dynamic_cast<ArrayDeclarationModifier*>(modifier.get())->m_size);
|
||||
}
|
||||
|
||||
for(; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::POINTER)
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
m_stream << " " << variable->m_type_declaration->m_type->GetFullName();
|
||||
for (auto p = 0; p < pointerDepth; p++)
|
||||
m_stream << '*';
|
||||
m_stream << " " << variable->m_name;
|
||||
for (auto size : arraySize)
|
||||
m_stream << '[' << size << ']';
|
||||
m_stream << std::endl;
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintVariable(Variable* variable) const
|
||||
{
|
||||
const auto& declarationModifiers = variable->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
{
|
||||
std::cout << " " << variable->m_type_declaration->m_type->GetFullName() << " " << variable->m_name << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (declarationModifiers[0]->GetType() == DeclarationModifierType::POINTER
|
||||
&& std::any_of(declarationModifiers.begin(), declarationModifiers.end(), [](const std::unique_ptr<DeclarationModifier>& modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::ARRAY;
|
||||
}))
|
||||
{
|
||||
PrintVariablePointerToArray(variable);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintVariableArrayOfPointers(variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintTypedefPointerToArray(TypedefDefinition* typedefDefinition) const
|
||||
{
|
||||
const auto& declarationModifiers = typedefDefinition->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
std::vector<int> arraySize;
|
||||
auto pointerDepth = 0;
|
||||
auto modifierOffset = 0u;
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::POINTER)
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
arraySize.push_back(dynamic_cast<ArrayDeclarationModifier*>(modifier.get())->m_size);
|
||||
}
|
||||
|
||||
m_stream << " " << typedefDefinition->m_type_declaration->m_type->GetFullName() << '(';
|
||||
for (auto p = 0; p < pointerDepth; p++)
|
||||
m_stream << '*';
|
||||
m_stream << typedefDefinition->m_name << ")";
|
||||
for (auto size : arraySize)
|
||||
m_stream << '[' << size << ']';
|
||||
m_stream << std::endl;
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintTypedefArrayOfPointers(TypedefDefinition* typedefDefinition) const
|
||||
{
|
||||
const auto& declarationModifiers = typedefDefinition->m_type_declaration->m_declaration_modifiers;
|
||||
|
||||
std::vector<int> arraySize;
|
||||
auto pointerDepth = 0;
|
||||
auto modifierOffset = 0u;
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::ARRAY)
|
||||
break;
|
||||
|
||||
arraySize.push_back(dynamic_cast<ArrayDeclarationModifier*>(modifier.get())->m_size);
|
||||
}
|
||||
|
||||
for (; modifierOffset < declarationModifiers.size(); modifierOffset++)
|
||||
{
|
||||
const auto& modifier = declarationModifiers[modifierOffset];
|
||||
if (modifier->GetType() != DeclarationModifierType::POINTER)
|
||||
break;
|
||||
|
||||
pointerDepth++;
|
||||
}
|
||||
|
||||
m_stream << " " << typedefDefinition->m_type_declaration->m_type->GetFullName();
|
||||
for (auto p = 0; p < pointerDepth; p++)
|
||||
m_stream << '*';
|
||||
m_stream << " " << typedefDefinition->m_name;
|
||||
for (auto size : arraySize)
|
||||
m_stream << '[' << size << ']';
|
||||
m_stream << std::endl;
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintEnums() const
|
||||
{
|
||||
const auto& allEnums = m_repository->GetAllEnums();
|
||||
m_stream << allEnums.size() << " enums:" << std::endl;
|
||||
|
||||
for (auto* enumDefinition : allEnums)
|
||||
{
|
||||
m_stream << " Name: " << enumDefinition->GetFullName() << std::endl;
|
||||
m_stream << " Alignment: " << enumDefinition->GetAlignment() << std::endl;
|
||||
m_stream << " Size: " << enumDefinition->GetSize() << std::endl;
|
||||
|
||||
for (const auto& enumMember : enumDefinition->m_members)
|
||||
{
|
||||
m_stream << " " << enumMember->m_name << " = " << enumMember->m_value << std::endl;
|
||||
}
|
||||
|
||||
m_stream << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintStructs() const
|
||||
{
|
||||
const auto& allStructs = m_repository->GetAllStructs();
|
||||
m_stream << allStructs.size() << " structs:" << std::endl;
|
||||
|
||||
for (auto* structDefinition : allStructs)
|
||||
{
|
||||
m_stream << " Name: " << structDefinition->GetFullName() << std::endl;
|
||||
m_stream << " Alignment: " << structDefinition->GetAlignment() << std::endl;
|
||||
m_stream << " Size: " << structDefinition->GetSize() << std::endl;
|
||||
|
||||
for (const auto& variable : structDefinition->m_members)
|
||||
{
|
||||
PrintVariable(variable.get());
|
||||
}
|
||||
|
||||
m_stream << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintUnions() const
|
||||
{
|
||||
const auto& allUnions = m_repository->GetAllUnions();
|
||||
m_stream << allUnions.size() << " unions:" << std::endl;
|
||||
|
||||
for (auto* unionDefinition : allUnions)
|
||||
{
|
||||
m_stream << " Name: " << unionDefinition->GetFullName() << std::endl;
|
||||
m_stream << " Alignment: " << unionDefinition->GetAlignment() << std::endl;
|
||||
m_stream << " Size: " << unionDefinition->GetSize() << std::endl;
|
||||
|
||||
for (const auto& variable : unionDefinition->m_members)
|
||||
{
|
||||
PrintVariable(variable.get());
|
||||
}
|
||||
|
||||
m_stream << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintTypedefs() const
|
||||
{
|
||||
const auto& allTypedefs = m_repository->GetAllTypedefs();
|
||||
m_stream << allTypedefs.size() << " typedefs:" << std::endl;
|
||||
|
||||
for (auto* typedefDefinition : allTypedefs)
|
||||
{
|
||||
m_stream << " Name: " << typedefDefinition->GetFullName() << std::endl;
|
||||
m_stream << " Alignment: " << typedefDefinition->GetAlignment() << std::endl;
|
||||
m_stream << " Size: " << typedefDefinition->GetSize() << std::endl;
|
||||
|
||||
const auto& declarationModifiers = typedefDefinition->m_type_declaration->m_declaration_modifiers;
|
||||
if (declarationModifiers.empty())
|
||||
{
|
||||
std::cout << " " << typedefDefinition->m_type_declaration->m_type->GetFullName() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (declarationModifiers[0]->GetType() == DeclarationModifierType::POINTER
|
||||
&& std::any_of(declarationModifiers.begin(), declarationModifiers.end(), [](const std::unique_ptr<DeclarationModifier>& modifier)
|
||||
{
|
||||
return modifier->GetType() == DeclarationModifierType::ARRAY;
|
||||
}))
|
||||
{
|
||||
PrintTypedefPointerToArray(typedefDefinition);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintTypedefArrayOfPointers(typedefDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
m_stream << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PrettyPrinter::PrintAll() const
|
||||
{
|
||||
PrintEnums();
|
||||
|
||||
PrintSeparator();
|
||||
|
||||
PrintStructs();
|
||||
|
||||
PrintSeparator();
|
||||
|
||||
PrintUnions();
|
||||
|
||||
PrintSeparator();
|
||||
|
||||
PrintTypedefs();
|
||||
}
|
28
src/ZoneCodeGeneratorLib/Printing/PrettyPrinter.h
Normal file
28
src/ZoneCodeGeneratorLib/Printing/PrettyPrinter.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "Persistence/IDataRepository.h"
|
||||
|
||||
class PrettyPrinter
|
||||
{
|
||||
std::ostream& m_stream;
|
||||
const IDataRepository* const m_repository;
|
||||
|
||||
void PrintSeparator() const;
|
||||
void PrintVariablePointerToArray(Variable* variable) const;
|
||||
void PrintVariableArrayOfPointers(Variable* variable) const;
|
||||
void PrintVariable(Variable* variable) const;
|
||||
void PrintTypedefPointerToArray(TypedefDefinition* typedefDefinition) const;
|
||||
void PrintTypedefArrayOfPointers(TypedefDefinition* typedefDefinition) const;
|
||||
|
||||
void PrintEnums() const;
|
||||
void PrintStructs() const;
|
||||
void PrintUnions() const;
|
||||
void PrintTypedefs() const;
|
||||
|
||||
public:
|
||||
PrettyPrinter(std::ostream& stream, const IDataRepository* repository);
|
||||
|
||||
void PrintAll() const;
|
||||
};
|
11
src/ZoneCodeGeneratorLib/Utils/AlignmentUtils.h
Normal file
11
src/ZoneCodeGeneratorLib/Utils/AlignmentUtils.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class AlignmentUtils
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
static T Align(T number, T alignmentValue)
|
||||
{
|
||||
return (number + (alignmentValue - 1)) / alignmentValue * alignmentValue;
|
||||
}
|
||||
};
|
39
src/ZoneCodeGeneratorLib/Utils/NamespaceBuilder.cpp
Normal file
39
src/ZoneCodeGeneratorLib/Utils/NamespaceBuilder.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include "NamespaceBuilder.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
std::string NamespaceBuilder::Combine(const std::string& _namespace, const std::string& name)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << _namespace << "::" << name;
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void NamespaceBuilder::Push(std::string element)
|
||||
{
|
||||
m_elements.emplace_back(std::move(element));
|
||||
}
|
||||
|
||||
void NamespaceBuilder::Pop()
|
||||
{
|
||||
m_elements.pop_back();
|
||||
}
|
||||
|
||||
std::string NamespaceBuilder::ToString()
|
||||
{
|
||||
std::ostringstream str;
|
||||
auto first = true;
|
||||
|
||||
for(const auto& element : m_elements)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
str << "::";
|
||||
|
||||
str << element;
|
||||
}
|
||||
|
||||
return str.str();
|
||||
}
|
16
src/ZoneCodeGeneratorLib/Utils/NamespaceBuilder.h
Normal file
16
src/ZoneCodeGeneratorLib/Utils/NamespaceBuilder.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class NamespaceBuilder
|
||||
{
|
||||
std::vector<std::string> m_elements;
|
||||
|
||||
public:
|
||||
static std::string Combine(const std::string& _namespace, const std::string& name);
|
||||
|
||||
void Push(std::string element);
|
||||
void Pop();
|
||||
std::string ToString();
|
||||
};
|
106
src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp
Normal file
106
src/ZoneCodeGeneratorLib/ZoneCodeGenerator.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "ZoneCodeGenerator.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "ZoneCodeGeneratorArguments.h"
|
||||
#include "Parsing/Commands/CommandsFileReader.h"
|
||||
#include "Parsing/Header/HeaderFileReader.h"
|
||||
#include "Persistence/IDataRepository.h"
|
||||
#include "Persistence/InMemory/InMemoryRepository.h"
|
||||
#include "Printing/PrettyPrinter.h"
|
||||
|
||||
class ZoneCodeGenerator::Impl
|
||||
{
|
||||
ZoneCodeGeneratorArguments m_args;
|
||||
std::unique_ptr<IDataRepository> m_repository;
|
||||
|
||||
bool ReadHeaderData()
|
||||
{
|
||||
for (const auto& headerFile : m_args.m_header_paths)
|
||||
{
|
||||
HeaderFileReader headerFileReader(&m_args, headerFile);
|
||||
|
||||
if (!headerFileReader.ReadHeaderFile(m_repository.get()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadCommandsData()
|
||||
{
|
||||
for (const auto& commandsFile : m_args.m_command_paths)
|
||||
{
|
||||
CommandsFileReader commandsFileReader(&m_args, commandsFile);
|
||||
|
||||
if (!commandsFileReader.ReadCommandsFile(m_repository.get()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintData() const
|
||||
{
|
||||
const PrettyPrinter prettyPrinter(std::cout, m_repository.get());
|
||||
prettyPrinter.PrintAll();
|
||||
}
|
||||
|
||||
bool GenerateCode()
|
||||
{
|
||||
for(const auto& generationTask : m_args.m_generation_tasks)
|
||||
{
|
||||
// TODO: Implement
|
||||
std::cout << "Generating code for asset \"" << generationTask.m_asset_name << "\" and preset \"" << generationTask.m_preset_name << "\" ..." << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
Impl()
|
||||
{
|
||||
m_repository = std::make_unique<InMemoryRepository>();
|
||||
}
|
||||
|
||||
int Run(const int argc, const char** argv)
|
||||
{
|
||||
if (!m_args.Parse(argc, argv))
|
||||
return 1;
|
||||
|
||||
if (!ReadHeaderData() || !ReadCommandsData())
|
||||
return 1;
|
||||
|
||||
if(m_args.ShouldPrint())
|
||||
{
|
||||
PrintData();
|
||||
}
|
||||
|
||||
if(m_args.ShouldGenerate())
|
||||
{
|
||||
if (!GenerateCode())
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
ZoneCodeGenerator::ZoneCodeGenerator()
|
||||
{
|
||||
m_impl = new Impl();
|
||||
}
|
||||
|
||||
ZoneCodeGenerator::~ZoneCodeGenerator()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
int ZoneCodeGenerator::Run(const int argc, const char** argv) const
|
||||
{
|
||||
return m_impl->Run(argc, argv);
|
||||
}
|
17
src/ZoneCodeGeneratorLib/ZoneCodeGenerator.h
Normal file
17
src/ZoneCodeGeneratorLib/ZoneCodeGenerator.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
class ZoneCodeGenerator
|
||||
{
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
|
||||
public:
|
||||
ZoneCodeGenerator();
|
||||
~ZoneCodeGenerator();
|
||||
ZoneCodeGenerator(const ZoneCodeGenerator& other) = delete;
|
||||
ZoneCodeGenerator(ZoneCodeGenerator&& other) noexcept = default;
|
||||
ZoneCodeGenerator& operator=(const ZoneCodeGenerator& other) = delete;
|
||||
ZoneCodeGenerator& operator=(ZoneCodeGenerator&& other) noexcept = default;
|
||||
|
||||
int Run(int argc, const char** argv) const;
|
||||
};
|
193
src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp
Normal file
193
src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
#include "ZoneCodeGeneratorArguments.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "Utils/Arguments/CommandLineOption.h"
|
||||
#include "Utils/Arguments/UsageInformation.h"
|
||||
|
||||
const CommandLineOption* const OPTION_HELP = CommandLineOption::Builder::Create()
|
||||
.WithShortName("?")
|
||||
.WithLongName("help")
|
||||
.WithDescription("Displays usage information.")
|
||||
.Build();
|
||||
|
||||
const CommandLineOption* const OPTION_VERBOSE = CommandLineOption::Builder::Create()
|
||||
.WithShortName("v")
|
||||
.WithLongName("verbose")
|
||||
.WithDescription("Outputs a lot more and more detailed messages.")
|
||||
.Build();
|
||||
|
||||
// ------
|
||||
// INPUT
|
||||
// ------
|
||||
|
||||
constexpr const char* CATEGORY_INPUT = "Input";
|
||||
|
||||
const CommandLineOption* const OPTION_HEADER = CommandLineOption::Builder::Create()
|
||||
.WithShortName("h")
|
||||
.WithLongName("header")
|
||||
.WithDescription("Reads from the specified header file.")
|
||||
.WithCategory(CATEGORY_INPUT)
|
||||
.WithParameter("headerFile")
|
||||
.Reusable()
|
||||
.Build();
|
||||
|
||||
const CommandLineOption* const OPTION_COMMANDS_FILE = CommandLineOption::Builder::Create()
|
||||
.WithShortName("c")
|
||||
.WithLongName("commands-file")
|
||||
.WithDescription("Specifies the commands file. Defaults to stdin.")
|
||||
.WithCategory(CATEGORY_INPUT)
|
||||
.WithParameter("commandFile")
|
||||
.Reusable()
|
||||
.Build();
|
||||
|
||||
// ------
|
||||
// OUTPUT
|
||||
// ------
|
||||
constexpr const char* CATEGORY_OUTPUT = "Output";
|
||||
|
||||
const CommandLineOption* const OPTION_OUTPUT_FOLDER = CommandLineOption::Builder::Create()
|
||||
.WithShortName("o")
|
||||
.WithLongName("output")
|
||||
.WithDescription("Specify the folder to save the generate code files to. Defaults to the current directory.")
|
||||
.WithCategory(CATEGORY_OUTPUT)
|
||||
.WithParameter("outputPath")
|
||||
.Build();
|
||||
|
||||
const CommandLineOption* const OPTION_PRINT = CommandLineOption::Builder::Create()
|
||||
.WithShortName("p")
|
||||
.WithLongName("print")
|
||||
.WithDescription("Print the loaded data.")
|
||||
.WithCategory(CATEGORY_OUTPUT)
|
||||
.Build();
|
||||
|
||||
const CommandLineOption* const OPTION_GENERATE = CommandLineOption::Builder::Create()
|
||||
.WithShortName("g")
|
||||
.WithLongName("generate")
|
||||
.WithDescription(
|
||||
"Generates a specified asset/preset combination. Can be used multiple times. Available presets: "
|
||||
"ZoneLoad, ZoneWrite, AssetStructTests")
|
||||
.WithCategory(CATEGORY_OUTPUT)
|
||||
.WithParameter("assetName")
|
||||
.WithParameter("preset")
|
||||
.Reusable()
|
||||
.Build();
|
||||
|
||||
const CommandLineOption* const COMMAND_LINE_OPTIONS[]
|
||||
{
|
||||
OPTION_HELP,
|
||||
OPTION_VERBOSE,
|
||||
OPTION_HEADER,
|
||||
OPTION_COMMANDS_FILE,
|
||||
OPTION_OUTPUT_FOLDER,
|
||||
OPTION_PRINT,
|
||||
OPTION_GENERATE
|
||||
};
|
||||
|
||||
ZoneCodeGeneratorArguments::GenerationTask::GenerationTask()
|
||||
= default;
|
||||
|
||||
ZoneCodeGeneratorArguments::GenerationTask::GenerationTask(std::string assetName, std::string presetName)
|
||||
: m_asset_name(std::move(assetName)),
|
||||
m_preset_name(std::move(presetName))
|
||||
{
|
||||
}
|
||||
|
||||
ZoneCodeGeneratorArguments::ZoneCodeGeneratorArguments()
|
||||
: m_argument_parser(COMMAND_LINE_OPTIONS, _countof(COMMAND_LINE_OPTIONS)),
|
||||
m_task_flags(0)
|
||||
{
|
||||
m_verbose = false;
|
||||
}
|
||||
|
||||
void ZoneCodeGeneratorArguments::PrintUsage()
|
||||
{
|
||||
UsageInformation usage("ZoneCodeGenerator.exe");
|
||||
|
||||
for (const auto* commandLineOption : COMMAND_LINE_OPTIONS)
|
||||
{
|
||||
usage.AddCommandLineOption(commandLineOption);
|
||||
}
|
||||
|
||||
usage.Print();
|
||||
}
|
||||
|
||||
bool ZoneCodeGeneratorArguments::Parse(const int argc, const char** argv)
|
||||
{
|
||||
if (!m_argument_parser.ParseArguments(argc - 1, &argv[1]))
|
||||
{
|
||||
PrintUsage();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the user requested help
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_HELP))
|
||||
{
|
||||
PrintUsage();
|
||||
return false;
|
||||
}
|
||||
|
||||
// -v; --verbose
|
||||
m_verbose = m_argument_parser.IsOptionSpecified(OPTION_VERBOSE);
|
||||
|
||||
// -p; --print
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_PRINT))
|
||||
m_task_flags |= FLAG_TASK_PRINT;
|
||||
|
||||
// -o; --output
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER))
|
||||
m_output_directory = m_argument_parser.GetValueForOption(OPTION_OUTPUT_FOLDER);
|
||||
else
|
||||
m_output_directory = ".";
|
||||
|
||||
// -h; --header
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_HEADER))
|
||||
{
|
||||
for (const auto& arg : m_argument_parser.GetParametersForOption(OPTION_HEADER))
|
||||
m_header_paths.push_back(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "At least one header file must be specified via -h / --header." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// -c; --commands-file
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_COMMANDS_FILE))
|
||||
{
|
||||
for (const auto& arg : m_argument_parser.GetParametersForOption(OPTION_COMMANDS_FILE))
|
||||
m_command_paths.push_back(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "At least one commands file must be specified via -c / --commands-file." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_argument_parser.IsOptionSpecified(OPTION_GENERATE))
|
||||
{
|
||||
m_task_flags |= FLAG_TASK_GENERATE;
|
||||
const auto generateParameterValues = m_argument_parser.GetParametersForOption(OPTION_GENERATE);
|
||||
for (auto i = 0u; i < generateParameterValues.size(); i += 2)
|
||||
m_generation_tasks.emplace_back(generateParameterValues[i], generateParameterValues[i + 1]);
|
||||
}
|
||||
|
||||
if (m_task_flags == 0)
|
||||
{
|
||||
std::cout << "There was no output task specified." << std::endl;
|
||||
PrintUsage();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ZoneCodeGeneratorArguments::ShouldGenerate() const
|
||||
{
|
||||
return m_task_flags & FLAG_TASK_GENERATE;
|
||||
}
|
||||
|
||||
bool ZoneCodeGeneratorArguments::ShouldPrint() const
|
||||
{
|
||||
return m_task_flags & FLAG_TASK_PRINT;
|
||||
}
|
46
src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.h
Normal file
46
src/ZoneCodeGeneratorLib/ZoneCodeGeneratorArguments.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Utils/Arguments/ArgumentParser.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ZoneCodeGeneratorArguments
|
||||
{
|
||||
ArgumentParser m_argument_parser;
|
||||
|
||||
/**
|
||||
* \brief Prints a command line usage help text for the Unlinker tool to stdout.
|
||||
*/
|
||||
static void PrintUsage();
|
||||
|
||||
public:
|
||||
static constexpr unsigned FLAG_TASK_GENERATE = 1 << 0;
|
||||
static constexpr unsigned FLAG_TASK_PRINT = 1 << 1;
|
||||
|
||||
class GenerationTask
|
||||
{
|
||||
public:
|
||||
std::string m_asset_name;
|
||||
std::string m_preset_name;
|
||||
|
||||
GenerationTask();
|
||||
GenerationTask(std::string assetName, std::string presetName);
|
||||
};
|
||||
|
||||
bool m_verbose;
|
||||
|
||||
std::vector<std::string> m_header_paths;
|
||||
std::vector<std::string> m_command_paths;
|
||||
std::string m_output_directory;
|
||||
|
||||
unsigned m_task_flags;
|
||||
std::vector<GenerationTask> m_generation_tasks;
|
||||
|
||||
ZoneCodeGeneratorArguments();
|
||||
|
||||
bool Parse(int argc, const char** argv);
|
||||
|
||||
_NODISCARD bool ShouldGenerate() const;
|
||||
_NODISCARD bool ShouldPrint() const;
|
||||
};
|
Reference in New Issue
Block a user