From b30bb21646b08d82a123a91b047316580c6bbb55 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 7 Jan 2021 00:41:06 +0100 Subject: [PATCH] Added unary operators +, -, ~ and ! --- include/lang/parser.hpp | 1 + include/lang/token.hpp | 6 +++++- source/lang/evaluator.cpp | 8 ++++++++ source/lang/lexer.cpp | 6 ++++++ source/lang/parser.cpp | 17 ++++++++++++++--- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/lang/parser.hpp b/include/lang/parser.hpp index 74c1f248a..4f6d0dc09 100644 --- a/include/lang/parser.hpp +++ b/include/lang/parser.hpp @@ -56,6 +56,7 @@ namespace hex::lang { ASTNode* parseScopeResolution(std::vector &path); ASTNode* parseRValue(std::vector &path); ASTNode* parseFactor(); + ASTNode* parseUnaryExpression(); ASTNode* parseMultiplicativeExpression(); ASTNode* parseAdditiveExpression(); ASTNode* parseShiftExpression(); diff --git a/include/lang/token.hpp b/include/lang/token.hpp index db2f863dc..cd947a3b6 100644 --- a/include/lang/token.hpp +++ b/include/lang/token.hpp @@ -45,6 +45,7 @@ namespace hex::lang { BitOr, BitAnd, BitXor, + BitNot, BoolEquals, BoolNotEquals, BoolGreaterThan, @@ -53,7 +54,8 @@ namespace hex::lang { BoolLessThanOrEquals, BoolAnd, BoolOr, - BoolXor + BoolXor, + BoolNot }; enum class ValueType { @@ -204,6 +206,7 @@ namespace hex::lang { #define OPERATOR_BITOR COMPONENT(Operator, BitOr) #define OPERATOR_BITAND COMPONENT(Operator, BitAnd) #define OPERATOR_BITXOR COMPONENT(Operator, BitXor) +#define OPERATOR_BITNOT COMPONENT(Operator, BitNot) #define OPERATOR_BOOLEQUALS COMPONENT(Operator, BoolEquals) #define OPERATOR_BOOLNOTEQUALS COMPONENT(Operator, BoolNotEquals) #define OPERATOR_BOOLGREATERTHAN COMPONENT(Operator, BoolGreaterThan) @@ -213,6 +216,7 @@ namespace hex::lang { #define OPERATOR_BOOLAND COMPONENT(Operator, BoolAnd) #define OPERATOR_BOOLOR COMPONENT(Operator, BoolOr) #define OPERATOR_BOOLXOR COMPONENT(Operator, BoolXor) +#define OPERATOR_BOOLNOT COMPONENT(Operator, BoolNot) #define VALUETYPE_CUSTOMTYPE COMPONENT(ValueType, CustomType) #define VALUETYPE_PADDING COMPONENT(ValueType, Padding) diff --git a/source/lang/evaluator.cpp b/source/lang/evaluator.cpp index 86549c6d8..4917b4bc2 100644 --- a/source/lang/evaluator.cpp +++ b/source/lang/evaluator.cpp @@ -123,6 +123,10 @@ namespace hex::lang { return left ^ right; } + FLOAT_BIT_OPERATION(bitNot) { + return ~right; + } + } ASTNodeIntegerLiteral* Evaluator::evaluateOperator(ASTNodeIntegerLiteral *left, ASTNodeIntegerLiteral *right, Token::Operator op) { @@ -170,6 +174,8 @@ namespace hex::lang { return new ASTNodeIntegerLiteral({ newType, bitXor(leftValue, rightValue) }); case Token::Operator::BitOr: return new ASTNodeIntegerLiteral({ newType, bitOr(leftValue, rightValue) }); + case Token::Operator::BitNot: + return new ASTNodeIntegerLiteral({ newType, bitNot(leftValue, rightValue) }); case Token::Operator::BoolEquals: return new ASTNodeIntegerLiteral({ newType, leftValue == rightValue }); case Token::Operator::BoolNotEquals: @@ -188,6 +194,8 @@ namespace hex::lang { return new ASTNodeIntegerLiteral({ newType, leftValue && !rightValue || !leftValue && rightValue }); case Token::Operator::BoolOr: return new ASTNodeIntegerLiteral({ newType, leftValue || rightValue }); + case Token::Operator::BoolNot: + return new ASTNodeIntegerLiteral({ newType, !rightValue }); default: throwEvaluateError("invalid operator used in mathematical expression", left->getLineNumber()); } diff --git a/source/lang/lexer.cpp b/source/lang/lexer.cpp index 7ab6c825e..6ee5f4976 100644 --- a/source/lang/lexer.cpp +++ b/source/lang/lexer.cpp @@ -242,6 +242,9 @@ namespace hex::lang { } else if (c == '<') { tokens.emplace_back(TOKEN(Operator, BoolLessThan)); offset += 1; + } else if (c == '!') { + tokens.emplace_back(TOKEN(Operator, BoolNot)); + offset += 1; } else if (c == '|') { tokens.emplace_back(TOKEN(Operator, BitOr)); offset += 1; @@ -251,6 +254,9 @@ namespace hex::lang { } else if (c == '^') { tokens.emplace_back(TOKEN(Operator, BitXor)); offset += 1; + } else if (c == '~') { + tokens.emplace_back(TOKEN(Operator, BitNot)); + offset += 1; } else if (c == '\'') { offset += 1; diff --git a/source/lang/parser.cpp b/source/lang/parser.cpp index 571c90365..62136e45f 100644 --- a/source/lang/parser.cpp +++ b/source/lang/parser.cpp @@ -68,13 +68,24 @@ namespace hex::lang { throwParseError("expected integer or parenthesis"); } - // (parseFactor) <*|/> (parseFactor) + // <+|-|!|~> (parseFactor) + ASTNode* Parser::parseUnaryExpression() { + if (MATCHES(sequence(OPERATOR_PLUS) || sequence(OPERATOR_MINUS) || sequence(OPERATOR_BOOLNOT) || sequence(OPERATOR_BITNOT))) { + auto op = getValue(-1); + + return new ASTNodeNumericExpression(new ASTNodeIntegerLiteral({ Token::ValueType::Signed32Bit, 0}), this->parseFactor(), op); + } + + return this->parseFactor(); + } + + // (parseUnaryExpression) <*|/> (parseUnaryExpression) ASTNode* Parser::parseMultiplicativeExpression() { - auto node = this->parseFactor(); + auto node = this->parseUnaryExpression(); while (MATCHES(variant(OPERATOR_STAR, OPERATOR_SLASH))) { auto op = getValue(-1); - node = new ASTNodeNumericExpression(node, this->parseFactor(), op); + node = new ASTNodeNumericExpression(node, this->parseUnaryExpression(), op); } return node;