diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dd13c61c..ebfdf004d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ add_executable(ImHex source/parser/lexer.cpp source/parser/parser.cpp + source/parser/validator.cpp source/provider/file_provider.cpp diff --git a/include/parser/validator.hpp b/include/parser/validator.hpp new file mode 100644 index 000000000..cf12c46a8 --- /dev/null +++ b/include/parser/validator.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "token.hpp" +#include "ast_node.hpp" + +#include +#include + +namespace hex::lang { + + class Validator { + public: + Validator(); + + bool validate(const std::vector& ast); + }; + +} \ No newline at end of file diff --git a/include/views/view_pattern.hpp b/include/views/view_pattern.hpp index cc6843b4f..952a34d7f 100644 --- a/include/views/view_pattern.hpp +++ b/include/views/view_pattern.hpp @@ -1,8 +1,6 @@ #pragma once #include "parser/ast_node.hpp" -#include "parser/parser.hpp" -#include "parser/lexer.hpp" #include "views/view.hpp" #include "views/pattern_data.hpp" diff --git a/source/parser/validator.cpp b/source/parser/validator.cpp new file mode 100644 index 000000000..585603979 --- /dev/null +++ b/source/parser/validator.cpp @@ -0,0 +1,68 @@ +#include "parser/validator.hpp" + +#include +#include + +namespace hex::lang { + + Validator::Validator() { + + } + + bool Validator::validate(const std::vector& ast) { + + std::unordered_set typeNames; + + for (const auto &node : ast) { + switch (node->getType()) { + case ASTNode::Type::VariableDecl: + { + // Check for duplicate variable names + auto varDeclNode = static_cast(node); + if (!typeNames.insert(varDeclNode->getVariableName()).second) + return false; + } + break; + case ASTNode::Type::TypeDecl: + { + // Check for duplicate type names + auto typeDeclNode = static_cast(node); + if (!typeNames.insert(typeDeclNode->getTypeName()).second) + return false; + } + break; + case ASTNode::Type::Struct: + { + // Check for duplicate type name + auto structNode = static_cast(node); + if (!typeNames.insert(structNode->getName()).second) + return false; + + // Check for duplicate member names + std::unordered_set memberNames; + for (const auto &member : structNode->getNodes()) + if (!memberNames.insert(static_cast(member)->getVariableName()).second) + return false; + } + break; + case ASTNode::Type::Enum: + { + // Check for duplicate type name + auto enumNode = static_cast(node); + if (!typeNames.insert(enumNode->getName()).second) + return false; + + // Check for duplicate constant names + std::unordered_set constantNames; + for (const auto &[value, name] : enumNode->getValues()) + if (!constantNames.insert(name).second) + return false; + } + break; + } + } + + return true; + } + +} \ No newline at end of file diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index fe592c0ad..c9859eb18 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -1,6 +1,9 @@ -#include #include "views/view_pattern.hpp" +#include +#include "parser/parser.hpp" +#include "parser/lexer.hpp" +#include "parser/validator.hpp" #include "utils.hpp" namespace hex { @@ -111,6 +114,7 @@ namespace hex { void ViewPattern::parsePattern(char *buffer) { static hex::lang::Lexer lexer; static hex::lang::Parser parser; + static hex::lang::Validator validator; this->clearPatternData(); this->postEvent(Events::PatternChanged); @@ -127,6 +131,12 @@ namespace hex { return; } + auto validatorResult = validator.validate(ast); + if (!validatorResult) { + for(auto &node : ast) delete node; + return; + } + for (auto &varNode : findNodes(lang::ASTNode::Type::VariableDecl, ast)) { if (!varNode->getOffset().has_value()) continue;