Calculate size and alignment in post processor

This commit is contained in:
Jan 2021-02-19 16:23:16 +01:00
parent 1264be4274
commit 7c51c26255
48 changed files with 966 additions and 246 deletions

View File

@ -1,5 +1,6 @@
// Game: Modern Warfare 2 (IW4) // Game: Modern Warfare 2 (IW4)
game IW4; game IW4;
architecture x86;
// Game Assets // Game Assets
asset PhysPreset ASSET_TYPE_PHYSPRESET; asset PhysPreset ASSET_TYPE_PHYSPRESET;

View File

@ -1,5 +1,6 @@
// Game: Black Ops 2 (T6) // Game: Black Ops 2 (T6)
game T6; game T6;
architecture x86;
// Game Assets // Game Assets
asset PhysPreset ASSET_TYPE_PHYSPRESET; asset PhysPreset ASSET_TYPE_PHYSPRESET;

View File

@ -36,27 +36,21 @@ DefinitionWithMembers::DefinitionWithMembers(std::string _namespace, std::string
unsigned DefinitionWithMembers::GetAlignment() const unsigned DefinitionWithMembers::GetAlignment() const
{ {
assert(m_flags & FLAG_ALIGNMENT_CALCULATED); assert(m_flags & FLAG_FIELDS_CALCULATED);
/*if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
CalculateAlignment();*/
return m_alignment; return m_alignment;
} }
bool DefinitionWithMembers::GetForceAlignment() const bool DefinitionWithMembers::GetForceAlignment() const
{ {
assert(m_flags & FLAG_ALIGNMENT_CALCULATED); assert(m_flags & FLAG_FIELDS_CALCULATED);
/*if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0)
CalculateAlignment();*/
return m_flags & FLAG_ALIGNMENT_FORCED; return m_flags & FLAG_ALIGNMENT_FORCED;
} }
unsigned DefinitionWithMembers::GetSize() const unsigned DefinitionWithMembers::GetSize() const
{ {
assert(m_flags & FLAG_SIZE_CALCULATED); assert(m_flags & FLAG_FIELDS_CALCULATED);
/*if ((m_flags & FLAG_SIZE_CALCULATED) == 0)
CalculateSize();*/
return m_size; return m_size;
} }

View File

@ -9,17 +9,14 @@
class DefinitionWithMembers : public DataDefinition class DefinitionWithMembers : public DataDefinition
{ {
public: public:
static constexpr int FLAG_SIZE_CALCULATED = 1 << 0; static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0;
static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1; static constexpr int FLAG_FIELDS_CALCULATING = 1 << 1;
static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2; static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2;
unsigned m_flags; unsigned m_flags;
unsigned m_size; unsigned m_size;
unsigned m_alignment; unsigned m_alignment;
/*virtual void CalculateSize() = 0;
void CalculateAlignment();*/
bool m_has_alignment_override; bool m_has_alignment_override;
bool m_anonymous; bool m_anonymous;

View File

@ -1,43 +1,5 @@
#include "StructDefinition.h" #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) StructDefinition::StructDefinition(std::string _namespace, std::string name, const int pack)
: DefinitionWithMembers(std::move(_namespace), std::move(name), pack) : DefinitionWithMembers(std::move(_namespace), std::move(name), pack)
{ {

View File

@ -4,9 +4,6 @@
class StructDefinition final : public DefinitionWithMembers class StructDefinition final : public DefinitionWithMembers
{ {
//protected:
// void CalculateSize() override;
public: public:
StructDefinition(std::string _namespace, std::string name, int pack); StructDefinition(std::string _namespace, std::string name, int pack);

View File

@ -16,75 +16,20 @@ TypeDeclaration::TypeDeclaration(const DataDefinition* type)
assert(m_type != nullptr); assert(m_type != nullptr);
} }
void TypeDeclaration::CalculateSize() unsigned TypeDeclaration::GetSize() const
{ {
auto currentSize = m_type->GetSize(); assert(m_flags & FLAG_FIELDS_CALCULATED);
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; return m_size;
} }
unsigned TypeDeclaration::GetAlignment() unsigned TypeDeclaration::GetAlignment() const
{ {
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) assert(m_flags & FLAG_FIELDS_CALCULATED);
CalculateAlignment();
return m_alignment; return m_alignment;
} }
bool TypeDeclaration::GetForceAlignment() bool TypeDeclaration::GetForceAlignment() const
{ {
if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) assert(m_flags & FLAG_FIELDS_CALCULATED);
CalculateAlignment();
return m_flags & FLAG_ALIGNMENT_FORCED; return m_flags & FLAG_ALIGNMENT_FORCED;
} }

View File

@ -1,26 +1,22 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <cstdint>
#include "Utils/ClassUtils.h"
#include "DataDefinition.h" #include "DataDefinition.h"
#include "DeclarationModifier.h" #include "DeclarationModifier.h"
class TypeDeclaration class TypeDeclaration
{ {
static constexpr unsigned POINTER_SIZE = sizeof(uint32_t); // TODO: Change this to support 64bit public:
static constexpr int FLAG_SIZE_CALCULATED = 1 << 0; static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0;
static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1; static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 1;
static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2;
unsigned m_flags; unsigned m_flags;
unsigned m_size; unsigned m_size;
unsigned m_alignment; unsigned m_alignment;
void CalculateSize();
void CalculateAlignment();
public:
explicit TypeDeclaration(const DataDefinition* type); explicit TypeDeclaration(const DataDefinition* type);
bool m_is_const; bool m_is_const;
@ -31,7 +27,7 @@ public:
std::vector<std::unique_ptr<DeclarationModifier>> m_declaration_modifiers; std::vector<std::unique_ptr<DeclarationModifier>> m_declaration_modifiers;
unsigned GetSize(); _NODISCARD unsigned GetSize() const;
unsigned GetAlignment(); _NODISCARD unsigned GetAlignment() const;
bool GetForceAlignment(); _NODISCARD bool GetForceAlignment() const;
}; };

View File

@ -1,23 +1,5 @@
#include "UnionDefinition.h" #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) UnionDefinition::UnionDefinition(std::string _namespace, std::string name, const int pack)
: DefinitionWithMembers(std::move(_namespace), std::move(name), pack) : DefinitionWithMembers(std::move(_namespace), std::move(name), pack)
{ {

View File

@ -8,7 +8,7 @@ Variable::Variable(std::string name, std::unique_ptr<TypeDeclaration> typeDeclar
{ {
} }
unsigned Variable::GetAlignment() unsigned Variable::GetAlignment() const
{ {
if (m_has_alignment_override) if (m_has_alignment_override)
return m_alignment_override; return m_alignment_override;
@ -16,7 +16,7 @@ unsigned Variable::GetAlignment()
return m_type_declaration->GetAlignment(); return m_type_declaration->GetAlignment();
} }
bool Variable::GetForceAlignment() bool Variable::GetForceAlignment() const
{ {
return m_has_alignment_override || m_type_declaration->GetForceAlignment(); return m_has_alignment_override || m_type_declaration->GetForceAlignment();
} }

View File

@ -15,6 +15,6 @@ public:
Variable(std::string name, std::unique_ptr<TypeDeclaration> typeDeclaration); Variable(std::string name, std::unique_ptr<TypeDeclaration> typeDeclaration);
unsigned GetAlignment(); unsigned GetAlignment() const;
bool GetForceAlignment(); bool GetForceAlignment() const;
}; };

View File

@ -0,0 +1,8 @@
#pragma once
enum class Architecture
{
UNKNOWN,
X86,
X64
};

View File

@ -7,6 +7,13 @@ OperandDynamic::OperandDynamic(StructureInformation* structure)
{ {
} }
OperandDynamic::OperandDynamic(StructureInformation* structure, std::vector<MemberInformation*> referencedMemberChain, std::vector<std::unique_ptr<IEvaluation>> arrayIndices)
: m_structure(structure),
m_referenced_member_chain(std::move(referencedMemberChain)),
m_array_indices(std::move(arrayIndices))
{
}
EvaluationType OperandDynamic::GetType() const EvaluationType OperandDynamic::GetType() const
{ {
return EvaluationType::OPERAND_DYNAMIC; return EvaluationType::OPERAND_DYNAMIC;

View File

@ -14,6 +14,7 @@ public:
std::vector<std::unique_ptr<IEvaluation>> m_array_indices; std::vector<std::unique_ptr<IEvaluation>> m_array_indices;
explicit OperandDynamic(StructureInformation* structure); explicit OperandDynamic(StructureInformation* structure);
OperandDynamic(StructureInformation* structure, std::vector<MemberInformation*> referencedMemberChain, std::vector<std::unique_ptr<IEvaluation>> arrayIndices);
_NODISCARD EvaluationType GetType() const override; _NODISCARD EvaluationType GetType() const override;
_NODISCARD bool IsStatic() const override; _NODISCARD bool IsStatic() const override;

View File

@ -6,8 +6,8 @@ OperandStatic::OperandStatic(const int value)
{ {
} }
OperandStatic::OperandStatic(const int value, EnumMember* enumMember) OperandStatic::OperandStatic(EnumMember* enumMember)
: m_value(value), : m_value(enumMember->m_value),
m_enum_member(enumMember) m_enum_member(enumMember)
{ {
} }

View File

@ -10,7 +10,7 @@ public:
EnumMember* const m_enum_member; EnumMember* const m_enum_member;
explicit OperandStatic(int value); explicit OperandStatic(int value);
OperandStatic(int value, EnumMember* enumMember); explicit OperandStatic(EnumMember* enumMember);
_NODISCARD EvaluationType GetType() const override; _NODISCARD EvaluationType GetType() const override;
_NODISCARD bool IsStatic() const override; _NODISCARD bool IsStatic() const override;

View File

@ -5,6 +5,13 @@ Operation::Operation(const OperationType* type)
{ {
} }
Operation::Operation(const OperationType* type, std::unique_ptr<IEvaluation> operand1, std::unique_ptr<IEvaluation> operand2)
: m_operation_type(type),
m_operand1(std::move(operand1)),
m_operand2(std::move(operand2))
{
}
EvaluationType Operation::GetType() const EvaluationType Operation::GetType() const
{ {
return EvaluationType::OPERATION; return EvaluationType::OPERATION;

View File

@ -14,6 +14,7 @@ public:
std::unique_ptr<IEvaluation> m_operand2; std::unique_ptr<IEvaluation> m_operand2;
explicit Operation(const OperationType* type); explicit Operation(const OperationType* type);
Operation(const OperationType* type, std::unique_ptr<IEvaluation> operand1, std::unique_ptr<IEvaluation> operand2);
_NODISCARD EvaluationType GetType() const override; _NODISCARD EvaluationType GetType() const override;
_NODISCARD bool IsStatic() const override; _NODISCARD bool IsStatic() const override;

View File

@ -73,7 +73,7 @@ const OperationType* const OperationType::OPERATION_GREATER_THAN
return op1 > op2 ? 1 : 0; return op1 > op2 ? 1 : 0;
}); });
const OperationType* const OperationType::OPERATION_GREATER_EQUALS_THAN const OperationType* const OperationType::OPERATION_GREATER_EQUAL_THAN
= new OperationType(">=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2) = new OperationType(">=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
{ {
return op1 >= op2 ? 1 : 0; return op1 >= op2 ? 1 : 0;
@ -85,7 +85,7 @@ const OperationType* const OperationType::OPERATION_LESS_THAN
return op1 < op2 ? 1 : 0; return op1 < op2 ? 1 : 0;
}); });
const OperationType* const OperationType::OPERATION_LESS_EQUALS_THAN const OperationType* const OperationType::OPERATION_LESS_EQUAL_THAN
= new OperationType("<=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2) = new OperationType("<=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2)
{ {
return op1 <= op2 ? 1 : 0; return op1 <= op2 ? 1 : 0;
@ -97,7 +97,7 @@ const OperationType* const OperationType::OPERATION_EQUALS
return op1 == op2 ? 1 : 0; return op1 == op2 ? 1 : 0;
}); });
const OperationType* const OperationType::OPERATION_NOT_EQUALS const OperationType* const OperationType::OPERATION_NOT_EQUAL
= new OperationType("!=", OperationPrecedence::RELATIONAL_EQUALS, [](auto op1, auto op2) = new OperationType("!=", OperationPrecedence::RELATIONAL_EQUALS, [](auto op1, auto op2)
{ {
return op1 != op2 ? 1 : 0; return op1 != op2 ? 1 : 0;
@ -129,11 +129,11 @@ const OperationType* const OperationType::ALL_OPERATION_TYPES[]
OPERATION_SHIFT_LEFT, OPERATION_SHIFT_LEFT,
OPERATION_SHIFT_RIGHT, OPERATION_SHIFT_RIGHT,
OPERATION_GREATER_THAN, OPERATION_GREATER_THAN,
OPERATION_GREATER_EQUALS_THAN, OPERATION_GREATER_EQUAL_THAN,
OPERATION_LESS_THAN, OPERATION_LESS_THAN,
OPERATION_LESS_EQUALS_THAN, OPERATION_LESS_EQUAL_THAN,
OPERATION_EQUALS, OPERATION_EQUALS,
OPERATION_NOT_EQUALS, OPERATION_NOT_EQUAL,
OPERATION_AND, OPERATION_AND,
OPERATION_OR OPERATION_OR
}; };

View File

@ -40,11 +40,11 @@ public:
static const OperationType* const OPERATION_SHIFT_LEFT; static const OperationType* const OPERATION_SHIFT_LEFT;
static const OperationType* const OPERATION_SHIFT_RIGHT; static const OperationType* const OPERATION_SHIFT_RIGHT;
static const OperationType* const OPERATION_GREATER_THAN; static const OperationType* const OPERATION_GREATER_THAN;
static const OperationType* const OPERATION_GREATER_EQUALS_THAN; static const OperationType* const OPERATION_GREATER_EQUAL_THAN;
static const OperationType* const OPERATION_LESS_THAN; static const OperationType* const OPERATION_LESS_THAN;
static const OperationType* const OPERATION_LESS_EQUALS_THAN; static const OperationType* const OPERATION_LESS_EQUAL_THAN;
static const OperationType* const OPERATION_EQUALS; static const OperationType* const OPERATION_EQUALS;
static const OperationType* const OPERATION_NOT_EQUALS; static const OperationType* const OPERATION_NOT_EQUAL;
static const OperationType* const OPERATION_AND; static const OperationType* const OPERATION_AND;
static const OperationType* const OPERATION_OR; static const OperationType* const OPERATION_OR;

View File

@ -1,5 +1,6 @@
#include "CommandsFileReader.h" #include "CommandsFileReader.h"
#include <algorithm>
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
@ -9,12 +10,14 @@
#include "Parsing/Impl/DefinesStreamProxy.h" #include "Parsing/Impl/DefinesStreamProxy.h"
#include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/IncludingStreamProxy.h"
#include "Parsing/Impl/ParserFilesystemStream.h" #include "Parsing/Impl/ParserFilesystemStream.h"
#include "Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h"
CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
: m_args(args), : m_args(args),
m_filename(std::move(filename)), m_filename(std::move(filename)),
m_stream(nullptr) m_stream(nullptr)
{ {
SetupPostProcessors();
} }
bool CommandsFileReader::OpenBaseStream() bool CommandsFileReader::OpenBaseStream()
@ -45,6 +48,11 @@ void CommandsFileReader::SetupStreamProxies()
m_open_streams.emplace_back(std::move(definesProxy)); m_open_streams.emplace_back(std::move(definesProxy));
} }
void CommandsFileReader::SetupPostProcessors()
{
m_post_processors.emplace_back(std::make_unique<CalculateSizeAndAlignPostProcessor>());
}
bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository) bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository)
{ {
std::cout << "Reading commands file: " << m_filename << std::endl; std::cout << "Reading commands file: " << m_filename << std::endl;
@ -62,5 +70,11 @@ bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository)
const auto end = std::chrono::steady_clock::now(); const auto end = std::chrono::steady_clock::now();
std::cout << "Processing commands took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl; std::cout << "Processing commands took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
return result; if (!result)
return false;
return std::all_of(m_post_processors.begin(), m_post_processors.end(), [repository](const std::unique_ptr<IPostProcessor>& postProcessor)
{
return postProcessor->PostProcess(repository);
});
} }

