mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 21:47:40 -05:00
Added if, else and else if to pattern language
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user