Added if, else and else if to pattern language
This commit is contained in:
parent
d8b16766f5
commit
acfd5aa02f
@ -366,4 +366,48 @@ namespace hex::lang {
|
||||
std::vector<std::string> m_path;
|
||||
};
|
||||
|
||||
class ASTNodeConditionalStatement : public ASTNode {
|
||||
public:
|
||||
explicit ASTNodeConditionalStatement(ASTNode *condition, std::vector<ASTNode*> trueBody, std::vector<ASTNode*> falseBody)
|
||||
: ASTNode(), m_condition(condition), m_trueBody(std::move(trueBody)), m_falseBody(std::move(falseBody)) { }
|
||||
|
||||
~ASTNodeConditionalStatement() override {
|
||||
delete this->m_condition;
|
||||
|
||||
for (auto &statement : this->m_trueBody)
|
||||
delete statement;
|
||||
for (auto &statement : this->m_falseBody)
|
||||
delete statement;
|
||||
}
|
||||
|
||||
ASTNodeConditionalStatement(const ASTNodeConditionalStatement &other) : ASTNode(other) {
|
||||
this->m_condition = other.m_condition->clone();
|
||||
|
||||
for (auto &statement : other.m_trueBody)
|
||||
this->m_trueBody.push_back(statement->clone());
|
||||
for (auto &statement : other.m_falseBody)
|
||||
this->m_falseBody.push_back(statement->clone());
|
||||
}
|
||||
|
||||
ASTNode* clone() const override {
|
||||
return new ASTNodeConditionalStatement(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] ASTNode* getCondition() {
|
||||
return this->m_condition;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<ASTNode*>& getTrueBody() const {
|
||||
return this->m_trueBody;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<ASTNode*>& getFalseBody() const {
|
||||
return this->m_falseBody;
|
||||
}
|
||||
|
||||
private:
|
||||
ASTNode *m_condition;
|
||||
std::vector<ASTNode*> m_trueBody, m_falseBody;
|
||||
};
|
||||
|
||||
}
|
@ -47,6 +47,7 @@ namespace hex::lang {
|
||||
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
||||
|
||||
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
|
||||
std::vector<PatternData*> evaluateMember(ASTNode *node);
|
||||
PatternData* evaluateStruct(ASTNodeStruct *node);
|
||||
PatternData* evaluateUnion(ASTNodeUnion *node);
|
||||
PatternData* evaluateEnum(ASTNodeEnum *node);
|
||||
|
@ -59,17 +59,24 @@ namespace hex::lang {
|
||||
ASTNode* parseMultiplicativeExpression();
|
||||
ASTNode* parseAdditiveExpression();
|
||||
ASTNode* parseShiftExpression();
|
||||
ASTNode* parseRelationExpression();
|
||||
ASTNode* parseEqualityExpression();
|
||||
ASTNode* parseBinaryAndExpression();
|
||||
ASTNode* parseBinaryXorExpression();
|
||||
ASTNode* parseBinaryOrExpression();
|
||||
ASTNode* parseBooleanAnd();
|
||||
ASTNode* parseBooleanXor();
|
||||
ASTNode* parseBooleanOr();
|
||||
ASTNode* parseMathematicalExpression();
|
||||
|
||||
ASTNode* parseConditional();
|
||||
ASTNode* parseType(s32 startIndex);
|
||||
ASTNode* parseUsingDeclaration();
|
||||
ASTNode* parsePadding();
|
||||
ASTNode* parseMemberVariable();
|
||||
ASTNode* parseMemberArrayVariable();
|
||||
ASTNode* parseMemberPointerVariable();
|
||||
ASTNode* parseMember();
|
||||
ASTNode* parseStruct();
|
||||
ASTNode* parseUnion();
|
||||
ASTNode* parseEnum();
|
||||
|
@ -28,6 +28,8 @@ namespace hex::lang {
|
||||
Bitfield,
|
||||
LittleEndian,
|
||||
BigEndian,
|
||||
If,
|
||||
Else
|
||||
};
|
||||
|
||||
enum class Operator {
|
||||
@ -42,7 +44,16 @@ namespace hex::lang {
|
||||
ShiftRight,
|
||||
BitOr,
|
||||
BitAnd,
|
||||
BitXor
|
||||
BitXor,
|
||||
BoolEquals,
|
||||
BoolNotEquals,
|
||||
BoolGreaterThan,
|
||||
BoolLessThan,
|
||||
BoolGreaterThanOrEquals,
|
||||
BoolLessThanOrEquals,
|
||||
BoolAnd,
|
||||
BoolOr,
|
||||
BoolXor
|
||||
};
|
||||
|
||||
enum class ValueType {
|
||||
@ -168,46 +179,57 @@ namespace hex::lang {
|
||||
|
||||
#define COMPONENT(type, value) hex::lang::Token::Type::type, hex::lang::Token::type::value
|
||||
|
||||
#define KEYWORD_STRUCT COMPONENT(Keyword, Struct)
|
||||
#define KEYWORD_UNION COMPONENT(Keyword, Union)
|
||||
#define KEYWORD_USING COMPONENT(Keyword, Using)
|
||||
#define KEYWORD_ENUM COMPONENT(Keyword, Enum)
|
||||
#define KEYWORD_BITFIELD COMPONENT(Keyword, Bitfield)
|
||||
#define KEYWORD_LE COMPONENT(Keyword, LittleEndian)
|
||||
#define KEYWORD_BE COMPONENT(Keyword, BigEndian)
|
||||
#define KEYWORD_STRUCT COMPONENT(Keyword, Struct)
|
||||
#define KEYWORD_UNION COMPONENT(Keyword, Union)
|
||||
#define KEYWORD_USING COMPONENT(Keyword, Using)
|
||||
#define KEYWORD_ENUM COMPONENT(Keyword, Enum)
|
||||
#define KEYWORD_BITFIELD COMPONENT(Keyword, Bitfield)
|
||||
#define KEYWORD_LE COMPONENT(Keyword, LittleEndian)
|
||||
#define KEYWORD_BE COMPONENT(Keyword, BigEndian)
|
||||
#define KEYWORD_IF COMPONENT(Keyword, If)
|
||||
#define KEYWORD_ELSE COMPONENT(Keyword, Else)
|
||||
|
||||
#define INTEGER hex::lang::Token::Type::Integer, hex::lang::Token::IntegerLiteral({ hex::lang::Token::ValueType::Any, 0xFFFF'FFFF'FFFF'FFFF })
|
||||
#define IDENTIFIER hex::lang::Token::Type::Identifier, ""
|
||||
#define INTEGER hex::lang::Token::Type::Integer, hex::lang::Token::IntegerLiteral({ hex::lang::Token::ValueType::Any, 0xFFFF'FFFF'FFFF'FFFF })
|
||||
#define IDENTIFIER hex::lang::Token::Type::Identifier, ""
|
||||
|
||||
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
|
||||
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
|
||||
#define OPERATOR_INHERIT COMPONENT(Operator, Inherit)
|
||||
#define OPERATOR_PLUS COMPONENT(Operator, Plus)
|
||||
#define OPERATOR_MINUS COMPONENT(Operator, Minus)
|
||||
#define OPERATOR_STAR COMPONENT(Operator, Star)
|
||||
#define OPERATOR_SLASH COMPONENT(Operator, Slash)
|
||||
#define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft)
|
||||
#define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight)
|
||||
#define OPERATOR_BITOR COMPONENT(Operator, BitOr)
|
||||
#define OPERATOR_BITAND COMPONENT(Operator, BitAnd)
|
||||
#define OPERATOR_BITXOR COMPONENT(Operator, BitXor)
|
||||
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
|
||||
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
|
||||
#define OPERATOR_INHERIT COMPONENT(Operator, Inherit)
|
||||
#define OPERATOR_PLUS COMPONENT(Operator, Plus)
|
||||
#define OPERATOR_MINUS COMPONENT(Operator, Minus)
|
||||
#define OPERATOR_STAR COMPONENT(Operator, Star)
|
||||
#define OPERATOR_SLASH COMPONENT(Operator, Slash)
|
||||
#define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft)
|
||||
#define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight)
|
||||
#define OPERATOR_BITOR COMPONENT(Operator, BitOr)
|
||||
#define OPERATOR_BITAND COMPONENT(Operator, BitAnd)
|
||||
#define OPERATOR_BITXOR COMPONENT(Operator, BitXor)
|
||||
#define OPERATOR_BOOLEQUALS COMPONENT(Operator, BoolEquals)
|
||||
#define OPERATOR_BOOLNOTEQUALS COMPONENT(Operator, BoolNotEquals)
|
||||
#define OPERATOR_BOOLGREATERTHAN COMPONENT(Operator, BoolGreaterThan)
|
||||
#define OPERATOR_BOOLLESSTHAN COMPONENT(Operator, BoolLessThan)
|
||||
#define OPERATOR_BOOLGREATERTHANOREQUALS COMPONENT(Operator, BoolGreaterThanOrEquals)
|
||||
#define OPERATOR_BOOLLESSTHANOREQUALS COMPONENT(Operator, BoolLessThanOrEquals)
|
||||
#define OPERATOR_BOOLAND COMPONENT(Operator, BoolAnd)
|
||||
#define OPERATOR_BOOLOR COMPONENT(Operator, BoolOr)
|
||||
#define OPERATOR_BOOLXOR COMPONENT(Operator, BoolXor)
|
||||
|
||||
#define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType)
|
||||
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
||||
#define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned)
|
||||
#define VALUETYPE_SIGNED COMPONENT(ValueType, Signed)
|
||||
#define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint)
|
||||
#define VALUETYPE_INTEGER COMPONENT(ValueType, Integer)
|
||||
#define VALUETYPE_ANY COMPONENT(ValueType, Any)
|
||||
#define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType)
|
||||
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
||||
#define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned)
|
||||
#define VALUETYPE_SIGNED COMPONENT(ValueType, Signed)
|
||||
#define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint)
|
||||
#define VALUETYPE_INTEGER COMPONENT(ValueType, Integer)
|
||||
#define VALUETYPE_ANY COMPONENT(ValueType, Any)
|
||||
|
||||
#define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen)
|
||||
#define SEPARATOR_ROUNDBRACKETCLOSE COMPONENT(Separator, RoundBracketClose)
|
||||
#define SEPARATOR_CURLYBRACKETOPEN COMPONENT(Separator, CurlyBracketOpen)
|
||||
#define SEPARATOR_CURLYBRACKETCLOSE COMPONENT(Separator, CurlyBracketClose)
|
||||
#define SEPARATOR_SQUAREBRACKETOPEN COMPONENT(Separator, SquareBracketOpen)
|
||||
#define SEPARATOR_SQUAREBRACKETCLOSE COMPONENT(Separator, SquareBracketClose)
|
||||
#define SEPARATOR_COMMA COMPONENT(Separator, Comma)
|
||||
#define SEPARATOR_DOT COMPONENT(Separator, Dot)
|
||||
#define SEPARATOR_SCOPE_RESOLUTION COMPONENT(Separator, ScopeResolution)
|
||||
#define SEPARATOR_ENDOFEXPRESSION COMPONENT(Separator, EndOfExpression)
|
||||
#define SEPARATOR_ENDOFPROGRAM COMPONENT(Separator, EndOfProgram)
|
||||
#define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen)
|
||||
#define SEPARATOR_ROUNDBRACKETCLOSE COMPONENT(Separator, RoundBracketClose)
|
||||
#define SEPARATOR_CURLYBRACKETOPEN COMPONENT(Separator, CurlyBracketOpen)
|
||||
#define SEPARATOR_CURLYBRACKETCLOSE COMPONENT(Separator, CurlyBracketClose)
|
||||
#define SEPARATOR_SQUAREBRACKETOPEN COMPONENT(Separator, SquareBracketOpen)
|
||||
#define SEPARATOR_SQUAREBRACKETCLOSE COMPONENT(Separator, SquareBracketClose)
|
||||
#define SEPARATOR_COMMA COMPONENT(Separator, Comma)
|
||||
#define SEPARATOR_DOT COMPONENT(Separator, Dot)
|
||||
#define SEPARATOR_SCOPE_RESOLUTION COMPONENT(Separator, ScopeResolution)
|
||||
#define SEPARATOR_ENDOFEXPRESSION COMPONENT(Separator, EndOfExpression)
|
||||
#define SEPARATOR_ENDOFPROGRAM COMPONENT(Separator, EndOfProgram)
|
@ -79,6 +79,18 @@ namespace hex::lang {
|
||||
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, *reinterpret_cast<s128*>(value) });
|
||||
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
|
||||
}
|
||||
} else if (auto enumPattern = dynamic_cast<PatternDataEnum*>(currPattern); enumPattern != nullptr) {
|
||||
u8 value[enumPattern->getSize()];
|
||||
this->m_provider->read(enumPattern->getOffset(), value, enumPattern->getSize());
|
||||
|
||||
switch (enumPattern->getSize()) {
|
||||
case 1: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed8Bit, *reinterpret_cast<s8*>(value) });
|
||||
case 2: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed16Bit, *reinterpret_cast<s16*>(value) });
|
||||
case 4: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed32Bit, *reinterpret_cast<s32*>(value) });
|
||||
case 8: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed64Bit, *reinterpret_cast<s64*>(value) });
|
||||
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, *reinterpret_cast<s128*>(value) });
|
||||
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
|
||||
}
|
||||
} else
|
||||
throwEvaluateError("tried to use non-integer value in numeric expression", node->getLineNumber());
|
||||
}
|
||||
@ -158,6 +170,24 @@ namespace hex::lang {
|
||||
return new ASTNodeIntegerLiteral({ newType, bitXor(leftValue, rightValue) });
|
||||
case Token::Operator::BitOr:
|
||||
return new ASTNodeIntegerLiteral({ newType, bitOr(leftValue, rightValue) });
|
||||
case Token::Operator::BoolEquals:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue == rightValue });
|
||||
case Token::Operator::BoolNotEquals:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue != rightValue });
|
||||
case Token::Operator::BoolGreaterThan:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue > rightValue });
|
||||
case Token::Operator::BoolLessThan:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue < rightValue });
|
||||
case Token::Operator::BoolGreaterThanOrEquals:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue >= rightValue });
|
||||
case Token::Operator::BoolLessThanOrEquals:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue <= rightValue });
|
||||
case Token::Operator::BoolAnd:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue && rightValue });
|
||||
case Token::Operator::BoolXor:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue && !rightValue || !leftValue && rightValue });
|
||||
case Token::Operator::BoolOr:
|
||||
return new ASTNodeIntegerLiteral({ newType, leftValue || rightValue });
|
||||
default:
|
||||
throwEvaluateError("invalid operator used in mathematical expression", left->getLineNumber());
|
||||
}
|
||||
@ -220,6 +250,39 @@ namespace hex::lang {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
std::vector<PatternData*> Evaluator::evaluateMember(ASTNode *node) {
|
||||
this->m_currEndian.reset();
|
||||
|
||||
if (auto memberVariableNode = dynamic_cast<ASTNodeVariableDecl*>(node); memberVariableNode != nullptr)
|
||||
return { this->evaluateVariable(memberVariableNode) };
|
||||
else if (auto memberArrayNode = dynamic_cast<ASTNodeArrayVariableDecl*>(node); memberArrayNode != nullptr)
|
||||
return { this->evaluateArray(memberArrayNode) };
|
||||
else if (auto memberPointerNode = dynamic_cast<ASTNodePointerVariableDecl*>(node); memberPointerNode != nullptr)
|
||||
return { this->evaluatePointer(memberPointerNode) };
|
||||
else if (auto conditionalNode = dynamic_cast<ASTNodeConditionalStatement*>(node); conditionalNode != nullptr) {
|
||||
auto condition = this->evaluateMathematicalExpression(static_cast<ASTNodeNumericExpression*>(conditionalNode->getCondition()));
|
||||
|
||||
std::vector<PatternData*> patterns;
|
||||
if (std::visit([](auto &&value) { return value != 0; }, condition->getValue())) {
|
||||
for (auto &statement : conditionalNode->getTrueBody()) {
|
||||
auto statementPatterns = this->evaluateMember(statement);
|
||||
std::copy(statementPatterns.begin(), statementPatterns.end(), std::back_inserter(patterns));
|
||||
}
|
||||
} else {
|
||||
for (auto &statement : conditionalNode->getFalseBody()) {
|
||||
auto statementPatterns = this->evaluateMember(statement);
|
||||
std::copy(statementPatterns.begin(), statementPatterns.end(), std::back_inserter(patterns));
|
||||
}
|
||||
}
|
||||
|
||||
delete condition;
|
||||
|
||||
return patterns;
|
||||
}
|
||||
else
|
||||
throwEvaluateError("invalid struct member", node->getLineNumber());
|
||||
}
|
||||
|
||||
PatternData* Evaluator::evaluateStruct(ASTNodeStruct *node) {
|
||||
std::vector<PatternData*> memberPatterns;
|
||||
|
||||
@ -228,16 +291,8 @@ namespace hex::lang {
|
||||
|
||||
auto startOffset = this->m_currOffset;
|
||||
for (auto &member : node->getMembers()) {
|
||||
if (auto memberVariableNode = dynamic_cast<ASTNodeVariableDecl*>(member); memberVariableNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluateVariable(memberVariableNode));
|
||||
else if (auto memberArrayNode = dynamic_cast<ASTNodeArrayVariableDecl*>(member); memberArrayNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluateArray(memberArrayNode));
|
||||
else if (auto memberPointerNode = dynamic_cast<ASTNodePointerVariableDecl*>(member); memberPointerNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluatePointer(memberPointerNode));
|
||||
else
|
||||
throwEvaluateError("invalid struct member", member->getLineNumber());
|
||||
|
||||
this->m_currEndian.reset();
|
||||
auto newMembers = this->evaluateMember(member);
|
||||
std::copy(newMembers.begin(), newMembers.end(), std::back_inserter(memberPatterns));
|
||||
}
|
||||
|
||||
return new PatternDataStruct(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
||||
@ -251,17 +306,10 @@ namespace hex::lang {
|
||||
|
||||
auto startOffset = this->m_currOffset;
|
||||
for (auto &member : node->getMembers()) {
|
||||
if (auto memberVariableNode = dynamic_cast<ASTNodeVariableDecl*>(member); memberVariableNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluateVariable(memberVariableNode));
|
||||
else if (auto memberArrayNode = dynamic_cast<ASTNodeArrayVariableDecl*>(member); memberArrayNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluateArray(memberArrayNode));
|
||||
else if (auto memberPointerNode = dynamic_cast<ASTNodePointerVariableDecl*>(member); memberPointerNode != nullptr)
|
||||
memberPatterns.emplace_back(this->evaluatePointer(memberPointerNode));
|
||||
else
|
||||
throwEvaluateError("invalid union member", member->getLineNumber());
|
||||
auto newMembers = this->evaluateMember(member);
|
||||
std::copy(newMembers.begin(), newMembers.end(), std::back_inserter(memberPatterns));
|
||||
|
||||
this->m_currOffset = startOffset;
|
||||
this->m_currEndian.reset();
|
||||
}
|
||||
|
||||
return new PatternDataUnion(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
||||
|
@ -188,6 +188,27 @@ namespace hex::lang {
|
||||
} else if (c == '@') {
|
||||
tokens.emplace_back(TOKEN(Operator, AtDeclaration));
|
||||
offset += 1;
|
||||
} else if (code.substr(offset, 2) == "==") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolEquals));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == "!=") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolNotEquals));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == ">=") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolGreaterThanOrEquals));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == "<=") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolLessThanOrEquals));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == "&&") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolAnd));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == "||") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolOr));
|
||||
offset += 2;
|
||||
} else if (code.substr(offset, 2) == "^^") {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolXor));
|
||||
offset += 2;
|
||||
} else if (c == '=') {
|
||||
tokens.emplace_back(TOKEN(Operator, Assignment));
|
||||
offset += 1;
|
||||
@ -215,6 +236,12 @@ namespace hex::lang {
|
||||
} else if (code.substr(offset, 2) == ">>") {
|
||||
tokens.emplace_back(TOKEN(Operator, ShiftRight));
|
||||
offset += 2;
|
||||
} else if (c == '>') {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolGreaterThan));
|
||||
offset += 1;
|
||||
} else if (c == '<') {
|
||||
tokens.emplace_back(TOKEN(Operator, BoolLessThan));
|
||||
offset += 1;
|
||||
} else if (c == '|') {
|
||||
tokens.emplace_back(TOKEN(Operator, BitOr));
|
||||
offset += 1;
|
||||
@ -276,6 +303,10 @@ namespace hex::lang {
|
||||
tokens.emplace_back(TOKEN(Keyword, BigEndian));
|
||||
else if (identifier == "le")
|
||||
tokens.emplace_back(TOKEN(Keyword, LittleEndian));
|
||||
else if (identifier == "if")
|
||||
tokens.emplace_back(TOKEN(Keyword, If));
|
||||
else if (identifier == "else")
|
||||
tokens.emplace_back(TOKEN(Keyword, Else));
|
||||
|
||||
// Check for built-in types
|
||||
else if (identifier == "u8")
|
||||
|
@ -55,8 +55,9 @@ namespace hex::lang {
|
||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE)))
|
||||
throwParseError("expected closing parenthesis");
|
||||
return node;
|
||||
} else if (MATCHES(sequence(IDENTIFIER) && peek(SEPARATOR_SCOPE_RESOLUTION))) {
|
||||
} else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SCOPE_RESOLUTION))) {
|
||||
std::vector<std::string> path;
|
||||
this->m_curr--;
|
||||
return this->parseScopeResolution(path);
|
||||
}
|
||||
else if (MATCHES(sequence(IDENTIFIER))) {
|
||||
@ -72,10 +73,8 @@ namespace hex::lang {
|
||||
auto node = this->parseFactor();
|
||||
|
||||
while (MATCHES(variant(OPERATOR_STAR, OPERATOR_SLASH))) {
|
||||
if (peek(OPERATOR_STAR, -1))
|
||||
node = new ASTNodeNumericExpression(node, this->parseFactor(), Token::Operator::Star);
|
||||
else
|
||||
node = new ASTNodeNumericExpression(node, this->parseFactor(), Token::Operator::Slash);
|
||||
auto op = getValue<Token::Operator>(-1);
|
||||
node = new ASTNodeNumericExpression(node, this->parseFactor(), op);
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -86,35 +85,55 @@ namespace hex::lang {
|
||||
auto node = this->parseMultiplicativeExpression();
|
||||
|
||||
while (MATCHES(variant(OPERATOR_PLUS, OPERATOR_MINUS))) {
|
||||
if (peek(OPERATOR_PLUS, -1))
|
||||
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), Token::Operator::Plus);
|
||||
else
|
||||
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), Token::Operator::Minus);
|
||||
auto op = getValue<Token::Operator>(-1);
|
||||
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), op);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseAdditiveExpression) <>>|<<> (parseAdditiveExpression)
|
||||
// (parseAdditiveExpression) < >>|<< > (parseAdditiveExpression)
|
||||
ASTNode* Parser::parseShiftExpression() {
|
||||
auto node = this->parseAdditiveExpression();
|
||||
|
||||
while (MATCHES(variant(OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT))) {
|
||||
if (peek(OPERATOR_SHIFTLEFT, -1))
|
||||
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), Token::Operator::ShiftLeft);
|
||||
else
|
||||
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), Token::Operator::ShiftRight);
|
||||
auto op = getValue<Token::Operator>(-1);
|
||||
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), op);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseShiftExpression) & (parseShiftExpression)
|
||||
ASTNode* Parser::parseBinaryAndExpression() {
|
||||
// (parseAdditiveExpression) < >=|<=|>|< > (parseAdditiveExpression)
|
||||
ASTNode* Parser::parseRelationExpression() {
|
||||
auto node = this->parseShiftExpression();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BOOLGREATERTHAN) || sequence(OPERATOR_BOOLLESSTHAN) || sequence(OPERATOR_BOOLGREATERTHANOREQUALS) || sequence(OPERATOR_BOOLLESSTHANOREQUALS))) {
|
||||
auto op = getValue<Token::Operator>(-1);
|
||||
node = new ASTNodeNumericExpression(node, this->parseShiftExpression(), op);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseRelationExpression) <==|!=> (parseRelationExpression)
|
||||
ASTNode* Parser::parseEqualityExpression() {
|
||||
auto node = this->parseRelationExpression();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BOOLEQUALS) || sequence(OPERATOR_BOOLNOTEQUALS))) {
|
||||
auto op = getValue<Token::Operator>(-1);
|
||||
node = new ASTNodeNumericExpression(node, this->parseRelationExpression(), op);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseEqualityExpression) & (parseEqualityExpression)
|
||||
ASTNode* Parser::parseBinaryAndExpression() {
|
||||
auto node = this->parseEqualityExpression();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BITAND))) {
|
||||
node = new ASTNodeNumericExpression(node, this->parseShiftExpression(), Token::Operator::BitAnd);
|
||||
node = new ASTNodeNumericExpression(node, this->parseEqualityExpression(), Token::Operator::BitAnd);
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -142,9 +161,80 @@ namespace hex::lang {
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseBinaryOrExpression) && (parseBinaryOrExpression)
|
||||
ASTNode* Parser::parseBooleanAnd() {
|
||||
auto node = this->parseBinaryOrExpression();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BOOLAND))) {
|
||||
node = new ASTNodeNumericExpression(node, this->parseBinaryOrExpression(), Token::Operator::BitOr);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseBooleanAnd) ^^ (parseBooleanAnd)
|
||||
ASTNode* Parser::parseBooleanXor() {
|
||||
auto node = this->parseBooleanAnd();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BOOLXOR))) {
|
||||
node = new ASTNodeNumericExpression(node, this->parseBooleanAnd(), Token::Operator::BitOr);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseBooleanXor) || (parseBooleanXor)
|
||||
ASTNode* Parser::parseBooleanOr() {
|
||||
auto node = this->parseBooleanXor();
|
||||
|
||||
while (MATCHES(sequence(OPERATOR_BOOLOR))) {
|
||||
node = new ASTNodeNumericExpression(node, this->parseBooleanXor(), Token::Operator::BitOr);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
// (parseBinaryOrExpression)
|
||||
ASTNode* Parser::parseMathematicalExpression() {
|
||||
return this->parseBinaryOrExpression();
|
||||
return this->parseBooleanOr();
|
||||
}
|
||||
|
||||
|
||||
/* Control flow */
|
||||
|
||||
// if ((parseMathematicalExpression)) { (parseMember) }
|
||||
ASTNode* Parser::parseConditional() {
|
||||
auto condition = parseMathematicalExpression();
|
||||
std::vector<ASTNode*> trueBody, falseBody;
|
||||
|
||||
ScopeExit cleanup([&]{
|
||||
delete condition;
|
||||
for (auto &statement : trueBody)
|
||||
delete statement;
|
||||
for (auto &statement : falseBody)
|
||||
delete statement;
|
||||
});
|
||||
|
||||
if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE, SEPARATOR_CURLYBRACKETOPEN))) {
|
||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||
trueBody.push_back(parseMember());
|
||||
}
|
||||
} else if (MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE))) {
|
||||
trueBody.push_back(parseMember());
|
||||
} else
|
||||
throwParseError("expected body of conditional statement");
|
||||
|
||||
if (MATCHES(sequence(KEYWORD_ELSE, SEPARATOR_CURLYBRACKETOPEN))) {
|
||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||
falseBody.push_back(parseMember());
|
||||
}
|
||||
} else if (MATCHES(sequence(KEYWORD_ELSE))) {
|
||||
falseBody.push_back(parseMember());
|
||||
}
|
||||
|
||||
cleanup.release();
|
||||
|
||||
return new ASTNodeConditionalStatement(condition, trueBody, falseBody);
|
||||
}
|
||||
|
||||
/* Type declarations */
|
||||
@ -235,6 +325,31 @@ namespace hex::lang {
|
||||
return new ASTNodePointerVariableDecl(name, temporaryPointerType->getType()->clone(), temporarySizeType->getType()->clone());
|
||||
}
|
||||
|
||||
// [(parsePadding)|(parseMemberVariable)|(parseMemberArrayVariable)|(parseMemberPointerVariable)]
|
||||
ASTNode* Parser::parseMember() {
|
||||
ASTNode *member;
|
||||
|
||||
if (MATCHES(sequence(VALUETYPE_PADDING, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||
member = parsePadding();
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||
member = parseMemberArrayVariable();
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
||||
member = parseMemberVariable();
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(OPERATOR_STAR, IDENTIFIER, OPERATOR_INHERIT)))
|
||||
member = parseMemberPointerVariable();
|
||||
else if (MATCHES(sequence(KEYWORD_IF, SEPARATOR_ROUNDBRACKETOPEN)))
|
||||
return parseConditional();
|
||||
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
||||
throwParseError("unexpected end of program", -2);
|
||||
else
|
||||
throwParseError("invalid struct member", 0);
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
||||
throwParseError("missing ';' at end of expression", -1);
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
// struct Identifier { <(parseMember)...> }
|
||||
ASTNode* Parser::parseStruct() {
|
||||
const auto structNode = new ASTNodeStruct();
|
||||
@ -242,21 +357,7 @@ namespace hex::lang {
|
||||
ScopeExit structGuard([&]{ delete structNode; });
|
||||
|
||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||
if (MATCHES(sequence(VALUETYPE_PADDING, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||
structNode->addMember(parsePadding());
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||
structNode->addMember(parseMemberArrayVariable());
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
||||
structNode->addMember(parseMemberVariable());
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(OPERATOR_STAR, IDENTIFIER, OPERATOR_INHERIT)))
|
||||
structNode->addMember(parseMemberPointerVariable());
|
||||
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
||||
throwParseError("unexpected end of program", -2);
|
||||
else
|
||||
throwParseError("invalid struct member", 0);
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
||||
throwParseError("missing ';' at end of expression", -1);
|
||||
structNode->addMember(parseMember());
|
||||
}
|
||||
|
||||
structGuard.release();
|
||||
@ -271,19 +372,7 @@ namespace hex::lang {
|
||||
ScopeExit unionGuard([&]{ delete unionNode; });
|
||||
|
||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||
if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||
unionNode->addMember(parseMemberArrayVariable());
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
||||
unionNode->addMember(parseMemberVariable());
|
||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(OPERATOR_STAR, IDENTIFIER, OPERATOR_INHERIT)))
|
||||
unionNode->addMember(parseMemberPointerVariable());
|
||||
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
||||
throwParseError("unexpected end of program", -2);
|
||||
else
|
||||
throwParseError("invalid union member", 0);
|
||||
|
||||
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
||||
throwParseError("missing ';' at end of expression", -1);
|
||||
unionNode->addMember(parseMember());
|
||||
}
|
||||
|
||||
unionGuard.release();
|
||||
|
@ -18,7 +18,7 @@ namespace hex {
|
||||
static TextEditor::LanguageDefinition langDef;
|
||||
if (!initialized) {
|
||||
static const char* const keywords[] = {
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le"
|
||||
"using", "struct", "union", "enum", "bitfield", "be", "le", "if", "else"
|
||||
};
|
||||
for (auto& k : keywords)
|
||||
langDef.mKeywords.insert(k);
|
||||
|
Loading…
Reference in New Issue
Block a user