View File

@ -4,6 +4,7 @@
#include "ZoneCodeGeneratorArguments.h" #include "ZoneCodeGeneratorArguments.h"
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
#include "Parsing/PostProcessing/IPostProcessor.h"
#include "Persistence/IDataRepository.h" #include "Persistence/IDataRepository.h"
class CommandsFileReader class CommandsFileReader
@ -17,8 +18,11 @@ class CommandsFileReader
std::vector<std::unique_ptr<IParserLineStream>> m_open_streams; std::vector<std::unique_ptr<IParserLineStream>> m_open_streams;
IParserLineStream* m_stream; IParserLineStream* m_stream;
std::vector<std::unique_ptr<IPostProcessor>> m_post_processors;
bool OpenBaseStream(); bool OpenBaseStream();
void SetupStreamProxies(); void SetupStreamProxies();
void SetupPostProcessors();
public: public:
explicit CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename); explicit CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);

View File

@ -1,6 +1,7 @@
#include "CommandsParser.h" #include "CommandsParser.h"
#include "Parsing/Commands/Sequence/SequenceAction.h" #include "Parsing/Commands/Sequence/SequenceAction.h"
#include "Parsing/Commands/Sequence/SequenceArchitecture.h"
#include "Parsing/Commands/Sequence/SequenceArrayCount.h" #include "Parsing/Commands/Sequence/SequenceArrayCount.h"
#include "Parsing/Commands/Sequence/SequenceArraySize.h" #include "Parsing/Commands/Sequence/SequenceArraySize.h"
#include "Parsing/Commands/Sequence/SequenceAsset.h" #include "Parsing/Commands/Sequence/SequenceAsset.h"
@ -26,6 +27,7 @@ const std::vector<CommandsParser::sequence_t*>& CommandsParser::GetTestsForState
{ {
static std::vector<sequence_t*> tests({ static std::vector<sequence_t*> tests({
new SequenceAction(), new SequenceAction(),
new SequenceArchitecture(),
new SequenceArrayCount(), new SequenceArrayCount(),
new SequenceArraySize(), new SequenceArraySize(),
new SequenceAsset(), new SequenceAsset(),

View File

@ -16,6 +16,11 @@ void CommandsParserState::AddBlock(std::unique_ptr<FastFileBlock> block) const
m_repository->Add(std::move(block)); m_repository->Add(std::move(block));
} }
void CommandsParserState::SetArchitecture(const Architecture architecture) const
{
m_repository->SetArchitecture(architecture);
}
void CommandsParserState::SetGame(std::string gameName) const void CommandsParserState::SetGame(std::string gameName) const
{ {
m_repository->SetGame(std::move(gameName)); m_repository->SetGame(std::move(gameName));
@ -31,12 +36,105 @@ void CommandsParserState::SetInUse(StructureInformation* structure)
m_in_use = structure; m_in_use = structure;
} }
bool CommandsParserState::GetMembersFromParts(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members) MemberInformation* CommandsParserState::GetMemberWithName(const std::string& memberName, StructureInformation* type)
{ {
for (const auto& member : type->m_ordered_members)
{
if (member->m_member->m_name == memberName)
{
return member.get();
}
}
return nullptr;
}
bool CommandsParserState::GetNextTypenameSeparatorPos(const std::string& typeNameValue, const unsigned startPos, unsigned& separatorPos)
{
const auto typeNameValueSize = typeNameValue.size();
for (auto currentHead = startPos + 1; currentHead < typeNameValueSize; currentHead++)
{
if (typeNameValue[currentHead] == ':'
&& typeNameValue[currentHead - 1] == ':')
{
separatorPos = currentHead - 1;
return true;
}
}
return false; return false;
} }
bool CommandsParserState::GetTypenameAndMembersFromParts(const std::string& typeNameValue, StructureInformation*& structure, std::vector<MemberInformation*>& members) bool CommandsParserState::ExtractMembersFromTypenameInternal(const std::string& typeNameValue, unsigned typeNameOffset, StructureInformation* type, std::vector<MemberInformation*>& members)
{ {
return false; auto startOffset = typeNameOffset;
while (GetNextTypenameSeparatorPos(typeNameValue, typeNameOffset, typeNameOffset))
{
auto* foundMember = GetMemberWithName(std::string(typeNameValue, startOffset, typeNameOffset - startOffset), type);
if (foundMember == nullptr)
return false;
members.push_back(foundMember);
type = foundMember->m_type;
typeNameOffset += 2;
startOffset = typeNameOffset;
}
auto* foundMember = GetMemberWithName(std::string(typeNameValue, startOffset, typeNameValue.size() - startOffset), type);
if (foundMember == nullptr)
return false;
members.push_back(foundMember);
return true;
}
bool CommandsParserState::GetMembersFromTypename(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members) const
{
return m_in_use != nullptr && ExtractMembersFromTypenameInternal(typeNameValue, 0, m_in_use, members)
|| ExtractMembersFromTypenameInternal(typeNameValue, 0, baseType, members);
}
bool CommandsParserState::GetTypenameAndMembersFromTypename(const std::string& typeNameValue, StructureInformation*& structure, std::vector<MemberInformation*>& members) const
{
if (m_in_use != nullptr)
{
if (ExtractMembersFromTypenameInternal(typeNameValue, 0, m_in_use, members))
{
structure = m_in_use;
return true;
}
members.clear();
}
DataDefinition* foundDefinition = nullptr;
unsigned currentSeparatorPos = 0;
while (GetNextTypenameSeparatorPos(typeNameValue, currentSeparatorPos, currentSeparatorPos))
{
std::string currentTypename(typeNameValue, 0, currentSeparatorPos);
currentSeparatorPos += 2;
foundDefinition = m_repository->GetDataDefinitionByName(currentTypename);
if (foundDefinition != nullptr)
break;
}
if (foundDefinition == nullptr)
{
currentSeparatorPos = typeNameValue.size();
foundDefinition = m_repository->GetDataDefinitionByName(typeNameValue);
}
if (foundDefinition == nullptr)
return false;
auto* definitionWithMembers = dynamic_cast<DefinitionWithMembers*>(foundDefinition);
if (definitionWithMembers == nullptr)
return false;
structure = m_repository->GetInformationFor(definitionWithMembers);
if (currentSeparatorPos >= typeNameValue.size())
return true;
return ExtractMembersFromTypenameInternal(typeNameValue, currentSeparatorPos, structure, members);
} }

View File

@ -11,17 +11,22 @@ class CommandsParserState
IDataRepository* m_repository; IDataRepository* m_repository;
StructureInformation* m_in_use; StructureInformation* m_in_use;
static MemberInformation* GetMemberWithName(const std::string& memberName, StructureInformation* type);
static bool GetNextTypenameSeparatorPos(const std::string& typeNameValue, unsigned startPos, unsigned& separatorPos);
static bool ExtractMembersFromTypenameInternal(const std::string& typeNameValue, unsigned typeNameOffset, StructureInformation* type, std::vector<MemberInformation*>& members);
public: public:
explicit CommandsParserState(IDataRepository* repository); explicit CommandsParserState(IDataRepository* repository);
_NODISCARD const IDataRepository* GetRepository() const; _NODISCARD const IDataRepository* GetRepository() const;
void AddBlock(std::unique_ptr<FastFileBlock> block) const; void AddBlock(std::unique_ptr<FastFileBlock> block) const;
void SetArchitecture(Architecture architecture) const;
void SetGame(std::string gameName) const; void SetGame(std::string gameName) const;
_NODISCARD StructureInformation* GetInUse() const; _NODISCARD StructureInformation* GetInUse() const;
void SetInUse(StructureInformation* structure); void SetInUse(StructureInformation* structure);
bool GetMembersFromParts(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members); bool GetMembersFromTypename(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members) const;
bool GetTypenameAndMembersFromParts(const std::string& typeNameValue, StructureInformation*& structure, std::vector<MemberInformation*>& members); bool GetTypenameAndMembersFromTypename(const std::string& typeNameValue, StructureInformation*& structure, std::vector<MemberInformation*>& members) const;
}; };

View File

@ -105,6 +105,13 @@ CommandsParserValue CommandsParserValue::TypeName(const TokenPos pos, std::strin
return pv; return pv;
} }
CommandsParserValue CommandsParserValue::OpType(const TokenPos pos, const OperationType* operationType)
{
CommandsParserValue pv(pos, CommandsParserValueType::OPERATION_TYPE);
pv.m_value.op_type_value = operationType;
return pv;
}
CommandsParserValue::CommandsParserValue(const TokenPos pos, const CommandsParserValueType type) CommandsParserValue::CommandsParserValue(const TokenPos pos, const CommandsParserValueType type)
: m_pos(pos), : m_pos(pos),
m_type(type), m_type(type),
@ -201,3 +208,9 @@ std::string& CommandsParserValue::TypeNameValue() const
assert(m_type == CommandsParserValueType::TYPE_NAME); assert(m_type == CommandsParserValueType::TYPE_NAME);
return *m_value.string_value; return *m_value.string_value;
} }
const OperationType* CommandsParserValue::OpTypeValue() const
{
assert(m_type == CommandsParserValueType::OPERATION_TYPE);
return m_value.op_type_value;
}

