diff --git a/plugins/builtin/source/content/lang_builtin_functions.cpp b/plugins/builtin/source/content/lang_builtin_functions.cpp index 463a7b019..d2fcecb3f 100644 --- a/plugins/builtin/source/content/lang_builtin_functions.cpp +++ b/plugins/builtin/source/content/lang_builtin_functions.cpp @@ -153,36 +153,6 @@ namespace hex::plugin::builtin { return nullptr; }); - /* addressof(rValueString) */ - ContentRegistry::PatternLanguageFunctions::add("addressof", 1, [](auto &ctx, auto params) -> ASTNode* { - auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString(); - - std::vector path = splitString(name, "."); - auto pattern = ctx.patternFromName(path); - - return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getOffset()) }); - }); - - /* sizeof(rValueString) */ - ContentRegistry::PatternLanguageFunctions::add("sizeof", 1, [](auto &ctx, auto params) -> ASTNode* { - auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString(); - - std::vector path = splitString(name, "."); - auto pattern = ctx.patternFromName(path); - - return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getSize()) }); - }); - - /* nextAfter(rValueString) */ - ContentRegistry::PatternLanguageFunctions::add("nextAfter", 1, [](auto &ctx, auto params) -> ASTNode* { - auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString(); - - std::vector path = splitString(name, "."); - auto pattern = ctx.patternFromName(path); - - return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getOffset() + pattern->getSize()) }); - }); - /* alignTo(alignment, value) */ ContentRegistry::PatternLanguageFunctions::add("alignTo", 2, [](auto &ctx, auto params) -> ASTNode* { auto alignment = AS_TYPE(ASTNodeIntegerLiteral, params[0])->getValue(); diff --git a/plugins/libimhex/include/hex/lang/ast_node.hpp b/plugins/libimhex/include/hex/lang/ast_node.hpp index 402df433b..79f62e381 100644 --- a/plugins/libimhex/include/hex/lang/ast_node.hpp +++ b/plugins/libimhex/include/hex/lang/ast_node.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace hex::lang { @@ -394,20 +395,29 @@ namespace hex::lang { class ASTNodeRValue : public ASTNode { public: - explicit ASTNodeRValue(std::vector path) : ASTNode(), m_path(std::move(path)) { } + using Path = std::vector>; + + explicit ASTNodeRValue(Path path) : ASTNode(), m_path(std::move(path)) { } ASTNodeRValue(const ASTNodeRValue&) = default; + ~ASTNodeRValue() override { + for (auto &part : this->m_path) { + if (auto node = std::get_if(&part); node != nullptr) + delete *node; + } + } + [[nodiscard]] ASTNode* clone() const override { return new ASTNodeRValue(*this); } - const std::vector& getPath() { + const Path& getPath() { return this->m_path; } private: - std::vector m_path; + Path m_path; }; class ASTNodeScopeResolution : public ASTNode { @@ -557,4 +567,35 @@ namespace hex::lang { std::optional m_value; }; + class ASTNodeTypeOperator : public ASTNode { + public: + ASTNodeTypeOperator(Token::Operator op, ASTNode *expression) : m_op(op), m_expression(expression) { + + } + + ASTNodeTypeOperator(const ASTNodeTypeOperator &other) : ASTNode(other) { + this->m_op = other.m_op; + this->m_expression = other.m_expression->clone(); + } + + [[nodiscard]] ASTNode* clone() const override { + return new ASTNodeTypeOperator(*this); + } + + ~ASTNodeTypeOperator() override { + delete this->m_expression; + } + + Token::Operator getOperator() const { + return this->m_op; + } + + ASTNode* getExpression() const { + return this->m_expression; + } + + private: + Token::Operator m_op; + ASTNode *m_expression; + }; } \ No newline at end of file diff --git a/plugins/libimhex/include/hex/lang/evaluator.hpp b/plugins/libimhex/include/hex/lang/evaluator.hpp index efe3660a1..182a7d46f 100644 --- a/plugins/libimhex/include/hex/lang/evaluator.hpp +++ b/plugins/libimhex/include/hex/lang/evaluator.hpp @@ -28,7 +28,7 @@ namespace hex::lang { void setProvider(prv::Provider *provider) { this->m_provider = provider; } [[nodiscard]] std::endian getCurrentEndian() const { return this->m_endianStack.back(); } - PatternData* patternFromName(const std::vector &name); + PatternData* patternFromName(const ASTNodeRValue::Path &name); template T* asType(ASTNode *param) { @@ -56,12 +56,13 @@ namespace hex::lang { ASTNodeIntegerLiteral* evaluateScopeResolution(ASTNodeScopeResolution *node); ASTNodeIntegerLiteral* evaluateRValue(ASTNodeRValue *node); ASTNode* evaluateFunctionCall(ASTNodeFunctionCall *node); + ASTNodeIntegerLiteral* evaluateTypeOperator(ASTNodeTypeOperator *typeOperatorNode); ASTNodeIntegerLiteral* evaluateOperator(ASTNodeIntegerLiteral *left, ASTNodeIntegerLiteral *right, Token::Operator op); ASTNodeIntegerLiteral* evaluateOperand(ASTNode *node); ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node); ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node); - PatternData* findPattern(std::vector currMembers, const std::vector &path); + PatternData* findPattern(std::vector currMembers, const ASTNodeRValue::Path &path); PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern); PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node); void evaluateMember(ASTNode *node, std::vector &currMembers, bool increaseOffset); diff --git a/plugins/libimhex/include/hex/lang/parser.hpp b/plugins/libimhex/include/hex/lang/parser.hpp index f0d1dc76a..b330523cc 100644 --- a/plugins/libimhex/include/hex/lang/parser.hpp +++ b/plugins/libimhex/include/hex/lang/parser.hpp @@ -54,7 +54,7 @@ namespace hex::lang { ASTNode* parseFunctionCall(); ASTNode* parseStringLiteral(); ASTNode* parseScopeResolution(std::vector &path); - ASTNode* parseRValue(std::vector &path); + ASTNode* parseRValue(ASTNodeRValue::Path &path); ASTNode* parseFactor(); ASTNode* parseUnaryExpression(); ASTNode* parseMultiplicativeExpression(); diff --git a/plugins/libimhex/include/hex/lang/token.hpp b/plugins/libimhex/include/hex/lang/token.hpp index 18e860045..7bbf51a16 100644 --- a/plugins/libimhex/include/hex/lang/token.hpp +++ b/plugins/libimhex/include/hex/lang/token.hpp @@ -61,7 +61,9 @@ namespace hex::lang { BoolXor, BoolNot, TernaryConditional, - Dollar + Dollar, + AddressOf, + SizeOf }; enum class ValueType { @@ -251,6 +253,8 @@ namespace hex::lang { #define OPERATOR_BOOLNOT COMPONENT(Operator, BoolNot) #define OPERATOR_TERNARYCONDITIONAL COMPONENT(Operator, TernaryConditional) #define OPERATOR_DOLLAR COMPONENT(Operator, Dollar) +#define OPERATOR_ADDRESSOF COMPONENT(Operator, AddressOf) +#define OPERATOR_SIZEOF COMPONENT(Operator, SizeOf) #define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType) #define VALUETYPE_PADDING COMPONENT(ValueType, Padding) diff --git a/plugins/libimhex/include/hex/lang/validator.hpp b/plugins/libimhex/include/hex/lang/validator.hpp index 069e6eda9..96d279de2 100644 --- a/plugins/libimhex/include/hex/lang/validator.hpp +++ b/plugins/libimhex/include/hex/lang/validator.hpp @@ -15,7 +15,6 @@ namespace hex::lang { Validator(); bool validate(const std::vector& ast); - void printAST(const std::vector& ast); const std::pair& getError() { return this->m_error; } diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index 36692dd1b..1b7fd5a18 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -30,43 +30,73 @@ namespace hex::lang { this->getConsole().abortEvaluation("failed to find identifier"); } - PatternData* Evaluator::findPattern(std::vector currMembers, const std::vector &path) { + PatternData* Evaluator::findPattern(std::vector currMembers, const ASTNodeRValue::Path &path) { PatternData *currPattern = nullptr; - for (const auto &identifier : path) { - if (identifier == "parent") { - if (currPattern == nullptr) { - if (!currMembers.empty()) - currPattern = this->m_currMemberScope.back(); + for (const auto &part : path) { + if (auto stringPart = std::get_if(&part); stringPart != nullptr) { + if (*stringPart == "parent") { + if (currPattern == nullptr) { + if (!currMembers.empty()) + currPattern = this->m_currMemberScope.back(); - if (currPattern == nullptr) - this->getConsole().abortEvaluation("attempted to get parent of global namespace"); - } + if (currPattern == nullptr) + this->getConsole().abortEvaluation("attempted to get parent of global namespace"); + } - auto parent = currPattern->getParent(); + auto parent = currPattern->getParent(); - if (parent == nullptr) { - this->getConsole().abortEvaluation(hex::format("no parent available for identifier '{0}'", currPattern->getVariableName())); + if (parent == nullptr) { + this->getConsole().abortEvaluation(hex::format("no parent available for identifier '{0}'", currPattern->getVariableName())); + } else { + currPattern = parent; + } } else { - currPattern = parent; - } - } else { - if (currPattern != nullptr) { - if (auto structPattern = dynamic_cast(currPattern); structPattern != nullptr) - currMembers = structPattern->getMembers(); - else if (auto unionPattern = dynamic_cast(currPattern); unionPattern != nullptr) - currMembers = unionPattern->getMembers(); + if (currPattern != nullptr) { + if (auto structPattern = dynamic_cast(currPattern); structPattern != nullptr) + currMembers = structPattern->getMembers(); + else if (auto unionPattern = dynamic_cast(currPattern); unionPattern != nullptr) + currMembers = unionPattern->getMembers(); + else if (auto arrayPattern = dynamic_cast(currPattern); arrayPattern != nullptr) { + currMembers = arrayPattern->getEntries(); + continue; + } + else + this->getConsole().abortEvaluation("tried to access member of a non-struct/union type"); + } + + auto candidate = std::find_if(currMembers.begin(), currMembers.end(), [&](auto member) { + return member->getVariableName() == *stringPart; + }); + + if (candidate != currMembers.end()) + currPattern = *candidate; else - this->getConsole().abortEvaluation("tried to access member of a non-struct/union type"); + this->getConsole().abortEvaluation(hex::format("no member found with identifier '{0}'", *stringPart)); } + } else if (auto nodePart = std::get_if(&part); nodePart != nullptr) { + if (auto numericalExpressionNode = dynamic_cast(*nodePart)) { + auto arrayIndexNode = evaluateMathematicalExpression(numericalExpressionNode); + ON_SCOPE_EXIT { delete arrayIndexNode; }; - auto candidate = std::find_if(currMembers.begin(), currMembers.end(), [&](auto member) { - return member->getVariableName() == identifier; - }); + if (currPattern != nullptr) { + if (auto arrayPattern = dynamic_cast(currPattern); arrayPattern != nullptr) { + if (Token::isFloatingPoint(arrayIndexNode->getType())) + this->getConsole().abortEvaluation("cannot use float to index into array"); - if (candidate != currMembers.end()) - currPattern = *candidate; - else - this->getConsole().abortEvaluation(hex::format("no member found with identifier '{0}'", identifier)); + std::visit([&](auto &&arrayIndex){ + if (arrayIndex >= 0 && arrayIndex < arrayPattern->getEntries().size()) + currPattern = arrayPattern->getEntries()[arrayIndex]; + else + this->getConsole().abortEvaluation(hex::format("tried to access out of bounds index {} of '{}'", arrayIndex, currPattern->getVariableName())); + }, arrayIndexNode->getValue()); + + } + else + this->getConsole().abortEvaluation("tried to index into non-array type"); + } + } else { + this->getConsole().abortEvaluation(hex::format("invalid node in rvalue path. This is a bug!'")); + } } if (auto pointerPattern = dynamic_cast(currPattern); pointerPattern != nullptr) @@ -76,7 +106,7 @@ namespace hex::lang { return currPattern; } - PatternData* Evaluator::patternFromName(const std::vector &path) { + PatternData* Evaluator::patternFromName(const ASTNodeRValue::Path &path) { PatternData *currPattern = nullptr; @@ -90,56 +120,34 @@ namespace hex::lang { } // If still no pattern was found, the path is invalid - if (currPattern == nullptr) - this->getConsole().abortEvaluation(hex::format("no identifier with name '{}' was found", hex::combineStrings(path, "."))); + if (currPattern == nullptr) { + std::string identifier; + for (const auto& part : path) { + if (part.index() == 0) { + // Path part is a identifier + identifier += std::get(part); + } else if (part.index() == 1) { + // Path part is a array index + identifier += "[..]"; + } - return currPattern; - - /*std::vector currMembers; - - if (!this->m_currMembers.empty()) - std::copy(this->m_currMembers.back()->begin(), this->m_currMembers.back()->end(), std::back_inserter(currMembers)); - if (!this->m_globalMembers.empty()) - std::copy(this->m_globalMembers.begin(), this->m_globalMembers.end(), std::back_inserter(currMembers)); - - PatternData *currPattern = nullptr; - for (u32 i = 0; i < path.size(); i++) { - const auto &identifier = path[i]; - - if (auto structPattern = dynamic_cast(currPattern); structPattern != nullptr) - currMembers = structPattern->getMembers(); - else if (auto unionPattern = dynamic_cast(currPattern); unionPattern != nullptr) - currMembers = unionPattern->getMembers(); - else if (auto pointerPattern = dynamic_cast(currPattern); pointerPattern != nullptr) { - currPattern = pointerPattern->getPointedAtPattern(); - i--; - continue; + identifier += "."; } - else if (currPattern != nullptr) - this->getConsole().abortEvaluation("tried to access member of a non-struct/union type"); - - auto candidate = std::find_if(currMembers.begin(), currMembers.end(), [&](auto member) { - return member->getVariableName() == identifier; - }); - - if (candidate != currMembers.end()) - currPattern = *candidate; - else - this->getConsole().abortEvaluation(hex::format("could not find identifier '{0}'", identifier.c_str())); + identifier.pop_back(); + this->getConsole().abortEvaluation(hex::format("no identifier with name '{}' was found", identifier)); } - if (auto pointerPattern = dynamic_cast(currPattern); pointerPattern != nullptr) - currPattern = pointerPattern->getPointedAtPattern(); - - return currPattern;*/ + return currPattern; } ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) { if (this->m_currMembers.empty() && this->m_globalMembers.empty()) this->getConsole().abortEvaluation("no variables available"); - if (node->getPath().size() == 1 && node->getPath()[0] == "$") - return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset }); + if (node->getPath().size() == 1) { + if (auto part = std::get_if(&node->getPath()[0]); part != nullptr && *part == "$") + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset }); + } auto currPattern = this->patternFromName(node->getPath()); @@ -193,6 +201,8 @@ namespace hex::lang { for (auto ¶m : node->getParams()) { if (auto numericExpression = dynamic_cast(param); numericExpression != nullptr) evaluatedParams.push_back(this->evaluateMathematicalExpression(numericExpression)); + else if (auto typeOperatorExpression = dynamic_cast(param)) + evaluatedParams.push_back(this->evaluateTypeOperator(typeOperatorExpression)); else if (auto stringLiteral = dynamic_cast(param); stringLiteral != nullptr) evaluatedParams.push_back(stringLiteral->clone()); } @@ -218,6 +228,23 @@ namespace hex::lang { return function.func(*this, evaluatedParams); } + ASTNodeIntegerLiteral* Evaluator::evaluateTypeOperator(ASTNodeTypeOperator *typeOperatorNode) { + if (auto rvalue = dynamic_cast(typeOperatorNode->getExpression()); rvalue != nullptr) { + auto pattern = this->patternFromName(rvalue->getPath()); + + switch (typeOperatorNode->getOperator()) { + case Token::Operator::AddressOf: + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() }); + case Token::Operator::SizeOf: + return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getSize() }); + default: + this->getConsole().abortEvaluation("invalid type operator used. This is a bug!"); + } + } else { + this->getConsole().abortEvaluation("non-rvalue used in type operator"); + } + } + #define FLOAT_BIT_OPERATION(name) \ auto name(hex::floating_point auto left, auto right) { throw std::runtime_error(""); return 0; } \ auto name(auto left, hex::floating_point auto right) { throw std::runtime_error(""); return 0; } \ @@ -365,7 +392,8 @@ namespace hex::lang { return integerNode; else this->getConsole().abortEvaluation("function not returning a numeric value used in expression"); - } + } else if (auto typeOperator = dynamic_cast(node); typeOperator != nullptr) + return evaluateTypeOperator(typeOperator); else this->getConsole().abortEvaluation("invalid operand"); } diff --git a/plugins/libimhex/source/lang/lexer.cpp b/plugins/libimhex/source/lang/lexer.cpp index 392f80cf2..9f587abc3 100644 --- a/plugins/libimhex/source/lang/lexer.cpp +++ b/plugins/libimhex/source/lang/lexer.cpp @@ -365,7 +365,15 @@ namespace hex::lang { } else if (c == '$') { tokens.emplace_back(TOKEN(Operator, Dollar)); offset += 1; - } else if (c == '\'') { + } else if (code.substr(offset, 9) == "addressof") { + tokens.emplace_back(TOKEN(Operator, AddressOf)); + offset += 9; + } + else if (code.substr(offset, 6) == "sizeof") { + tokens.emplace_back(TOKEN(Operator, SizeOf)); + offset += 6; + } + else if (c == '\'') { auto character = getCharacterLiteral(code.substr(offset)); if (!character.has_value()) diff --git a/plugins/libimhex/source/lang/parser.cpp b/plugins/libimhex/source/lang/parser.cpp index 13aadc537..c2bc224de 100644 --- a/plugins/libimhex/source/lang/parser.cpp +++ b/plugins/libimhex/source/lang/parser.cpp @@ -66,19 +66,25 @@ namespace hex::lang { } // - ASTNode* Parser::parseRValue(std::vector &path) { + ASTNode* Parser::parseRValue(ASTNodeRValue::Path &path) { if (peek(IDENTIFIER, -1)) path.push_back(getValue(-1)); else if (peek(KEYWORD_PARENT, -1)) path.emplace_back("parent"); + if (MATCHES(sequence(SEPARATOR_SQUAREBRACKETOPEN))) { + path.push_back(parseMathematicalExpression()); + if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE))) + throwParseError("expected closing ']' at end of array indexing"); + } + if (MATCHES(sequence(SEPARATOR_DOT))) { if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) return this->parseRValue(path); else throwParseError("expected member name or 'parent' keyword", -1); } else - return TO_NUMERIC_EXPRESSION(new ASTNodeRValue(path)); + return new ASTNodeRValue(path); } // @@ -87,8 +93,10 @@ namespace hex::lang { return TO_NUMERIC_EXPRESSION(new ASTNodeIntegerLiteral(getValue(-1))); else if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETOPEN))) { auto node = this->parseMathematicalExpression(); - if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) + if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) { + delete node; throwParseError("expected closing parenthesis"); + } return node; } else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SCOPE_RESOLUTION))) { std::vector path; @@ -97,10 +105,24 @@ namespace hex::lang { } else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_ROUNDBRACKETOPEN))) { return TO_NUMERIC_EXPRESSION(this->parseFunctionCall()); } else if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) { - std::vector path; - return this->parseRValue(path); + ASTNodeRValue::Path path; + return TO_NUMERIC_EXPRESSION(this->parseRValue(path)); } else if (MATCHES(sequence(OPERATOR_DOLLAR))) { return new ASTNodeRValue({ "$" }); + } else if (MATCHES(oneOf(OPERATOR_ADDRESSOF, OPERATOR_SIZEOF) && sequence(SEPARATOR_ROUNDBRACKETOPEN))) { + auto op = getValue(-2); + + if (!MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) { + throwParseError("expected rvalue identifier"); + } + + ASTNodeRValue::Path path; + auto node = new ASTNodeTypeOperator(op, this->parseRValue(path)); + if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) { + delete node; + throwParseError("expected closing parenthesis"); + } + return TO_NUMERIC_EXPRESSION(node); } else throwParseError("expected integer or parenthesis"); } diff --git a/plugins/libimhex/source/lang/validator.cpp b/plugins/libimhex/source/lang/validator.cpp index 0e2cabf90..a028de4c4 100644 --- a/plugins/libimhex/source/lang/validator.cpp +++ b/plugins/libimhex/source/lang/validator.cpp @@ -50,114 +50,4 @@ namespace hex::lang { return true; } - - void Validator::printAST(const std::vector& ast){ - #if DEBUG - #define INDENT_VALUE indent, ' ' - static s32 indent = -2; - - indent += 2; - for (const auto &node : ast) { - if (auto variableDeclNode = dynamic_cast(node); variableDeclNode != nullptr) { - if (auto offset = dynamic_cast(variableDeclNode->getPlacementOffset()); offset != nullptr) { - printf("%*c ASTNodeVariableDecl (%s) @\n", INDENT_VALUE, variableDeclNode->getName().data()); - printAST({ offset }); - } - else - printf("%*c ASTNodeVariableDecl (%s)\n", INDENT_VALUE, variableDeclNode->getName().data()); - printAST({ variableDeclNode->getType() }); - } else if (auto pointerDeclNode = dynamic_cast(node); pointerDeclNode != nullptr) { - if (auto offset = dynamic_cast(pointerDeclNode->getPlacementOffset()); offset != nullptr) { - printf("%*c ASTNodePointerVariableDecl (*%s) @\n", INDENT_VALUE, pointerDeclNode->getName().data()); - printAST({ offset }); - } - else - printf("%*c ASTNodePointerVariableDecl (*%s)\n", INDENT_VALUE, pointerDeclNode->getName().data()); - printAST({ pointerDeclNode->getType() }); - printAST({ pointerDeclNode->getSizeType() }); - } else if (auto arrayDeclNode = dynamic_cast(node); arrayDeclNode != nullptr) { - auto sizeExpr = dynamic_cast(arrayDeclNode->getSize()); - if (sizeExpr == nullptr) { - printf("%*c Invalid size!\n", INDENT_VALUE); - continue; - } - - if (auto offset = dynamic_cast(arrayDeclNode->getPlacementOffset()); offset != nullptr) { - printf("%*c ASTNodeArrayVariableDecl (%s[]) @\n", INDENT_VALUE, arrayDeclNode->getName().data()); - printAST({ sizeExpr }); - printAST({ offset }); - } - else { - printf("%*c ASTNodeArrayVariableDecl (%s[])\n", INDENT_VALUE, arrayDeclNode->getName().data()); - printAST({ sizeExpr }); - } - - printAST({ arrayDeclNode->getType() }); - printAST({ arrayDeclNode->getSize() }); - } else if (auto typeDeclNode = dynamic_cast(node); typeDeclNode != nullptr) { - printf("%*c ASTNodeTypeDecl (%s %s)\n", INDENT_VALUE, typeDeclNode->getEndian().value_or(std::endian::native) == std::endian::little ? "le" : "be", typeDeclNode->getName().empty() ? "" : typeDeclNode->getName().data()); - printAST({ typeDeclNode->getType() }); - } else if (auto builtinTypeNode = dynamic_cast(node); builtinTypeNode != nullptr) { - std::string typeName = Token::getTypeName(builtinTypeNode->getType()); - printf("%*c ASTNodeTypeDecl (%s)\n", INDENT_VALUE, typeName.c_str()); - } else if (auto integerLiteralNode = dynamic_cast(node); integerLiteralNode != nullptr) { - printf("%*c ASTNodeIntegerLiteral %lld\n", INDENT_VALUE, (s64)std::get(integerLiteralNode->getValue())); - } else if (auto numericExpressionNode = dynamic_cast(node); numericExpressionNode != nullptr) { - std::string op; - switch (numericExpressionNode->getOperator()) { - case Token::Operator::Plus: op = "+"; break; - case Token::Operator::Minus: op = "-"; break; - case Token::Operator::Star: op = "*"; break; - case Token::Operator::Slash: op = "/"; break; - - case Token::Operator::ShiftLeft: op = ">>"; break; - case Token::Operator::ShiftRight: op = "<<"; break; - - case Token::Operator::BitAnd: op = "&"; break; - case Token::Operator::BitOr: op = "|"; break; - case Token::Operator::BitXor: op = "^"; break; - default: op = "???"; - } - printf("%*c ASTNodeNumericExpression %s\n", INDENT_VALUE, op.c_str()); - printf("%*c Left:\n", INDENT_VALUE); - printAST({ numericExpressionNode->getLeftOperand() }); - printf("%*c Right:\n", INDENT_VALUE); - printAST({ numericExpressionNode->getRightOperand() }); - } else if (auto structNode = dynamic_cast(node); structNode != nullptr) { - printf("%*c ASTNodeStruct\n", INDENT_VALUE); - printAST(structNode->getMembers()); - } else if (auto unionNode = dynamic_cast(node); unionNode != nullptr) { - printf("%*c ASTNodeUnion\n", INDENT_VALUE); - printAST(unionNode->getMembers()); - } else if (auto enumNode = dynamic_cast(node); enumNode != nullptr) { - printf("%*c ASTNodeEnum\n", INDENT_VALUE); - - for (const auto &[name, entry] : enumNode->getEntries()) { - printf("%*c ::%s\n", INDENT_VALUE, name.c_str()); - printAST({ entry }); - } - } else if (auto bitfieldNode = dynamic_cast(node); bitfieldNode != nullptr) { - printf("%*c ASTNodeBitfield\n", INDENT_VALUE); - - for (const auto &[name, entry] : bitfieldNode->getEntries()) { - printf("%*c %s : \n", INDENT_VALUE, name.c_str()); - printAST({ entry }); - } - } else if (auto rvalueNode = dynamic_cast(node); rvalueNode != nullptr) { - printf("%*c ASTNodeRValue\n", INDENT_VALUE); - - printf("%*c ", INDENT_VALUE); - for (const auto &path : rvalueNode->getPath()) - printf("%s.", path.c_str()); - printf("\n"); - } else { - printf("%*c Invalid AST node!\n", INDENT_VALUE); - } - } - indent -= 2; - - #undef INDENT_VALUE - #endif - } - } \ No newline at end of file diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index 128d0c6f3..115341059 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -15,7 +15,7 @@ namespace hex { static TextEditor::LanguageDefinition langDef; if (!initialized) { static const char* const keywords[] = { - "using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "parent" + "using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "parent", "addressof", "sizeof" }; for (auto& k : keywords) langDef.mKeywords.insert(k);