Added overriding of endianess for individual variables

This commit is contained in:
WerWolv
2020-12-06 21:40:57 +01:00
parent 4720cf9fbe
commit 7a9d7b59e8
10 changed files with 345 additions and 113 deletions

View File

@@ -5,8 +5,8 @@
namespace hex::lang {
Evaluator::Evaluator(prv::Provider* &provider, std::endian dataEndianess) : m_provider(provider), m_dataEndianess(dataEndianess) {
PatternData::setEndianess(dataEndianess);
Evaluator::Evaluator(prv::Provider* &provider, std::endian defaultDataEndianess) : m_provider(provider), m_defaultDataEndianess(defaultDataEndianess) {
}
std::pair<PatternData*, size_t> Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -28,7 +28,7 @@ namespace hex::lang {
if (member->getPointerSize().has_value()) {
this->m_provider->read(offset + structSize, &memberOffset, member->getPointerSize().value());
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess);
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)));
}
else
memberOffset = offset + structSize;
@@ -58,7 +58,7 @@ namespace hex::lang {
u64 value = 0;
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess);
value = hex::changeEndianess(value, prevMember->getSize(), prevMember->getEndianess());
arraySize = value;
}
@@ -83,8 +83,10 @@ namespace hex::lang {
if (pattern == nullptr)
return { nullptr, 0 };
pattern->setEndianess(member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)));
if (member->getPointerSize().has_value()) {
members.push_back(new PatternDataPointer(offset + structSize, member->getPointerSize().value(), member->getVariableName(), pattern));
members.push_back(new PatternDataPointer(offset + structSize, member->getPointerSize().value(), member->getVariableName(), pattern, member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess))));
structSize += member->getPointerSize().value();
}
else {
@@ -93,7 +95,7 @@ namespace hex::lang {
}
}
return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), structNode->getName(), members, 0x00FFFFFF), structSize };
return { new PatternDataStruct(offset, structSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), structNode->getName(), members, 0x00FFFFFF), structSize };
}
std::pair<PatternData*, size_t> Evaluator::createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -115,7 +117,7 @@ namespace hex::lang {
if (member->getPointerSize().has_value()) {
this->m_provider->read(offset + unionSize, &memberOffset, member->getPointerSize().value());
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess);
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), member->getEndianess().value_or(this->m_defaultDataEndianess));
}
else
memberOffset = offset;
@@ -148,7 +150,7 @@ namespace hex::lang {
u64 value = 0;
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess);
value = hex::changeEndianess(value, prevMember->getSize(), prevMember->getEndianess());
arraySize = value;
}
@@ -178,8 +180,10 @@ namespace hex::lang {
if (pattern == nullptr)
return { nullptr, 0 };
pattern->setEndianess(member->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)));
if (member->getPointerSize().has_value()) {
members.push_back(new PatternDataPointer(offset, member->getPointerSize().value(), member->getVariableName(), pattern));
members.push_back(new PatternDataPointer(offset, member->getPointerSize().value(), member->getVariableName(), pattern, member->getEndianess().value_or(this->m_defaultDataEndianess)));
unionSize = std::max(size_t(member->getPointerSize().value()), unionSize);
}
else {
@@ -188,7 +192,7 @@ namespace hex::lang {
}
}
return { new PatternDataUnion(offset, unionSize, varDeclNode->getVariableName(), unionNode->getName(), members, 0x00FFFFFF), unionSize };
return { new PatternDataUnion(offset, unionSize, varDeclNode->getVariableName(), unionNode->getName(), members, varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), 0x00FFFFFF), unionSize };
}
std::pair<PatternData*, size_t> Evaluator::createEnumPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -201,7 +205,7 @@ namespace hex::lang {
size_t size = getTypeSize(enumType->getUnderlyingType());
return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues()), size };
return { new PatternDataEnum(offset, size, varDeclNode->getVariableName(), enumType->getName(), enumType->getValues(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), size };
}
std::pair<PatternData*, size_t> Evaluator::createBitfieldPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -219,7 +223,7 @@ namespace hex::lang {
size = std::bit_ceil(size) / 8;
return { new PatternDataBitfield(offset, size, varDeclNode->getVariableName(), bitfieldType->getName(), bitfieldType->getFields()), size };
return { new PatternDataBitfield(offset, size, varDeclNode->getVariableName(), bitfieldType->getName(), bitfieldType->getFields(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), size };
}
std::pair<PatternData*, size_t> Evaluator::createArrayPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -236,8 +240,12 @@ namespace hex::lang {
} else if (varDeclNode->getVariableType() != Token::TypeToken::Type::CustomType) {
const auto& [pattern, size] = this->createBuiltInTypePattern(nonArrayVarDeclNode, offset + arrayOffset);
if (pattern == nullptr)
if (pattern == nullptr) {
delete nonArrayVarDeclNode;
return { nullptr, 0 };
}
pattern->setEndianess(varDeclNode->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)));
if (!arrayColor.has_value())
arrayColor = pattern->getColor();
@@ -249,8 +257,12 @@ namespace hex::lang {
} else {
const auto &[pattern, size] = this->createCustomTypePattern(nonArrayVarDeclNode, offset + arrayOffset);
if (pattern == nullptr)
if (pattern == nullptr) {
delete nonArrayVarDeclNode;
return { nullptr, 0 };
}
pattern->setEndianess(varDeclNode->getEndianess().value_or(varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)));
if (!arrayColor.has_value())
arrayColor = pattern->getColor();
@@ -264,13 +276,13 @@ namespace hex::lang {
delete nonArrayVarDeclNode;
}
return { new PatternDataArray(offset, arrayOffset, varDeclNode->getVariableName(), entries, arrayColor.value()), arrayOffset };
return { new PatternDataArray(offset, arrayOffset, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess), entries, arrayColor.value()), arrayOffset };
}
std::pair<PatternData*, size_t> Evaluator::createStringPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
size_t arraySize = varDeclNode->getArraySize();
return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName()), arraySize };
return { new PatternDataString(offset, arraySize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), arraySize };
}
std::pair<PatternData*, size_t> Evaluator::createCustomTypePattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
@@ -314,21 +326,21 @@ namespace hex::lang {
if (isSigned(type)) {
if (typeSize == 1 && arraySize == 1)
return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName()), 1 };
return { new PatternDataCharacter(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), 1 };
else if (arraySize > 1)
return createArrayPattern(varDeclNode, offset);
else
return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize };
return { new PatternDataSigned(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize };
} else if (isUnsigned(varDeclNode->getVariableType())) {
if (arraySize > 1)
return createArrayPattern(varDeclNode, offset);
else
return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize };
return { new PatternDataUnsigned(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize };
} else if (isFloatingPoint(varDeclNode->getVariableType())) {
if (arraySize > 1)
return createArrayPattern(varDeclNode, offset);
else
return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName()), typeSize * arraySize };
return { new PatternDataFloat(offset, typeSize, varDeclNode->getVariableName(), varDeclNode->getEndianess().value_or(this->m_defaultDataEndianess)), typeSize * arraySize };
}
return { nullptr, 0 };