View File

@ -3,6 +3,8 @@
#include <string> #include <string>
#include "Domain/Evaluation/OperationType.h"
#include "Parsing/IParserValue.h" #include "Parsing/IParserValue.h"
#include "Utils/ClassUtils.h" #include "Utils/ClassUtils.h"
#include "Parsing/TokenPos.h" #include "Parsing/TokenPos.h"
@ -43,6 +45,7 @@ enum class CommandsParserValueType
// Parser created // Parser created
TYPE_NAME, TYPE_NAME,
OPERATION_TYPE,
// End // End
MAX MAX
@ -60,6 +63,7 @@ public:
int int_value; int int_value;
double double_value; double double_value;
std::string* string_value; std::string* string_value;
const OperationType* op_type_value;
} m_value; } m_value;
static CommandsParserValue Invalid(TokenPos pos); static CommandsParserValue Invalid(TokenPos pos);
@ -78,6 +82,7 @@ public:
static CommandsParserValue String(TokenPos pos, std::string* stringValue); static CommandsParserValue String(TokenPos pos, std::string* stringValue);
static CommandsParserValue Identifier(TokenPos pos, std::string* identifier); static CommandsParserValue Identifier(TokenPos pos, std::string* identifier);
static CommandsParserValue TypeName(TokenPos pos, std::string* typeName); static CommandsParserValue TypeName(TokenPos pos, std::string* typeName);
static CommandsParserValue OpType(TokenPos pos, const OperationType* operationType);
private: private:
CommandsParserValue(TokenPos pos, CommandsParserValueType type); CommandsParserValue(TokenPos pos, CommandsParserValueType type);
@ -99,4 +104,5 @@ public:
_NODISCARD std::string& IdentifierValue() const; _NODISCARD std::string& IdentifierValue() const;
_NODISCARD size_t IdentifierHash() const; _NODISCARD size_t IdentifierHash() const;
_NODISCARD std::string& TypeNameValue() const; _NODISCARD std::string& TypeNameValue() const;
_NODISCARD const OperationType* OpTypeValue() const;
}; };

