From 879ada6be105ef25445256561ffc0ab232967496 Mon Sep 17 00:00:00 2001 From: Jamiras <32680403+Jamiras@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:29:28 -0600 Subject: [PATCH] support for unary minus (#539) --- Source/Parser/Expressions/ExpressionBase.cs | 11 +++ .../Parser/Expressions/ExpressionBaseTests.cs | 14 ++++ .../Expressions/MathematicExpressionTests.cs | 78 +++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/Source/Parser/Expressions/ExpressionBase.cs b/Source/Parser/Expressions/ExpressionBase.cs index 506cf225..5c924571 100644 --- a/Source/Parser/Expressions/ExpressionBase.cs +++ b/Source/Parser/Expressions/ExpressionBase.cs @@ -170,6 +170,7 @@ private enum OperationPriority AddSubtract, MulDivMod, Not, + Negate, Parenthesis, } @@ -642,6 +643,16 @@ private static ExpressionBase ParseClauseCore(PositionalTokenizer tokenizer) result.Location = new TextRange(tokenStart, tokenEnd); return result; } + else if (Char.IsLetter(tokenizer.NextChar) || tokenizer.NextChar == '(') + { + var next = ParseExpression(tokenizer, OperationPriority.Negate); + if (next.Type == ExpressionType.Error) + return next; + + var result = new MathematicExpression(new IntegerConstantExpression(0), MathematicOperation.Subtract, next); + result.Location = new TextRange(tokenStart, next.Location.End); + return result; + } return ParseError(tokenizer, "Minus without value", tokenStart.Line, tokenStart.Column); case '{': diff --git a/Tests/Parser/Expressions/ExpressionBaseTests.cs b/Tests/Parser/Expressions/ExpressionBaseTests.cs index 2820e697..d237b107 100644 --- a/Tests/Parser/Expressions/ExpressionBaseTests.cs +++ b/Tests/Parser/Expressions/ExpressionBaseTests.cs @@ -694,5 +694,19 @@ public void TestParseLineColumnValues() Assert.That(expression.Location.End.Line, Is.EqualTo(7)); Assert.That(expression.Location.End.Column, Is.EqualTo(8)); } + + [Test] + public void TestParseUnaryMinusVariable() + { + var tokenizer = CreateTokenizer("-a"); + var expression = ExpressionBase.Parse(tokenizer); + + Assert.That(expression, Is.InstanceOf()); + var mathematic = (MathematicExpression)expression; + Assert.That(mathematic.Left, Is.EqualTo(new IntegerConstantExpression(0))); + Assert.That(mathematic.Operation, Is.EqualTo(MathematicOperation.Subtract)); + Assert.That(mathematic.Right, Is.InstanceOf()); + Assert.That(((VariableExpression)mathematic.Right).Name, Is.EqualTo("a")); + } } } diff --git a/Tests/Parser/Expressions/MathematicExpressionTests.cs b/Tests/Parser/Expressions/MathematicExpressionTests.cs index de28b4a9..de739a21 100644 --- a/Tests/Parser/Expressions/MathematicExpressionTests.cs +++ b/Tests/Parser/Expressions/MathematicExpressionTests.cs @@ -425,5 +425,83 @@ public void TestCombining(string input, string expected) result.AppendString(builder); Assert.That(builder.ToString(), Is.EqualTo(expected)); } + + [Test] + public void TestUnaryMinusVariable() + { + var scope = AchievementScriptTests.Evaluate( + "a = 8\n" + + "b = -a" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-8)); + } + + [Test] + public void TestUnaryMinusAddition() + { + var scope = AchievementScriptTests.Evaluate( + "a = 8\n" + + "b = -a + 2" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-6)); + } + + [Test] + public void TestUnaryMinusMultiplication() + { + var scope = AchievementScriptTests.Evaluate( + "a = 8\n" + + "b = -a * 2" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-16)); + } + + [Test] + public void TestUnaryMinusParenthesis() + { + var scope = AchievementScriptTests.Evaluate( + "a = 8\n" + + "b = -(a + 2)" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-10)); + } + + [Test] + public void TestUnaryMinusArrayValue() + { + var scope = AchievementScriptTests.Evaluate( + "a = [8]\n" + + "b = -a[0]" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-8)); + } + + [Test] + public void TestUnaryMinusFunctionCall() + { + var scope = AchievementScriptTests.Evaluate( + "function a(n) => n\n" + + "b = -a(8)" + ); + + var b = scope.GetVariable("b"); + Assert.That(b, Is.InstanceOf()); + Assert.That(((IntegerConstantExpression)b).Value, Is.EqualTo(-8)); + } } }