mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 21:47:40 -05:00
Implemented union support into the pattern language
This commit is contained in:
@@ -75,6 +75,72 @@ namespace hex::lang {
|
||||
return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), structNode->getName(), members, 0x00FFFFFF), structSize };
|
||||
}
|
||||
|
||||
std::pair<PatternData*, size_t> Evaluator::createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
|
||||
std::vector<PatternData*> members;
|
||||
|
||||
auto unionNode = static_cast<ASTNodeUnion*>(this->m_types[varDeclNode->getCustomVariableTypeName()]);
|
||||
|
||||
if (unionNode == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
size_t unionSize = 0;
|
||||
for (const auto &node : unionNode->getNodes()) {
|
||||
const auto &member = static_cast<ASTNodeVariableDecl*>(node);
|
||||
|
||||
const auto typeDeclNode = static_cast<ASTNodeTypeDecl*>(this->m_types[member->getCustomVariableTypeName()]);
|
||||
|
||||
if (member->getVariableType() == Token::TypeToken::Type::Signed8Bit && member->getArraySize() > 1) {
|
||||
const auto &[pattern, size] = this->createStringPattern(member, offset);
|
||||
|
||||
if (pattern == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
members.push_back(pattern);
|
||||
unionSize = std::max(size, unionSize);
|
||||
} else if (member->getVariableType() == Token::TypeToken::Type::CustomType
|
||||
&& typeDeclNode != nullptr && typeDeclNode->getAssignedType() == Token::TypeToken::Type::Signed8Bit
|
||||
&& member->getArraySize() > 1) {
|
||||
|
||||
const auto &[pattern, size] = this->createStringPattern(member, offset);
|
||||
|
||||
if (pattern == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
members.push_back(pattern);
|
||||
unionSize = std::max(size, unionSize);
|
||||
}
|
||||
else if (member->getArraySize() > 1) {
|
||||
const auto &[pattern, size] = this->createArrayPattern(member, offset);
|
||||
|
||||
if (pattern == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
members.push_back(pattern);
|
||||
unionSize = std::max(size, unionSize);
|
||||
}
|
||||
else if (member->getVariableType() != Token::TypeToken::Type::CustomType) {
|
||||
const auto &[pattern, size] = this->createBuiltInTypePattern(member, offset);
|
||||
|
||||
if (pattern == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
members.push_back(pattern);
|
||||
unionSize = std::max(size, unionSize);
|
||||
}
|
||||
else {
|
||||
const auto &[pattern, size] = this->createCustomTypePattern(member, offset);
|
||||
|
||||
if (pattern == nullptr)
|
||||
return { nullptr, 0 };
|
||||
|
||||
members.push_back(pattern);
|
||||
unionSize = std::max(size, unionSize);
|
||||
}
|
||||
}
|
||||
|
||||
return { new PatternDataUnion(offset, unionSize, varDeclNode->getVariableName(), unionNode->getName(), members, 0x00FFFFFF), unionSize };
|
||||
}
|
||||
|
||||
std::pair<PatternData*, size_t> Evaluator::createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
|
||||
std::vector<std::pair<u64, std::string>> enumValues;
|
||||
|
||||
@@ -150,6 +216,8 @@ namespace hex::lang {
|
||||
switch (currType->getType()) {
|
||||
case ASTNode::Type::Struct:
|
||||
return this->createStructPattern(varDeclNode, offset);
|
||||
case ASTNode::Type::Union:
|
||||
return this->createUnionPattern(varDeclNode, offset);
|
||||
case ASTNode::Type::Enum:
|
||||
return this->createEnumPattern(varDeclNode, offset);
|
||||
case ASTNode::Type::Bitfield:
|
||||
@@ -208,6 +276,12 @@ namespace hex::lang {
|
||||
this->m_types.emplace(structNode->getName(), structNode);
|
||||
}
|
||||
break;
|
||||
case ASTNode::Type::Union:
|
||||
{
|
||||
auto *unionNode = static_cast<ASTNodeUnion*>(node);
|
||||
this->m_types.emplace(unionNode->getName(), unionNode);
|
||||
}
|
||||
break;
|
||||
case ASTNode::Type::Enum:
|
||||
{
|
||||
auto *enumNode = static_cast<ASTNodeEnum*>(node);
|
||||
|
||||
@@ -135,6 +135,8 @@ namespace hex::lang {
|
||||
|
||||
if (identifier == "struct")
|
||||
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Struct } });
|
||||
else if (identifier == "union")
|
||||
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Union } });
|
||||
else if (identifier == "using")
|
||||
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Using } });
|
||||
else if (identifier == "enum")
|
||||
|
||||
@@ -75,6 +75,30 @@ namespace hex::lang {
|
||||
return new ASTNodeStruct(structName, nodes);
|
||||
}
|
||||
|
||||
ASTNode* parseUnion(TokenIter &curr) {
|
||||
const std::string &unionName = curr[-2].identifierToken.identifier;
|
||||
std::vector<ASTNode*> nodes;
|
||||
|
||||
while (!tryConsume(curr, {Token::Type::ScopeClose})) {
|
||||
if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression}))
|
||||
nodes.push_back(parseBuiltinVariableDecl(curr));
|
||||
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression}))
|
||||
nodes.push_back(parseCustomTypeVariableDecl(curr));
|
||||
else if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
|
||||
nodes.push_back(parseBuiltinArrayDecl(curr));
|
||||
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
|
||||
nodes.push_back(parseCustomTypeArrayDecl(curr));
|
||||
else break;
|
||||
}
|
||||
|
||||
if (!tryConsume(curr, {Token::Type::EndOfExpression})) {
|
||||
for(auto &node : nodes) delete node;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new ASTNodeUnion(unionName, nodes);
|
||||
}
|
||||
|
||||
ASTNode* parseEnum(TokenIter &curr) {
|
||||
const std::string &enumName = curr[-4].identifierToken.identifier;
|
||||
const Token::TypeToken::Type underlyingType = curr[-2].typeToken.type;
|
||||
@@ -183,6 +207,15 @@ namespace hex::lang {
|
||||
}
|
||||
|
||||
program.push_back(structAst);
|
||||
} else if (curr[-3].keywordToken.keyword == Token::KeywordToken::Keyword::Union) {
|
||||
auto unionAst = parseUnion(curr);
|
||||
|
||||
if (unionAst == nullptr) {
|
||||
for(auto &node : program) delete node;
|
||||
return { };
|
||||
}
|
||||
|
||||
program.push_back(unionAst);
|
||||
} else if (curr[-3].keywordToken.keyword == Token::KeywordToken::Keyword::Bitfield) {
|
||||
auto bitfieldAst = parseBitField(curr);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace hex {
|
||||
static TextEditor::LanguageDefinition langDef;
|
||||
if (!initialized) {
|
||||
static const char* const keywords[] = {
|
||||
"using", "struct", "enum", "bitfield"
|
||||
"using", "struct", "union", "enum", "bitfield"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
||||
Reference in New Issue
Block a user