View File

@ -1,8 +1,13 @@
#include "CommandsCommonMatchers.h" #include "CommandsCommonMatchers.h"
#include <list>
#include <sstream> #include <sstream>
#include <vector>
#include "CommandsMatcherFactory.h" #include "CommandsMatcherFactory.h"
#include "Domain/Evaluation/OperandDynamic.h"
#include "Domain/Evaluation/OperandStatic.h"
#include "Domain/Evaluation/Operation.h"
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Typename(const supplier_t* labelSupplier) std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Typename(const supplier_t* labelSupplier)
{ {
@ -86,43 +91,23 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Array
}); });
} }
static constexpr int TAG_OPERATION_TYPE = std::numeric_limits<int>::max() - 1; static constexpr int TAG_OPERAND = std::numeric_limits<int>::max() - 1;
static constexpr int TAG_ADD = std::numeric_limits<int>::max() - 2; static constexpr int TAG_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 2;
static constexpr int TAG_MINUS = std::numeric_limits<int>::max() - 3; static constexpr int TAG_OPERAND_ARRAY = std::numeric_limits<int>::max() - 3;
static constexpr int TAG_MULTIPLY = std::numeric_limits<int>::max() - 4; static constexpr int TAG_OPERAND_ARRAY_END = std::numeric_limits<int>::max() - 4;
static constexpr int TAG_DIVIDE = std::numeric_limits<int>::max() - 5; static constexpr int TAG_OPERAND_INTEGER = std::numeric_limits<int>::max() - 5;
static constexpr int TAG_REMAINDER = std::numeric_limits<int>::max() - 6; static constexpr int TAG_EVALUATION_NOT = std::numeric_limits<int>::max() - 6;
static constexpr int TAG_BITWISE_AND = std::numeric_limits<int>::max() - 7; static constexpr int TAG_EVALUATION_PARENTHESIS = std::numeric_limits<int>::max() - 7;
static constexpr int TAG_BITWISE_XOR = std::numeric_limits<int>::max() - 8; static constexpr int TAG_EVALUATION_PARENTHESIS_END = std::numeric_limits<int>::max() - 8;
static constexpr int TAG_BITWISE_OR = std::numeric_limits<int>::max() - 9; static constexpr int TAG_EVALUATION = std::numeric_limits<int>::max() - 9;
static constexpr int TAG_SHIFT_LEFT = std::numeric_limits<int>::max() - 10; static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits<int>::max() - 10;
static constexpr int TAG_SHIFT_RIGHT = std::numeric_limits<int>::max() - 11;
static constexpr int TAG_GREATER_THAN = std::numeric_limits<int>::max() - 12;
static constexpr int TAG_GREATER_EQUAL = std::numeric_limits<int>::max() - 13;
static constexpr int TAG_LESS_THAN = std::numeric_limits<int>::max() - 14;
static constexpr int TAG_LESS_EQUAL = std::numeric_limits<int>::max() - 15;
static constexpr int TAG_EQUALS = std::numeric_limits<int>::max() - 16;
static constexpr int TAG_NOT_EQUAL = std::numeric_limits<int>::max() - 17;
static constexpr int TAG_LOGICAL_AND = std::numeric_limits<int>::max() - 18;
static constexpr int TAG_LOGICAL_OR = std::numeric_limits<int>::max() - 19;
static constexpr int TAG_OPERAND = std::numeric_limits<int>::max() - 20;
static constexpr int TAG_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 21;
static constexpr int TAG_OPERAND_ARRAY = std::numeric_limits<int>::max() - 22;
static constexpr int TAG_OPERAND_ARRAY_END = std::numeric_limits<int>::max() - 23;
static constexpr int TAG_OPERAND_INTEGER = std::numeric_limits<int>::max() - 24;
static constexpr int TAG_OPERAND_FLOATING_POINT = std::numeric_limits<int>::max() - 25;
static constexpr int TAG_EVALUATION_NOT = std::numeric_limits<int>::max() - 26;
static constexpr int TAG_EVALUATION_PARENTHESIS = std::numeric_limits<int>::max() - 27;
static constexpr int TAG_EVALUATION_PARENTHESIS_END = std::numeric_limits<int>::max() - 28;
static constexpr int TAG_EVALUATION = std::numeric_limits<int>::max() - 29;
static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits<int>::max() - 30;
static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 1; static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 1;
static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 1; static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits<int>::max() - 1;
static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 2; static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits<int>::max() - 2;
static constexpr int CAPTURE_OPERAND_FLOATING_POINT = std::numeric_limits<int>::max() - 3; static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits<int>::max() - 3;
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::OperandArray(const supplier_t* labelSupplier) std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier)
{ {
const CommandsMatcherFactory create(labelSupplier); const CommandsMatcherFactory create(labelSupplier);
@ -133,44 +118,97 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Opera
}).Tag(TAG_OPERAND_ARRAY); }).Tag(TAG_OPERAND_ARRAY);
} }
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Operand(const supplier_t* labelSupplier) std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperand(const supplier_t* labelSupplier)
{ {
const CommandsMatcherFactory create(labelSupplier); const CommandsMatcherFactory create(labelSupplier);
return create.Or({ return create.Or({
create.And({ create.And({
create.Label(LABEL_TYPENAME).Capture(CAPTURE_OPERAND_TYPENAME), create.Label(LABEL_TYPENAME).Capture(CAPTURE_OPERAND_TYPENAME),
create.OptionalLoop(MatcherFactoryWrapper<CommandsParserValue>(OperandArray(labelSupplier)).Capture(CAPTURE_OPERAND_ARRAY)) create.OptionalLoop(MatcherFactoryWrapper<CommandsParserValue>(ParseOperandArray(labelSupplier)).Capture(CAPTURE_OPERAND_ARRAY))
}).Tag(TAG_OPERAND_TYPENAME), }).Tag(TAG_OPERAND_TYPENAME),
create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER), create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER)
create.FloatingPoint().Tag(TAG_OPERAND_FLOATING_POINT).Capture(CAPTURE_OPERAND_FLOATING_POINT)
}).Tag(TAG_OPERAND); }).Tag(TAG_OPERAND);
} }
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::OperationType(const supplier_t* labelSupplier) std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::ParseOperationType(const supplier_t* labelSupplier)
{ {
const CommandsMatcherFactory create(labelSupplier); const CommandsMatcherFactory create(labelSupplier);
return create.Or({ return create.Or({
create.Char('+').Tag(TAG_ADD), create.Char('+').Transform([](CommandsMatcherFactory::token_list_t& values)
create.Char('-').Tag(TAG_MINUS), {
create.Char('*').Tag(TAG_MULTIPLY), return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_ADD);
create.Char('/').Tag(TAG_DIVIDE), }),
create.Char('%').Tag(TAG_REMAINDER), create.Char('-').Transform([](CommandsMatcherFactory::token_list_t& values)
create.Char('&').Tag(TAG_BITWISE_AND), {
create.Char('^').Tag(TAG_BITWISE_XOR), return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SUBTRACT);
create.Char('|').Tag(TAG_BITWISE_OR), }),
create.Type(CommandsParserValueType::SHIFT_LEFT).Tag(TAG_SHIFT_LEFT), create.Char('*').Transform([](CommandsMatcherFactory::token_list_t& values)
create.Type(CommandsParserValueType::SHIFT_RIGHT).Tag(TAG_SHIFT_RIGHT), {
create.Char('>').Tag(TAG_GREATER_THAN), return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_MULTIPLY);
create.Type(CommandsParserValueType::GREATER_EQUAL).Tag(TAG_GREATER_EQUAL), }),
create.Char('<').Tag(TAG_LESS_THAN), create.Char('/').Transform([](CommandsMatcherFactory::token_list_t& values)
create.Type(CommandsParserValueType::LESS_EQUAL).Tag(TAG_LESS_EQUAL), {
create.Type(CommandsParserValueType::EQUALS).Tag(TAG_EQUALS), return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_DIVIDE);
create.Type(CommandsParserValueType::NOT_EQUAL).Tag(TAG_NOT_EQUAL), }),
create.Type(CommandsParserValueType::LOGICAL_AND).Tag(TAG_LOGICAL_AND), create.Char('%').Transform([](CommandsMatcherFactory::token_list_t& values)
create.Type(CommandsParserValueType::LOGICAL_OR).Tag(TAG_LOGICAL_OR) {
}).Tag(TAG_OPERATION_TYPE); return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_REMAINDER);
}),
create.Char('&').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_AND);
}),
create.Char('^').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_XOR);
}),
create.Char('|').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_OR);
}),
create.Type(CommandsParserValueType::SHIFT_LEFT).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SHIFT_LEFT);
}),
create.Type(CommandsParserValueType::SHIFT_RIGHT).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SHIFT_RIGHT);
}),
create.Char('>').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_GREATER_THAN);
}),
create.Type(CommandsParserValueType::GREATER_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_GREATER_EQUAL_THAN);
}),
create.Char('<').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_LESS_THAN);
}),
create.Type(CommandsParserValueType::LESS_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_LESS_EQUAL_THAN);
}),
create.Type(CommandsParserValueType::EQUALS).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_EQUALS);
}),
create.Type(CommandsParserValueType::NOT_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_NOT_EQUAL);
}),
create.Type(CommandsParserValueType::LOGICAL_AND).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_AND);
}),
create.Type(CommandsParserValueType::LOGICAL_OR).Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_OR);
})
}).Capture(CAPTURE_OPERATION_TYPE);
} }
std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evaluation(const supplier_t* labelSupplier) std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evaluation(const supplier_t* labelSupplier)
@ -185,21 +223,123 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evalu
create.Label(LABEL_EVALUATION), create.Label(LABEL_EVALUATION),
create.Char(')').Tag(TAG_EVALUATION_PARENTHESIS_END) create.Char(')').Tag(TAG_EVALUATION_PARENTHESIS_END)
}).Tag(TAG_EVALUATION_PARENTHESIS), }).Tag(TAG_EVALUATION_PARENTHESIS),
Operand(labelSupplier) ParseOperand(labelSupplier)
}), }),
create.Optional(create.And({ create.Optional(create.And({
OperationType(labelSupplier), ParseOperationType(labelSupplier),
create.Label(LABEL_EVALUATION) create.Label(LABEL_EVALUATION)
})).Tag(TAG_EVALUATION_OPERATION) }).Tag(TAG_EVALUATION_OPERATION))
}).Tag(TAG_EVALUATION); }).Tag(TAG_EVALUATION);
} }
std::unique_ptr<IEvaluation> CommandsCommonMatchers::ParseEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) std::unique_ptr<IEvaluation> CommandsCommonMatchers::ProcessEvaluationInParenthesis(CommandsParserState* state, SequenceResult<CommandsParserValue>& result)
{
const auto isNegated = result.PeekAndRemoveIfTag(TAG_EVALUATION_NOT) == TAG_EVALUATION_NOT;
auto processedEvaluation = ProcessEvaluation(state, result);
if (result.PeekAndRemoveIfTag(TAG_EVALUATION_PARENTHESIS_END) != TAG_EVALUATION_PARENTHESIS_END)
throw ParsingException(TokenPos(), "Expected parenthesis end tag @ EvaluationInParenthesis");
if (isNegated)
processedEvaluation = std::make_unique<Operation>(OperationType::OPERATION_EQUALS, std::move(processedEvaluation), std::make_unique<OperandStatic>(0));
return processedEvaluation;
}
std::unique_ptr<IEvaluation> CommandsCommonMatchers::ProcessOperand(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, StructureInformation* currentType)
{
const auto nextTag = result.NextTag();
if (nextTag == TAG_OPERAND_INTEGER)
{
return std::make_unique<OperandStatic>(result.NextCapture(CAPTURE_OPERAND_INTEGER).IntegerValue());
}
if (nextTag == TAG_OPERAND_TYPENAME)
{
const auto& typeNameToken = result.NextCapture(CAPTURE_OPERAND_TYPENAME);
std::vector<std::unique_ptr<IEvaluation>> arrayIndexEvaluations;
while (result.PeekAndRemoveIfTag(TAG_OPERAND_ARRAY) == TAG_OPERAND_ARRAY)
{
arrayIndexEvaluations.emplace_back(ProcessEvaluation(state, result, currentType));
if (result.PeekAndRemoveIfTag(TAG_OPERAND_ARRAY_END) != TAG_OPERAND_ARRAY_END)
throw ParsingException(TokenPos(), "Expected operand array end tag @ Operand");
}
auto* foundEnumMember = state->GetRepository()->GetEnumMemberByName(typeNameToken.TypeNameValue());
if (foundEnumMember != nullptr)
return std::make_unique<OperandStatic>(foundEnumMember);
StructureInformation* structure;
std::vector<MemberInformation*> memberChain;
if (state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), structure, memberChain))
return std::make_unique<OperandDynamic>(structure, std::move(memberChain), std::move(arrayIndexEvaluations));
if (currentType != nullptr && state->GetMembersFromTypename(typeNameToken.TypeNameValue(), currentType, memberChain))
return std::make_unique<OperandDynamic>(currentType, std::move(memberChain), std::move(arrayIndexEvaluations));
throw ParsingException(typeNameToken.GetPos(), "Unknown type");
}
throw ParsingException(TokenPos(), "Unknown operand type @ Operand");
}
std::unique_ptr<IEvaluation> CommandsCommonMatchers::ProcessEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result)
{
return ProcessEvaluation(state, result, nullptr);
}
std::unique_ptr<IEvaluation> CommandsCommonMatchers::ProcessEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, StructureInformation* currentType)
{ {
if (result.PeekAndRemoveIfTag(TAG_EVALUATION) != TAG_EVALUATION) if (result.PeekAndRemoveIfTag(TAG_EVALUATION) != TAG_EVALUATION)
return nullptr; return nullptr;
if (currentType == state->GetInUse())
currentType = nullptr;
std::list<std::unique_ptr<IEvaluation>> operands;
std::list<std::pair<unsigned, const OperationType*>> operators;
while (true)
{
std::unique_ptr<IEvaluation> firstStatementPart;
const auto nextTag = result.NextTag();
switch (nextTag)
{
case TAG_EVALUATION_PARENTHESIS:
firstStatementPart = ProcessEvaluationInParenthesis(state, result);
break;
case TAG_OPERAND:
firstStatementPart = ProcessOperand(state, result, currentType);
break;
default:
throw ParsingException(TokenPos(), "Invalid followup tag @ Evaluation");
}
operands.emplace_back(std::move(firstStatementPart));
if (result.PeekAndRemoveIfTag(TAG_EVALUATION_OPERATION) == TAG_EVALUATION_OPERATION)
operators.emplace_back(operators.size(), result.NextCapture(CAPTURE_OPERATION_TYPE).OpTypeValue());
else
break;
if (result.PeekAndRemoveIfTag(TAG_EVALUATION) != TAG_EVALUATION)
throw ParsingException(TokenPos(), "Expected EvaluationTag @ Evaluation");
}
operators.sort([](const std::pair<unsigned, const OperationType*>& p1, const std::pair<unsigned, const OperationType*>& p2)
{
return p1.second->m_precedence > p2.second->m_precedence;
});
while (!operators.empty())
{
operators.pop_back();
}
return nullptr; return nullptr;
} }

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include "Domain/Evaluation/IEvaluation.h" #include "Domain/Evaluation/IEvaluation.h"
#include "Domain/Evaluation/OperationType.h"
#include "Parsing/Commands/Impl/CommandsParserState.h" #include "Parsing/Commands/Impl/CommandsParserState.h"
#include "Parsing/Commands/Impl/CommandsParserValue.h" #include "Parsing/Commands/Impl/CommandsParserValue.h"
#include "Parsing/Matcher/AbstractMatcher.h" #include "Parsing/Matcher/AbstractMatcher.h"
@ -24,11 +25,15 @@ public:
static std::unique_ptr<matcher_t> ArrayDef(const supplier_t* labelSupplier); static std::unique_ptr<matcher_t> ArrayDef(const supplier_t* labelSupplier);
private: private:
static std::unique_ptr<matcher_t> OperandArray(const supplier_t* labelSupplier); static std::unique_ptr<matcher_t> ParseOperandArray(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> Operand(const supplier_t* labelSupplier); static std::unique_ptr<matcher_t> ParseOperand(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> OperationType(const supplier_t* labelSupplier); static std::unique_ptr<matcher_t> ParseOperationType(const supplier_t* labelSupplier);
static std::unique_ptr<IEvaluation> ProcessEvaluationInParenthesis(CommandsParserState* state, SequenceResult<CommandsParserValue>& result);
static std::unique_ptr<IEvaluation> ProcessOperand(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, StructureInformation* currentType);
public: public:
static std::unique_ptr<matcher_t> Evaluation(const supplier_t* labelSupplier); static std::unique_ptr<matcher_t> Evaluation(const supplier_t* labelSupplier);
static std::unique_ptr<IEvaluation> ParseEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result); static std::unique_ptr<IEvaluation> ProcessEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result);
static std::unique_ptr<IEvaluation> ProcessEvaluation(CommandsParserState* state, SequenceResult<CommandsParserValue>& result, StructureInformation* currentType);
}; };

