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 IW4;
architecture x86;
// Game Assets
asset PhysPreset ASSET_TYPE_PHYSPRESET;

View File

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

View File

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

View File

@ -9,17 +9,14 @@
class DefinitionWithMembers : public DataDefinition
{
public:
static constexpr int FLAG_SIZE_CALCULATED = 1 << 0;
static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1;
static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0;
static constexpr int FLAG_FIELDS_CALCULATING = 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();*/
bool m_has_alignment_override;
bool m_anonymous;

View File

@ -1,43 +1,5 @@
#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)
{

View File

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

View File

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

View File

@ -1,26 +1,22 @@
#pragma once
#include <memory>
#include <vector>
#include <cstdint>
#include "Utils/ClassUtils.h"
#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;
public:
static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0;
static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 1;
unsigned m_flags;
unsigned m_size;
unsigned m_alignment;
void CalculateSize();
void CalculateAlignment();
public:
explicit TypeDeclaration(const DataDefinition* type);
bool m_is_const;
@ -31,7 +27,7 @@ public:
std::vector<std::unique_ptr<DeclarationModifier>> m_declaration_modifiers;
unsigned GetSize();
unsigned GetAlignment();
bool GetForceAlignment();
_NODISCARD unsigned GetSize() const;
_NODISCARD unsigned GetAlignment() const;
_NODISCARD bool GetForceAlignment() const;
};

View File

@ -1,23 +1,5 @@
#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)
{

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)
return m_alignment_override;
@ -16,7 +16,7 @@ unsigned Variable::GetAlignment()
return m_type_declaration->GetAlignment();
}
bool Variable::GetForceAlignment()
bool Variable::GetForceAlignment() const
{
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);
unsigned GetAlignment();
bool GetForceAlignment();
unsigned GetAlignment() const;
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
{
return EvaluationType::OPERAND_DYNAMIC;

View File

@ -14,6 +14,7 @@ public:
std::vector<std::unique_ptr<IEvaluation>> m_array_indices;
explicit OperandDynamic(StructureInformation* structure);
OperandDynamic(StructureInformation* structure, std::vector<MemberInformation*> referencedMemberChain, std::vector<std::unique_ptr<IEvaluation>> arrayIndices);
_NODISCARD EvaluationType GetType() 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)
: m_value(value),
OperandStatic::OperandStatic(EnumMember* enumMember)
: m_value(enumMember->m_value),
m_enum_member(enumMember)
{
}

View File

@ -10,7 +10,7 @@ public:
EnumMember* const m_enum_member;
explicit OperandStatic(int value);
OperandStatic(int value, EnumMember* enumMember);
explicit OperandStatic(EnumMember* enumMember);
_NODISCARD EvaluationType GetType() 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
{
return EvaluationType::OPERATION;

View File

@ -14,6 +14,7 @@ public:
std::unique_ptr<IEvaluation> m_operand2;
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 bool IsStatic() const override;

View File

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

View File

@ -40,11 +40,11 @@ public:
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_GREATER_EQUAL_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_NOT_EQUALS;
static const OperationType* const OPERATION_NOT_EQUAL;
static const OperationType* const OPERATION_AND;
static const OperationType* const OPERATION_OR;

View File

@ -1,5 +1,6 @@
#include "CommandsFileReader.h"
#include <algorithm>
#include <chrono>
#include <iostream>
@ -9,12 +10,14 @@
#include "Parsing/Impl/DefinesStreamProxy.h"
#include "Parsing/Impl/IncludingStreamProxy.h"
#include "Parsing/Impl/ParserFilesystemStream.h"
#include "Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h"
CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename)
: m_args(args),
m_filename(std::move(filename)),
m_stream(nullptr)
{
SetupPostProcessors();
}
bool CommandsFileReader::OpenBaseStream()
@ -45,6 +48,11 @@ void CommandsFileReader::SetupStreamProxies()
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)
{
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();
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 "Parsing/IParserLineStream.h"
#include "Parsing/PostProcessing/IPostProcessor.h"
#include "Persistence/IDataRepository.h"
class CommandsFileReader
@ -17,8 +18,11 @@ class CommandsFileReader
std::vector<std::unique_ptr<IParserLineStream>> m_open_streams;
IParserLineStream* m_stream;
std::vector<std::unique_ptr<IPostProcessor>> m_post_processors;
bool OpenBaseStream();
void SetupStreamProxies();
void SetupPostProcessors();
public:
explicit CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename);

