diff --git a/plugins/libimhex/include/hex/lang/evaluator.hpp b/plugins/libimhex/include/hex/lang/evaluator.hpp index 50b85a2aa..c289be06e 100644 --- a/plugins/libimhex/include/hex/lang/evaluator.hpp +++ b/plugins/libimhex/include/hex/lang/evaluator.hpp @@ -17,13 +17,14 @@ namespace hex::lang { class Evaluator { public: - Evaluator(prv::Provider* &provider, std::endian defaultDataEndian = std::endian::native); + Evaluator() = default; std::optional> evaluate(const std::vector& ast); LogConsole& getConsole() { return this->m_console; } void setDefaultEndian(std::endian endian) { this->m_defaultDataEndian = endian; } + 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); @@ -38,8 +39,8 @@ namespace hex::lang { private: std::map m_types; - prv::Provider* &m_provider; - std::endian m_defaultDataEndian; + prv::Provider* m_provider = nullptr; + std::endian m_defaultDataEndian = std::endian::native; u64 m_currOffset = 0; std::vector m_endianStack; std::vector m_globalMembers; diff --git a/plugins/libimhex/include/hex/lang/pattern_language.hpp b/plugins/libimhex/include/hex/lang/pattern_language.hpp index 8bb32b72c..9156eca91 100644 --- a/plugins/libimhex/include/hex/lang/pattern_language.hpp +++ b/plugins/libimhex/include/hex/lang/pattern_language.hpp @@ -23,14 +23,14 @@ namespace hex::lang { class PatternLanguage { public: - PatternLanguage(prv::Provider *provider); + PatternLanguage(); ~PatternLanguage(); - std::optional> executeString(std::string_view string); - std::optional> executeFile(std::string_view path); + std::optional> executeString(prv::Provider *provider, std::string_view string); + std::optional> executeFile(prv::Provider *provider, std::string_view path); - std::vector> getConsoleLog(); - std::optional> getError(); + const std::vector>& getConsoleLog(); + const std::optional>& getError(); private: Preprocessor *m_preprocessor; diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index d9de1f59e..e1c1bfc56 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -11,10 +11,6 @@ namespace hex::lang { - Evaluator::Evaluator(prv::Provider* &provider, std::endian defaultDataEndian) - : m_provider(provider), m_defaultDataEndian(defaultDataEndian) { - } - ASTNodeIntegerLiteral* Evaluator::evaluateScopeResolution(ASTNodeScopeResolution *node) { ASTNode *currScope = nullptr; for (const auto &identifier : node->getPath()) { @@ -743,6 +739,12 @@ namespace hex::lang { std::optional> Evaluator::evaluate(const std::vector &ast) { + this->m_globalMembers.clear(); + this->m_currMembers.clear(); + this->m_types.clear(); + this->m_endianStack.clear(); + this->m_currOffset = 0; + try { for (const auto& node : ast) { this->m_endianStack.push_back(this->m_defaultDataEndian); @@ -764,13 +766,10 @@ namespace hex::lang { } } catch (LogConsole::EvaluateError &e) { this->getConsole().log(LogConsole::Level::Error, e); - this->m_endianStack.clear(); return { }; } - this->m_endianStack.clear(); - return this->m_globalMembers; } diff --git a/plugins/libimhex/source/lang/pattern_language.cpp b/plugins/libimhex/source/lang/pattern_language.cpp index 367d94a59..ae6144c5d 100644 --- a/plugins/libimhex/source/lang/pattern_language.cpp +++ b/plugins/libimhex/source/lang/pattern_language.cpp @@ -13,12 +13,27 @@ namespace hex::lang { - PatternLanguage::PatternLanguage(prv::Provider *provider) : m_provider(provider) { + PatternLanguage::PatternLanguage() { this->m_preprocessor = new Preprocessor(); this->m_lexer = new Lexer(); this->m_parser = new Parser(); this->m_validator = new Validator(); - this->m_evaluator = new Evaluator(provider); + this->m_evaluator = new Evaluator(); + + this->m_preprocessor->addPragmaHandler("endian", [this](std::string value) { + if (value == "big") { + this->m_defaultEndian = std::endian::big; + return true; + } else if (value == "little") { + this->m_defaultEndian = std::endian::little; + return true; + } else if (value == "native") { + this->m_defaultEndian = std::endian::native; + return true; + } else + return false; + }); + this->m_preprocessor->addDefaultPragmaHandlers(); } PatternLanguage::~PatternLanguage() { @@ -30,68 +45,45 @@ namespace hex::lang { } - std::optional> PatternLanguage::executeString(std::string_view string) { + std::optional> PatternLanguage::executeString(prv::Provider *provider, std::string_view string) { this->m_currError.reset(); this->m_evaluator->getConsole().clear(); + this->m_evaluator->setProvider(provider); - hex::lang::Preprocessor preprocessor; - - std::endian defaultEndian; - preprocessor.addPragmaHandler("endian", [&defaultEndian](std::string value) { - if (value == "big") { - defaultEndian = std::endian::big; - return true; - } else if (value == "little") { - defaultEndian = std::endian::little; - return true; - } else if (value == "native") { - defaultEndian = std::endian::native; - return true; - } else - return false; - }); - preprocessor.addDefaultPragmaHandlers(); - - auto preprocessedCode = preprocessor.preprocess(string.data()); + auto preprocessedCode = this->m_preprocessor->preprocess(string.data()); if (!preprocessedCode.has_value()) { - this->m_currError = preprocessor.getError(); + this->m_currError = this->m_preprocessor->getError(); return { }; } - hex::lang::Lexer lexer; - auto tokens = lexer.lex(preprocessedCode.value()); + auto tokens = this->m_lexer->lex(preprocessedCode.value()); if (!tokens.has_value()) { - this->m_currError = lexer.getError(); + this->m_currError = this->m_lexer->getError(); return { }; } - hex::lang::Parser parser; - auto ast = parser.parse(tokens.value()); + auto ast = this->m_parser->parse(tokens.value()); if (!ast.has_value()) { - this->m_currError = parser.getError(); + this->m_currError = this->m_parser->getError(); return { }; } SCOPE_EXIT( for(auto &node : ast.value()) delete node; ); - hex::lang::Validator validator; - auto validatorResult = validator.validate(ast.value()); + auto validatorResult = this->m_validator->validate(ast.value()); if (!validatorResult) { - this->m_currError = validator.getError(); + this->m_currError = this->m_validator->getError(); return { }; } - auto provider = SharedData::currentProvider; - hex::lang::Evaluator evaluator(provider, defaultEndian); - - auto patternData = evaluator.evaluate(ast.value()); + auto patternData = this->m_evaluator->evaluate(ast.value()); if (!patternData.has_value()) return { }; return patternData.value(); } - std::optional> PatternLanguage::executeFile(std::string_view path) { + std::optional> PatternLanguage::executeFile(prv::Provider *provider, std::string_view path) { FILE *file = fopen(path.data(), "r"); if (file == nullptr) return { }; @@ -105,15 +97,15 @@ namespace hex::lang { fclose(file); - return this->executeString(code); + return this->executeString(provider, code); } - std::vector> PatternLanguage::getConsoleLog() { + const std::vector>& PatternLanguage::getConsoleLog() { return this->m_evaluator->getConsole().getLog(); } - std::optional> PatternLanguage::getError() { + const std::optional>& PatternLanguage::getError() { return this->m_currError; } diff --git a/source/views/view_pattern.cpp b/source/views/view_pattern.cpp index e3f412ca0..a9424cdd5 100644 --- a/source/views/view_pattern.cpp +++ b/source/views/view_pattern.cpp @@ -75,7 +75,7 @@ namespace hex { ViewPattern::ViewPattern(std::vector &patternData) : View("Pattern"), m_patternData(patternData) { - this->m_patternLanguageRuntime = new lang::PatternLanguage(SharedData::currentProvider); + this->m_patternLanguageRuntime = new lang::PatternLanguage(); this->m_textEditor.SetLanguageDefinition(PatternLanguage()); this->m_textEditor.SetShowWhitespaces(false); @@ -335,16 +335,19 @@ namespace hex { this->m_console.clear(); this->postEvent(Events::PatternChanged); - auto result = this->m_patternLanguageRuntime->executeString(buffer); + auto result = this->m_patternLanguageRuntime->executeString(SharedData::currentProvider, buffer); - if (!result.has_value()) { - this->m_textEditor.SetErrorMarkers({ this->m_patternLanguageRuntime->getError().value() }); + auto error = this->m_patternLanguageRuntime->getError(); + if (error.has_value()) { + this->m_textEditor.SetErrorMarkers({ error.value() }); } this->m_console = this->m_patternLanguageRuntime->getConsoleLog(); - this->m_patternData = result.value(); - View::postEvent(Events::PatternChanged); + if (result.has_value()) { + this->m_patternData = std::move(result.value()); + View::postEvent(Events::PatternChanged); + } } } \ No newline at end of file