View File

@ -0,0 +1,35 @@
#include "SequenceArchitecture.h"
#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h"
#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h"
SequenceArchitecture::SequenceArchitecture()
{
const CommandsMatcherFactory create(this);
AddMatchers({
create.Keyword("architecture"),
create.Or({
create.Keyword("x86").Tag(TAG_X86),
create.Keyword("x64").Tag(TAG_X64)
}),
create.Char(';')
});
}
void SequenceArchitecture::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const
{
switch (result.NextTag())
{
case TAG_X86:
state->SetArchitecture(Architecture::X86);
break;
case TAG_X64:
state->SetArchitecture(Architecture::X64);
break;
default:
throw ParsingException(TokenPos(), "Unknown architecture!");
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "Parsing/Commands/Impl/CommandsParser.h"
class SequenceArchitecture final : public CommandsParser::sequence_t
{
static constexpr auto TAG_X86 = 1;
static constexpr auto TAG_X64 = 2;
protected:
void ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const override;
public:
SequenceArchitecture();
};

View File

@ -1,5 +1,7 @@
#include "SequenceArrayCount.h" #include "SequenceArrayCount.h"
#include "Domain/Definition/ArrayDeclarationModifier.h"
#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h" #include "Parsing/Commands/Matcher/CommandsMatcherFactory.h"
#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h" #include "Parsing/Commands/Matcher/CommandsCommonMatchers.h"
@ -13,11 +15,38 @@ SequenceArrayCount::SequenceArrayCount()
create.Keyword("set"), create.Keyword("set"),
create.Keyword("arraycount"), create.Keyword("arraycount"),
create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE), create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE),
create.Label(CommandsCommonMatchers::LABEL_EVALUATION).Capture(CAPTURE_EVALUATION), create.Label(CommandsCommonMatchers::LABEL_EVALUATION),
create.Char(';') create.Char(';')
}); });
} }
void SequenceArrayCount::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const void SequenceArrayCount::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const
{ {
const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE);
StructureInformation* structure;
std::vector<MemberInformation*> memberChain;
if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), structure, memberChain))
throw ParsingException(typeNameToken.GetPos(), "Unknown type");
if(memberChain.empty())
throw ParsingException(typeNameToken.GetPos(), "Must specify type with member");
const auto& memberDeclarationModifiers = memberChain.back()->m_member->m_type_declaration->m_declaration_modifiers;
ArrayDeclarationModifier* arrayModifier = nullptr;
for (const auto& modifier : memberDeclarationModifiers)
{
if (modifier->GetType() == DeclarationModifierType::ARRAY)
{
arrayModifier = dynamic_cast<ArrayDeclarationModifier*>(modifier.get());
break;
}
}
if (arrayModifier == nullptr)
throw ParsingException(typeNameToken.GetPos(), "Specified member is not an array");
auto evaluation = CommandsCommonMatchers::ProcessEvaluation(state, result, structure);
arrayModifier->m_dynamic_count_evaluation = std::move(evaluation);
} }

