diff --git a/plugins/libimhex/include/hex/lang/parser.hpp b/plugins/libimhex/include/hex/lang/parser.hpp index b3dbbc9e8..a9bb56367 100644 --- a/plugins/libimhex/include/hex/lang/parser.hpp +++ b/plugins/libimhex/include/hex/lang/parser.hpp @@ -136,6 +136,14 @@ namespace hex::lang { return true; } + bool oneOf() { + return false; + } + + bool oneOf(Token::Type type, auto value, auto ... args) { + return sequence(type, value) || oneOf(args...); + } + bool variant(Token::Type type1, auto value1, Token::Type type2, auto value2) { if (!peek(type1, value1)) { if (!peek(type2, value2)) { diff --git a/plugins/libimhex/include/hex/lang/token.hpp b/plugins/libimhex/include/hex/lang/token.hpp index 642078989..f0c693e24 100644 --- a/plugins/libimhex/include/hex/lang/token.hpp +++ b/plugins/libimhex/include/hex/lang/token.hpp @@ -42,6 +42,7 @@ namespace hex::lang { Minus, Star, Slash, + Percent, ShiftLeft, ShiftRight, BitOr, @@ -206,6 +207,7 @@ namespace hex::lang { #define OPERATOR_MINUS COMPONENT(Operator, Minus) #define OPERATOR_STAR COMPONENT(Operator, Star) #define OPERATOR_SLASH COMPONENT(Operator, Slash) +#define OPERATOR_PERCENT COMPONENT(Operator, Percent) #define OPERATOR_SHIFTLEFT COMPONENT(Operator, ShiftLeft) #define OPERATOR_SHIFTRIGHT COMPONENT(Operator, ShiftRight) #define OPERATOR_BITOR COMPONENT(Operator, BitOr) diff --git a/plugins/libimhex/source/lang/evaluator.cpp b/plugins/libimhex/source/lang/evaluator.cpp index 66a2aa4ae..55e35d9fd 100644 --- a/plugins/libimhex/source/lang/evaluator.cpp +++ b/plugins/libimhex/source/lang/evaluator.cpp @@ -192,6 +192,10 @@ namespace hex::lang { return ~right; } + FLOAT_BIT_OPERATION(modulus) { + return left % right; + } + } ASTNodeIntegerLiteral* Evaluator::evaluateOperator(ASTNodeIntegerLiteral *left, ASTNodeIntegerLiteral *right, Token::Operator op) { @@ -235,6 +239,8 @@ namespace hex::lang { return new ASTNodeIntegerLiteral({ newType, leftValue * rightValue }); case Token::Operator::Slash: return new ASTNodeIntegerLiteral({ newType, leftValue / rightValue }); + case Token::Operator::Percent: + return new ASTNodeIntegerLiteral({ newType, modulus(leftValue, rightValue) }); case Token::Operator::ShiftLeft: return new ASTNodeIntegerLiteral({ newType, shiftLeft(leftValue, rightValue) }); case Token::Operator::ShiftRight: diff --git a/plugins/libimhex/source/lang/lexer.cpp b/plugins/libimhex/source/lang/lexer.cpp index 43b6120d3..d24be2ad7 100644 --- a/plugins/libimhex/source/lang/lexer.cpp +++ b/plugins/libimhex/source/lang/lexer.cpp @@ -329,6 +329,9 @@ namespace hex::lang { } else if (c == '/') { tokens.emplace_back(TOKEN(Operator, Slash)); offset += 1; + } else if (c == '%') { + tokens.emplace_back(TOKEN(Operator, Percent)); + offset += 1; } else if (code.substr(offset, 2) == "<<") { tokens.emplace_back(TOKEN(Operator, ShiftLeft)); offset += 2; diff --git a/plugins/libimhex/source/lang/parser.cpp b/plugins/libimhex/source/lang/parser.cpp index a47d4dc0a..7caf1792c 100644 --- a/plugins/libimhex/source/lang/parser.cpp +++ b/plugins/libimhex/source/lang/parser.cpp @@ -103,7 +103,7 @@ namespace hex::lang { // <+|-|!|~> (parseFactor) ASTNode* Parser::parseUnaryExpression() { - if (MATCHES(sequence(OPERATOR_PLUS) || sequence(OPERATOR_MINUS) || sequence(OPERATOR_BOOLNOT) || sequence(OPERATOR_BITNOT))) { + if (MATCHES(oneOf(OPERATOR_PLUS, OPERATOR_MINUS, OPERATOR_BOOLNOT, OPERATOR_BITNOT))) { auto op = getValue(-1); return new ASTNodeNumericExpression(new ASTNodeIntegerLiteral({ Token::ValueType::Any, 0 }), this->parseFactor(), op); @@ -112,11 +112,11 @@ namespace hex::lang { return this->parseFactor(); } - // (parseUnaryExpression) <*|/> (parseUnaryExpression) + // (parseUnaryExpression) <*|/|%> (parseUnaryExpression) ASTNode* Parser::parseMultiplicativeExpression() { auto node = this->parseUnaryExpression(); - while (MATCHES(variant(OPERATOR_STAR, OPERATOR_SLASH))) { + while (MATCHES(oneOf(OPERATOR_STAR, OPERATOR_SLASH, OPERATOR_PERCENT))) { auto op = getValue(-1); node = new ASTNodeNumericExpression(node, this->parseUnaryExpression(), op); }