View File

@@ -192,8 +192,12 @@ namespace hex::lang {
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Enum }, .lineNumber = lineNumber });
else if (identifier == "bitfield")
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::Bitfield }, .lineNumber = lineNumber });
else if (identifier == "be")
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::BigEndian }, .lineNumber = lineNumber });
else if (identifier == "le")
tokens.push_back({ .type = Token::Type::Keyword, .keywordToken = { .keyword = Token::KeywordToken::Keyword::LittleEndian }, .lineNumber = lineNumber });
// Check for built-in types
// Check for built-in types
else if (identifier == "u8")
tokens.push_back({ .type = Token::Type::Type, .typeToken = { .type = Token::TypeToken::Type::Unsigned8Bit }, .lineNumber = lineNumber });
else if (identifier == "s8")

View File

@@ -25,15 +25,42 @@ namespace hex::lang {
}
ASTNode* Parser::parseBuiltinVariableDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-3].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier);
ASTNode* Parser::parseBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-4].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier, "", {}, 1, {}, {}, endianess);
}
else
return new ASTNodeVariableDecl(curr[-3].lineNumber, curr[-3].typeToken.type, curr[-2].identifierToken.identifier);
}
ASTNode* Parser::parseCustomTypeVariableDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-3].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier);
ASTNode* Parser::parseCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-4].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else return nullptr;
return new ASTNodeVariableDecl(curr[-4].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier, {}, 1, {}, {}, endianess);
}
else
return new ASTNodeVariableDecl(curr[-3].lineNumber, Token::TypeToken::Type::CustomType, curr[-2].identifierToken.identifier, curr[-3].identifierToken.identifier);
}
ASTNode* Parser::parseBuiltinPointerVariableDecl(TokenIter &curr) {
ASTNode* Parser::parseBuiltinPointerVariableDecl(TokenIter &curr, bool hasEndianDef) {
auto pointerType = curr[-2].typeToken.type;
if (!isUnsigned(pointerType)) {
@@ -51,10 +78,23 @@ namespace hex::lang {
return nullptr;
}
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType));
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else return nullptr;
return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType), endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-4].identifierToken.identifier, "", { }, 1, { }, getTypeSize(pointerType));
}
ASTNode* Parser::parseCustomTypePointerVariableDecl(TokenIter &curr) {
ASTNode* Parser::parseCustomTypePointerVariableDecl(TokenIter &curr, bool hasEndianDef) {
auto pointerType = curr[-2].typeToken.type;
if (!isUnsigned(pointerType)) {
@@ -72,35 +112,140 @@ namespace hex::lang {
return nullptr;
}
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType));
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-7].lineNumber,Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType), endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 1, { }, getTypeSize(pointerType));
}
ASTNode* Parser::parseBuiltinArrayDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer);
ASTNode* Parser::parseBuiltinArrayDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer, { }, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, curr[-3].integerToken.integer);
}
ASTNode* Parser::parseCustomTypeArrayDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer);
ASTNode* Parser::parseCustomTypeArrayDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-7].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer, { }, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, curr[-3].integerToken.integer);
}
ASTNode* Parser::parseBuiltinVariableArrayDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier);
ASTNode* Parser::parseBuiltinVariableArrayDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-7].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-6].typeToken.type, curr[-5].identifierToken.identifier, "", { }, 0, curr[-3].identifierToken.identifier);
}
ASTNode* Parser::parseCustomTypeVariableArrayDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier);
ASTNode* Parser::parseCustomTypeVariableArrayDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-7].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-7].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-5].identifierToken.identifier, curr[-6].identifierToken.identifier, { }, 0, curr[-3].identifierToken.identifier);
}
ASTNode* Parser::parsePaddingDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer);
return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, "", "", { }, curr[-3].integerToken.integer);
}
ASTNode* Parser::parseFreeBuiltinVariableDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer);
ASTNode* Parser::parseFreeBuiltinVariableDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-6].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer, 1, { }, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-5].lineNumber, curr[-5].typeToken.type, curr[-4].identifierToken.identifier, "", curr[-2].integerToken.integer);
}
ASTNode* Parser::parseFreeCustomTypeVariableDecl(TokenIter &curr) {
return new ASTNodeVariableDecl(curr[-5].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer);
ASTNode* Parser::parseFreeCustomTypeVariableDecl(TokenIter &curr, bool hasEndianDef) {
if (hasEndianDef) {
std::endian endianess;
if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::LittleEndian)
endianess = std::endian::little;
else if (curr[-6].keywordToken.keyword == Token::KeywordToken::Keyword::BigEndian)
endianess = std::endian::big;
else {
this->m_error = { curr->lineNumber, "Expected be or le identifier" };
return nullptr;
}
return new ASTNodeVariableDecl(curr[-6].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer, 1, { }, { }, endianess);
}
else
return new ASTNodeVariableDecl(curr[-5].lineNumber, Token::TypeToken::Type::CustomType, curr[-4].identifierToken.identifier, curr[-5].identifierToken.identifier, curr[-2].integerToken.integer);
}
ASTNode* Parser::parseStruct(TokenIter &curr) {
@@ -111,17 +256,17 @@ namespace hex::lang {
while (!tryConsume(curr, {Token::Type::ScopeClose})) {
if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableDecl(curr));
nodes.push_back(parseBuiltinVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableDecl(curr));
nodes.push_back(parseCustomTypeVariableDecl(curr, false));
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));
nodes.push_back(parseBuiltinArrayDecl(curr, false));
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));
nodes.push_back(parseCustomTypeArrayDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableArrayDecl(curr));
nodes.push_back(parseBuiltinVariableArrayDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableArrayDecl(curr));
nodes.push_back(parseCustomTypeVariableArrayDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Type, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression})) {
if (curr[-5].typeToken.type != Token::TypeToken::Type::Padding) {
for(auto &node : nodes) delete node;
@@ -131,9 +276,25 @@ namespace hex::lang {
}
nodes.push_back(parsePaddingDecl(curr));
} else if (tryConsume(curr, {Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinPointerVariableDecl(curr));
nodes.push_back(parseBuiltinPointerVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypePointerVariableDecl(curr));
nodes.push_back(parseCustomTypePointerVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Identifier, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinPointerVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypePointerVariableDecl(curr, true));
else {
for(auto &node : nodes) delete node;
this->m_error = { curr->lineNumber, "Invalid sequence, expected member declaration" };
@@ -158,17 +319,29 @@ namespace hex::lang {
while (!tryConsume(curr, {Token::Type::ScopeClose})) {
if (tryConsume(curr, {Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableDecl(curr));
nodes.push_back(parseBuiltinVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableDecl(curr));
nodes.push_back(parseCustomTypeVariableDecl(curr, false));
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));
nodes.push_back(parseBuiltinArrayDecl(curr, false));
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));
nodes.push_back(parseCustomTypeArrayDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinPointerVariableDecl(curr));
nodes.push_back(parseBuiltinPointerVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypePointerVariableDecl(curr));
nodes.push_back(parseCustomTypePointerVariableDecl(curr, false));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::ArrayOpen, Token::Type::Integer, Token::Type::ArrayClose, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypeArrayDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Type, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseBuiltinPointerVariableDecl(curr, true));
else if (tryConsume(curr, {Token::Type::Keyword, Token::Type::Identifier, Token::Type::Operator, Token::Type::Identifier, Token::Type::Operator, Token::Type::Type, Token::Type::EndOfExpression}))
nodes.push_back(parseCustomTypePointerVariableDecl(curr, true));
else {
for(auto &node : nodes) delete node;
this->m_error = { curr->lineNumber, "Invalid sequence, expected member declaration" };
@@ -390,7 +563,7 @@ namespace hex::lang {
return { };
}
auto variableDecl = parseFreeBuiltinVariableDecl(curr);
auto variableDecl = parseFreeBuiltinVariableDecl(curr, false);
program.push_back(variableDecl);
@@ -404,7 +577,35 @@ namespace hex::lang {
return { };
}
auto variableDecl = parseFreeCustomTypeVariableDecl(curr);
auto variableDecl = parseFreeCustomTypeVariableDecl(curr, false);
program.push_back(variableDecl);
return program;
// Variable placement declaration with built-in type and big/little endian setting
} else if (tryConsume(curr, { Token::Type::Keyword, Token::Type::Type, Token::Type::Identifier, Token::Type::Operator, Token::Type::Integer, Token::Type::EndOfExpression})) {
if (curr[-3].operatorToken.op != Token::OperatorToken::Operator::AtDeclaration) {
this->m_error = { curr[-3].lineNumber, "Expected '@' after variable placement declaration" };
for(auto &node : program) delete node;
return { };
}
auto variableDecl = parseFreeBuiltinVariableDecl(curr, true);
program.push_back(variableDecl);
return program;
// Variable placement declaration with custom type and big/little endian setting
} else if (tryConsume(curr, { Token::Type::Keyword, Token::Type::Identifier, Token::Type::Identifier, Token::Type::Operator, Token::Type::Integer, Token::Type::EndOfExpression})) {
if (curr[-3].operatorToken.op != Token::OperatorToken::Operator::AtDeclaration) {
this->m_error = { curr[-3].lineNumber, "Expected '@' after variable placement declaration" };
for(auto &node : program) delete node;
return { };
}
auto variableDecl = parseFreeCustomTypeVariableDecl(curr, true);
program.push_back(variableDecl);

View File

@@ -110,11 +110,13 @@ namespace hex {
ImGui::TextWrapped(
"Normal variables as well as arrays are used to highlight and display values. "
"It is possible to create arrays within structs and unions that use the value of a previously "
"declared variable as size.");
"declared variable as size. In order to override the native / globally set endianess setting, every "
"type in a variable declaration may be prefixed with be or le to turn only it into a big or little endian type.");
drawCodeSegment("vars arrays",
"u32 variable;\n"
"s8 string[16];\n"
"u8 customSizedArray[variable];"
"u8 customSizedArray[variable];\n"
"be u32 bigEndianVariable;"
);
drawTitle("Structs");

View File

@@ -18,7 +18,7 @@ namespace hex {
static TextEditor::LanguageDefinition langDef;
if (!initialized) {
static const char* const keywords[] = {
"using", "struct", "union", "enum", "bitfield"
"using", "struct", "union", "enum", "bitfield", "be", "le"
};
for (auto& k : keywords)
langDef.mKeywords.insert(k);
@@ -262,17 +262,17 @@ namespace hex {
this->postEvent(Events::PatternChanged);
hex::lang::Preprocessor preprocessor;
std::endian dataEndianess = std::endian::native;
std::endian defaultDataEndianess = std::endian::native;
preprocessor.addPragmaHandler("endian", [&dataEndianess](std::string value) {
preprocessor.addPragmaHandler("endian", [&defaultDataEndianess](std::string value) {
if (value == "big") {
dataEndianess = std::endian::big;
defaultDataEndianess = std::endian::big;
return true;
} else if (value == "little") {
dataEndianess = std::endian::little;
defaultDataEndianess = std::endian::little;
return true;
} else if (value == "native") {
dataEndianess = std::endian::native;
defaultDataEndianess = std::endian::native;
return true;
} else
return false;
@@ -308,7 +308,7 @@ namespace hex {
return;
}
hex::lang::Evaluator evaluator(this->m_dataProvider, dataEndianess);
hex::lang::Evaluator evaluator(this->m_dataProvider, defaultDataEndianess);
auto [evaluateResult, patternData] = evaluator.evaluate(ast);
if (evaluateResult.failed()) {
this->m_textEditor.SetErrorMarkers({ evaluator.getError() });