View File

@ -5,7 +5,6 @@
class SequenceArrayCount final : public CommandsParser::sequence_t class SequenceArrayCount final : public CommandsParser::sequence_t
{ {
static constexpr auto CAPTURE_TYPE = 1; static constexpr auto CAPTURE_TYPE = 1;
static constexpr auto CAPTURE_EVALUATION = 2;
protected: protected:
void ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const override; void ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const override;

View File

@ -17,4 +17,14 @@ SequenceUse::SequenceUse()
void SequenceUse::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const void SequenceUse::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const
{ {
const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE);
auto* definition = state->GetRepository()->GetDataDefinitionByName(typeNameToken.TypeNameValue());
if (definition == nullptr)
throw ParsingException(typeNameToken.GetPos(), "Unknown type");
auto* definitionWithMembers = dynamic_cast<DefinitionWithMembers*>(definition);
if (definitionWithMembers == nullptr)
throw ParsingException(typeNameToken.GetPos(), "Type must be able to have members");
state->SetInUse(state->GetRepository()->GetInformationFor(definitionWithMembers));
} }

View File

@ -102,7 +102,7 @@ void HeaderBlockStruct::SetBlockName(const TokenPos& nameTokenPos, std::string n
bool HeaderBlockStruct::IsDefiningVariable() bool HeaderBlockStruct::IsDefiningVariable()
{ {
return !m_is_typedef && !m_variable_name.empty(); return true;
} }
DataDefinition* HeaderBlockStruct::GetVariableType() DataDefinition* HeaderBlockStruct::GetVariableType()

View File

@ -102,7 +102,7 @@ void HeaderBlockUnion::SetBlockName(const TokenPos& nameTokenPos, std::string na
bool HeaderBlockUnion::IsDefiningVariable() bool HeaderBlockUnion::IsDefiningVariable()
{ {
return !m_is_typedef && !m_variable_name.empty(); return true;
} }
DataDefinition* HeaderBlockUnion::GetVariableType() DataDefinition* HeaderBlockUnion::GetVariableType()

View File

@ -1,6 +1,6 @@
#include "HeaderFileReader.h" #include "HeaderFileReader.h"
#include <algorithm>
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
@ -11,6 +11,9 @@
#include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/IncludingStreamProxy.h"
#include "Parsing/Impl/PackDefinitionStreamProxy.h" #include "Parsing/Impl/PackDefinitionStreamProxy.h"
#include "Parsing/Impl/ParserFilesystemStream.h" #include "Parsing/Impl/ParserFilesystemStream.h"
#include "Parsing/PostProcessing/CreateMemberInformationPostProcessor.h"
#include "Parsing/PostProcessing/CreateStructureInformationPostProcessor.h"
#include "Parsing/PostProcessing/IPostProcessor.h"
HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
: m_args(args), : m_args(args),
@ -18,6 +21,7 @@ HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::
m_pack_value_supplier(nullptr), m_pack_value_supplier(nullptr),
m_stream(nullptr) m_stream(nullptr)
{ {
SetupPostProcessors();
} }
bool HeaderFileReader::OpenBaseStream() bool HeaderFileReader::OpenBaseStream()
@ -51,6 +55,13 @@ void HeaderFileReader::SetupStreamProxies()
m_open_streams.emplace_back(std::move(definesProxy)); m_open_streams.emplace_back(std::move(definesProxy));
} }
void HeaderFileReader::SetupPostProcessors()
{
// Order is important
m_post_processors.emplace_back(std::make_unique<CreateStructureInformationPostProcessor>());
m_post_processors.emplace_back(std::make_unique<CreateMemberInformationPostProcessor>());
}
bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository)
{ {
std::cout << "Reading header file: " << m_filename << std::endl; std::cout << "Reading header file: " << m_filename << std::endl;
@ -64,11 +75,17 @@ bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository)
const auto parser = std::make_unique<HeaderParser>(lexer.get(), m_pack_value_supplier); const auto parser = std::make_unique<HeaderParser>(lexer.get(), m_pack_value_supplier);
const auto start = std::chrono::steady_clock::now(); const auto start = std::chrono::steady_clock::now();
const auto result = parser->Parse(); auto result = parser->Parse();
if (result) if (result)
parser->SaveToRepository(repository); result = parser->SaveToRepository(repository);
const auto end = std::chrono::steady_clock::now(); const auto end = std::chrono::steady_clock::now();
std::cout << "Processing header took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl; std::cout << "Processing header took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;
return result; if (!result)
return false;
return std::all_of(m_post_processors.begin(), m_post_processors.end(), [repository](const std::unique_ptr<IPostProcessor>& postProcessor)
{
return postProcessor->PostProcess(repository);
});
} }

View File

