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;
|
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);
|
ASTNodeIntegerLiteral* evaluateMathematicalExpression(ASTNodeNumericExpression *node);
|
||||||
|
|
||||||
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
|
PatternData* evaluateBuiltinType(ASTNodeBuiltinType *node);
|
||||||
|
std::vector<PatternData*> evaluateMember(ASTNode *node);
|
||||||
PatternData* evaluateStruct(ASTNodeStruct *node);
|
PatternData* evaluateStruct(ASTNodeStruct *node);
|
||||||
PatternData* evaluateUnion(ASTNodeUnion *node);
|
PatternData* evaluateUnion(ASTNodeUnion *node);
|
||||||
PatternData* evaluateEnum(ASTNodeEnum *node);
|
PatternData* evaluateEnum(ASTNodeEnum *node);
|
||||||
|
@ -59,17 +59,24 @@ namespace hex::lang {
|
|||||||
ASTNode* parseMultiplicativeExpression();
|
ASTNode* parseMultiplicativeExpression();
|
||||||
ASTNode* parseAdditiveExpression();
|
ASTNode* parseAdditiveExpression();
|
||||||
ASTNode* parseShiftExpression();
|
ASTNode* parseShiftExpression();
|
||||||
|
ASTNode* parseRelationExpression();
|
||||||
|
ASTNode* parseEqualityExpression();
|
||||||
ASTNode* parseBinaryAndExpression();
|
ASTNode* parseBinaryAndExpression();
|
||||||
ASTNode* parseBinaryXorExpression();
|
ASTNode* parseBinaryXorExpression();
|
||||||
ASTNode* parseBinaryOrExpression();
|
ASTNode* parseBinaryOrExpression();
|
||||||
|
ASTNode* parseBooleanAnd();
|
||||||
|
ASTNode* parseBooleanXor();
|
||||||
|
ASTNode* parseBooleanOr();
|
||||||
ASTNode* parseMathematicalExpression();
|
ASTNode* parseMathematicalExpression();
|
||||||
|
|
||||||
|
ASTNode* parseConditional();
|
||||||
ASTNode* parseType(s32 startIndex);
|
ASTNode* parseType(s32 startIndex);
|
||||||
ASTNode* parseUsingDeclaration();
|
ASTNode* parseUsingDeclaration();
|
||||||
ASTNode* parsePadding();
|
ASTNode* parsePadding();
|
||||||
ASTNode* parseMemberVariable();
|
ASTNode* parseMemberVariable();
|
||||||
ASTNode* parseMemberArrayVariable();
|
ASTNode* parseMemberArrayVariable();
|
||||||
ASTNode* parseMemberPointerVariable();
|
ASTNode* parseMemberPointerVariable();
|
||||||
|
ASTNode* parseMember();
|
||||||
ASTNode* parseStruct();
|
ASTNode* parseStruct();
|
||||||
ASTNode* parseUnion();
|
ASTNode* parseUnion();
|
||||||
ASTNode* parseEnum();
|
ASTNode* parseEnum();
|
||||||
|
@ -28,6 +28,8 @@ namespace hex::lang {
|
|||||||
Bitfield,
|
Bitfield,
|
||||||
LittleEndian,
|
LittleEndian,
|
||||||
BigEndian,
|
BigEndian,
|
||||||
|
If,
|
||||||
|
Else
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Operator {
|
enum class Operator {
|
||||||
@ -42,7 +44,16 @@ namespace hex::lang {
|
|||||||
ShiftRight,
|
ShiftRight,
|
||||||
BitOr,
|
BitOr,
|
||||||
BitAnd,
|
BitAnd,
|
||||||
BitXor
|
BitXor,
|
||||||
|
BoolEquals,
|
||||||
|
BoolNotEquals,
|
||||||
|
BoolGreaterThan,
|
||||||
|
BoolLessThan,
|
||||||
|
BoolGreaterThanOrEquals,
|
||||||
|
BoolLessThanOrEquals,
|
||||||
|
BoolAnd,
|
||||||
|
BoolOr,
|
||||||
|
BoolXor
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
@ -175,6 +186,8 @@ namespace hex::lang {
|
|||||||
#define KEYWORD_BITFIELD COMPONENT(Keyword, Bitfield)
|
#define KEYWORD_BITFIELD COMPONENT(Keyword, Bitfield)
|
||||||
#define KEYWORD_LE COMPONENT(Keyword, LittleEndian)
|
#define KEYWORD_LE COMPONENT(Keyword, LittleEndian)
|
||||||
#define KEYWORD_BE COMPONENT(Keyword, BigEndian)
|
#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 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 IDENTIFIER hex::lang::Token::Type::Identifier, ""
|
||||||
@ -191,6 +204,15 @@ namespace hex::lang {
|
|||||||
#define OPERATOR_BITOR COMPONENT(Operator, BitOr)
|
#define OPERATOR_BITOR COMPONENT(Operator, BitOr)
|
||||||
#define OPERATOR_BITAND COMPONENT(Operator, BitAnd)
|
#define OPERATOR_BITAND COMPONENT(Operator, BitAnd)
|
||||||
#define OPERATOR_BITXOR COMPONENT(Operator, BitXor)
|
#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_CUSTOMTYPE COMPONENT(ValueType, CustomType)
|
||||||
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
#define VALUETYPE_PADDING COMPONENT(ValueType, Padding)
|
||||||
|
@ -79,6 +79,18 @@ namespace hex::lang {
|
|||||||
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, *reinterpret_cast<s128*>(value) });
|
case 16: return new ASTNodeIntegerLiteral({ Token::ValueType::Signed128Bit, *reinterpret_cast<s128*>(value) });
|
||||||
default: throwEvaluateError("invalid rvalue size", node->getLineNumber());
|
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
|
} else
|
||||||
throwEvaluateError("tried to use non-integer value in numeric expression", node->getLineNumber());
|
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) });
|
return new ASTNodeIntegerLiteral({ newType, bitXor(leftValue, rightValue) });
|
||||||
case Token::Operator::BitOr:
|
case Token::Operator::BitOr:
|
||||||
return new ASTNodeIntegerLiteral({ newType, bitOr(leftValue, rightValue) });
|
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:
|
default:
|
||||||
throwEvaluateError("invalid operator used in mathematical expression", left->getLineNumber());
|
throwEvaluateError("invalid operator used in mathematical expression", left->getLineNumber());
|
||||||
}
|
}
|
||||||
@ -220,6 +250,39 @@ namespace hex::lang {
|
|||||||
return pattern;
|
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) {
|
PatternData* Evaluator::evaluateStruct(ASTNodeStruct *node) {
|
||||||
std::vector<PatternData*> memberPatterns;
|
std::vector<PatternData*> memberPatterns;
|
||||||
|
|
||||||
@ -228,16 +291,8 @@ namespace hex::lang {
|
|||||||
|
|
||||||
auto startOffset = this->m_currOffset;
|
auto startOffset = this->m_currOffset;
|
||||||
for (auto &member : node->getMembers()) {
|
for (auto &member : node->getMembers()) {
|
||||||
if (auto memberVariableNode = dynamic_cast<ASTNodeVariableDecl*>(member); memberVariableNode != nullptr)
|
auto newMembers = this->evaluateMember(member);
|
||||||
memberPatterns.emplace_back(this->evaluateVariable(memberVariableNode));
|
std::copy(newMembers.begin(), newMembers.end(), std::back_inserter(memberPatterns));
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PatternDataStruct(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
return new PatternDataStruct(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
||||||
@ -251,17 +306,10 @@ namespace hex::lang {
|
|||||||
|
|
||||||
auto startOffset = this->m_currOffset;
|
auto startOffset = this->m_currOffset;
|
||||||
for (auto &member : node->getMembers()) {
|
for (auto &member : node->getMembers()) {
|
||||||
if (auto memberVariableNode = dynamic_cast<ASTNodeVariableDecl*>(member); memberVariableNode != nullptr)
|
auto newMembers = this->evaluateMember(member);
|
||||||
memberPatterns.emplace_back(this->evaluateVariable(memberVariableNode));
|
std::copy(newMembers.begin(), newMembers.end(), std::back_inserter(memberPatterns));
|
||||||
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());
|
|
||||||
|
|
||||||
this->m_currOffset = startOffset;
|
this->m_currOffset = startOffset;
|
||||||
this->m_currEndian.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PatternDataUnion(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
return new PatternDataUnion(startOffset, this->m_currOffset - startOffset, memberPatterns);
|
||||||
|
@ -188,6 +188,27 @@ namespace hex::lang {
|
|||||||
} else if (c == '@') {
|
} else if (c == '@') {
|
||||||
tokens.emplace_back(TOKEN(Operator, AtDeclaration));
|
tokens.emplace_back(TOKEN(Operator, AtDeclaration));
|
||||||
offset += 1;
|
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 == '=') {
|
} else if (c == '=') {
|
||||||
tokens.emplace_back(TOKEN(Operator, Assignment));
|
tokens.emplace_back(TOKEN(Operator, Assignment));
|
||||||
offset += 1;
|
offset += 1;
|
||||||
@ -215,6 +236,12 @@ namespace hex::lang {
|
|||||||
} else if (code.substr(offset, 2) == ">>") {
|
} else if (code.substr(offset, 2) == ">>") {
|
||||||
tokens.emplace_back(TOKEN(Operator, ShiftRight));
|
tokens.emplace_back(TOKEN(Operator, ShiftRight));
|
||||||
offset += 2;
|
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 == '|') {
|
} else if (c == '|') {
|
||||||
tokens.emplace_back(TOKEN(Operator, BitOr));
|
tokens.emplace_back(TOKEN(Operator, BitOr));
|
||||||
offset += 1;
|
offset += 1;
|
||||||
@ -276,6 +303,10 @@ namespace hex::lang {
|
|||||||
tokens.emplace_back(TOKEN(Keyword, BigEndian));
|
tokens.emplace_back(TOKEN(Keyword, BigEndian));
|
||||||
else if (identifier == "le")
|
else if (identifier == "le")
|
||||||
tokens.emplace_back(TOKEN(Keyword, LittleEndian));
|
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
|
// Check for built-in types
|
||||||
else if (identifier == "u8")
|
else if (identifier == "u8")
|
||||||
|
@ -55,8 +55,9 @@ namespace hex::lang {
|
|||||||
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE)))
|
if (!MATCHES(sequence(SEPARATOR_ROUNDBRACKETCLOSE)))
|
||||||
throwParseError("expected closing parenthesis");
|
throwParseError("expected closing parenthesis");
|
||||||
return node;
|
return node;
|
||||||
} else if (MATCHES(sequence(IDENTIFIER) && peek(SEPARATOR_SCOPE_RESOLUTION))) {
|
} else if (MATCHES(sequence(IDENTIFIER, SEPARATOR_SCOPE_RESOLUTION))) {
|
||||||
std::vector<std::string> path;
|
std::vector<std::string> path;
|
||||||
|
this->m_curr--;
|
||||||
return this->parseScopeResolution(path);
|
return this->parseScopeResolution(path);
|
||||||
}
|
}
|
||||||
else if (MATCHES(sequence(IDENTIFIER))) {
|
else if (MATCHES(sequence(IDENTIFIER))) {
|
||||||
@ -72,10 +73,8 @@ namespace hex::lang {
|
|||||||
auto node = this->parseFactor();
|
auto node = this->parseFactor();
|
||||||
|
|
||||||
while (MATCHES(variant(OPERATOR_STAR, OPERATOR_SLASH))) {
|
while (MATCHES(variant(OPERATOR_STAR, OPERATOR_SLASH))) {
|
||||||
if (peek(OPERATOR_STAR, -1))
|
auto op = getValue<Token::Operator>(-1);
|
||||||
node = new ASTNodeNumericExpression(node, this->parseFactor(), Token::Operator::Star);
|
node = new ASTNodeNumericExpression(node, this->parseFactor(), op);
|
||||||
else
|
|
||||||
node = new ASTNodeNumericExpression(node, this->parseFactor(), Token::Operator::Slash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -86,10 +85,8 @@ namespace hex::lang {
|
|||||||
auto node = this->parseMultiplicativeExpression();
|
auto node = this->parseMultiplicativeExpression();
|
||||||
|
|
||||||
while (MATCHES(variant(OPERATOR_PLUS, OPERATOR_MINUS))) {
|
while (MATCHES(variant(OPERATOR_PLUS, OPERATOR_MINUS))) {
|
||||||
if (peek(OPERATOR_PLUS, -1))
|
auto op = getValue<Token::Operator>(-1);
|
||||||
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), Token::Operator::Plus);
|
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), op);
|
||||||
else
|
|
||||||
node = new ASTNodeNumericExpression(node, this->parseMultiplicativeExpression(), Token::Operator::Minus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
@ -100,21 +97,43 @@ namespace hex::lang {
|
|||||||
auto node = this->parseAdditiveExpression();
|
auto node = this->parseAdditiveExpression();
|
||||||
|
|
||||||
while (MATCHES(variant(OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT))) {
|
while (MATCHES(variant(OPERATOR_SHIFTLEFT, OPERATOR_SHIFTRIGHT))) {
|
||||||
if (peek(OPERATOR_SHIFTLEFT, -1))
|
auto op = getValue<Token::Operator>(-1);
|
||||||
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), Token::Operator::ShiftLeft);
|
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), op);
|
||||||
else
|
|
||||||
node = new ASTNodeNumericExpression(node, this->parseAdditiveExpression(), Token::Operator::ShiftRight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (parseShiftExpression) & (parseShiftExpression)
|
// (parseAdditiveExpression) < >=|<=|>|< > (parseAdditiveExpression)
|
||||||
ASTNode* Parser::parseBinaryAndExpression() {
|
ASTNode* Parser::parseRelationExpression() {
|
||||||
auto node = this->parseShiftExpression();
|
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))) {
|
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;
|
return node;
|
||||||
@ -142,9 +161,80 @@ namespace hex::lang {
|
|||||||
return node;
|
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)
|
// (parseBinaryOrExpression)
|
||||||
ASTNode* Parser::parseMathematicalExpression() {
|
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 */
|
/* Type declarations */
|
||||||
@ -235,21 +325,20 @@ namespace hex::lang {
|
|||||||
return new ASTNodePointerVariableDecl(name, temporaryPointerType->getType()->clone(), temporarySizeType->getType()->clone());
|
return new ASTNodePointerVariableDecl(name, temporaryPointerType->getType()->clone(), temporarySizeType->getType()->clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct Identifier { <(parseMember)...> }
|
// [(parsePadding)|(parseMemberVariable)|(parseMemberArrayVariable)|(parseMemberPointerVariable)]
|
||||||
ASTNode* Parser::parseStruct() {
|
ASTNode* Parser::parseMember() {
|
||||||
const auto structNode = new ASTNodeStruct();
|
ASTNode *member;
|
||||||
const auto &typeName = getValue<std::string>(-2);
|
|
||||||
ScopeExit structGuard([&]{ delete structNode; });
|
|
||||||
|
|
||||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
|
||||||
if (MATCHES(sequence(VALUETYPE_PADDING, SEPARATOR_SQUAREBRACKETOPEN)))
|
if (MATCHES(sequence(VALUETYPE_PADDING, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||||
structNode->addMember(parsePadding());
|
member = parsePadding();
|
||||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
||||||
structNode->addMember(parseMemberArrayVariable());
|
member = parseMemberArrayVariable();
|
||||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER)))
|
||||||
structNode->addMember(parseMemberVariable());
|
member = parseMemberVariable();
|
||||||
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(OPERATOR_STAR, IDENTIFIER, OPERATOR_INHERIT)))
|
else if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(OPERATOR_STAR, IDENTIFIER, OPERATOR_INHERIT)))
|
||||||
structNode->addMember(parseMemberPointerVariable());
|
member = parseMemberPointerVariable();
|
||||||
|
else if (MATCHES(sequence(KEYWORD_IF, SEPARATOR_ROUNDBRACKETOPEN)))
|
||||||
|
return parseConditional();
|
||||||
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
else if (MATCHES(sequence(SEPARATOR_ENDOFPROGRAM)))
|
||||||
throwParseError("unexpected end of program", -2);
|
throwParseError("unexpected end of program", -2);
|
||||||
else
|
else
|
||||||
@ -257,6 +346,18 @@ namespace hex::lang {
|
|||||||
|
|
||||||
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
if (!MATCHES(sequence(SEPARATOR_ENDOFEXPRESSION)))
|
||||||
throwParseError("missing ';' at end of expression", -1);
|
throwParseError("missing ';' at end of expression", -1);
|
||||||
|
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct Identifier { <(parseMember)...> }
|
||||||
|
ASTNode* Parser::parseStruct() {
|
||||||
|
const auto structNode = new ASTNodeStruct();
|
||||||
|
const auto &typeName = getValue<std::string>(-2);
|
||||||
|
ScopeExit structGuard([&]{ delete structNode; });
|
||||||
|
|
||||||
|
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||||
|
structNode->addMember(parseMember());
|
||||||
}
|
}
|
||||||
|
|
||||||
structGuard.release();
|
structGuard.release();
|
||||||
@ -271,19 +372,7 @@ namespace hex::lang {
|
|||||||
ScopeExit unionGuard([&]{ delete unionNode; });
|
ScopeExit unionGuard([&]{ delete unionNode; });
|
||||||
|
|
||||||
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
|
||||||
if (MATCHES((optional(KEYWORD_BE), optional(KEYWORD_LE)) && variant(IDENTIFIER, VALUETYPE_ANY) && sequence(IDENTIFIER, SEPARATOR_SQUAREBRACKETOPEN)))
|
unionNode->addMember(parseMember());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unionGuard.release();
|
unionGuard.release();
|
||||||
|
@ -18,7 +18,7 @@ namespace hex {
|
|||||||
static TextEditor::LanguageDefinition langDef;
|
static TextEditor::LanguageDefinition langDef;
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
static const char* const keywords[] = {
|
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)
|
for (auto& k : keywords)
|
||||||
langDef.mKeywords.insert(k);
|
langDef.mKeywords.insert(k);
|
||||||
|
Loading…
Reference in New Issue
Block a user