Implemented union support into the pattern language

This commit is contained in:
WerWolv
2020-11-20 21:29:28 +01:00
parent e3cb078306
commit 48296775ae
8 changed files with 186 additions and 3 deletions

View File

@@ -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);

View File

@@ -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")

View File

@@ -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);

View File

@@ -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);