1
0
mirror of synced 2024-11-25 00:00:27 +01:00

Added if, else and else if to pattern language

This commit is contained in:
WerWolv 2021-01-07 00:02:51 +01:00
parent d8b16766f5
commit acfd5aa02f
8 changed files with 348 additions and 106 deletions

View File

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

View File

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

View File

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

View File

@ -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 {
@ -168,46 +179,57 @@ namespace hex::lang {
#define COMPONENT(type, value) hex::lang::Token::Type::type, hex::lang::Token::type::value #define COMPONENT(type, value) hex::lang::Token::Type::type, hex::lang::Token::type::value
#define KEYWORD_STRUCT COMPONENT(Keyword, Struct) #define KEYWORD_STRUCT COMPONENT(Keyword, Struct)
#define KEYWORD_UNION COMPONENT(Keyword, Union) #define KEYWORD_UNION COMPONENT(Keyword, Union)
#define KEYWORD_USING COMPONENT(Keyword, Using) #define KEYWORD_USING COMPONENT(Keyword, Using)
#define KEYWORD_ENUM COMPONENT(Keyword, Enum) #define KEYWORD_ENUM COMPONENT(Keyword, Enum)
#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, ""
#define OPERATOR_AT COMPONENT(Operator, AtDeclaration) #define OPERATOR_AT COMPONENT(Operator, AtDeclaration)
#define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment) #define OPERATOR_ASSIGNMENT COMPONENT(Operator, Assignment)
#define OPERATOR_INHERIT COMPONENT(Operator, Inherit) #define OPERATOR_INHERIT COMPONENT(Operator, Inherit)
#define OPERATOR_PLUS COMPONENT(Operator, Plus) #define OPERATOR_PLUS COMPONENT(Operator, Plus)
#define OPERATOR_MINUS COMPONENT(Operator, Minus) #define OPERATOR_MINUS COMPONENT(Operator, Minus)
#define OPERATOR_STAR COMPONENT(Operator, Star) #define OPERATOR_STAR COMPONENT(Operator, Star)
#define OPERATOR_SLASH COMPONENT(Operator, Slash) #define OPERATOR_SLASH COMPONENT(Operator, Slash)
#define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft) #define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft)
#define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight) #define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight)
#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)
#define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned) #define VALUETYPE_UNSIGNED COMPONENT(ValueType, Unsigned)
#define VALUETYPE_SIGNED COMPONENT(ValueType, Signed) #define VALUETYPE_SIGNED COMPONENT(ValueType, Signed)
#define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint) #define VALUETYPE_FLOATINGPOINT COMPONENT(ValueType, FloatingPoint)
#define VALUETYPE_INTEGER COMPONENT(ValueType, Integer) #define VALUETYPE_INTEGER COMPONENT(ValueType, Integer)
#define VALUETYPE_ANY COMPONENT(ValueType, Any) #define VALUETYPE_ANY COMPONENT(ValueType, Any)
#define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen) #define SEPARATOR_ROUNDBRACKETOPEN COMPONENT(Separator, RoundBracketOpen)
#define SEPARATOR_ROUNDBRACKETCLOSE COMPONENT(Separator, RoundBracketClose) #define SEPARATOR_ROUNDBRACKETCLOSE COMPONENT(Separator, RoundBracketClose)
#define SEPARATOR_CURLYBRACKETOPEN COMPONENT(Separator, CurlyBracketOpen) #define SEPARATOR_CURLYBRACKETOPEN COMPONENT(Separator, CurlyBracketOpen)
#define SEPARATOR_CURLYBRACKETCLOSE COMPONENT(Separator, CurlyBracketClose) #define SEPARATOR_CURLYBRACKETCLOSE COMPONENT(Separator, CurlyBracketClose)
#define SEPARATOR_SQUAREBRACKETOPEN COMPONENT(Separator, SquareBracketOpen) #define SEPARATOR_SQUAREBRACKETOPEN COMPONENT(Separator, SquareBracketOpen)
#define SEPARATOR_SQUAREBRACKETCLOSE COMPONENT(Separator, SquareBracketClose) #define SEPARATOR_SQUAREBRACKETCLOSE COMPONENT(Separator, SquareBracketClose)
#define SEPARATOR_COMMA COMPONENT(Separator, Comma) #define SEPARATOR_COMMA COMPONENT(Separator, Comma)
#define SEPARATOR_DOT COMPONENT(Separator, Dot) #define SEPARATOR_DOT COMPONENT(Separator, Dot)
#define SEPARATOR_SCOPE_RESOLUTION COMPONENT(Separator, ScopeResolution) #define SEPARATOR_SCOPE_RESOLUTION COMPONENT(Separator, ScopeResolution)
#define SEPARATOR_ENDOFEXPRESSION COMPONENT(Separator, EndOfExpression) #define SEPARATOR_ENDOFEXPRESSION COMPONENT(Separator, EndOfExpression)
#define SEPARATOR_ENDOFPROGRAM COMPONENT(Separator, EndOfProgram) #define SEPARATOR_ENDOFPROGRAM COMPONENT(Separator, EndOfProgram)

View File

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

View File

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

View File

@ -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,35 +85,55 @@ 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;
} }
// (parseAdditiveExpression) <>>|<<> (parseAdditiveExpression) // (parseAdditiveExpression) < >>|<< > (parseAdditiveExpression)
ASTNode* Parser::parseShiftExpression() { ASTNode* Parser::parseShiftExpression() {
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,6 +325,31 @@ namespace hex::lang {
return new ASTNodePointerVariableDecl(name, temporaryPointerType->getType()->clone(), temporarySizeType->getType()->clone()); 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)...> } // struct Identifier { <(parseMember)...> }
ASTNode* Parser::parseStruct() { ASTNode* Parser::parseStruct() {
const auto structNode = new ASTNodeStruct(); const auto structNode = new ASTNodeStruct();
@ -242,21 +357,7 @@ namespace hex::lang {
ScopeExit structGuard([&]{ delete structNode; }); ScopeExit structGuard([&]{ delete structNode; });
while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) { while (!MATCHES(sequence(SEPARATOR_CURLYBRACKETCLOSE))) {
if (MATCHES(sequence(VALUETYPE_PADDING, SEPARATOR_SQUAREBRACKETOPEN))) structNode->addMember(parseMember());
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);
} }
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();

View File

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