mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-30 13:05:25 -05:00
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
This commit is contained in:
@@ -4,130 +4,351 @@
|
||||
|
||||
#include <bit>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::lang {
|
||||
|
||||
class ASTNode {
|
||||
public:
|
||||
enum class Type {
|
||||
VariableDecl,
|
||||
TypeDecl,
|
||||
Struct,
|
||||
Union,
|
||||
Enum,
|
||||
Bitfield,
|
||||
Scope,
|
||||
};
|
||||
constexpr ASTNode() = default;
|
||||
constexpr virtual ~ASTNode() = default;
|
||||
constexpr ASTNode(const ASTNode &) = default;
|
||||
|
||||
explicit ASTNode(Type type, u32 lineNumber) : m_type(type), m_lineNumber(lineNumber) {}
|
||||
virtual ~ASTNode() = default;
|
||||
[[nodiscard]] constexpr u32 getLineNumber() const { return this->m_lineNumber; }
|
||||
constexpr void setLineNumber(u32 lineNumber) { this->m_lineNumber = lineNumber; }
|
||||
|
||||
Type getType() { return this->m_type; }
|
||||
u32 getLineNumber() { return this->m_lineNumber; }
|
||||
virtual ASTNode* clone() = 0;
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
u32 m_lineNumber;
|
||||
u32 m_lineNumber = 1;
|
||||
};
|
||||
|
||||
class ASTNodeVariableDecl : public ASTNode {
|
||||
class ASTNodeIntegerLiteral : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeVariableDecl(u32 lineNumber, const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "", std::optional<u64> offset = { }, size_t arraySize = 1, std::optional<std::string> arraySizeVariable = { }, std::optional<u8> pointerSize = { }, std::optional<std::endian> endianess = { })
|
||||
: ASTNode(Type::VariableDecl, lineNumber), m_type(type), m_name(name), m_customTypeName(customTypeName), m_offset(offset), m_arraySize(arraySize), m_arraySizeVariable(arraySizeVariable), m_pointerSize(pointerSize), m_endianess(endianess) { }
|
||||
ASTNodeIntegerLiteral(std::variant<u128, s128> value, Token::ValueType type)
|
||||
: ASTNode(), m_value(value), m_type(type) {
|
||||
|
||||
const Token::TypeToken::Type& getVariableType() const { return this->m_type; }
|
||||
const std::string& getCustomVariableTypeName() const { return this->m_customTypeName; }
|
||||
const std::string& getVariableName() const { return this->m_name; };
|
||||
std::optional<u64> getOffset() const { return this->m_offset; }
|
||||
size_t getArraySize() const { return this->m_arraySize; }
|
||||
std::optional<std::string> getArraySizeVariable() const { return this->m_arraySizeVariable; }
|
||||
std::optional<u8> getPointerSize() const { return this->m_pointerSize; }
|
||||
std::optional<std::endian> getEndianess() const { return this->m_endianess; }
|
||||
}
|
||||
ASTNodeIntegerLiteral(const ASTNodeIntegerLiteral&) = default;
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeIntegerLiteral(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const auto& getValue() const {
|
||||
return this->m_value;
|
||||
}
|
||||
|
||||
[[nodiscard]] Token::ValueType getType() const {
|
||||
return this->m_type;
|
||||
}
|
||||
|
||||
private:
|
||||
Token::TypeToken::Type m_type;
|
||||
std::string m_name, m_customTypeName;
|
||||
std::optional<u64> m_offset;
|
||||
size_t m_arraySize;
|
||||
std::optional<std::string> m_arraySizeVariable;
|
||||
std::optional<u8> m_pointerSize;
|
||||
std::optional<std::endian> m_endianess = { };
|
||||
std::variant<u128, s128> m_value;
|
||||
Token::ValueType m_type;
|
||||
};
|
||||
|
||||
class ASTNodeScope : public ASTNode {
|
||||
class ASTNodeNumericExpression : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeScope(u32 lineNumber, std::vector<ASTNode*> nodes) : ASTNode(Type::Scope, lineNumber), m_nodes(nodes) { }
|
||||
ASTNodeNumericExpression(ASTNode *left, ASTNode *right, Token::Operator op)
|
||||
: ASTNode(), m_left(left), m_right(right), m_operator(op) { }
|
||||
|
||||
~ASTNodeNumericExpression() override {
|
||||
delete this->m_left;
|
||||
delete this->m_right;
|
||||
}
|
||||
|
||||
ASTNodeNumericExpression(const ASTNodeNumericExpression &other) : ASTNode(other) {
|
||||
this->m_operator = other.m_operator;
|
||||
this->m_left = other.m_left->clone();
|
||||
this->m_right = other.m_right->clone();
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeNumericExpression(*this);
|
||||
}
|
||||
|
||||
ASTNode *getLeftOperand() { return this->m_left; }
|
||||
ASTNode *getRightOperand() { return this->m_right; }
|
||||
Token::Operator getOperator() { return this->m_operator; }
|
||||
|
||||
std::vector<ASTNode*> &getNodes() { return this->m_nodes; }
|
||||
private:
|
||||
std::vector<ASTNode*> m_nodes;
|
||||
ASTNode *m_left, *m_right;
|
||||
Token::Operator m_operator;
|
||||
};
|
||||
|
||||
class ASTNodeStruct : public ASTNode {
|
||||
class ASTNodeBuiltinType : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeStruct(u32 lineNumber, std::string name, std::vector<ASTNode*> nodes)
|
||||
: ASTNode(Type::Struct, lineNumber), m_name(name), m_nodes(nodes) { }
|
||||
constexpr explicit ASTNodeBuiltinType(Token::ValueType type)
|
||||
: ASTNode(), m_type(type) { }
|
||||
|
||||
[[nodiscard]] constexpr const auto& getType() const { return this->m_type; }
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeBuiltinType(*this);
|
||||
}
|
||||
|
||||
const std::string& getName() const { return this->m_name; }
|
||||
std::vector<ASTNode*> &getNodes() { return this->m_nodes; }
|
||||
private:
|
||||
std::string m_name;
|
||||
std::vector<ASTNode*> m_nodes;
|
||||
};
|
||||
|
||||
class ASTNodeUnion : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeUnion(u32 lineNumber, std::string name, std::vector<ASTNode*> nodes)
|
||||
: ASTNode(Type::Union, lineNumber), m_name(name), m_nodes(nodes) { }
|
||||
|
||||
const std::string& getName() const { return this->m_name; }
|
||||
std::vector<ASTNode*> &getNodes() { return this->m_nodes; }
|
||||
private:
|
||||
std::string m_name;
|
||||
std::vector<ASTNode*> m_nodes;
|
||||
};
|
||||
|
||||
class ASTNodeBitField : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeBitField(u32 lineNumber, std::string name, std::vector<std::pair<std::string, size_t>> fields)
|
||||
: ASTNode(Type::Bitfield, lineNumber), m_name(name), m_fields(fields) { }
|
||||
|
||||
const std::string& getName() const { return this->m_name; }
|
||||
std::vector<std::pair<std::string, size_t>> &getFields() { return this->m_fields; }
|
||||
private:
|
||||
std::string m_name;
|
||||
std::vector<std::pair<std::string, size_t>> m_fields;
|
||||
const Token::ValueType m_type;
|
||||
};
|
||||
|
||||
class ASTNodeTypeDecl : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeTypeDecl(u32 lineNumber, const Token::TypeToken::Type &type, const std::string &name, const std::string& customTypeName = "")
|
||||
: ASTNode(Type::TypeDecl, lineNumber), m_type(type), m_name(name), m_customTypeName(customTypeName) { }
|
||||
ASTNodeTypeDecl(std::string_view name, ASTNode *type, std::optional<std::endian> endian = { })
|
||||
: ASTNode(), m_name(name), m_type(type), m_endian(endian) { }
|
||||
|
||||
const std::string& getTypeName() const { return this->m_name; };
|
||||
ASTNodeTypeDecl(const ASTNodeTypeDecl& other) : ASTNode(other) {
|
||||
this->m_name = other.m_name;
|
||||
this->m_type = other.m_type->clone();
|
||||
this->m_endian = other.m_endian;
|
||||
}
|
||||
|
||||
~ASTNodeTypeDecl() override {
|
||||
delete this->m_type;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeTypeDecl(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getName() const { return this->m_name; }
|
||||
[[nodiscard]] ASTNode* getType() { return this->m_type; }
|
||||
[[nodiscard]] std::optional<std::endian> getEndian() const { return this->m_endian; }
|
||||
|
||||
const Token::TypeToken::Type& getAssignedType() const { return this->m_type; }
|
||||
const std::string& getAssignedCustomTypeName() const { return this->m_customTypeName; }
|
||||
private:
|
||||
Token::TypeToken::Type m_type;
|
||||
std::string m_name, m_customTypeName;
|
||||
std::string m_name;
|
||||
ASTNode *m_type;
|
||||
std::optional<std::endian> m_endian;
|
||||
};
|
||||
|
||||
class ASTNodeVariableDecl : public ASTNode {
|
||||
public:
|
||||
ASTNodeVariableDecl(std::string_view name, ASTNode *type, ASTNode *placementOffset = nullptr)
|
||||
: ASTNode(), m_name(name), m_type(type), m_placementOffset(placementOffset) { }
|
||||
|
||||
ASTNodeVariableDecl(const ASTNodeVariableDecl &other) : ASTNode(other) {
|
||||
this->m_name = other.m_name;
|
||||
this->m_type = other.m_type->clone();
|
||||
|
||||
if (other.m_placementOffset != nullptr)
|
||||
this->m_placementOffset = other.m_placementOffset->clone();
|
||||
else
|
||||
this->m_placementOffset = nullptr;
|
||||
}
|
||||
|
||||
~ASTNodeVariableDecl() override {
|
||||
delete this->m_type;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeVariableDecl(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getName() const { return this->m_name; }
|
||||
[[nodiscard]] constexpr ASTNode* getType() const { return this->m_type; }
|
||||
[[nodiscard]] constexpr auto getPlacementOffset() const { return this->m_placementOffset; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
ASTNode *m_type;
|
||||
ASTNode *m_placementOffset;
|
||||
};
|
||||
|
||||
class ASTNodeArrayVariableDecl : public ASTNode {
|
||||
public:
|
||||
ASTNodeArrayVariableDecl(std::string_view name, ASTNode *type, ASTNode *size, ASTNode *placementOffset = nullptr)
|
||||
: ASTNode(), m_name(name), m_type(type), m_size(size), m_placementOffset(placementOffset) { }
|
||||
|
||||
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_placementOffset != nullptr)
|
||||
this->m_placementOffset = other.m_placementOffset->clone();
|
||||
else
|
||||
this->m_placementOffset = nullptr;
|
||||
}
|
||||
|
||||
~ASTNodeArrayVariableDecl() override {
|
||||
delete this->m_type;
|
||||
delete this->m_size;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeArrayVariableDecl(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getName() const { return this->m_name; }
|
||||
[[nodiscard]] constexpr ASTNode* getType() const { return this->m_type; }
|
||||
[[nodiscard]] constexpr ASTNode* getSize() const { return this->m_size; }
|
||||
[[nodiscard]] constexpr auto getPlacementOffset() const { return this->m_placementOffset; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
ASTNode *m_type;
|
||||
ASTNode *m_size;
|
||||
ASTNode *m_placementOffset;
|
||||
};
|
||||
|
||||
class ASTNodePointerVariableDecl : public ASTNode {
|
||||
public:
|
||||
ASTNodePointerVariableDecl(std::string_view name, ASTNode *type, ASTNode *sizeType, ASTNode *placementOffset = nullptr)
|
||||
: ASTNode(), m_name(name), m_type(type), m_sizeType(sizeType), m_placementOffset(placementOffset) { }
|
||||
|
||||
ASTNodePointerVariableDecl(const ASTNodePointerVariableDecl &other) : ASTNode(other) {
|
||||
this->m_name = other.m_name;
|
||||
this->m_type = other.m_type->clone();
|
||||
this->m_sizeType = other.m_sizeType->clone();
|
||||
|
||||
if (other.m_placementOffset != nullptr)
|
||||
this->m_placementOffset = other.m_placementOffset->clone();
|
||||
else
|
||||
this->m_placementOffset = nullptr;
|
||||
}
|
||||
|
||||
~ASTNodePointerVariableDecl() override {
|
||||
delete this->m_type;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodePointerVariableDecl(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getName() const { return this->m_name; }
|
||||
[[nodiscard]] constexpr ASTNode* getType() const { return this->m_type; }
|
||||
[[nodiscard]] constexpr ASTNode* getSizeType() const { return this->m_sizeType; }
|
||||
[[nodiscard]] constexpr auto getPlacementOffset() const { return this->m_placementOffset; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
ASTNode *m_type;
|
||||
ASTNode *m_sizeType;
|
||||
ASTNode *m_placementOffset;
|
||||
};
|
||||
|
||||
class ASTNodeStruct : public ASTNode {
|
||||
public:
|
||||
ASTNodeStruct() : ASTNode() { }
|
||||
|
||||
ASTNodeStruct(const ASTNodeStruct &other) : ASTNode(other) {
|
||||
for (const auto &otherMember : other.getMembers())
|
||||
this->m_members.push_back(otherMember->clone());
|
||||
}
|
||||
|
||||
~ASTNodeStruct() override {
|
||||
for (auto &member : this->m_members)
|
||||
delete member;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeStruct(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<ASTNode*>& getMembers() const { return this->m_members; }
|
||||
void addMember(ASTNode *node) { this->m_members.push_back(node); }
|
||||
|
||||
private:
|
||||
std::vector<ASTNode*> m_members;
|
||||
};
|
||||
|
||||
class ASTNodeUnion : public ASTNode {
|
||||
public:
|
||||
ASTNodeUnion() : ASTNode() { }
|
||||
|
||||
ASTNodeUnion(const ASTNodeUnion &other) : ASTNode(other) {
|
||||
for (const auto &otherMember : other.getMembers())
|
||||
this->m_members.push_back(otherMember->clone());
|
||||
}
|
||||
|
||||
~ASTNodeUnion() override {
|
||||
for (auto &member : this->m_members)
|
||||
delete member;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeUnion(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<ASTNode*>& getMembers() const { return this->m_members; }
|
||||
void addMember(ASTNode *node) { this->m_members.push_back(node); }
|
||||
|
||||
private:
|
||||
std::vector<ASTNode*> m_members;
|
||||
};
|
||||
|
||||
class ASTNodeEnum : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeEnum(u32 lineNumber, const Token::TypeToken::Type &type, const std::string &name)
|
||||
: ASTNode(Type::Enum, lineNumber), m_type(type), m_name(name) { }
|
||||
explicit ASTNodeEnum(ASTNode *underlyingType) : ASTNode(), m_underlyingType(underlyingType) { }
|
||||
|
||||
const std::string& getName() const { return this->m_name; };
|
||||
ASTNodeEnum(const ASTNodeEnum &other) : ASTNode(other) {
|
||||
for (const auto &[name, entry] : other.getEntries())
|
||||
this->m_entries.emplace_back(name, entry->clone());
|
||||
this->m_underlyingType = other.m_underlyingType->clone();
|
||||
}
|
||||
|
||||
~ASTNodeEnum() override {
|
||||
for (auto &[name, expr] : this->m_entries)
|
||||
delete expr;
|
||||
delete this->m_underlyingType;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeEnum(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<std::pair<std::string, ASTNode*>>& getEntries() const { return this->m_entries; }
|
||||
void addEntry(const std::string &name, ASTNode* expression) { this->m_entries.emplace_back(name, expression); }
|
||||
|
||||
[[nodiscard]] const ASTNode *getUnderlyingType() const { return this->m_underlyingType; }
|
||||
|
||||
const Token::TypeToken::Type& getUnderlyingType() const { return this->m_type; }
|
||||
std::vector<std::pair<u64, std::string>>& getValues() { return this->m_values; }
|
||||
private:
|
||||
Token::TypeToken::Type m_type;
|
||||
std::string m_name;
|
||||
std::vector<std::pair<u64, std::string>> m_values;
|
||||
std::vector<std::pair<std::string, ASTNode*>> m_entries;
|
||||
ASTNode *m_underlyingType;
|
||||
};
|
||||
|
||||
class ASTNodeBitfield : public ASTNode {
|
||||
public:
|
||||
ASTNodeBitfield() : ASTNode() { }
|
||||
|
||||
ASTNodeBitfield(const ASTNodeBitfield &other) : ASTNode(other) {
|
||||
for (const auto &[name, entry] : other.getEntries())
|
||||
this->m_entries.emplace_back(name, entry->clone());
|
||||
}
|
||||
|
||||
~ASTNodeBitfield() override {
|
||||
for (auto &[name, expr] : this->m_entries)
|
||||
delete expr;
|
||||
}
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeBitfield(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<std::pair<std::string, ASTNode*>>& getEntries() const { return this->m_entries; }
|
||||
void addEntry(const std::string &name, ASTNode* size) { this->m_entries.emplace_back(name, size); }
|
||||
|
||||
private:
|
||||
std::vector<std::pair<std::string, ASTNode*>> m_entries;
|
||||
};
|
||||
|
||||
class ASTNodeRValue : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeRValue(std::vector<std::string> path) : ASTNode(), m_path(std::move(path)) { }
|
||||
|
||||
ASTNodeRValue(const ASTNodeRValue&) = default;
|
||||
|
||||
ASTNode* clone() override {
|
||||
return new ASTNodeRValue(*this);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getPath() {
|
||||
return this->m_path;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_path;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user