View File

@ -1,6 +1,7 @@
#include "CommandsParser.h"
#include "Parsing/Commands/Sequence/SequenceAction.h"
#include "Parsing/Commands/Sequence/SequenceArchitecture.h"
#include "Parsing/Commands/Sequence/SequenceArrayCount.h"
#include "Parsing/Commands/Sequence/SequenceArraySize.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({
new SequenceAction(),
new SequenceArchitecture(),
new SequenceArrayCount(),
new SequenceArraySize(),
new SequenceAsset(),

View File

@ -16,6 +16,11 @@ void CommandsParserState::AddBlock(std::unique_ptr<FastFileBlock> block) const
m_repository->Add(std::move(block));
}
void CommandsParserState::SetArchitecture(const Architecture architecture) const
{
m_repository->SetArchitecture(architecture);
}
void CommandsParserState::SetGame(std::string gameName) const
{
m_repository->SetGame(std::move(gameName));
@ -31,12 +36,105 @@ void CommandsParserState::SetInUse(StructureInformation* 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;
}
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)
{
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;
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:
explicit CommandsParserState(IDataRepository* repository);
_NODISCARD const IDataRepository* GetRepository() const;
void AddBlock(std::unique_ptr<FastFileBlock> block) const;
void SetArchitecture(Architecture architecture) const;
void SetGame(std::string gameName) const;
_NODISCARD StructureInformation* GetInUse() const;
void SetInUse(StructureInformation* structure);
bool GetMembersFromParts(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members);
bool GetTypenameAndMembersFromParts(const std::string& typeNameValue, StructureInformation*& structure, std::vector<MemberInformation*>& members);
bool GetMembersFromTypename(const std::string& typeNameValue, StructureInformation* baseType, std::vector<MemberInformation*>& members) const;
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;
}
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)
: m_pos(pos),
m_type(type),
@ -201,3 +208,9 @@ std::string& CommandsParserValue::TypeNameValue() const
assert(m_type == CommandsParserValueType::TYPE_NAME);
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 "Domain/Evaluation/OperationType.h"
#include "Parsing/IParserValue.h"
#include "Utils/ClassUtils.h"
#include "Parsing/TokenPos.h"
@ -43,6 +45,7 @@ enum class CommandsParserValueType
// Parser created
TYPE_NAME,
OPERATION_TYPE,
// End
MAX
@ -60,6 +63,7 @@ public:
int int_value;
double double_value;
std::string* string_value;
const OperationType* op_type_value;
} m_value;
static CommandsParserValue Invalid(TokenPos pos);
@ -78,6 +82,7 @@ public:
static CommandsParserValue String(TokenPos pos, std::string* stringValue);
static CommandsParserValue Identifier(TokenPos pos, std::string* identifier);
static CommandsParserValue TypeName(TokenPos pos, std::string* typeName);
static CommandsParserValue OpType(TokenPos pos, const OperationType* operationType);
private:
CommandsParserValue(TokenPos pos, CommandsParserValueType type);
@ -99,4 +104,5 @@ public:
_NODISCARD std::string& IdentifierValue() const;
_NODISCARD size_t IdentifierHash() const;
_NODISCARD std::string& TypeNameValue() const;
_NODISCARD const OperationType* OpTypeValue() const;
};

View File

