From ed4ed6b43365e5ee00d453057b6c0da6d54a6d89 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 21 Nov 2020 20:19:33 +0100 Subject: [PATCH] Added array sizes based on other local variables --- include/lang/ast_node.hpp | 6 +++-- include/lang/evaluator.hpp | 4 +++- include/lang/pattern_data.hpp | 3 ++- source/lang/evaluator.cpp | 43 +++++++++++++++++++++++++++++++++-- source/lang/parser.cpp | 20 ++++++++++++---- source/lang/validator.cpp | 4 ++++ source/views/view_pattern.cpp | 6 ++--- 7 files changed, 73 insertions(+), 13 deletions(-) diff --git a/include/lang/ast_node.hpp b/include/lang/ast_node.hpp index d2a75bf0b..faa22649e 100644 --- a/include/lang/ast_node.hpp +++ b/include/lang/ast_node.hpp @@ -31,20 +31,22 @@ namespace hex::lang { class ASTNodeVariableDecl : public ASTNode { public: - explicit ASTNodeVariableDecl(const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "", std::optional offset = { }, size_t arraySize = 1) - : ASTNode(Type::VariableDecl), m_type(type), m_name(name), m_customTypeName(customTypeName), m_offset(offset), m_arraySize(arraySize) { } + explicit ASTNodeVariableDecl(const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "", std::optional offset = { }, size_t arraySize = 1, std::optional arraySizeVariable = { }) + : ASTNode(Type::VariableDecl), m_type(type), m_name(name), m_customTypeName(customTypeName), m_offset(offset), m_arraySize(arraySize), m_arraySizeVariable(arraySizeVariable) { } const Token::TypeToken::Type& getVariableType() const { return this->m_type; } const std::string& getCustomVariableTypeName() const { return this->m_customTypeName; } const std::string& getVariableName() const { return this->m_name; }; std::optional getOffset() const { return this->m_offset; } size_t getArraySize() const { return this->m_arraySize; } + std::optional getArraySizeVariable() const { return this->m_arraySizeVariable; } private: Token::TypeToken::Type m_type; std::string m_name, m_customTypeName; std::optional m_offset; size_t m_arraySize; + std::optional m_arraySizeVariable; }; class ASTNodeScope : public ASTNode { diff --git a/include/lang/evaluator.hpp b/include/lang/evaluator.hpp index e723804b9..44399a7d7 100644 --- a/include/lang/evaluator.hpp +++ b/include/lang/evaluator.hpp @@ -2,6 +2,7 @@ #include +#include "providers/provider.hpp" #include "lang/pattern_data.hpp" #include "ast_node.hpp" @@ -13,12 +14,13 @@ namespace hex::lang { class Evaluator { public: - Evaluator(); + Evaluator(prv::Provider* &provider); std::pair> evaluate(const std::vector& ast); private: std::unordered_map m_types; + prv::Provider* &m_provider; std::pair createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); std::pair createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset); diff --git a/include/lang/pattern_data.hpp b/include/lang/pattern_data.hpp index 070aab8f8..80bd0ff53 100644 --- a/include/lang/pattern_data.hpp +++ b/include/lang/pattern_data.hpp @@ -50,9 +50,10 @@ namespace hex::lang { [[nodiscard]] Type getPatternType() const { return this->m_type; } [[nodiscard]] u64 getOffset() const { return this->m_offset; } [[nodiscard]] size_t getSize() const { return this->m_size; } + [[nodiscard]] const std::string& getName() const { return this->m_name; } [[nodiscard]] u32 getColor() const { return this->m_color; } - [[nodiscard]] const std::string& getName() const { return this->m_name; } + void setColor(u32 color) { this->m_color = color; } virtual void createEntry(prv::Provider* &provider) = 0; virtual std::string getTypeName() = 0; diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp index 15982e622..a01f5f37d 100644 --- a/source/lang/evaluator.cpp +++ b/source/lang/evaluator.cpp @@ -5,7 +5,7 @@ namespace hex::lang { - Evaluator::Evaluator() { + Evaluator::Evaluator(prv::Provider* &provider) : m_provider(provider) { } @@ -52,6 +52,31 @@ namespace hex::lang { members.push_back(pattern); structSize += size; } + else if (member->getArraySizeVariable().has_value()) { + std::optional arraySize; + + + for (auto &prevMember : members) { + if (prevMember->getPatternType() == PatternData::Type::Unsigned && prevMember->getName() == member->getArraySizeVariable()) { + u64 value = 0; + this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize()); + arraySize = value; + } + } + + if (!arraySize.has_value()) + return { nullptr, 0 }; + + ASTNodeVariableDecl *processedMember = new ASTNodeVariableDecl(member->getVariableType(), member->getVariableName(), member->getCustomVariableTypeName(), member->getOffset(), arraySize.value()); + + const auto &[pattern, size] = this->createArrayPattern(processedMember, offset + structSize); + + if (pattern == nullptr) + return { nullptr, 0 }; + + members.push_back(pattern); + structSize += size; + } else if (member->getVariableType() != Token::TypeToken::Type::CustomType) { const auto &[pattern, size] = this->createBuiltInTypePattern(member, offset + structSize); @@ -173,18 +198,27 @@ namespace hex::lang { std::pair Evaluator::createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) { std::vector entries; + auto arraySizeVariable = varDeclNode->getArraySizeVariable(); + size_t arrayOffset = 0; + std::optional arrayColor; for (u32 i = 0; i < varDeclNode->getArraySize(); i++) { ASTNodeVariableDecl *nonArrayVarDeclNode = new ASTNodeVariableDecl(varDeclNode->getVariableType(), "[" + std::to_string(i) + "]", varDeclNode->getCustomVariableTypeName(), varDeclNode->getOffset(), 1); + if (varDeclNode->getVariableType() == Token::TypeToken::Type::Padding) { return { new PatternDataPadding(offset, varDeclNode->getArraySize()), varDeclNode->getArraySize() }; } else if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) { - const auto &[pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arrayOffset); + const auto& [pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arrayOffset); if (pattern == nullptr) return { nullptr, 0 }; + if (!arrayColor.has_value()) + arrayColor = pattern->getColor(); + + pattern->setColor(arrayColor.value()); + entries.push_back(pattern); arrayOffset += size; } else { @@ -193,6 +227,11 @@ namespace hex::lang { if (pattern == nullptr) return { nullptr, 0 }; + if (!arrayColor.has_value()) + arrayColor = pattern->getColor(); + + pattern->setColor(arrayColor.value()); + entries.push_back(pattern); arrayOffset += size; } diff --git a/source/lang/parser.cpp b/source/lang/parser.cpp index 98ab5ac10..d44638c0e 100644 --- a/source/lang/parser.cpp +++ b/source/lang/parser.cpp @@ -39,14 +39,22 @@ namespace hex::lang { return new ASTNodeVariableDecl(curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer); } - ASTNode* parsePaddingDecl(TokenIter &curr) { - return new ASTNodeVariableDecl(curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer); - } - ASTNode* parseCustomTypeArrayDecl(TokenIter &curr) { return new ASTNodeVariableDecl(Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer); } + ASTNode* parseBuiltinVariableArrayDecl(TokenIter &curr) { + return new ASTNodeVariableDecl(curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier); + } + + ASTNode* parseCustomTypeVariableArrayDecl(TokenIter &curr) { + return new ASTNodeVariableDecl(Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier); + } + + ASTNode* parsePaddingDecl(TokenIter &curr) { + return new ASTNodeVariableDecl(curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer); + } + ASTNode* parseFreeBuiltinVariableDecl(TokenIter &curr) { return new ASTNodeVariableDecl(curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer); } @@ -68,6 +76,10 @@ namespace hex::lang { nodes.push_back(parseBuiltinArrayDecl(curr)); 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)); + 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)); + 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)); 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; diff --git a/source/lang/validator.cpp b/source/lang/validator.cpp index ae752fee8..018df4cd5 100644 --- a/source/lang/validator.cpp +++ b/source/lang/validator.cpp @@ -21,6 +21,10 @@ namespace hex::lang { auto varDeclNode = static_cast(node); if (!typeNames.insert(varDeclNode->getVariableName()).second) return false; + + if (varDeclNode->getArraySize() == 0 && !varDeclNode->getArraySizeVariable().has_value() || + varDeclNode->getArraySize() != 0 && varDeclNode->getArraySizeVariable().has_value()) + return false; } break; case ASTNode::Type::TypeDecl: diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index 09d3982ea..b1496f918 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -85,7 +85,7 @@ namespace hex { magicFiles += entry.path().string() + MAGIC_PATH_SEPARATOR; } - std::vector buffer(this->m_dataProvider->getSize(), 0x00); + std::vector buffer(std::min(this->m_dataProvider->getSize(), size_t(0xFF'FFFF)), 0x00); this->m_dataProvider->read(0, buffer.data(), buffer.size()); std::string mimeType; @@ -172,7 +172,7 @@ namespace hex { this->loadPatternFile(this->m_fileBrowser.selected_path); } - if (ImGui::BeginPopupModal("Accept Pattern", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) { + if (ImGui::BeginPopupModal("Accept Pattern", nullptr, ImGuiWindowFlags_NoResize)) { ImGui::TextUnformatted("A pattern compatible with this data type has been found:"); ImGui::Text("%ls", this->m_possiblePatternFile.filename().c_str()); ImGui::NewLine(); @@ -241,7 +241,7 @@ namespace hex { hex::lang::Lexer lexer; hex::lang::Parser parser; hex::lang::Validator validator; - hex::lang::Evaluator evaluator; + hex::lang::Evaluator evaluator(this->m_dataProvider); this->clearPatternData(); this->postEvent(Events::PatternChanged);