patterns: Added array index syntax to rvalues and turned addressof/sizeof into operators
This commit is contained in:
parent
407c13fcce
commit
32d47456de
@ -153,36 +153,6 @@ namespace hex::plugin::builtin {
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
/* addressof(rValueString) */
|
||||
ContentRegistry::PatternLanguageFunctions::add("addressof", 1, [](auto &ctx, auto params) -> ASTNode* {
|
||||
auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString();
|
||||
|
||||
std::vector<std::string> path = splitString(name, ".");
|
||||
auto pattern = ctx.patternFromName(path);
|
||||
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getOffset()) });
|
||||
});
|
||||
|
||||
/* sizeof(rValueString) */
|
||||
ContentRegistry::PatternLanguageFunctions::add("sizeof", 1, [](auto &ctx, auto params) -> ASTNode* {
|
||||
auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString();
|
||||
|
||||
std::vector<std::string> path = splitString(name, ".");
|
||||
auto pattern = ctx.patternFromName(path);
|
||||
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getSize()) });
|
||||
});
|
||||
|
||||
/* nextAfter(rValueString) */
|
||||
ContentRegistry::PatternLanguageFunctions::add("nextAfter", 1, [](auto &ctx, auto params) -> ASTNode* {
|
||||
auto name = AS_TYPE(ASTNodeStringLiteral, params[0])->getString();
|
||||
|
||||
std::vector<std::string> path = splitString(name, ".");
|
||||
auto pattern = ctx.patternFromName(path);
|
||||
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, u64(pattern->getOffset() + pattern->getSize()) });
|
||||
});
|
||||
|
||||
/* alignTo(alignment, value) */
|
||||
ContentRegistry::PatternLanguageFunctions::add("alignTo", 2, [](auto &ctx, auto params) -> ASTNode* {
|
||||
auto alignment = AS_TYPE(ASTNodeIntegerLiteral, params[0])->getValue();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <bit>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace hex::lang {
|
||||
@ -394,20 +395,29 @@ namespace hex::lang {
|
||||
|
||||
class ASTNodeRValue : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeRValue(std::vector<std::string> path) : ASTNode(), m_path(std::move(path)) { }
|
||||
using Path = std::vector<std::variant<std::string, ASTNode*>>;
|
||||
|
||||
explicit ASTNodeRValue(Path path) : ASTNode(), m_path(std::move(path)) { }
|
||||
|
||||
ASTNodeRValue(const ASTNodeRValue&) = default;
|
||||
|
||||
~ASTNodeRValue() override {
|
||||
for (auto &part : this->m_path) {
|
||||
if (auto node = std::get_if<ASTNode*>(&part); node != nullptr)
|
||||
delete *node;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] ASTNode* clone() const override {
|
||||
return new ASTNodeRValue(*this);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& getPath() {
|
||||
const Path& getPath() {
|
||||
return this->m_path;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_path;
|
||||
Path m_path;
|
||||
};
|
||||
|
||||
class ASTNodeScopeResolution : public ASTNode {
|
||||
@ -557,4 +567,35 @@ namespace hex::lang {
|
||||
std::optional<std::string> m_value;
|
||||
};
|
||||
|
||||
class ASTNodeTypeOperator : public ASTNode {
|
||||
public:
|
||||
ASTNodeTypeOperator(Token::Operator op, ASTNode *expression) : m_op(op), m_expression(expression) {
|
||||
|
||||
}
|
||||
|
||||
ASTNodeTypeOperator(const ASTNodeTypeOperator &other) : ASTNode(other) {
|
||||
this->m_op = other.m_op;
|
||||
this->m_expression = other.m_expression->clone();
|
||||
}
|
||||
|
||||
[[nodiscard]] ASTNode* clone() const override {
|
||||
return new ASTNodeTypeOperator(*this);
|
||||
}
|
||||
|
||||
~ASTNodeTypeOperator() override {
|
||||
delete this->m_expression;
|
||||
}
|
||||
|
||||
Token::Operator getOperator() const {
|
||||
return this->m_op;
|
||||
}
|
||||
|
||||
ASTNode* getExpression() const {
|
||||
return this->m_expression;
|
||||
}
|
||||
|
||||
private:
|
||||
Token::Operator m_op;
|
||||
ASTNode *m_expression;
|
||||
};
|
||||
}
|
@ -28,7 +28,7 @@ namespace hex::lang {
|
||||
void setProvider(prv::Provider *provider) { this->m_provider = provider; }
|
||||
[[nodiscard]] std::endian getCurrentEndian() const { return this->m_endianStack.back(); }
|
||||
|
||||
PatternData* patternFromName(const std::vector<std::string> &name);
|
||||
PatternData* patternFromName(const ASTNodeRValue::Path &name);
|
||||
|
||||
template<typename T>
|
||||
T* asType(ASTNode *param) {
|
||||
@ -56,12 +56,13 @@ namespace hex::lang {
|
||||
ASTNodeIntegerLiteral* evaluateScopeResolution(ASTNodeScopeResolution *node);
|
||||
ASTNodeIntegerLiteral* evaluateRValue(ASTNodeRValue *node);
|
||||
ASTNode* evaluateFunctionCall(ASTNodeFunctionCall *node);
|
||||
ASTNodeIntegerLiteral* evaluateTypeOperator(ASTNodeTypeOperator *typeOperatorNode);
|
||||
ASTNodeIntegerLiteral* evaluateOperator(ASTNodeIntegerLiteral *left, ASTNodeIntegerLiteral *right, Token::Operator op);
|
||||
ASTNodeIntegerLiteral* evaluateOperand(ASTNode *node);
|
||||
ASTNodeIntegerLiteral* evaluateTernaryExpression(ASTNodeTernaryExpression *node);
|
||||
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
||||
|
||||
PatternData* findPattern(std::vector<PatternData*> currMembers, const std::vector<std::string> &path);
|
||||
PatternData* findPattern(std::vector<PatternData*> currMembers, const ASTNodeRValue::Path &path);
|
||||
PatternData* evaluateAttributes(ASTNode *currNode, PatternData *currPattern);
|
||||
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
|
||||
void evaluateMember(ASTNode *node, std::vector<PatternData*> &currMembers, bool increaseOffset);
|
||||
|
@ -54,7 +54,7 @@ namespace hex::lang {
|
||||
ASTNode* parseFunctionCall();
|
||||
ASTNode* parseStringLiteral();
|
||||
ASTNode* parseScopeResolution(std::vector<std::string> &path);
|
||||
ASTNode* parseRValue(std::vector<std::string> &path);
|
||||
ASTNode* parseRValue(ASTNodeRValue::Path &path);
|
||||
ASTNode* parseFactor();
|
||||
ASTNode* parseUnaryExpression();
|
||||
ASTNode* parseMultiplicativeExpression();
|
||||
|
@ -61,7 +61,9 @@ namespace hex::lang {
|
||||
BoolXor,
|
||||
BoolNot,
|
||||
TernaryConditional,
|
||||
Dollar
|
||||
Dollar,
|
||||
AddressOf,
|
||||
SizeOf
|
||||
};
|
||||
|
||||
enum class ValueType {
|
||||
@ -251,6 +253,8 @@ namespace hex::lang {
|
||||
#define OPERATOR_BOOLNOT COMPONENT(Operator, BoolNot)
|
||||
#define OPERATOR_TERNARYCONDITIONAL COMPONENT(Operator, TernaryConditional)
|
||||
#define OPERATOR_DOLLAR COMPONENT(Operator, Dollar)
|
||||
#define OPERATOR_ADDRESSOF COMPONENT(Operator, AddressOf)
|
||||
#define OPERATOR_SIZEOF COMPONENT(Operator, SizeOf)
|
||||
|
||||
#define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType)
|
||||
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
||||
|
@ -15,7 +15,6 @@ namespace hex::lang {
|
||||
Validator();
|
||||
|
||||
bool validate(const std::vector<ASTNode*>& ast);
|
||||
void printAST(const std::vector<ASTNode*>& ast);
|
||||
|
||||
const std::pair<u32, std::string>& getError() { return this->m_error; }
|
||||
|
||||
|
@ -30,43 +30,73 @@ namespace hex::lang {
|
||||
this->getConsole().abortEvaluation("failed to find identifier");
|
||||
}
|
||||
|
||||
PatternData* Evaluator::findPattern(std::vector<PatternData*> currMembers, const std::vector<std::string> &path) {
|
||||
PatternData* Evaluator::findPattern(std::vector<PatternData*> currMembers, const ASTNodeRValue::Path &path) {
|
||||
PatternData *currPattern = nullptr;
|
||||
for (const auto &identifier : path) {
|
||||
if (identifier == "parent") {
|
||||
if (currPattern == nullptr) {
|
||||
if (!currMembers.empty())
|
||||
currPattern = this->m_currMemberScope.back();
|
||||
for (const auto &part : path) {
|
||||
if (auto stringPart = std::get_if<std::string>(&part); stringPart != nullptr) {
|
||||
if (*stringPart == "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");
|
||||
}
|
||||
if (currPattern == nullptr)
|
||||
this->getConsole().abortEvaluation("attempted to get parent of global namespace");
|
||||
}
|
||||
|
||||
auto parent = currPattern->getParent();
|
||||
auto parent = currPattern->getParent();
|
||||
|
||||
if (parent == nullptr) {
|
||||
this->getConsole().abortEvaluation(hex::format("no parent available for identifier '{0}'", currPattern->getVariableName()));
|
||||
if (parent == nullptr) {
|
||||
this->getConsole().abortEvaluation(hex::format("no parent available for identifier '{0}'", currPattern->getVariableName()));
|
||||
} else {
|
||||
currPattern = parent;
|
||||
}
|
||||
} 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();
|
||||
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 if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
||||
currMembers = arrayPattern->getEntries();
|
||||
continue;
|
||||
}
|
||||
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() == *stringPart;
|
||||
});
|
||||
|
||||
if (candidate != currMembers.end())
|
||||
currPattern = *candidate;
|
||||
else
|
||||
this->getConsole().abortEvaluation("tried to access member of a non-struct/union type");
|
||||
this->getConsole().abortEvaluation(hex::format("no member found with identifier '{0}'", *stringPart));
|
||||
}
|
||||
} else if (auto nodePart = std::get_if<ASTNode*>(&part); nodePart != nullptr) {
|
||||
if (auto numericalExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(*nodePart)) {
|
||||
auto arrayIndexNode = evaluateMathematicalExpression(numericalExpressionNode);
|
||||
ON_SCOPE_EXIT { delete arrayIndexNode; };
|
||||
|
||||
auto candidate = std::find_if(currMembers.begin(), currMembers.end(), [&](auto member) {
|
||||
return member->getVariableName() == identifier;
|
||||
});
|
||||
if (currPattern != nullptr) {
|
||||
if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
||||
if (Token::isFloatingPoint(arrayIndexNode->getType()))
|
||||
this->getConsole().abortEvaluation("cannot use float to index into array");
|
||||
|
||||
if (candidate != currMembers.end())
|
||||
currPattern = *candidate;
|
||||
else
|
||||
this->getConsole().abortEvaluation(hex::format("no member found with identifier '{0}'", identifier));
|
||||
std::visit([&](auto &&arrayIndex){
|
||||
if (arrayIndex >= 0 && arrayIndex < arrayPattern->getEntries().size())
|
||||
currPattern = arrayPattern->getEntries()[arrayIndex];
|
||||
else
|
||||
this->getConsole().abortEvaluation(hex::format("tried to access out of bounds index {} of '{}'", arrayIndex, currPattern->getVariableName()));
|
||||
}, arrayIndexNode->getValue());
|
||||
|
||||
}
|
||||
else
|
||||
this->getConsole().abortEvaluation("tried to index into non-array type");
|
||||
}
|
||||
} else {
|
||||
this->getConsole().abortEvaluation(hex::format("invalid node in rvalue path. This is a bug!'"));
|
||||
}
|
||||
}
|
||||
|
||||
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
|
||||
@ -76,7 +106,7 @@ namespace hex::lang {
|
||||
return currPattern;
|
||||
}
|
||||
|
||||
PatternData* Evaluator::patternFromName(const std::vector<std::string> &path) {
|
||||
PatternData* Evaluator::patternFromName(const ASTNodeRValue::Path &path) {
|
||||
|
||||
PatternData *currPattern = nullptr;
|
||||
|
||||
@ -90,56 +120,34 @@ namespace hex::lang {
|
||||
}
|
||||
|
||||
// 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, ".")));
|
||||
if (currPattern == nullptr) {
|
||||
std::string identifier;
|
||||
for (const auto& part : path) {
|
||||
if (part.index() == 0) {
|
||||
// Path part is a identifier
|
||||
identifier += std::get<std::string>(part);
|
||||
} else if (part.index() == 1) {
|
||||
// Path part is a array index
|
||||
identifier += "[..]";
|
||||
}
|
||||
|
||||
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));
|
||||
if (!this->m_globalMembers.empty())
|
||||
std::copy(this->m_globalMembers.begin(), this->m_globalMembers.end(), std::back_inserter(currMembers));
|
||||
|
||||
PatternData *currPattern = nullptr;
|
||||
for (u32 i = 0; i < path.size(); i++) {
|
||||
const auto &identifier = path[i];
|
||||
|
||||
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 if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr) {
|
||||
currPattern = pointerPattern->getPointedAtPattern();
|
||||
i--;
|
||||
continue;
|
||||
identifier += ".";
|
||||
}
|
||||
else if (currPattern != nullptr)
|
||||
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("could not find identifier '{0}'", identifier.c_str()));
|
||||
identifier.pop_back();
|
||||
this->getConsole().abortEvaluation(hex::format("no identifier with name '{}' was found", identifier));
|
||||
}
|
||||
|
||||
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(currPattern); pointerPattern != nullptr)
|
||||
currPattern = pointerPattern->getPointedAtPattern();
|
||||
|
||||
return currPattern;*/
|
||||
return currPattern;
|
||||
}
|
||||
|
||||
ASTNodeIntegerLiteral* Evaluator::evaluateRValue(ASTNodeRValue *node) {
|
||||
if (this->m_currMembers.empty() && this->m_globalMembers.empty())
|
||||
this->getConsole().abortEvaluation("no variables available");
|
||||
|
||||
if (node->getPath().size() == 1 && node->getPath()[0] == "$")
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset });
|
||||
if (node->getPath().size() == 1) {
|
||||
if (auto part = std::get_if<std::string>(&node->getPath()[0]); part != nullptr && *part == "$")
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, this->m_currOffset });
|
||||
}
|
||||
|
||||
auto currPattern = this->patternFromName(node->getPath());
|
||||
|
||||
@ -193,6 +201,8 @@ namespace hex::lang {
|
||||
for (auto ¶m : node->getParams()) {
|
||||
if (auto numericExpression = dynamic_cast<ASTNodeNumericExpression*>(param); numericExpression != nullptr)
|
||||
evaluatedParams.push_back(this->evaluateMathematicalExpression(numericExpression));
|
||||
else if (auto typeOperatorExpression = dynamic_cast<ASTNodeTypeOperator*>(param))
|
||||
evaluatedParams.push_back(this->evaluateTypeOperator(typeOperatorExpression));
|
||||
else if (auto stringLiteral = dynamic_cast<ASTNodeStringLiteral*>(param); stringLiteral != nullptr)
|
||||
evaluatedParams.push_back(stringLiteral->clone());
|
||||
}
|
||||
@ -218,6 +228,23 @@ namespace hex::lang {
|
||||
return function.func(*this, evaluatedParams);
|
||||
}
|
||||
|
||||
ASTNodeIntegerLiteral* Evaluator::evaluateTypeOperator(ASTNodeTypeOperator *typeOperatorNode) {
|
||||
if (auto rvalue = dynamic_cast<ASTNodeRValue*>(typeOperatorNode->getExpression()); rvalue != nullptr) {
|
||||
auto pattern = this->patternFromName(rvalue->getPath());
|
||||
|
||||
switch (typeOperatorNode->getOperator()) {
|
||||
case Token::Operator::AddressOf:
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getOffset() });
|
||||
case Token::Operator::SizeOf:
|
||||
return new ASTNodeIntegerLiteral({ Token::ValueType::Unsigned64Bit, pattern->getSize() });
|
||||
default:
|
||||
this->getConsole().abortEvaluation("invalid type operator used. This is a bug!");
|
||||
}
|
||||
} else {
|
||||
this->getConsole().abortEvaluation("non-rvalue used in type operator");
|
||||
}
|
||||
}
|
||||
|
||||
#define FLOAT_BIT_OPERATION(name) \
|
||||
auto name(hex::floating_point auto left, auto right) { throw std::runtime_error(""); return 0; } \
|
||||
auto name(auto left, hex::floating_point auto right) { throw std::runtime_error(""); return 0; } \
|
||||
@ -365,7 +392,8 @@ namespace hex::lang {
|
||||
return integerNode;
|
||||
else
|
||||
this->getConsole().abortEvaluation("function not returning a numeric value used in expression");
|
||||
}
|
||||
} else if (auto typeOperator = dynamic_cast<ASTNodeTypeOperator*>(node); typeOperator != nullptr)
|
||||
return evaluateTypeOperator(typeOperator);
|
||||
else
|
||||
this->getConsole().abortEvaluation("invalid operand");
|
||||
}
|
||||
|
@ -365,7 +365,15 @@ namespace hex::lang {
|
||||
} else if (c == '$') {
|
||||
tokens.emplace_back(TOKEN(Operator, Dollar));
|
||||
offset += 1;
|
||||
} else if (c == '\'') {
|
||||
} else if (code.substr(offset, 9) == "addressof") {
|
||||
tokens.emplace_back(TOKEN(Operator, AddressOf));
|
||||
offset += 9;
|
||||
}
|
||||
else if (code.substr(offset, 6) == "sizeof") {
|
||||
tokens.emplace_back(TOKEN(Operator, SizeOf));
|
||||
offset += 6;
|
||||
}
|
||||
else if (c == '\'') {
|
||||
auto character = getCharacterLiteral(code.substr(offset));
|
||||
|
||||
if (!character.has_value())
|
||||
|
@ -66,19 +66,25 @@ namespace hex::lang {
|
||||
}
|
||||
|
||||
// <Identifier[.]...>
|
||||
ASTNode* Parser::parseRValue(std::vector<std::string> &path) {
|
||||
ASTNode* Parser::parseRValue(ASTNodeRValue::Path &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_SQUAREBRACKETOPEN))) {
|
||||
path.push_back(parseMathematicalExpression());
|
||||
if (!MATCHES(sequence(SEPARATOR_SQUAREBRACKETCLOSE)))
|
||||
throwParseError("expected closing ']' at end of array indexing");
|
||||
}
|
||||
|
||||
if (MATCHES(sequence(SEPARATOR_DOT))) {
|
||||
if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT)))
|
||||
return this->parseRValue(path);
|
||||
else
|
||||
throwParseError("expected member name or 'parent' keyword", -1);
|
||||
} else
|
||||
return TO_NUMERIC_EXPRESSION(new ASTNodeRValue(path));
|
||||
return new ASTNodeRValue(path);
|
||||
}
|
||||
|
||||
// <Integer|((parseMathematicalExpression))>
|
||||
@ -87,8 +93,10 @@ namespace hex::lang {
|
||||
return TO_NUMERIC_EXPRESSION(new ASTNodeIntegerLiteral(getValue<Token::IntegerLiteral>(-1)));
|
||||
else if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
auto node = this->parseMathematicalExpression();
|
||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE)))
|
||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) {
|
||||
delete node;
|
||||
throwParseError("expected closing parenthesis");
|
||||
}
|
||||
return node;
|
||||
} else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SCOPE_RESOLUTION))) {
|
||||
std::vector<std::string> path;
|
||||
@ -97,10 +105,24 @@ namespace hex::lang {
|
||||
} else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
return TO_NUMERIC_EXPRESSION(this->parseFunctionCall());
|
||||
} else if (MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) {
|
||||
std::vector<std::string> path;
|
||||
return this->parseRValue(path);
|
||||
ASTNodeRValue::Path path;
|
||||
return TO_NUMERIC_EXPRESSION(this->parseRValue(path));
|
||||
} else if (MATCHES(sequence(OPERATOR_DOLLAR))) {
|
||||
return new ASTNodeRValue({ "$" });
|
||||
} else if (MATCHES(oneOf(OPERATOR_ADDRESSOF, OPERATOR_SIZEOF) && sequence(SEPARATOR_ROUNDBRACKETOPEN))) {
|
||||
auto op = getValue<Token::Operator>(-2);
|
||||
|
||||
if (!MATCHES(oneOf(IDENTIFIER, KEYWORD_PARENT))) {
|
||||
throwParseError("expected rvalue identifier");
|
||||
}
|
||||
|
||||
ASTNodeRValue::Path path;
|
||||
auto node = new ASTNodeTypeOperator(op, this->parseRValue(path));
|
||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) {
|
||||
delete node;
|
||||
throwParseError("expected closing parenthesis");
|
||||
}
|
||||
return TO_NUMERIC_EXPRESSION(node);
|
||||
} else
|
||||
throwParseError("expected integer or parenthesis");
|
||||
}
|
||||
|
@ -50,114 +50,4 @@ namespace hex::lang {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Validator::printAST(const std::vector<ASTNode*>& ast){
|
||||
#if DEBUG
|
||||
#define INDENT_VALUE indent, ' '
|
||||
static s32 indent = -2;
|
||||
|
||||
indent += 2;
|
||||
for (const auto &node : ast) {
|
||||
if (auto variableDeclNode = dynamic_cast<ASTNodeVariableDecl*>(node); variableDeclNode != nullptr) {
|
||||
if (auto offset = dynamic_cast<ASTNodeNumericExpression*>(variableDeclNode->getPlacementOffset()); offset != nullptr) {
|
||||
printf("%*c ASTNodeVariableDecl (%s) @\n", INDENT_VALUE, variableDeclNode->getName().data());
|
||||
printAST({ offset });
|
||||
}
|
||||
else
|
||||
printf("%*c ASTNodeVariableDecl (%s)\n", INDENT_VALUE, variableDeclNode->getName().data());
|
||||
printAST({ variableDeclNode->getType() });
|
||||
} else if (auto pointerDeclNode = dynamic_cast<ASTNodePointerVariableDecl*>(node); pointerDeclNode != nullptr) {
|
||||
if (auto offset = dynamic_cast<ASTNodeNumericExpression*>(pointerDeclNode->getPlacementOffset()); offset != nullptr) {
|
||||
printf("%*c ASTNodePointerVariableDecl (*%s) @\n", INDENT_VALUE, pointerDeclNode->getName().data());
|
||||
printAST({ offset });
|
||||
}
|
||||
else
|
||||
printf("%*c ASTNodePointerVariableDecl (*%s)\n", INDENT_VALUE, pointerDeclNode->getName().data());
|
||||
printAST({ pointerDeclNode->getType() });
|
||||
printAST({ pointerDeclNode->getSizeType() });
|
||||
} else if (auto arrayDeclNode = dynamic_cast<ASTNodeArrayVariableDecl*>(node); arrayDeclNode != nullptr) {
|
||||
auto sizeExpr = dynamic_cast<ASTNodeNumericExpression*>(arrayDeclNode->getSize());
|
||||
if (sizeExpr == nullptr) {
|
||||
printf("%*c Invalid size!\n", INDENT_VALUE);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto offset = dynamic_cast<ASTNodeNumericExpression*>(arrayDeclNode->getPlacementOffset()); offset != nullptr) {
|
||||
printf("%*c ASTNodeArrayVariableDecl (%s[]) @\n", INDENT_VALUE, arrayDeclNode->getName().data());
|
||||
printAST({ sizeExpr });
|
||||
printAST({ offset });
|
||||
}
|
||||
else {
|
||||
printf("%*c ASTNodeArrayVariableDecl (%s[])\n", INDENT_VALUE, arrayDeclNode->getName().data());
|
||||
printAST({ sizeExpr });
|
||||
}
|
||||
|
||||
printAST({ arrayDeclNode->getType() });
|
||||
printAST({ arrayDeclNode->getSize() });
|
||||
} else if (auto typeDeclNode = dynamic_cast<ASTNodeTypeDecl*>(node); typeDeclNode != nullptr) {
|
||||
printf("%*c ASTNodeTypeDecl (%s %s)\n", INDENT_VALUE, typeDeclNode->getEndian().value_or(std::endian::native) == std::endian::little ? "le" : "be", typeDeclNode->getName().empty() ? "<unnamed>" : typeDeclNode->getName().data());
|
||||
printAST({ typeDeclNode->getType() });
|
||||
} else if (auto builtinTypeNode = dynamic_cast<ASTNodeBuiltinType*>(node); builtinTypeNode != nullptr) {
|
||||
std::string typeName = Token::getTypeName(builtinTypeNode->getType());
|
||||
printf("%*c ASTNodeTypeDecl (%s)\n", INDENT_VALUE, typeName.c_str());
|
||||
} else if (auto integerLiteralNode = dynamic_cast<ASTNodeIntegerLiteral*>(node); integerLiteralNode != nullptr) {
|
||||
printf("%*c ASTNodeIntegerLiteral %lld\n", INDENT_VALUE, (s64)std::get<s128>(integerLiteralNode->getValue()));
|
||||
} else if (auto numericExpressionNode = dynamic_cast<ASTNodeNumericExpression*>(node); numericExpressionNode != nullptr) {
|
||||
std::string op;
|
||||
switch (numericExpressionNode->getOperator()) {
|
||||
case Token::Operator::Plus: op = "+"; break;
|
||||
case Token::Operator::Minus: op = "-"; break;
|
||||
case Token::Operator::Star: op = "*"; break;
|
||||
case Token::Operator::Slash: op = "/"; break;
|
||||
|
||||
case Token::Operator::ShiftLeft: op = ">>"; break;
|
||||
case Token::Operator::ShiftRight: op = "<<"; break;
|
||||
|
||||
case Token::Operator::BitAnd: op = "&"; break;
|
||||
case Token::Operator::BitOr: op = "|"; break;
|
||||
case Token::Operator::BitXor: op = "^"; break;
|
||||
default: op = "???";
|
||||
}
|
||||
printf("%*c ASTNodeNumericExpression %s\n", INDENT_VALUE, op.c_str());
|
||||
printf("%*c Left:\n", INDENT_VALUE);
|
||||
printAST({ numericExpressionNode->getLeftOperand() });
|
||||
printf("%*c Right:\n", INDENT_VALUE);
|
||||
printAST({ numericExpressionNode->getRightOperand() });
|
||||
} else if (auto structNode = dynamic_cast<ASTNodeStruct*>(node); structNode != nullptr) {
|
||||
printf("%*c ASTNodeStruct\n", INDENT_VALUE);
|
||||
printAST(structNode->getMembers());
|
||||
} else if (auto unionNode = dynamic_cast<ASTNodeUnion*>(node); unionNode != nullptr) {
|
||||
printf("%*c ASTNodeUnion\n", INDENT_VALUE);
|
||||
printAST(unionNode->getMembers());
|
||||
} else if (auto enumNode = dynamic_cast<ASTNodeEnum*>(node); enumNode != nullptr) {
|
||||
printf("%*c ASTNodeEnum\n", INDENT_VALUE);
|
||||
|
||||
for (const auto &[name, entry] : enumNode->getEntries()) {
|
||||
printf("%*c ::%s\n", INDENT_VALUE, name.c_str());
|
||||
printAST({ entry });
|
||||
}
|
||||
} else if (auto bitfieldNode = dynamic_cast<ASTNodeBitfield*>(node); bitfieldNode != nullptr) {
|
||||
printf("%*c ASTNodeBitfield\n", INDENT_VALUE);
|
||||
|
||||
for (const auto &[name, entry] : bitfieldNode->getEntries()) {
|
||||
printf("%*c %s : \n", INDENT_VALUE, name.c_str());
|
||||
printAST({ entry });
|
||||
}
|
||||
} else if (auto rvalueNode = dynamic_cast<ASTNodeRValue*>(node); rvalueNode != nullptr) {
|
||||
printf("%*c ASTNodeRValue\n", INDENT_VALUE);
|
||||
|
||||
printf("%*c ", INDENT_VALUE);
|
||||
for (const auto &path : rvalueNode->getPath())
|
||||
printf("%s.", path.c_str());
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%*c Invalid AST node!\n", INDENT_VALUE);
|
||||
}
|
||||
}
|
||||
indent -= 2;
|
||||
|
||||
#undef INDENT_VALUE
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
@ -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", "parent"
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else", "false", "true", "parent", "addressof", "sizeof"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
Loading…
x
Reference in New Issue
Block a user