@ -1,8 +1,13 @@
#include "CommandsCommonMatchers.h"
#include <list>
#include <sstream>
#include <vector>
#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)
{
@ -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_ADD = std::numeric_limits<int>::max() - 2;
static constexpr int TAG_MINUS = std::numeric_limits<int>::max() - 3;
static constexpr int TAG_MULTIPLY = std::numeric_limits<int>::max() - 4;
static constexpr int TAG_DIVIDE = std::numeric_limits<int>::max() - 5;
static constexpr int TAG_REMAINDER = std::numeric_limits<int>::max() - 6;
static constexpr int TAG_BITWISE_AND = std::numeric_limits<int>::max() - 7;
static constexpr int TAG_BITWISE_XOR = std::numeric_limits<int>::max() - 8;
static constexpr int TAG_BITWISE_OR = std::numeric_limits<int>::max() - 9;
static constexpr int TAG_SHIFT_LEFT = 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 TAG_OPERAND = std::numeric_limits<int>::max() - 1;
static constexpr int TAG_OPERAND_TYPENAME = std::numeric_limits<int>::max() - 2;
static constexpr int TAG_OPERAND_ARRAY = std::numeric_limits<int>::max() - 3;
static constexpr int TAG_OPERAND_ARRAY_END = std::numeric_limits<int>::max() - 4;
static constexpr int TAG_OPERAND_INTEGER = std::numeric_limits<int>::max() - 5;
static constexpr int TAG_EVALUATION_NOT = std::numeric_limits<int>::max() - 6;
static constexpr int TAG_EVALUATION_PARENTHESIS = std::numeric_limits<int>::max() - 7;
static constexpr int TAG_EVALUATION_PARENTHESIS_END = std::numeric_limits<int>::max() - 8;
static constexpr int TAG_EVALUATION = std::numeric_limits<int>::max() - 9;
static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits<int>::max() - 10;
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_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);
@ -133,44 +118,97 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Opera
}).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);
return create.Or({
create.And({
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),
create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER),
create.FloatingPoint().Tag(TAG_OPERAND_FLOATING_POINT).Capture(CAPTURE_OPERAND_FLOATING_POINT)
create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER)
}).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);
return create.Or({
create.Char('+').Tag(TAG_ADD),
create.Char('-').Tag(TAG_MINUS),
create.Char('*').Tag(TAG_MULTIPLY),
create.Char('/').Tag(TAG_DIVIDE),
create.Char('%').Tag(TAG_REMAINDER),
create.Char('&').Tag(TAG_BITWISE_AND),
create.Char('^').Tag(TAG_BITWISE_XOR),
create.Char('|').Tag(TAG_BITWISE_OR),
create.Type(CommandsParserValueType::SHIFT_LEFT).Tag(TAG_SHIFT_LEFT),
create.Type(CommandsParserValueType::SHIFT_RIGHT).Tag(TAG_SHIFT_RIGHT),
create.Char('>').Tag(TAG_GREATER_THAN),
create.Type(CommandsParserValueType::GREATER_EQUAL).Tag(TAG_GREATER_EQUAL),
create.Char('<').Tag(TAG_LESS_THAN),
create.Type(CommandsParserValueType::LESS_EQUAL).Tag(TAG_LESS_EQUAL),
create.Type(CommandsParserValueType::EQUALS).Tag(TAG_EQUALS),
create.Type(CommandsParserValueType::NOT_EQUAL).Tag(TAG_NOT_EQUAL),
create.Type(CommandsParserValueType::LOGICAL_AND).Tag(TAG_LOGICAL_AND),
create.Type(CommandsParserValueType::LOGICAL_OR).Tag(TAG_LOGICAL_OR)
}).Tag(TAG_OPERATION_TYPE);
create.Char('+').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_ADD);
}),
create.Char('-').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SUBTRACT);
}),
create.Char('*').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_MULTIPLY);
}),
create.Char('/').Transform([](CommandsMatcherFactory::token_list_t& values)
{
return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_DIVIDE);
}),
create.Char('%').Transform([](CommandsMatcherFactory::token_list_t& values)
{
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)
@ -185,21 +223,123 @@ std::unique_ptr<CommandsCommonMatchers::matcher_t> CommandsCommonMatchers::Evalu
create.Label(LABEL_EVALUATION),
create.Char(')').Tag(TAG_EVALUATION_PARENTHESIS_END)
}).Tag(TAG_EVALUATION_PARENTHESIS),
Operand(labelSupplier)
ParseOperand(labelSupplier)
}),
create.Optional(create.And({
OperationType(labelSupplier),
ParseOperationType(labelSupplier),
create.Label(LABEL_EVALUATION)
})).Tag(TAG_EVALUATION_OPERATION)
}).Tag(TAG_EVALUATION_OPERATION))
}).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)
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;
}

View File