@ -5,6 +5,7 @@
#include "ZoneCodeGeneratorArguments.h" #include "ZoneCodeGeneratorArguments.h"
#include "Parsing/IPackValueSupplier.h" #include "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h" #include "Parsing/IParserLineStream.h"
#include "Parsing/PostProcessing/IPostProcessor.h"
#include "Persistence/IDataRepository.h" #include "Persistence/IDataRepository.h"
class HeaderFileReader class HeaderFileReader
@ -19,8 +20,11 @@ class HeaderFileReader
const IPackValueSupplier* m_pack_value_supplier; const IPackValueSupplier* m_pack_value_supplier;
IParserLineStream* m_stream; IParserLineStream* m_stream;
std::vector<std::unique_ptr<IPostProcessor>> m_post_processors;
bool OpenBaseStream(); bool OpenBaseStream();
void SetupStreamProxies(); void SetupStreamProxies();
void SetupPostProcessors();
public: public:
HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename); HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);

View File

@ -0,0 +1,300 @@
#include "CalculateSizeAndAlignPostProcessor.h"
#include <cassert>
#include <iostream>
#include <cstdint>
#include "Domain/Definition/ArrayDeclarationModifier.h"
#include "Utils/AlignmentUtils.h"
unsigned CalculateSizeAndAlignPostProcessor::GetPointerSizeForArchitecture(const Architecture architecture)
{
switch (architecture)
{
case Architecture::X86:
return sizeof(uint32_t);
case Architecture::X64:
return sizeof(uint64_t);
default:
assert(false);
return sizeof(uint32_t);
}
}
bool CalculateSizeAndAlignPostProcessor::CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration)
{
auto hasPointerModifier = false;
for (const auto& declarationModifier : declaration->m_declaration_modifiers)
{
if (declarationModifier->GetType() == DeclarationModifierType::POINTER)
{
hasPointerModifier = true;
break;
}
}
if (hasPointerModifier)
{
declaration->m_alignment = GetPointerSizeForArchitecture(repository->GetArchitecture());
}
else
{
if (!CalculateFieldsIfNecessary(repository, declaration->m_type))
return false;
declaration->m_alignment = declaration->m_type->GetAlignment();
if (declaration->m_type->GetForceAlignment())
declaration->m_flags |= TypeDeclaration::FLAG_ALIGNMENT_FORCED;
}
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateAlign(IDataRepository* repository, DefinitionWithMembers* definition)
{
if (definition->m_has_alignment_override)
{
definition->m_flags |= DefinitionWithMembers::FLAG_ALIGNMENT_FORCED;
definition->m_alignment = definition->m_alignment_override;
}
else
{
definition->m_alignment = 0;
for (const auto& member : definition->m_members)
{
if (!CalculateFields(repository, member->m_type_declaration.get()))
return false;
const auto memberAlignment = member->GetAlignment();
if (memberAlignment > definition->m_alignment)
definition->m_alignment = memberAlignment;
}
}
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, TypeDeclaration* declaration)
{
if (declaration->m_declaration_modifiers.empty())
{
if (!CalculateFieldsIfNecessary(repository, declaration->m_type))
return false;
declaration->m_size = declaration->m_type->GetSize();
}
else
{
auto currentSize = 0u;
// If the first modifier is a pointer we do not need the actual type size
if (declaration->m_declaration_modifiers.back()->GetType() != DeclarationModifierType::POINTER)
{
if (!CalculateFieldsIfNecessary(repository, declaration->m_type))
return false;
currentSize = declaration->m_type->GetSize();
}
for (auto i = declaration->m_declaration_modifiers.size(); i > 0; i--)
{
const auto& declarationModifier = declaration->m_declaration_modifiers[i - 1];
switch (declarationModifier->GetType())
{
case DeclarationModifierType::POINTER:
currentSize = GetPointerSizeForArchitecture(repository->GetArchitecture());
break;
case DeclarationModifierType::ARRAY:
currentSize *= dynamic_cast<ArrayDeclarationModifier*>(declarationModifier.get())->m_size;
break;
}
}
declaration->m_size = currentSize;
}
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, StructDefinition* definition)
{
definition->m_size = 0;
auto currentBitOffset = 0u;
for (const auto& member : definition->m_members)
{
if (!CalculateFields(repository, member->m_type_declaration.get()))
return false;
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);
definition->m_size += currentBitOffset / 8;
currentBitOffset = 0;
}
definition->m_size = AlignmentUtils::Align(definition->m_size, member->GetForceAlignment() ? member->GetAlignment() : std::min(member->GetAlignment(), definition->m_pack));
definition->m_size += member->m_type_declaration->GetSize();
}
}
if (currentBitOffset > 0)
{
currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u);
definition->m_size += currentBitOffset / 8;
}
definition->m_size = AlignmentUtils::Align(definition->m_size, definition->m_alignment);
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, UnionDefinition* definition)
{
definition->m_size = 0;
for (const auto& member : definition->m_members)
{
if (!CalculateFields(repository, member->m_type_declaration.get()))
return false;
const auto memberSize = member->m_type_declaration->GetSize();
if (memberSize > definition->m_size)
definition->m_size = memberSize;
}
definition->m_size = AlignmentUtils::Align(definition->m_size, definition->m_alignment);
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, TypeDeclaration* declaration)
{
if (declaration->m_flags & TypeDeclaration::FLAG_FIELDS_CALCULATED)
return true;
if(!CalculateAlign(repository, declaration)
|| !CalculateSize(repository, declaration))
{
return false;
}
declaration->m_flags |= TypeDeclaration::FLAG_FIELDS_CALCULATED;
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, StructDefinition* structDefinition)
{
if (structDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATED)
return true;
if (structDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATING)
{
std::cout << "Detected circular dependency:\n";
return false;
}
structDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATING;
if (!CalculateAlign(repository, structDefinition)
|| !CalculateSize(repository, structDefinition))
{
return false;
}
structDefinition->m_flags &= ~DefinitionWithMembers::FLAG_FIELDS_CALCULATING;
structDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATED;
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, UnionDefinition* unionDefinition)
{
if (unionDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATED)
return true;
if (unionDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATING)
{
std::cout << "Detected circular dependency:\n";
return false;
}
unionDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATING;
if (!CalculateAlign(repository, unionDefinition)
|| !CalculateSize(repository, unionDefinition))
{
return false;
}
unionDefinition->m_flags &= ~DefinitionWithMembers::FLAG_FIELDS_CALCULATING;
unionDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATED;
return true;
}
bool CalculateSizeAndAlignPostProcessor::CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition)
{
if(definition->GetType() == DataDefinitionType::STRUCT)
{
// We can do a const cast here because the only reason that field is const anyway is because it could be a base type
return CalculateFields(repository, dynamic_cast<StructDefinition*>(const_cast<DataDefinition*>(definition)));
}
if(definition->GetType() == DataDefinitionType::UNION)
{
// We can do a const cast here because the only reason that field is const anyway is because it could be a base type
return CalculateFields(repository, dynamic_cast<UnionDefinition*>(const_cast<DataDefinition*>(definition)));
}
if(definition->GetType() == DataDefinitionType::TYPEDEF)
{
// We can do a const cast here because the only reason that field is const anyway is because it could be a base type
return CalculateFields(repository, dynamic_cast<TypedefDefinition*>(const_cast<DataDefinition*>(definition))->m_type_declaration.get());
}
return true;
}
bool CalculateSizeAndAlignPostProcessor::PostProcess(IDataRepository* repository)
{
if (repository->GetArchitecture() == Architecture::UNKNOWN)
{
std::cout << "You must set an architecture!" << std::endl;
return false;
}
for (auto* structDefinition : repository->GetAllStructs())
{
if (!CalculateFields(repository, structDefinition))
{
std::cout << std::endl;
return false;
}
}
for (auto* unionDefinition : repository->GetAllUnions())
{
if (!CalculateFields(repository, unionDefinition))
{
std::cout << std::endl;
return false;
}
}
for (auto* typedefDeclaration : repository->GetAllTypedefs())
{
if (!CalculateFields(repository, typedefDeclaration->m_type_declaration.get()))
{
std::cout << std::endl;
return false;
}
}
return true;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IPostProcessor.h"
class CalculateSizeAndAlignPostProcessor final : public IPostProcessor
{
static unsigned GetPointerSizeForArchitecture(Architecture architecture);
static bool CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration);
static bool CalculateAlign(IDataRepository* repository, DefinitionWithMembers* definition);
static bool CalculateSize(IDataRepository* repository, TypeDeclaration* declaration);
static bool CalculateSize(IDataRepository* repository, StructDefinition* definition);
static bool CalculateSize(IDataRepository* repository, UnionDefinition* definition);
static bool CalculateFields(IDataRepository* repository, TypeDeclaration* declaration);
static bool CalculateFields(IDataRepository* repository, StructDefinition* structDefinition);
static bool CalculateFields(IDataRepository* repository, UnionDefinition* unionDefinition);
static bool CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition);
public:
bool PostProcess(IDataRepository* repository) override;
};

