diff --git a/include/lang/ast_node.hpp b/include/lang/ast_node.hpp index 52622c9bb..3840ff188 100644 --- a/include/lang/ast_node.hpp +++ b/include/lang/ast_node.hpp @@ -2,6 +2,7 @@ #include "token.hpp" +#include #include #include #include @@ -33,8 +34,8 @@ namespace hex::lang { class ASTNodeVariableDecl : public ASTNode { public: - explicit ASTNodeVariableDecl(u32 lineNumber, const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "", std::optional offset = { }, size_t arraySize = 1, std::optional arraySizeVariable = { }, std::optional pointerSize = { }) - : ASTNode(Type::VariableDecl, lineNumber), m_type(type), m_name(name), m_customTypeName(customTypeName), m_offset(offset), m_arraySize(arraySize), m_arraySizeVariable(arraySizeVariable), m_pointerSize(pointerSize) { } + explicit ASTNodeVariableDecl(u32 lineNumber, const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "", std::optional offset = { }, size_t arraySize = 1, std::optional arraySizeVariable = { }, std::optional pointerSize = { }, std::optional endianess = { }) + : ASTNode(Type::VariableDecl, lineNumber), m_type(type), m_name(name), m_customTypeName(customTypeName), m_offset(offset), m_arraySize(arraySize), m_arraySizeVariable(arraySizeVariable), m_pointerSize(pointerSize), m_endianess(endianess) { } const Token::TypeToken::Type& getVariableType() const { return this->m_type; } const std::string& getCustomVariableTypeName() const { return this->m_customTypeName; } @@ -43,6 +44,7 @@ namespace hex::lang { size_t getArraySize() const { return this->m_arraySize; } std::optional getArraySizeVariable() const { return this->m_arraySizeVariable; } std::optional getPointerSize() const { return this->m_pointerSize; } + std::optional getEndianess() const { return this->m_endianess; } private: Token::TypeToken::Type m_type; @@ -51,6 +53,7 @@ namespace hex::lang { size_t m_arraySize; std::optional m_arraySizeVariable; std::optional m_pointerSize; + std::optional m_endianess = { }; }; class ASTNodeScope : public ASTNode { diff --git a/include/lang/evaluator.hpp b/include/lang/evaluator.hpp index 9176818ff..78f5b3b91 100644 --- a/include/lang/evaluator.hpp +++ b/include/lang/evaluator.hpp @@ -15,7 +15,7 @@ namespace hex::lang { class Evaluator { public: - Evaluator(prv::Provider* &provider, std::endian dataEndianess); + Evaluator(prv::Provider* &provider, std::endian defaultDataEndianess); std::pair> evaluate(const std::vector& ast); @@ -24,7 +24,7 @@ namespace hex::lang { private: std::unordered_map m_types; prv::Provider* &m_provider; - std::endian m_dataEndianess; + std::endian m_defaultDataEndianess; std::pair m_error; diff --git a/include/lang/parser.hpp b/include/lang/parser.hpp index 8c9d9511c..84f5f68ee 100644 --- a/include/lang/parser.hpp +++ b/include/lang/parser.hpp @@ -22,17 +22,18 @@ namespace hex::lang { std::pair m_error; - ASTNode* parseBuiltinVariableDecl(TokenIter &curr); - ASTNode* parseCustomTypeVariableDecl(TokenIter &curr); - ASTNode* parseBuiltinPointerVariableDecl(TokenIter &curr); - ASTNode* parseCustomTypePointerVariableDecl(TokenIter &curr); - ASTNode* parseBuiltinArrayDecl(TokenIter &curr); - ASTNode* parseCustomTypeArrayDecl(TokenIter &curr); - ASTNode* parseBuiltinVariableArrayDecl(TokenIter &curr); - ASTNode* parseCustomTypeVariableArrayDecl(TokenIter &curr); + ASTNode* parseBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseBuiltinPointerVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseCustomTypePointerVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseBuiltinArrayDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseCustomTypeArrayDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseBuiltinVariableArrayDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseCustomTypeVariableArrayDecl(TokenIter &curr, bool hasEndianDef); ASTNode* parsePaddingDecl(TokenIter &curr); - ASTNode* parseFreeBuiltinVariableDecl(TokenIter &curr); - ASTNode* parseFreeCustomTypeVariableDecl(TokenIter &curr); + ASTNode* parseFreeBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseFreeCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef); + ASTNode* parseStruct(TokenIter &curr); ASTNode* parseUnion(TokenIter &curr); ASTNode* parseEnum(TokenIter &curr); diff --git a/include/lang/pattern_data.hpp b/include/lang/pattern_data.hpp index cf74a65e2..969413b52 100644 --- a/include/lang/pattern_data.hpp +++ b/include/lang/pattern_data.hpp @@ -35,8 +35,8 @@ namespace hex::lang { public: enum class Type { Padding, Unsigned, Signed, Float, Character, String, Struct, Union, Array, Enum }; - PatternData(Type type, u64 offset, size_t size, const std::string &name, u32 color = 0) - : m_type(type), m_offset(offset), m_size(size), m_color(color), m_name(name) { + PatternData(Type type, u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : m_type(type), m_offset(offset), m_size(size), m_name(name), m_endianess(endianess), m_color(color) { constexpr u32 Palette[] = { 0x50b4771f, 0x500e7fff, 0x502ca02c, 0x502827d6, 0x50bd6794, 0x504b568c, 0x50c277e3, 0x507f7f7f, 0x5022bdbc, 0x50cfbe17 }; if (color != 0) @@ -59,6 +59,9 @@ namespace hex::lang { [[nodiscard]] u32 getColor() const { return this->m_color; } void setColor(u32 color) { this->m_color = color; } + [[nodiscard]] std::endian getEndianess() const { return this->m_endianess; } + void setEndianess(std::endian endianess) { this->m_endianess = endianess; } + virtual void createEntry(prv::Provider* &provider) = 0; virtual std::string getTypeName() = 0; @@ -97,10 +100,10 @@ namespace hex::lang { provider->read(left->getOffset(), leftBuffer.data(), left->getSize()); provider->read(right->getOffset(), rightBuffer.data(), right->getSize()); - if (PatternData::s_endianess != std::endian::native) { + if (left->m_endianess != std::endian::native) std::reverse(leftBuffer.begin(), leftBuffer.end()); + if (right->m_endianess != std::endian::native) std::reverse(rightBuffer.begin(), rightBuffer.end()); - } if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) return leftBuffer > rightBuffer; @@ -124,7 +127,6 @@ namespace hex::lang { } static void resetPalette() { PatternData::s_paletteOffset = 0; } - static void setEndianess(std::endian endianess) { PatternData::s_endianess = endianess; } protected: void createDefaultEntry(std::string value) { @@ -150,7 +152,7 @@ namespace hex::lang { } protected: - static inline std::endian s_endianess = std::endian::native; + std::endian m_endianess = std::endian::native; private: Type m_type; @@ -166,7 +168,7 @@ namespace hex::lang { class PatternDataPadding : public PatternData { public: - PatternDataPadding(u64 offset, size_t size) : PatternData(Type::Padding, offset, size, "", 0x00FFFFFF) { } + PatternDataPadding(u64 offset, size_t size) : PatternData(Type::Padding, offset, size, "", { }, 0x00FFFFFF) { } void createEntry(prv::Provider* &provider) override { } @@ -178,15 +180,15 @@ namespace hex::lang { class PatternDataPointer : public PatternData { public: - PatternDataPointer(u64 offset, size_t size, const std::string &name, PatternData *pointedAt, u32 color = 0) - : PatternData(Type::Unsigned, offset, size, name, color), m_pointedAt(pointedAt) { + PatternDataPointer(u64 offset, size_t size, const std::string &name, PatternData *pointedAt, std::endian endianess, u32 color = 0) + : PatternData(Type::Unsigned, offset, size, name, endianess, color), m_pointedAt(pointedAt) { this->m_pointedAt->setName("*" + this->m_pointedAt->getName()); } void createEntry(prv::Provider* &provider) override { u64 data = 0; provider->read(this->getOffset(), &data, this->getSize()); - data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess); + data = hex::changeEndianess(data, this->getSize(), this->m_endianess); ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -228,12 +230,13 @@ namespace hex::lang { class PatternDataUnsigned : public PatternData { public: - PatternDataUnsigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(Type::Unsigned, offset, size, name, color) { } + PatternDataUnsigned(u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : PatternData(Type::Unsigned, offset, size, name, endianess, color) { } void createEntry(prv::Provider* &provider) override { u64 data = 0; provider->read(this->getOffset(), &data, this->getSize()); - data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess); + data = hex::changeEndianess(data, this->getSize(), this->m_endianess); this->createDefaultEntry(hex::format("%lu (0x%0*lx)", data, this->getSize() * 2, data)); } @@ -252,12 +255,13 @@ namespace hex::lang { class PatternDataSigned : public PatternData { public: - PatternDataSigned(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(Type::Signed, offset, size, name, color) { } + PatternDataSigned(u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : PatternData(Type::Signed, offset, size, name, endianess, color) { } void createEntry(prv::Provider* &provider) override { u64 data = 0; provider->read(this->getOffset(), &data, this->getSize()); - data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess); + data = hex::changeEndianess(data, this->getSize(), this->m_endianess); s64 signedData = signedData = hex::signExtend(data, this->getSize(), 64); @@ -278,20 +282,21 @@ namespace hex::lang { class PatternDataFloat : public PatternData { public: - PatternDataFloat(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(Type::Float, offset, size, name, color) { } + PatternDataFloat(u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : PatternData(Type::Float, offset, size, name, endianess, color) { } void createEntry(prv::Provider* &provider) override { double formatData = 0; if (this->getSize() == 4) { float data = 0; provider->read(this->getOffset(), &data, 4); - data = hex::changeEndianess(data, 4, PatternData::s_endianess); + data = hex::changeEndianess(data, 4, this->m_endianess); formatData = data; } else if (this->getSize() == 8) { double data = 0; provider->read(this->getOffset(), &data, 8); - data = hex::changeEndianess(data, 8, PatternData::s_endianess); + data = hex::changeEndianess(data, 8, this->m_endianess); formatData = data; } @@ -310,7 +315,8 @@ namespace hex::lang { class PatternDataCharacter : public PatternData { public: - PatternDataCharacter(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(Type::Character, offset, size, name, color) { } + PatternDataCharacter(u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : PatternData(Type::Character, offset, size, name, endianess, color) { } void createEntry(prv::Provider* &provider) override { char character; @@ -326,7 +332,8 @@ namespace hex::lang { class PatternDataString : public PatternData { public: - PatternDataString(u64 offset, size_t size, const std::string &name, u32 color = 0) : PatternData(Type::String, offset, size, name, color) { } + PatternDataString(u64 offset, size_t size, const std::string &name, std::endian endianess, u32 color = 0) + : PatternData(Type::String, offset, size, name, endianess, color) { } void createEntry(prv::Provider* &provider) override { std::vector buffer(this->getSize() + 1, 0x00); @@ -343,8 +350,8 @@ namespace hex::lang { class PatternDataArray : public PatternData { public: - PatternDataArray(u64 offset, size_t size, const std::string &name, const std::vector & entries, u32 color = 0) - : PatternData(Type::Array, offset, size, name, color), m_entries(entries) { } + PatternDataArray(u64 offset, size_t size, const std::string &name, std::endian endianess, const std::vector & entries, u32 color = 0) + : PatternData(Type::Array, offset, size, name, endianess, color), m_entries(entries) { } void createEntry(prv::Provider* &provider) override { ImGui::TableNextRow(); @@ -396,8 +403,8 @@ namespace hex::lang { class PatternDataStruct : public PatternData { public: - PatternDataStruct(u64 offset, size_t size, const std::string &name, const std::string &structName, const std::vector & members, u32 color = 0) - : PatternData(Type::Struct, offset, size, name, color), m_structName(structName), m_members(members), m_sortedMembers(members) { } + PatternDataStruct(u64 offset, size_t size, const std::string &name, std::endian endianess, const std::string &structName, const std::vector & members, u32 color = 0) + : PatternData(Type::Struct, offset, size, name, endianess, color), m_structName(structName), m_members(members), m_sortedMembers(members) { } void createEntry(prv::Provider* &provider) override { ImGui::TableNextRow(); @@ -454,8 +461,8 @@ namespace hex::lang { class PatternDataUnion : public PatternData { public: - PatternDataUnion(u64 offset, size_t size, const std::string &name, const std::string &unionName, const std::vector & members, u32 color = 0) - : PatternData(Type::Union, offset, size, name, color), m_unionName(unionName), m_members(members), m_sortedMembers(members) { } + PatternDataUnion(u64 offset, size_t size, const std::string &name, const std::string &unionName, const std::vector & members, std::endian endianess, u32 color = 0) + : PatternData(Type::Union, offset, size, name, endianess, color), m_unionName(unionName), m_members(members), m_sortedMembers(members) { } void createEntry(prv::Provider* &provider) override { ImGui::TableNextRow(); @@ -513,13 +520,13 @@ namespace hex::lang { class PatternDataEnum : public PatternData { public: - PatternDataEnum(u64 offset, size_t size, const std::string &name, const std::string &enumName, std::vector> enumValues, u32 color = 0) - : PatternData(Type::Enum, offset, size, name, color), m_enumName(enumName), m_enumValues(enumValues) { } + PatternDataEnum(u64 offset, size_t size, const std::string &name, const std::string &enumName, std::vector> enumValues, std::endian endianess, u32 color = 0) + : PatternData(Type::Enum, offset, size, name, endianess, color), m_enumName(enumName), m_enumValues(enumValues) { } void createEntry(prv::Provider* &provider) override { u64 value = 0; provider->read(this->getOffset(), &value, this->getSize()); - value = hex::changeEndianess(value, this->getSize(), PatternData::s_endianess); + value = hex::changeEndianess(value, this->getSize(), this->m_endianess); std::string valueString = this->m_enumName + "::"; @@ -567,13 +574,13 @@ namespace hex::lang { class PatternDataBitfield : public PatternData { public: - PatternDataBitfield(u64 offset, size_t size, const std::string &name, const std::string &bitfieldName, std::vector> fields, u32 color = 0) - : PatternData(Type::Enum, offset, size, name, color), m_bitfieldName(bitfieldName), m_fields(fields) { } + PatternDataBitfield(u64 offset, size_t size, const std::string &name, const std::string &bitfieldName, std::vector> fields, std::endian endianess, u32 color = 0) + : PatternData(Type::Enum, offset, size, name, endianess, color), m_bitfieldName(bitfieldName), m_fields(fields) { } void createEntry(prv::Provider* &provider) override { u64 value = 0; provider->read(this->getOffset(), &value, this->getSize()); - value = hex::changeEndianess(value, this->getSize(), PatternData::s_endianess); + value = hex::changeEndianess(value, this->getSize(), this->m_endianess); ImGui::TableNextRow(); ImGui::TableNextColumn(); diff --git a/include/lang/token.hpp b/include/lang/token.hpp index ef9554196..44aa2b2a3 100644 --- a/include/lang/token.hpp +++ b/include/lang/token.hpp @@ -28,7 +28,9 @@ namespace hex::lang { Union, Using, Enum, - Bitfield + Bitfield, + LittleEndian, + BigEndian } keyword; } keywordToken; struct IdentifierToken { diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp index d6bc05a74..faa52af42 100644 --- a/source/lang/evaluator.cpp +++ b/source/lang/evaluator.cpp @@ -5,8 +5,8 @@ namespace hex::lang { - Evaluator::Evaluator(prv::Provider* &provider, std::endian dataEndianess) : m_provider(provider), m_dataEndianess(dataEndianess) { - PatternData::setEndianess(dataEndianess); + Evaluator::Evaluator(prv::Provider* &provider, std::endian defaultDataEndianess) : m_provider(provider), m_defaultDataEndianess(defaultDataEndianess) { + } std::pair Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -28,7 +28,7 @@ namespace hex::lang { if (member->getPointerSize().has_value()) { this->m_provider->read(offset + structSize, &memberOffset, member->getPointerSize().value()); - memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess); + memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))); } else memberOffset = offset + structSize; @@ -58,7 +58,7 @@ namespace hex::lang { u64 value = 0; this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize()); - value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess); + value = hex::changeEndianess(value, prevMember->getSize(), prevMember->getEndianess()); arraySize = value; } @@ -83,8 +83,10 @@ namespace hex::lang { if (pattern == nullptr) return { nullptr, 0 }; + pattern->setEndianess(member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))); + if (member->getPointerSize().has_value()) { - members.push_back(new PatternDataPointer(offset + structSize, member->getPointerSize().value(), member->getVariableName(), pattern)); + members.push_back(new PatternDataPointer(offset + structSize, member->getPointerSize().value(), member->getVariableName(), pattern, member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)))); structSize += member->getPointerSize().value(); } else { @@ -93,7 +95,7 @@ namespace hex::lang { } } - return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), structNode->getName(), members, 0x00FFFFFF), structSize }; + return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), structNode->getName(), members, 0x00FFFFFF), structSize }; } std::pair Evaluator::createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -115,7 +117,7 @@ namespace hex::lang { if (member->getPointerSize().has_value()) { this->m_provider->read(offset + unionSize, &memberOffset, member->getPointerSize().value()); - memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess); + memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), member->getEndianess().value_or(this->m_defaultDataEndianess)); } else memberOffset = offset; @@ -148,7 +150,7 @@ namespace hex::lang { u64 value = 0; this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize()); - value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess); + value = hex::changeEndianess(value, prevMember->getSize(), prevMember->getEndianess()); arraySize = value; } @@ -178,8 +180,10 @@ namespace hex::lang { if (pattern == nullptr) return { nullptr, 0 }; + pattern->setEndianess(member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))); + if (member->getPointerSize().has_value()) { - members.push_back(new PatternDataPointer(offset, member->getPointerSize().value(), member->getVariableName(), pattern)); + members.push_back(new PatternDataPointer(offset, member->getPointerSize().value(), member->getVariableName(), pattern, member->getEndianess().value_or(this->m_defaultDataEndianess))); unionSize = std::max(size_t(member->getPointerSize().value()), unionSize); } else { @@ -188,7 +192,7 @@ namespace hex::lang { } } - return { new PatternDataUnion(offset, unionSize, varDeclNode->getVariableName(), unionNode->getName(), members, 0x00FFFFFF), unionSize }; + return { new PatternDataUnion(offset, unionSize, varDeclNode->getVariableName(), unionNode->getName(), members, varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), 0x00FFFFFF), unionSize }; } std::pair Evaluator::createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -201,7 +205,7 @@ namespace hex::lang { size_t size = getTypeSize(enumType->getUnderlyingType()); - return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues()), size }; + return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), size }; } std::pair Evaluator::createBitfieldPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -219,7 +223,7 @@ namespace hex::lang { size = std::bit_ceil(size) / 8; - return { new PatternDataBitfield(offset, size, varDeclNode->getVariableName(), bitfieldType->getName(), bitfieldType->getFields()), size }; + return { new PatternDataBitfield(offset, size, varDeclNode->getVariableName(), bitfieldType->getName(), bitfieldType->getFields(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), size }; } std::pair Evaluator::createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -236,8 +240,12 @@ namespace hex::lang { } else if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) { const auto& [pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arrayOffset); - if (pattern == nullptr) + if (pattern == nullptr) { + delete nonArrayVarDeclNode; return { nullptr, 0 }; + } + + pattern->setEndianess(varDeclNode->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))); if (!arrayColor.has_value()) arrayColor = pattern->getColor(); @@ -249,8 +257,12 @@ namespace hex::lang { } else { const auto &[pattern, size] = this->createCustomTypePattern(nonArrayVarDeclNode, offset + arrayOffset); - if (pattern == nullptr) + if (pattern == nullptr) { + delete nonArrayVarDeclNode; return { nullptr, 0 }; + } + + pattern->setEndianess(varDeclNode->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))); if (!arrayColor.has_value()) arrayColor = pattern->getColor(); @@ -264,13 +276,13 @@ namespace hex::lang { delete nonArrayVarDeclNode; } - return { new PatternDataArray(offset, arrayOffset, varDeclNode->getVariableName(), entries, arrayColor.value()), arrayOffset }; + return { new PatternDataArray(offset, arrayOffset, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), entries, arrayColor.value()), arrayOffset }; } std::pair Evaluator::createStringPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { size_t arraySize = varDeclNode->getArraySize(); - return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName()), arraySize }; + return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), arraySize }; } std::pair Evaluator::createCustomTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { @@ -314,21 +326,21 @@ namespace hex::lang { if (isSigned(type)) { if (typeSize == 1 && arraySize == 1) - return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName()), 1 }; + return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), 1 }; else if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else - return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize }; } else if (isUnsigned(varDeclNode->getVariableType())) { if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else - return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize }; } else if (isFloatingPoint(varDeclNode->getVariableType())) { if (arraySize > 1) return createArrayPattern(varDeclNode, offset); else - return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize }; + return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize }; } return { nullptr, 0 }; diff --git a/source/lang/lexer.cpp b/source/lang/lexer.cpp index f607f55b0..8099d830f 100644 --- a/source/lang/lexer.cpp +++ b/source/lang/lexer.cpp @@ -192,8 +192,12 @@ namespace hex::lang { tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Enum }, .lineNumber = lineNumber }); else if (identifier == "bitfield") tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Bitfield }, .lineNumber = lineNumber }); + else if (identifier == "be") + tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::BigEndian }, .lineNumber = lineNumber }); + else if (identifier == "le") + tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::LittleEndian }, .lineNumber = lineNumber }); - // Check for built-in types + // Check for built-in types else if (identifier == "u8") tokens.push_back({ .type = Token::Type::Type, .typeToken = { .type = Token::TypeToken::Type::Unsigned8Bit }, .lineNumber = lineNumber }); else if (identifier == "s8") diff --git a/source/lang/parser.cpp b/source/lang/parser.cpp index a3e3562a8..b21c57a13 100644 --- a/source/lang/parser.cpp +++ b/source/lang/parser.cpp @@ -25,15 +25,42 @@ namespace hex::lang { } - ASTNode* Parser::parseBuiltinVariableDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-3].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier); + ASTNode* Parser::parseBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-4].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier, "", {}, 1, {}, {}, endianess); + } + else + return new ASTNodeVariableDecl(curr[-3].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier); } - ASTNode* Parser::parseCustomTypeVariableDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-3].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier); + ASTNode* Parser::parseCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else return nullptr; + + return new ASTNodeVariableDecl(curr[-4].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier, {}, 1, {}, {}, endianess); + } + else + return new ASTNodeVariableDecl(curr[-3].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier); } - ASTNode* Parser::parseBuiltinPointerVariableDecl(TokenIter &curr) { + ASTNode* Parser::parseBuiltinPointerVariableDecl(TokenIter &curr, bool hasEndianDef) { auto pointerType = curr[-2].typeToken.type; if (!isUnsigned(pointerType)) { @@ -51,10 +78,23 @@ namespace hex::lang { return nullptr; } - return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType)); + + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else return nullptr; + + return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType), endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType)); } - ASTNode* Parser::parseCustomTypePointerVariableDecl(TokenIter &curr) { + ASTNode* Parser::parseCustomTypePointerVariableDecl(TokenIter &curr, bool hasEndianDef) { auto pointerType = curr[-2].typeToken.type; if (!isUnsigned(pointerType)) { @@ -72,35 +112,140 @@ namespace hex::lang { return nullptr; } - return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType)); + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-7].lineNumber,Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType), endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType)); } - ASTNode* Parser::parseBuiltinArrayDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer); + ASTNode* Parser::parseBuiltinArrayDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer, { }, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer); } - ASTNode* Parser::parseCustomTypeArrayDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer); + ASTNode* Parser::parseCustomTypeArrayDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-7].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer, { }, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer); } - ASTNode* Parser::parseBuiltinVariableArrayDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier); + ASTNode* Parser::parseBuiltinVariableArrayDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier); } - ASTNode* Parser::parseCustomTypeVariableArrayDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier); + ASTNode* Parser::parseCustomTypeVariableArrayDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-7].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier); } ASTNode* Parser::parsePaddingDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer); + return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer); } - ASTNode* Parser::parseFreeBuiltinVariableDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer); + ASTNode* Parser::parseFreeBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer, 1, { }, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer); } - ASTNode* Parser::parseFreeCustomTypeVariableDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-5].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer); + ASTNode* Parser::parseFreeCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef) { + if (hasEndianDef) { + std::endian endianess; + + if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian) + endianess = std::endian::little; + else if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian) + endianess = std::endian::big; + else { + this->m_error = { curr->lineNumber, "Expected be or le identifier" }; + return nullptr; + } + + return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer, 1, { }, { }, endianess); + } + else + return new ASTNodeVariableDecl(curr[-5].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer); } ASTNode* Parser::parseStruct(TokenIter &curr) { @@ -111,17 +256,17 @@ namespace hex::lang { while (!tryConsume(curr, {Token::Type::ScopeClose})) { if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinVariableDecl(curr)); + nodes.push_back(parseBuiltinVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypeVariableDecl(curr)); + nodes.push_back(parseCustomTypeVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinArrayDecl(curr)); + nodes.push_back(parseBuiltinArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypeArrayDecl(curr)); + nodes.push_back(parseCustomTypeArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinVariableArrayDecl(curr)); + nodes.push_back(parseBuiltinVariableArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypeVariableArrayDecl(curr)); + nodes.push_back(parseCustomTypeVariableArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Type, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) { if (curr[-5].typeToken.type != Token::TypeToken::Type::Padding) { for(auto &node : nodes) delete node; @@ -131,9 +276,25 @@ namespace hex::lang { } nodes.push_back(parsePaddingDecl(curr)); } else if (tryConsume(curr, {Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinPointerVariableDecl(curr)); + nodes.push_back(parseBuiltinPointerVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypePointerVariableDecl(curr)); + nodes.push_back(parseCustomTypePointerVariableDecl(curr, false)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypeVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypeArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinVariableArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypeVariableArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinPointerVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypePointerVariableDecl(curr, true)); else { for(auto &node : nodes) delete node; this->m_error = { curr->lineNumber, "Invalid sequence, expected member declaration" }; @@ -158,17 +319,29 @@ namespace hex::lang { while (!tryConsume(curr, {Token::Type::ScopeClose})) { if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinVariableDecl(curr)); + nodes.push_back(parseBuiltinVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypeVariableDecl(curr)); + nodes.push_back(parseCustomTypeVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinArrayDecl(curr)); + nodes.push_back(parseBuiltinArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypeArrayDecl(curr)); + nodes.push_back(parseCustomTypeArrayDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) - nodes.push_back(parseBuiltinPointerVariableDecl(curr)); + nodes.push_back(parseBuiltinPointerVariableDecl(curr, false)); else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) - nodes.push_back(parseCustomTypePointerVariableDecl(curr)); + nodes.push_back(parseCustomTypePointerVariableDecl(curr, false)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypeVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypeArrayDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) + nodes.push_back(parseBuiltinPointerVariableDecl(curr, true)); + else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression})) + nodes.push_back(parseCustomTypePointerVariableDecl(curr, true)); else { for(auto &node : nodes) delete node; this->m_error = { curr->lineNumber, "Invalid sequence, expected member declaration" }; @@ -390,7 +563,7 @@ namespace hex::lang { return { }; } - auto variableDecl = parseFreeBuiltinVariableDecl(curr); + auto variableDecl = parseFreeBuiltinVariableDecl(curr, false); program.push_back(variableDecl); @@ -404,7 +577,35 @@ namespace hex::lang { return { }; } - auto variableDecl = parseFreeCustomTypeVariableDecl(curr); + auto variableDecl = parseFreeCustomTypeVariableDecl(curr, false); + + program.push_back(variableDecl); + + return program; + + // Variable placement declaration with built-in type and big/little endian setting + } else if (tryConsume(curr, { Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::Operator, Token::Type::Integer, Token::Type::EndOfExpression})) { + if (curr[-3].operatorToken.op != Token::OperatorToken::Operator::AtDeclaration) { + this->m_error = { curr[-3].lineNumber, "Expected '@' after variable placement declaration" }; + for(auto &node : program) delete node; + return { }; + } + + auto variableDecl = parseFreeBuiltinVariableDecl(curr, true); + + program.push_back(variableDecl); + + return program; + + // Variable placement declaration with custom type and big/little endian setting + } else if (tryConsume(curr, { Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::Operator, Token::Type::Integer, Token::Type::EndOfExpression})) { + if (curr[-3].operatorToken.op != Token::OperatorToken::Operator::AtDeclaration) { + this->m_error = { curr[-3].lineNumber, "Expected '@' after variable placement declaration" }; + for(auto &node : program) delete node; + return { }; + } + + auto variableDecl = parseFreeCustomTypeVariableDecl(curr, true); program.push_back(variableDecl); diff --git a/source/views/view_help.cpp b/source/views/view_help.cpp index 006d16c24..51b49decb 100644 --- a/source/views/view_help.cpp +++ b/source/views/view_help.cpp @@ -110,11 +110,13 @@ namespace hex { ImGui::TextWrapped( "Normal variables as well as arrays are used to highlight and display values. " "It is possible to create arrays within structs and unions that use the value of a previously " - "declared variable as size."); + "declared variable as size. In order to override the native / globally set endianess setting, every " + "type in a variable declaration may be prefixed with be or le to turn only it into a big or little endian type."); drawCodeSegment("vars arrays", "u32 variable;\n" "s8 string[16];\n" - "u8 customSizedArray[variable];" + "u8 customSizedArray[variable];\n" + "be u32 bigEndianVariable;" ); drawTitle("Structs"); diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index 09ea7dcef..c74bc3099 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -18,7 +18,7 @@ namespace hex { static TextEditor::LanguageDefinition langDef; if (!initialized) { static const char* const keywords[] = { - "using", "struct", "union", "enum", "bitfield" + "using", "struct", "union", "enum", "bitfield", "be", "le" }; for (auto& k : keywords) langDef.mKeywords.insert(k); @@ -262,17 +262,17 @@ namespace hex { this->postEvent(Events::PatternChanged); hex::lang::Preprocessor preprocessor; - std::endian dataEndianess = std::endian::native; + std::endian defaultDataEndianess = std::endian::native; - preprocessor.addPragmaHandler("endian", [&dataEndianess](std::string value) { + preprocessor.addPragmaHandler("endian", [&defaultDataEndianess](std::string value) { if (value == "big") { - dataEndianess = std::endian::big; + defaultDataEndianess = std::endian::big; return true; } else if (value == "little") { - dataEndianess = std::endian::little; + defaultDataEndianess = std::endian::little; return true; } else if (value == "native") { - dataEndianess = std::endian::native; + defaultDataEndianess = std::endian::native; return true; } else return false; @@ -308,7 +308,7 @@ namespace hex { return; } - hex::lang::Evaluator evaluator(this->m_dataProvider, dataEndianess); + hex::lang::Evaluator evaluator(this->m_dataProvider, defaultDataEndianess); auto [evaluateResult, patternData] = evaluator.evaluate(ast); if (evaluateResult.failed()) { this->m_textEditor.SetErrorMarkers({ evaluator.getError() });