patterns: Added parent
keyword to access members of the parent struct
This commit is contained in:
parent
2d7dd36b0d
commit
907f25c231
@ -166,6 +166,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
std::vector<std::string> splitString(std::string_view string, std::string_view delimiter);
|
||||
std::string combineStrings(const std::vector<std::string> &strings, std::string_view delimiter = "");
|
||||
|
||||
std::string toEngineeringString(double value);
|
||||
|
||||
|
@ -46,6 +46,7 @@ namespace hex::lang {
|
||||
std::vector<std::endian> m_endianStack;
|
||||
std::vector<PatternData*> m_globalMembers;
|
||||
std::vector<std::vector<PatternData*>*> m_currMembers;
|
||||
std::vector<PatternData*> m_currMemberScope;
|
||||
LogConsole m_console;
|
||||
|
||||
u32 m_recursionLimit;
|
||||
@ -60,6 +61,7 @@ namespace hex::lang {
|
||||
ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node);
|
||||
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
||||
|
||||
PatternData* findPattern(std::vector<PatternData*> currMembers, const std::vector<std::string> &path);
|
||||
PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern);
|
||||
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
|
||||
void evaluateMember(ASTNode *node, std::vector<PatternData*> &currMembers, bool increaseOffset);
|
||||
|
@ -25,7 +25,7 @@ namespace hex::lang {
|
||||
if (iscntrl(*c) || *c > 0x7F)
|
||||
result += " ";
|
||||
else
|
||||
result += *c;
|
||||
result += static_cast<char>(*c);
|
||||
}
|
||||
|
||||
if (*(data + size - 1) == '\x00')
|
||||
@ -39,7 +39,7 @@ namespace hex::lang {
|
||||
class PatternData {
|
||||
public:
|
||||
PatternData(u64 offset, size_t size, u32 color = 0)
|
||||
: m_offset(offset), m_size(size), m_color(color) {
|
||||
: m_offset(offset), m_size(size), m_color(color), m_parent(nullptr) {
|
||||
constexpr u32 Palette[] = { 0x70b4771f, 0x700e7fff, 0x702ca02c, 0x702827d6, 0x70bd6794, 0x704b568c, 0x70c277e3, 0x707f7f7f, 0x7022bdbc, 0x70cfbe17 };
|
||||
|
||||
if (color != 0)
|
||||
@ -55,7 +55,10 @@ namespace hex::lang {
|
||||
virtual PatternData* clone() = 0;
|
||||
|
||||
[[nodiscard]] u64 getOffset() const { return this->m_offset; }
|
||||
void setOffset(u64 offset) { this->m_offset = offset; }
|
||||
|
||||
[[nodiscard]] size_t getSize() const { return this->m_size; }
|
||||
void setSize(size_t size) { this->m_size = size; }
|
||||
|
||||
[[nodiscard]] const std::string& getVariableName() const { return this->m_variableName; }
|
||||
void setVariableName(std::string name) { this->m_variableName = std::move(name); }
|
||||
@ -72,6 +75,9 @@ namespace hex::lang {
|
||||
[[nodiscard]] std::endian getEndian() const { return this->m_endian; }
|
||||
void setEndian(std::endian endian) { this->m_endian = endian; }
|
||||
|
||||
[[nodiscard]] PatternData* getParent() const { return this->m_parent; }
|
||||
void setParent(PatternData *parent) { this->m_parent = parent; }
|
||||
|
||||
virtual void createEntry(prv::Provider* &provider) = 0;
|
||||
[[nodiscard]] virtual std::string getFormattedName() const = 0;
|
||||
|
||||
@ -191,6 +197,8 @@ namespace hex::lang {
|
||||
std::string m_variableName;
|
||||
std::optional<std::string> m_comment;
|
||||
std::string m_typeName;
|
||||
|
||||
PatternData *m_parent;
|
||||
};
|
||||
|
||||
class PatternDataPadding : public PatternData {
|
||||
@ -211,11 +219,15 @@ namespace hex::lang {
|
||||
|
||||
class PatternDataPointer : public PatternData {
|
||||
public:
|
||||
PatternDataPointer(u64 offset, size_t size, PatternData *pointedAt, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_pointedAt(pointedAt) {
|
||||
PatternDataPointer(u64 offset, size_t size, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_pointedAt(nullptr) {
|
||||
this->m_pointedAt->setVariableName("*" + this->m_pointedAt->getVariableName());
|
||||
}
|
||||
|
||||
PatternDataPointer(const PatternDataPointer &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
this->m_pointedAt = other.m_pointedAt->clone();
|
||||
}
|
||||
|
||||
~PatternDataPointer() override {
|
||||
delete this->m_pointedAt;
|
||||
}
|
||||
@ -275,6 +287,10 @@ namespace hex::lang {
|
||||
return "Pointer";
|
||||
}
|
||||
|
||||
void setPointedAtPattern(PatternData *pattern) {
|
||||
this->m_pointedAt = pattern;
|
||||
}
|
||||
|
||||
[[nodiscard]] PatternData* getPointedAtPattern() {
|
||||
return this->m_pointedAt;
|
||||
}
|
||||
@ -448,16 +464,16 @@ namespace hex::lang {
|
||||
|
||||
class PatternDataArray : public PatternData {
|
||||
public:
|
||||
PatternDataArray(u64 offset, size_t size, std::vector<PatternData*> entries, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_entries(std::move(entries)) {
|
||||
|
||||
for (auto &entry : entries)
|
||||
entry->setColor(color);
|
||||
PatternDataArray(u64 offset, size_t size, u32 color = 0)
|
||||
: PatternData(offset, size, color) {
|
||||
}
|
||||
|
||||
PatternDataArray(const PatternDataArray &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
std::vector<PatternData*> entries;
|
||||
for (const auto &entry : other.m_entries)
|
||||
this->m_entries.push_back(entry->clone());
|
||||
entries.push_back(entry->clone());
|
||||
|
||||
this->setEntries(entries);
|
||||
}
|
||||
|
||||
~PatternDataArray() override {
|
||||
@ -522,18 +538,32 @@ namespace hex::lang {
|
||||
|
||||
return this->m_highlightedAddresses;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string getFormattedName() const override {
|
||||
return this->m_entries[0]->getTypeName() + "[" + std::to_string(this->m_entries.size()) + "]";
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<PatternData*>& getEntries() {
|
||||
return this->m_entries;
|
||||
}
|
||||
|
||||
void setEntries(const std::vector<PatternData*> &entries) {
|
||||
this->m_entries = entries;
|
||||
|
||||
for (auto &entry : this->m_entries) {
|
||||
entry->setColor(this->getColor());
|
||||
entry->setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<PatternData*> m_entries;
|
||||
};
|
||||
|
||||
class PatternDataStruct : public PatternData {
|
||||
public:
|
||||
PatternDataStruct(u64 offset, size_t size, const std::vector<PatternData*> & members, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_members(members), m_sortedMembers(members) { }
|
||||
PatternDataStruct(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color){
|
||||
}
|
||||
|
||||
PatternDataStruct(const PatternDataStruct &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
for (const auto &member : other.m_members)
|
||||
@ -607,10 +637,18 @@ namespace hex::lang {
|
||||
return "struct " + PatternData::getTypeName();
|
||||
}
|
||||
|
||||
const auto& getMembers() const {
|
||||
[[nodiscard]] const auto& getMembers() const {
|
||||
return this->m_members;
|
||||
}
|
||||
|
||||
void setMembers(const std::vector<PatternData*> & members) {
|
||||
this->m_members = members;
|
||||
this->m_sortedMembers = members;
|
||||
|
||||
for (auto &member : this->m_members)
|
||||
member->setParent(this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<PatternData*> m_members;
|
||||
std::vector<PatternData*> m_sortedMembers;
|
||||
@ -618,8 +656,9 @@ namespace hex::lang {
|
||||
|
||||
class PatternDataUnion : public PatternData {
|
||||
public:
|
||||
PatternDataUnion(u64 offset, size_t size, const std::vector<PatternData*> & members, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_members(members), m_sortedMembers(members) { }
|
||||
PatternDataUnion(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
|
||||
|
||||
}
|
||||
|
||||
PatternDataUnion(const PatternDataUnion &other) : PatternData(other.getOffset(), other.getSize(), other.getColor()) {
|
||||
for (const auto &member : other.m_members)
|
||||
@ -694,10 +733,18 @@ namespace hex::lang {
|
||||
return "union " + PatternData::getTypeName();;
|
||||
}
|
||||
|
||||
const auto& getMembers() const {
|
||||
[[nodiscard]] const auto& getMembers() const {
|
||||
return this->m_members;
|
||||
}
|
||||
|
||||
void setMembers(const std::vector<PatternData*> & members) {
|
||||
this->m_members = members;
|
||||
this->m_sortedMembers = members;
|
||||
|
||||
for (auto &member : this->m_members)
|
||||
member->setParent(this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<PatternData*> m_members;
|
||||
std::vector<PatternData*> m_sortedMembers;
|
||||
@ -705,8 +752,9 @@ namespace hex::lang {
|
||||
|
||||
class PatternDataEnum : public PatternData {
|
||||
public:
|
||||
PatternDataEnum(u64 offset, size_t size, std::vector<std::pair<Token::IntegerLiteral, std::string>> enumValues, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_enumValues(std::move(enumValues)) { }
|
||||
PatternDataEnum(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
|
||||
|
||||
}
|
||||
|
||||
PatternData* clone() override {
|
||||
return new PatternDataEnum(*this);
|
||||
@ -762,18 +810,23 @@ namespace hex::lang {
|
||||
return "enum " + PatternData::getTypeName();
|
||||
}
|
||||
|
||||
const auto& getEnumValues() const {
|
||||
[[nodiscard]] const auto& getEnumValues() const {
|
||||
return this->m_enumValues;
|
||||
}
|
||||
|
||||
void setEnumValues(const std::vector<std::pair<Token::IntegerLiteral, std::string>> &enumValues) {
|
||||
this->m_enumValues = enumValues;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Token::IntegerLiteral, std::string>> m_enumValues;
|
||||
};
|
||||
|
||||
class PatternDataBitfield : public PatternData {
|
||||
public:
|
||||
PatternDataBitfield(u64 offset, size_t size, std::vector<std::pair<std::string, size_t>> fields, u32 color = 0)
|
||||
: PatternData(offset, size, color), m_fields(std::move(fields)) { }
|
||||
PatternDataBitfield(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
|
||||
|
||||
}
|
||||
|
||||
PatternData* clone() override {
|
||||
return new PatternDataBitfield(*this);
|
||||
@ -800,8 +853,8 @@ namespace hex::lang {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
std::string valueString = "{ ";
|
||||
for (u64 i = 0; i < value.size(); i++)
|
||||
valueString += hex::format("{0:02X} ", value[i]);
|
||||
for (auto i : value)
|
||||
valueString += hex::format("{0:02X} ", i);
|
||||
valueString += "}";
|
||||
|
||||
ImGui::TextUnformatted(valueString.c_str());
|
||||
@ -842,13 +895,16 @@ namespace hex::lang {
|
||||
return "bitfield " + PatternData::getTypeName();
|
||||
}
|
||||
|
||||
const auto& getFields() const {
|
||||
[[nodiscard]] const auto& getFields() const {
|
||||
return this->m_fields;
|
||||
}
|
||||
|
||||
void setFields(const std::vector<std::pair<std::string, size_t>> &fields) {
|
||||
this->m_fields = fields;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<std::string, size_t>> m_fields;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -31,7 +31,8 @@ namespace hex::lang {
|
||||
LittleEndian,
|
||||
BigEndian,
|
||||
If,
|
||||
Else
|
||||
Else,
|
||||
Parent
|
||||
};
|
||||
|
||||
enum class Operator {
|
||||
@ -218,6 +219,7 @@ namespace hex::lang {
|
||||
#define KEYWORD_BE COMPONENT(Keyword, BigEndian)
|
||||
#define KEYWORD_IF COMPONENT(Keyword, If)
|
||||
#define KEYWORD_ELSE COMPONENT(Keyword, Else)
|
||||
#define KEYWORD_PARENT COMPONENT(Keyword, Parent)
|
||||
|
||||
#define INTEGER hex::lang::Token::Type::Integer, hex::lang::Token::IntegerLiteral(hex::lang::Token::ValueType::Any, u64(0))
|
||||
#define IDENTIFIER hex::lang::Token::Type::Identifier, ""
|
||||
|
@ -127,10 +127,20 @@ namespace hex {
|
||||
res.push_back(token);
|
||||
}
|
||||
|
||||
res.push_back(std::string(string.substr(start)));
|
||||
res.emplace_back(string.substr(start));
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string combineStrings(const std::vector<std::string> &strings, std::string_view delimiter) {
|
||||
std::string result;
|
||||
for (const auto &string : strings) {
|
||||
result += string;
|
||||
result += delimiter;
|
||||
}
|
||||
|
||||
return result.substr(0, result.length() - delimiter.length());
|
||||
}
|
||||
|
||||
std::string toEngineeringString(double value) {
|
||||
constexpr std::array Suffixes = { "a", "f", "p", "n", "u", "m", "", "k", "M", "G", "T", "P", "E" };
|
||||
|
||||
|
@ -30,8 +30,71 @@ namespace hex::lang {
|
||||
this->getConsole().abortEvaluation("failed to find identifier");
|
||||
}
|
||||
|
||||
PatternData* Evaluator::findPattern(std::vector<PatternData*> currMembers, const std::vector<std::string> &path) {
|
||||
PatternData *currPattern = nullptr;
|
||||
for (const auto &identifier : path) {
|
||||
if (identifier == "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");
|
||||
}
|
||||
|
||||
auto parent = currPattern->getParent();
|
||||
|
||||
if (parent == nullptr) {
|
||||
this->getConsole().abortEvaluation(hex::format("no parent available for identifier '{0}'", currPattern->getVariableName()));
|
||||
} else {
|
||||
currPattern = parent;
|
||||
}
|
||||
} else {
|
||||
if (currPattern != nullptr) {
|
||||
if (auto structPattern = dynamic_cast<PatternDataStruct*>(currPattern); structPattern != nullptr)
|
||||
currMembers = structPattern->getMembers();
|
||||
else if (auto unionPattern = dynamic_cast<PatternDataUnion*>(currPattern); unionPattern != nullptr)
|
||||
currMembers = unionPattern->getMembers();
|
||||
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() == identifier;
|
||||
});
|
||||
|
||||
if (candidate != currMembers.end())
|
||||
currPattern = *candidate;
|
||||
else
|
||||
this->getConsole().abortEvaluation(hex::format("no member found with identifier '{0}'", identifier));
|
||||
}
|
||||
|
||||
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
|
||||
currPattern = pointerPattern->getPointedAtPattern();
|
||||
}
|
||||
|
||||
return currPattern;
|
||||
}
|
||||
|
||||
PatternData* Evaluator::patternFromName(const std::vector<std::string> &path) {
|
||||
std::vector<PatternData*> currMembers;
|
||||
|
||||
PatternData *currPattern = nullptr;
|
||||
|
||||
// Local member access
|
||||
currPattern = this->findPattern(*this->m_currMembers.back(), path);
|
||||
|
||||
// If no local member was found, try globally
|
||||
if (currPattern == nullptr) {
|
||||
currPattern = this->findPattern(this->m_globalMembers, path);
|
||||
}
|
||||
|
||||
// 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, ".")));
|
||||
|
||||
return currPattern;
|
||||
|
||||
/*std::vector<PatternData*> currMembers;
|
||||
|
||||
if (!this->m_currMembers.empty())
|
||||
std::copy(this->m_currMembers.back()->begin(), this->m_currMembers.back()->end(), std::back_inserter(currMembers));
|
||||
@ -67,7 +130,7 @@ namespace hex::lang {
|
||||
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
|
||||
currPattern = pointerPattern->getPointedAtPattern();
|
||||
|
||||
return currPattern;
|
||||
return currPattern;*/
|
||||
}
|
||||
|
||||
ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) {
|
||||
@ -436,8 +499,15 @@ namespace hex::lang {
|
||||
PatternData* Evaluator::evaluateStruct(ASTNodeStruct *node) {
|
||||
std::vector<PatternData*> memberPatterns;
|
||||
|
||||
auto structPattern = new PatternDataStruct(this->m_currOffset, 0);
|
||||
structPattern->setParent(this->m_currMemberScope.back());
|
||||
|
||||
this->m_currMembers.push_back(&memberPatterns);
|
||||
ON_SCOPE_EXIT { this->m_currMembers.pop_back(); };
|
||||
this->m_currMemberScope.push_back(structPattern);
|
||||
ON_SCOPE_EXIT {
|
||||
this->m_currMembers.pop_back();
|
||||
this->m_currMemberScope.pop_back();
|
||||
};
|
||||
|
||||
this->m_currRecursionDepth++;
|
||||
if (this->m_currRecursionDepth > this->m_recursionLimit)
|
||||
@ -446,18 +516,31 @@ namespace hex::lang {
|
||||
auto startOffset = this->m_currOffset;
|
||||
for (auto &member : node->getMembers()) {
|
||||
this->evaluateMember(member, memberPatterns, true);
|
||||
structPattern->setMembers(memberPatterns);
|
||||
|
||||
for (auto &pmember : memberPatterns)
|
||||
hex::print("{}\n", pmember->getVariableName());
|
||||
hex::print("======\n");
|
||||
}
|
||||
structPattern->setSize(this->m_currOffset - startOffset);
|
||||
|
||||
this->m_currRecursionDepth--;
|
||||
|
||||
return this->evaluateAttributes(node, new PatternDataStruct(startOffset, this->m_currOffset - startOffset, memberPatterns));
|
||||
return this->evaluateAttributes(node, structPattern);
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateUnion(ASTNodeUnion *node) {
|
||||
std::vector<PatternData*> memberPatterns;
|
||||
|
||||
auto unionPattern = new PatternDataUnion(this->m_currOffset, 0);
|
||||
unionPattern->setParent(this->m_currMemberScope.back());
|
||||
|
||||
this->m_currMembers.push_back(&memberPatterns);
|
||||
ON_SCOPE_EXIT { this->m_currMembers.pop_back(); };
|
||||
this->m_currMemberScope.push_back(unionPattern);
|
||||
ON_SCOPE_EXIT {
|
||||
this->m_currMembers.pop_back();
|
||||
this->m_currMemberScope.pop_back();
|
||||
};
|
||||
|
||||
auto startOffset = this->m_currOffset;
|
||||
|
||||
@ -467,6 +550,7 @@ namespace hex::lang {
|
||||
|
||||
for (auto &member : node->getMembers()) {
|
||||
this->evaluateMember(member, memberPatterns, false);
|
||||
unionPattern->setMembers(memberPatterns);
|
||||
}
|
||||
|
||||
this->m_currRecursionDepth--;
|
||||
@ -474,10 +558,11 @@ namespace hex::lang {
|
||||
size_t size = 0;
|
||||
for (const auto &pattern : memberPatterns)
|
||||
size = std::max(size, pattern->getSize());
|
||||
unionPattern->setSize(size);
|
||||
|
||||
this->m_currOffset += size;
|
||||
|
||||
return this->evaluateAttributes(node, new PatternDataUnion(startOffset, size, memberPatterns));
|
||||
return this->evaluateAttributes(node, unionPattern);
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateEnum(ASTNodeEnum *node) {
|
||||
@ -503,12 +588,16 @@ namespace hex::lang {
|
||||
auto valueNode = evaluateMathematicalExpression(expression);
|
||||
ON_SCOPE_EXIT { delete valueNode; };
|
||||
|
||||
entryPatterns.push_back({ Token::castTo(builtinUnderlyingType->getType(), valueNode->getValue()), name });
|
||||
entryPatterns.emplace_back(Token::castTo(builtinUnderlyingType->getType(), valueNode->getValue()), name);
|
||||
}
|
||||
|
||||
this->m_currOffset += size;
|
||||
|
||||
return this->evaluateAttributes(node, new PatternDataEnum(startOffset, size, entryPatterns));
|
||||
auto enumPattern = new PatternDataEnum(startOffset, size);
|
||||
enumPattern->setSize(size);
|
||||
enumPattern->setEnumValues(entryPatterns);
|
||||
|
||||
return this->evaluateAttributes(node, enumPattern);
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateBitfield(ASTNodeBitfield *node) {
|
||||
@ -541,7 +630,10 @@ namespace hex::lang {
|
||||
size_t size = (bits + 7) / 8;
|
||||
this->m_currOffset += size;
|
||||
|
||||
return this->evaluateAttributes(node, new PatternDataBitfield(startOffset, size, entryPatterns));
|
||||
auto bitfieldPattern = new PatternDataBitfield(startOffset, size);
|
||||
bitfieldPattern->setFields(entryPatterns);
|
||||
|
||||
return this->evaluateAttributes(node, bitfieldPattern);
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateType(ASTNodeTypeDecl *node) {
|
||||
@ -689,7 +781,10 @@ namespace hex::lang {
|
||||
else {
|
||||
if (node->getSize() == nullptr)
|
||||
this->getConsole().abortEvaluation("no bounds provided for array");
|
||||
pattern = new PatternDataArray(startOffset, (this->m_currOffset - startOffset), entries, color.value_or(0));
|
||||
auto arrayPattern = new PatternDataArray(startOffset, (this->m_currOffset - startOffset), color.value_or(0));
|
||||
|
||||
arrayPattern->setEntries(entries);
|
||||
pattern = arrayPattern;
|
||||
}
|
||||
|
||||
pattern->setVariableName(node->getName().data());
|
||||
@ -746,10 +841,11 @@ namespace hex::lang {
|
||||
|
||||
this->m_currOffset = pointerOffset + pointerSize;
|
||||
|
||||
auto pattern = new PatternDataPointer(pointerOffset, pointerSize, pointedAt);
|
||||
auto pattern = new PatternDataPointer(pointerOffset, pointerSize);
|
||||
|
||||
pattern->setVariableName(node->getName().data());
|
||||
pattern->setEndian(this->getCurrentEndian());
|
||||
pattern->setPointedAtPattern(pointedAt);
|
||||
|
||||
return this->evaluateAttributes(node, pattern);
|
||||
}
|
||||
@ -757,13 +853,16 @@ namespace hex::lang {
|
||||
std::optional<std::vector<PatternData*>> Evaluator::evaluate(const std::vector<ASTNode *> &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_currMembers.clear();
|
||||
this->m_currMemberScope.clear();
|
||||
this->m_currMemberScope.push_back(nullptr);
|
||||
|
||||
this->m_endianStack.push_back(this->m_defaultDataEndian);
|
||||
this->m_currRecursionDepth = 0;
|
||||
|
||||
|
@ -412,6 +412,8 @@ namespace hex::lang {
|
||||
tokens.emplace_back(VALUE_TOKEN(Integer, Token::IntegerLiteral(Token::ValueType::Boolean, s32(0))));
|
||||
else if (identifier == "true")
|
||||
tokens.emplace_back(VALUE_TOKEN(Integer, Token::IntegerLiteral(Token::ValueType::Boolean, s32(1))));
|
||||
else if (identifier == "parent")
|
||||
tokens.emplace_back(TOKEN(Keyword, Parent));
|
||||
|
||||
// Check for built-in types
|
||||
else if (identifier == "u8")
|
||||
|
@ -69,12 +69,14 @@ namespace hex::lang {
|
||||
ASTNode* Parser::parseRValue(std::vector<std::string> &path) {
|
||||
if (peek(IDENTIFIER, -1))
|
||||
path.push_back(getValue<std::string>(-1));
|
||||
else if (peek(KEYWORD_PARENT, -1))
|
||||
path.emplace_back("parent");
|
||||
|
||||
if (MATCHES(sequence(SEPARATOR_DOT))) {
|
||||
if (MATCHES(sequence(IDENTIFIER)))
|
||||
if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT)))
|
||||
return this->parseRValue(path);
|
||||
else
|
||||
throwParseError("expected member name", -1);
|
||||
throwParseError("expected member name or 'parent' keyword", -1);
|
||||
} else
|
||||
return TO_NUMERIC_EXPRESSION(new ASTNodeRValue(path));
|
||||
}
|
||||
@ -94,7 +96,7 @@ namespace hex::lang {
|
||||
return this->parseScopeResolution(path);
|
||||
} else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
return TO_NUMERIC_EXPRESSION(this->parseFunctionCall());
|
||||
} else if (MATCHES(sequence(IDENTIFIER))) {
|
||||
} else if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) {
|
||||
std::vector<std::string> path;
|
||||
return this->parseRValue(path);
|
||||
} else if (MATCHES(sequence(OPERATOR_DOLLAR))) {
|
||||
|
@ -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"
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "parent"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
Loading…
x
Reference in New Issue
Block a user