View File

@ -0,0 +1,29 @@
#include "CreateMemberInformationPostProcessor.h"
#include <algorithm>
bool CreateMemberInformationPostProcessor::CreateMemberInformationForStructure(IDataRepository* repository, StructureInformation* structure) const
{
for(const auto& member : structure->m_definition->m_members)
{
StructureInformation* typeInfo = nullptr;
const auto* memberDefinition = dynamic_cast<const DefinitionWithMembers*>(member->m_type_declaration->m_type);
if(memberDefinition != nullptr)
typeInfo = repository->GetInformationFor(memberDefinition);
structure->m_ordered_members.emplace_back(std::make_unique<MemberInformation>(structure, typeInfo, member.get()));
}
return true;
}
bool CreateMemberInformationPostProcessor::PostProcess(IDataRepository* repository)
{
const auto& allStructureInformation = repository->GetAllStructureInformation();
return std::all_of(allStructureInformation.begin(), allStructureInformation.end(), [this, repository](StructureInformation* structure)
{
return CreateMemberInformationForStructure(repository, structure);
});
}

View File

@ -0,0 +1,11 @@
#pragma once
#include "IPostProcessor.h"
class CreateMemberInformationPostProcessor final : public IPostProcessor
{
bool CreateMemberInformationForStructure(IDataRepository* repository, StructureInformation* structure) const;
public:
bool PostProcess(IDataRepository* repository) override;
};

View File

@ -0,0 +1,20 @@
#include "CreateStructureInformationPostProcessor.h"
bool CreateStructureInformationPostProcessor::PostProcess(IDataRepository* repository)
{
for(auto* structDefinition : repository->GetAllStructs())
{
auto* information = repository->GetInformationFor(structDefinition);
if(information == nullptr)
repository->Add(std::make_unique<StructureInformation>(structDefinition));
}
for(auto* unionDefinition : repository->GetAllUnions())
{
auto* information = repository->GetInformationFor(unionDefinition);
if(information == nullptr)
repository->Add(std::make_unique<StructureInformation>(unionDefinition));
}
return true;
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "IPostProcessor.h"
class CreateStructureInformationPostProcessor final : public IPostProcessor
{
public:
bool PostProcess(IDataRepository* repository) override;
};

View File

@ -0,0 +1,15 @@
#pragma once
#include "Persistence/IDataRepository.h"
class IPostProcessor
{
public:
IPostProcessor() = default;
virtual ~IPostProcessor() = default;
IPostProcessor(const IPostProcessor& other) = default;
IPostProcessor(IPostProcessor&& other) noexcept = default;
IPostProcessor& operator=(const IPostProcessor& other) = default;
IPostProcessor& operator=(IPostProcessor&& other) noexcept = default;
virtual bool PostProcess(IDataRepository* repository) = 0;
};

View File

@ -7,6 +7,7 @@
#include "Domain/Definition/StructDefinition.h" #include "Domain/Definition/StructDefinition.h"
#include "Domain/Definition/TypedefDefinition.h" #include "Domain/Definition/TypedefDefinition.h"
#include "Domain/Definition/UnionDefinition.h" #include "Domain/Definition/UnionDefinition.h"
#include "Domain/Environment/Architecture.h"
#include "Domain/Information/StructureInformation.h" #include "Domain/Information/StructureInformation.h"
#include "Domain/FastFile/FastFileBlock.h" #include "Domain/FastFile/FastFileBlock.h"
@ -29,6 +30,8 @@ public:
_NODISCARD virtual const std::string& GetGameName() const = 0; _NODISCARD virtual const std::string& GetGameName() const = 0;
virtual void SetGame(std::string gameName) = 0; virtual void SetGame(std::string gameName) = 0;
_NODISCARD virtual Architecture GetArchitecture() const = 0;
virtual void SetArchitecture(Architecture architecture) = 0;
_NODISCARD virtual const std::vector<EnumDefinition*>& GetAllEnums() const = 0; _NODISCARD virtual const std::vector<EnumDefinition*>& GetAllEnums() const = 0;
_NODISCARD virtual const std::vector<StructDefinition*>& GetAllStructs() const = 0; _NODISCARD virtual const std::vector<StructDefinition*>& GetAllStructs() const = 0;
@ -38,6 +41,6 @@ public:
_NODISCARD virtual const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const = 0; _NODISCARD virtual const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const = 0;
_NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0; _NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0;
_NODISCARD virtual StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const = 0; _NODISCARD virtual StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const = 0;
_NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0; _NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0;
}; };

View File

@ -1,5 +1,10 @@
#include "InMemoryRepository.h" #include "InMemoryRepository.h"
InMemoryRepository::InMemoryRepository()
: m_architecture(Architecture::UNKNOWN)
{
}
InMemoryRepository::~InMemoryRepository() InMemoryRepository::~InMemoryRepository()
{ {
for (auto* enumDefinition : m_enums) for (auto* enumDefinition : m_enums)
@ -22,7 +27,7 @@ void InMemoryRepository::Add(std::unique_ptr<EnumDefinition> enumsDefinition)
m_enums.push_back(raw); m_enums.push_back(raw);
m_data_definitions_by_name[raw->m_name] = raw; m_data_definitions_by_name[raw->m_name] = raw;
for(const auto& enumMember : raw->m_members) for (const auto& enumMember : raw->m_members)
m_enum_members_by_name[enumMember->m_name] = enumMember.get(); m_enum_members_by_name[enumMember->m_name] = enumMember.get();
} }
@ -69,6 +74,16 @@ void InMemoryRepository::SetGame(std::string gameName)
m_game_name = std::move(gameName); m_game_name = std::move(gameName);
} }
Architecture InMemoryRepository::GetArchitecture() const
{
return m_architecture;
}
void InMemoryRepository::SetArchitecture(const Architecture architecture)
{
m_architecture = architecture;
}
const std::vector<EnumDefinition*>& InMemoryRepository::GetAllEnums() const const std::vector<EnumDefinition*>& InMemoryRepository::GetAllEnums() const
{ {
return m_enums; return m_enums;
@ -109,7 +124,7 @@ DataDefinition* InMemoryRepository::GetDataDefinitionByName(const std::string& n
return nullptr; return nullptr;
} }
StructureInformation* InMemoryRepository::GetInformationFor(DefinitionWithMembers* definitionWithMembers) const StructureInformation* InMemoryRepository::GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const
{ {
const auto foundEntry = m_structure_information_by_definition.find(definitionWithMembers); const auto foundEntry = m_structure_information_by_definition.find(definitionWithMembers);

View File

@ -14,11 +14,12 @@ class InMemoryRepository final : public IDataRepository
std::vector<FastFileBlock*> m_fast_file_blocks; std::vector<FastFileBlock*> m_fast_file_blocks;
std::map<std::string, DataDefinition*> m_data_definitions_by_name; std::map<std::string, DataDefinition*> m_data_definitions_by_name;
std::map<std::string, EnumMember*> m_enum_members_by_name; std::map<std::string, EnumMember*> m_enum_members_by_name;
std::map<DefinitionWithMembers*, StructureInformation*> m_structure_information_by_definition; std::map<const DefinitionWithMembers*, StructureInformation*> m_structure_information_by_definition;
std::string m_game_name; std::string m_game_name;
Architecture m_architecture;
public: public:
InMemoryRepository() = default; InMemoryRepository();
~InMemoryRepository() override; ~InMemoryRepository() override;
InMemoryRepository(const InMemoryRepository& other) = delete; InMemoryRepository(const InMemoryRepository& other) = delete;
InMemoryRepository(InMemoryRepository&& other) noexcept = default; InMemoryRepository(InMemoryRepository&& other) noexcept = default;
@ -34,6 +35,8 @@ public:
_NODISCARD const std::string& GetGameName() const override; _NODISCARD const std::string& GetGameName() const override;
void SetGame(std::string gameName) override; void SetGame(std::string gameName) override;
Architecture GetArchitecture() const override;
void SetArchitecture(Architecture architecture) override;
_NODISCARD const std::vector<EnumDefinition*>& GetAllEnums() const override; _NODISCARD const std::vector<EnumDefinition*>& GetAllEnums() const override;
_NODISCARD const std::vector<StructDefinition*>& GetAllStructs() const override; _NODISCARD const std::vector<StructDefinition*>& GetAllStructs() const override;
@ -43,6 +46,6 @@ public:
_NODISCARD const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const override; _NODISCARD const std::vector<FastFileBlock*>& GetAllFastFileBlocks() const override;
_NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override; _NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override;
_NODISCARD StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const override; _NODISCARD StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const override;
_NODISCARD EnumMember* GetEnumMemberByName(const std::string& name) const override; _NODISCARD EnumMember* GetEnumMemberByName(const std::string& name) const override;
}; };