diff --git a/include/lang/ast_node.hpp b/include/lang/ast_node.hpp index 2ca0e8a51..afecffb63 100644 --- a/include/lang/ast_node.hpp +++ b/include/lang/ast_node.hpp @@ -192,7 +192,10 @@ namespace hex::lang { ASTNodeArrayVariableDecl(const ASTNodeArrayVariableDecl &other) : ASTNode(other) { this->m_name = other.m_name; this->m_type = other.m_type->clone(); - this->m_size = other.m_size->clone(); + if (other.m_size != nullptr) + this->m_size = other.m_size->clone(); + else + this->m_size = nullptr; if (other.m_placementOffset != nullptr) this->m_placementOffset = other.m_placementOffset->clone(); diff --git a/include/lang/pattern_data.hpp b/include/lang/pattern_data.hpp index 23277a620..52baa0959 100644 --- a/include/lang/pattern_data.hpp +++ b/include/lang/pattern_data.hpp @@ -28,6 +28,9 @@ namespace hex::lang { result += *c; } + if (*(data + size - 1) == '\x00') + result.pop_back(); + return result; } diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp index dcbe7d03a..0a7e4412e 100644 --- a/source/lang/evaluator.cpp +++ b/source/lang/evaluator.cpp @@ -512,27 +512,39 @@ namespace hex::lang { auto startOffset = this->m_currOffset; ASTNodeIntegerLiteral *valueNode; + u64 arraySize = 0; - if (auto sizeNumericExpression = dynamic_cast(node->getSize()); sizeNumericExpression != nullptr) - valueNode = evaluateMathematicalExpression(sizeNumericExpression); - else - throwEvaluateError("array size not a numeric expression", node->getLineNumber()); + if (node->getSize() != nullptr) { + if (auto sizeNumericExpression = dynamic_cast(node->getSize()); sizeNumericExpression != nullptr) + valueNode = evaluateMathematicalExpression(sizeNumericExpression); + else + throwEvaluateError("array size not a numeric expression", node->getLineNumber()); - SCOPE_EXIT( delete valueNode; ); + SCOPE_EXIT( delete valueNode; ); - auto arraySize = std::visit([node, type = valueNode->getType()] (auto &&value) { - if (Token::isFloatingPoint(type)) - throwEvaluateError("array size must be an integer value", node->getLineNumber()); - return static_cast(value); - }, valueNode->getValue()); + arraySize = std::visit([node, type = valueNode->getType()] (auto &&value) { + if (Token::isFloatingPoint(type)) + throwEvaluateError("array size must be an integer value", node->getLineNumber()); + return static_cast(value); + }, valueNode->getValue()); - if (auto typeDecl = dynamic_cast(node->getType()); typeDecl != nullptr) { - if (auto builtinType = dynamic_cast(typeDecl->getType()); builtinType != nullptr) { - if (builtinType->getType() == Token::ValueType::Padding) { - this->m_currOffset += arraySize; - return new PatternDataPadding(startOffset, arraySize); + if (auto typeDecl = dynamic_cast(node->getType()); typeDecl != nullptr) { + if (auto builtinType = dynamic_cast(typeDecl->getType()); builtinType != nullptr) { + if (builtinType->getType() == Token::ValueType::Padding) { + this->m_currOffset += arraySize; + return new PatternDataPadding(startOffset, arraySize); + } } } + } else { + u8 currByte = 0x00; + u64 offset = startOffset; + + do { + this->m_provider->read(offset, &currByte, sizeof(u8)); + offset += sizeof(u8); + arraySize += sizeof(u8); + } while (currByte != 0x00 && offset < this->m_provider->getSize()); } std::vector entries; @@ -563,12 +575,16 @@ namespace hex::lang { this->m_currEndian.reset(); PatternData *pattern; - if (entries.empty()) + if (entries.empty()) { pattern = new PatternDataPadding(startOffset, 0); + } else if (dynamic_cast(entries[0])) pattern = new PatternDataString(startOffset, (this->m_currOffset - startOffset), color.value_or(0)); - else + else { + if (node->getSize() == nullptr) + throwEvaluateError("no bounds provided for array", node->getLineNumber()); pattern = new PatternDataArray(startOffset, (this->m_currOffset - startOffset), entries, color.value_or(0)); + } pattern->setVariableName(node->getName().data()); diff --git a/source/lang/parser.cpp b/source/lang/parser.cpp index 267c2400b..d0e40917a 100644 --- a/source/lang/parser.cpp +++ b/source/lang/parser.cpp @@ -353,10 +353,18 @@ namespace hex::lang { SCOPE_EXIT( delete temporaryType; ); auto name = getValue(-2); - auto size = parseMathematicalExpression(); - if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) - throwParseError("expected closing ']' at end of array declaration", -1); + ASTNode *size = nullptr; + ScopeExit sizeCleanup([&]{ delete size; }); + + if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) { + size = parseMathematicalExpression(); + + if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) + throwParseError("expected closing ']' at end of array declaration", -1); + } + + sizeCleanup.release(); return new ASTNodeArrayVariableDecl(name, temporaryType->getType()->clone(), size); } @@ -558,21 +566,29 @@ namespace hex::lang { return new ASTNodeVariableDecl(getValue(-2), temporaryType->getType()->clone(), parseMathematicalExpression()); } - // (parseType) Identifier[(parseMathematicalExpression)] @ Integer + // (parseType) Identifier[[(parseMathematicalExpression)]] @ Integer ASTNode* Parser::parseArrayVariablePlacement() { auto temporaryType = dynamic_cast(parseType(-3)); if (temporaryType == nullptr) throwParseError("invalid type used in variable declaration", -1); SCOPE_EXIT( delete temporaryType; ); auto name = getValue(-2); - auto size = parseMathematicalExpression(); - if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) - throwParseError("expected closing ']' at end of array declaration", -1); + ASTNode *size = nullptr; + ScopeExit sizeCleanup([&]{ delete size; }); + + if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) { + size = parseMathematicalExpression(); + + if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) + throwParseError("expected closing ']' at end of array declaration", -1); + } if (!MATCHES(sequence(OPERATOR_AT))) throwParseError("expected placement instruction", -1); + sizeCleanup.release(); + return new ASTNodeArrayVariableDecl(name, temporaryType->getType()->clone(), size, parseMathematicalExpression()); }