2020-11-19 11:36:52 +01:00
|
|
|
#pragma once
|
|
|
|
|
2020-11-22 16:22:02 +01:00
|
|
|
#include <bit>
|
2021-08-29 22:15:18 +02:00
|
|
|
#include <map>
|
2021-09-21 21:29:18 +02:00
|
|
|
#include <optional>
|
2020-11-19 11:36:52 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
#include <hex/pattern_language/log_console.hpp>
|
|
|
|
#include <hex/api/content_registry.hpp>
|
2021-09-11 23:14:22 +02:00
|
|
|
|
2021-09-22 00:45:04 +02:00
|
|
|
#include <hex/helpers/fmt.hpp>
|
|
|
|
|
2021-08-29 22:15:18 +02:00
|
|
|
namespace hex::prv { class Provider; }
|
|
|
|
|
2021-09-08 15:18:24 +02:00
|
|
|
namespace hex::pl {
|
2020-11-19 11:36:52 +01:00
|
|
|
|
2021-08-29 22:15:18 +02:00
|
|
|
class PatternData;
|
2021-09-21 21:29:18 +02:00
|
|
|
class ASTNode;
|
2021-08-29 22:15:18 +02:00
|
|
|
|
2021-01-21 11:36:58 +01:00
|
|
|
class Evaluator {
|
|
|
|
public:
|
2021-01-23 14:00:09 +01:00
|
|
|
Evaluator() = default;
|
2021-01-09 23:48:42 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
std::optional<std::vector<PatternData*>> evaluate(const std::vector<ASTNode*> &ast);
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
LogConsole& getConsole() {
|
|
|
|
return this->m_console;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Scope { PatternData *parent; std::vector<PatternData*>* scope; };
|
2021-09-22 00:45:04 +02:00
|
|
|
void pushScope(PatternData *parent, std::vector<PatternData*> &scope) {
|
|
|
|
if (this->m_scopes.size() > this->m_evalDepth)
|
|
|
|
LogConsole::abortEvaluation(hex::format("recursion limit of {} reached", this->m_evalDepth));
|
|
|
|
|
|
|
|
this->m_scopes.push_back({ parent, &scope });
|
|
|
|
}
|
|
|
|
|
|
|
|
void popScope() {
|
|
|
|
this->m_scopes.pop_back();
|
|
|
|
}
|
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
const Scope& getScope(s32 index) {
|
|
|
|
static Scope empty;
|
2021-01-21 11:36:58 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
if (index > 0 || -index >= this->m_scopes.size()) return empty;
|
|
|
|
return this->m_scopes[this->m_scopes.size() - 1 + index];
|
|
|
|
}
|
2021-01-09 23:48:42 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
const Scope& getGlobalScope() {
|
|
|
|
return this->m_scopes.front();
|
|
|
|
}
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
void setProvider(prv::Provider *provider) {
|
|
|
|
this->m_provider = provider;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
prv::Provider *getProvider() const {
|
|
|
|
return this->m_provider;
|
|
|
|
}
|
2021-01-22 18:01:39 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
void setDefaultEndian(std::endian endian) {
|
|
|
|
this->m_defaultEndian = endian;
|
2021-01-22 18:01:39 +01:00
|
|
|
}
|
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
[[nodiscard]]
|
|
|
|
std::endian getDefaultEndian() const {
|
|
|
|
return this->m_defaultEndian;
|
|
|
|
}
|
|
|
|
|
2021-09-22 00:45:04 +02:00
|
|
|
void setEvaluationDepth(u32 evalDepth) {
|
|
|
|
this->m_evalDepth = evalDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
u32 getEvaluationDepth() const {
|
|
|
|
return this->m_evalDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setArrayLimit(u32 arrayLimit) {
|
|
|
|
this->m_arrayLimit = arrayLimit;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
u32 getArrayLimit() const {
|
|
|
|
return this->m_arrayLimit;
|
|
|
|
}
|
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
u64& dataOffset() { return this->m_currOffset; }
|
|
|
|
|
|
|
|
bool addCustomFunction(const std::string &name, u32 numParams, const ContentRegistry::PatternLanguageFunctions::Callback &function) {
|
|
|
|
const auto [iter, inserted] = this->m_customFunctions.insert({ name, { numParams, function } });
|
|
|
|
|
|
|
|
return inserted;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
const std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function>& getCustomFunctions() const {
|
|
|
|
return this->m_customFunctions;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
std::vector<Token::Literal>& getStack() {
|
|
|
|
return this->m_stack;
|
|
|
|
}
|
|
|
|
|
2021-09-23 23:43:16 +02:00
|
|
|
void createVariable(const std::string &name, ASTNode *type, const std::optional<Token::Literal> &value = std::nullopt);
|
2021-09-21 21:29:18 +02:00
|
|
|
|
|
|
|
void setVariable(const std::string &name, const Token::Literal& value);
|
|
|
|
|
2020-11-19 11:36:52 +01:00
|
|
|
private:
|
2021-09-21 21:29:18 +02:00
|
|
|
u64 m_currOffset;
|
|
|
|
prv::Provider *m_provider = nullptr;
|
2021-01-21 11:36:58 +01:00
|
|
|
LogConsole m_console;
|
Pattern Language rewrite (#111)
* Initial parser rewrite effort
Lexer and Token cleanup, Parser started over
* Greatly improved parser syntax
* Reimplemented using declarations and variable placement parsing
* Added back unions and structs
* Added enums as well as mathematical expressions (+, -, *, /, <<, >>, &, |, ^)
* Code style improvement
* Implemented arrays and fixed memory issues
* Fixed more memory issues in parser, reimplemented validator, evaluator and patterns
* Fixed builtin types, arrays and reimplemented strings
* Improved error messages
* Made character a distinct type, used for chars and strings
* Implemented padding, fixed arrays
* Added bitfields
* Added rvalue parsing, no evaluating yet
* Added .idea folder to gitignore
* Fixed build on MacOS
* Added custom implementation of integral concept if not available
* Rebased onto master
* Fixed array variable decl crash
* Added rvalues and dot syntax
* Lower case all pattern language error messages
* Fixed typo in variable name
* Fixed bug where preprocessor would not ignore commented out directives
* Reimplemented pointers
* Fixed rebase issues
2021-01-02 20:27:11 +01:00
|
|
|
|
2021-09-21 21:29:18 +02:00
|
|
|
std::endian m_defaultEndian = std::endian::native;
|
2021-09-22 00:45:04 +02:00
|
|
|
u32 m_evalDepth;
|
|
|
|
u32 m_arrayLimit;
|
2021-09-21 21:29:18 +02:00
|
|
|
|
|
|
|
std::vector<Scope> m_scopes;
|
|
|
|
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> m_customFunctions;
|
|
|
|
std::vector<ASTNode*> m_customFunctionDefinitions;
|
|
|
|
std::vector<Token::Literal> m_stack;
|
2020-11-19 11:36:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|