@ -4,6 +4,7 @@
#include <memory>
#include "Domain/Evaluation/IEvaluation.h"
#include "Domain/Evaluation/OperationType.h"
#include "Parsing/Commands/Impl/CommandsParserState.h"
#include "Parsing/Commands/Impl/CommandsParserValue.h"
#include "Parsing/Matcher/AbstractMatcher.h"
@ -24,11 +25,15 @@ public:
static std::unique_ptr<matcher_t> ArrayDef(const supplier_t* labelSupplier);
private:
static std::unique_ptr<matcher_t> OperandArray(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> Operand(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> OperationType(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> ParseOperandArray(const supplier_t* labelSupplier);
static std::unique_ptr<matcher_t> ParseOperand(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:
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 "Domain/Definition/ArrayDeclarationModifier.h"
#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h"
#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h"
@ -13,11 +15,38 @@ SequenceArrayCount::SequenceArrayCount()
create.Keyword("set"),
create.Keyword("arraycount"),
create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE),
create.Label(CommandsCommonMatchers::LABEL_EVALUATION).Capture(CAPTURE_EVALUATION),
create.Label(CommandsCommonMatchers::LABEL_EVALUATION),
create.Char(';')
});
}
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
{
static constexpr auto CAPTURE_TYPE = 1;
static constexpr auto CAPTURE_EVALUATION = 2;
protected:
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
{
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()
{
return !m_is_typedef && !m_variable_name.empty();
return true;
}
DataDefinition* HeaderBlockStruct::GetVariableType()

View File

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

View File

@ -1,6 +1,6 @@
#include "HeaderFileReader.h"
#include <algorithm>
#include <chrono>
#include <iostream>
@ -11,6 +11,9 @@
#include "Parsing/Impl/IncludingStreamProxy.h"
#include "Parsing/Impl/PackDefinitionStreamProxy.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)
: m_args(args),
@ -18,6 +21,7 @@ HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::
m_pack_value_supplier(nullptr),
m_stream(nullptr)
{
SetupPostProcessors();
}
bool HeaderFileReader::OpenBaseStream()
@ -51,6 +55,13 @@ void HeaderFileReader::SetupStreamProxies()
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)
{
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 start = std::chrono::steady_clock::now();
const auto result = parser->Parse();
auto result = parser->Parse();
if (result)
parser->SaveToRepository(repository);
result = parser->SaveToRepository(repository);
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;
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 "Parsing/IPackValueSupplier.h"
#include "Parsing/IParserLineStream.h"
#include "Parsing/PostProcessing/IPostProcessor.h"
#include "Persistence/IDataRepository.h"
class HeaderFileReader
@ -19,8 +20,11 @@ class HeaderFileReader
const IPackValueSupplier* m_pack_value_supplier;
IParserLineStream* m_stream;
std::vector<std::unique_ptr<IPostProcessor>> m_post_processors;
bool OpenBaseStream();
void SetupStreamProxies();
void SetupPostProcessors();
public:
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/TypedefDefinition.h"
#include "Domain/Definition/UnionDefinition.h"
#include "Domain/Environment/Architecture.h"
#include "Domain/Information/StructureInformation.h"
#include "Domain/FastFile/FastFileBlock.h"
@ -29,6 +30,8 @@ public:
_NODISCARD virtual const std::string& GetGameName() const = 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<StructDefinition*>& GetAllStructs() const = 0;
@ -38,6 +41,6 @@ public:
_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;
_NODISCARD virtual StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const = 0;
_NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0;
};

View File

@ -1,5 +1,10 @@
#include "InMemoryRepository.h"
InMemoryRepository::InMemoryRepository()
: m_architecture(Architecture::UNKNOWN)
{
}
InMemoryRepository::~InMemoryRepository()
{
for (auto* enumDefinition : m_enums)
@ -22,7 +27,7 @@ void InMemoryRepository::Add(std::unique_ptr<EnumDefinition> enumsDefinition)
m_enums.push_back(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();
}
@ -69,6 +74,16 @@ void InMemoryRepository::SetGame(std::string 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
{
return m_enums;
@ -109,7 +124,7 @@ DataDefinition* InMemoryRepository::GetDataDefinitionByName(const std::string& n
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);

View File

@ -14,11 +14,12 @@ class InMemoryRepository final : public IDataRepository
std::vector<FastFileBlock*> m_fast_file_blocks;
std::map<std::string, DataDefinition*> m_data_definitions_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;
Architecture m_architecture;
public:
InMemoryRepository() = default;
InMemoryRepository();
~InMemoryRepository() override;
InMemoryRepository(const InMemoryRepository& other) = delete;
InMemoryRepository(InMemoryRepository&& other) noexcept = default;
@ -34,6 +35,8 @@ public:
_NODISCARD const std::string& GetGameName() const 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<StructDefinition*>& GetAllStructs() const override;
@ -43,6 +46,6 @@ public:
_NODISCARD const std::vector<FastFileBlock*>& GetAllFastFileBlocks() 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;
};