diff --git a/MathEngine/EngineTests/Parser Tests/Nodes/NodesTests.cs b/MathEngine/EngineTests/Parser Tests/Nodes/NodesTests.cs new file mode 100644 index 0000000..13d1b69 --- /dev/null +++ b/MathEngine/EngineTests/Parser Tests/Nodes/NodesTests.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EngineTests.Parser_Tests +{ + /// + /// Class for testing the TreeNodes + /// + [TestClass] + public class NodesTests + { + /// + /// Test the Parser on a basic List of tokens + /// + [TestMethod] + public void TestParserBasicExpression() + { + + } + } +} diff --git a/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenIserTests.cs b/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenIserTests.cs new file mode 100644 index 0000000..75b4406 --- /dev/null +++ b/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenIserTests.cs @@ -0,0 +1,119 @@ +using MathEngine.Parser.Tokeniser; + +namespace EngineTests +{ + /// + /// Class for testing the Tokeniser + /// + [TestClass] + public class TokeniserTests + { + /// + /// Test the tokeniser on an empty string + /// + [TestMethod] + public void TestTokeniseEmptystringReturnsEmptyList() + { + //Arrange + string testString = ""; + Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0); + List expectedValue = new() + { + one, + Token.Plus, + one + }; + //Act + List returnedValue = Tokeniser.Tokenise(testString); + //Assert + Assert.AreEqual(returnedValue.Count, 0); + } + + + /// + /// Test the tokeniser on a basic string + /// + [TestMethod] + public void TestTokeniseBasicString() + { + //Arrange + string testString = "1+1"; + Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0); + List expectedValue = new() + { + one, + Token.Plus, + one + }; + //Act + List returnedValue = Tokeniser.Tokenise(testString); + //Assert + Assert.IsTrue(expectedValue.SequenceEqual(returnedValue)); + } + + /// + /// Test the tokeniser on a basic string, but with significant ammounts of whitespace + /// + [TestMethod] + public void TestTokeniseBasicStringWithWhiteSpace() + { + //Arrange + string testString = " 1 + 1 "; + Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0); + List expectedValue = new() + { + one, + Token.Plus, + one + }; + //Act + List returnedValue = Tokeniser.Tokenise(testString); + //Assert + Assert.IsTrue(expectedValue.SequenceEqual(returnedValue)); + } + + /// + /// Test the tokeniser on a string which contains a number which is not formatted correctly + /// + [TestMethod] + public void TestTokeniseStringWithInvalidNumbr() + { + //Arrange + string testString = "1+11.2.5"; + //Act and Assert + Assert.ThrowsException(() => Tokeniser.Tokenise(testString)); + } + + + /// + /// Test the tokeniser with all operators + /// + [TestMethod] + public void TestTokeniseStringWithAllOperators() + { + //Arrange + string testString = "1+2-3*4/5"; + Token one = new("1", Token.Type.Numeric, Token.NumericType.Decimal, 0); + Token two = new("2", Token.Type.Numeric, Token.NumericType.Decimal, 0); + Token three = new("3", Token.Type.Numeric, Token.NumericType.Decimal, 0); + Token four = new("4", Token.Type.Numeric, Token.NumericType.Decimal, 0); + Token five = new("5", Token.Type.Numeric, Token.NumericType.Decimal, 0); + List expectedValue = new() + { + one, + Token.Plus, + two, + Token.Minus, + three, + Token.Multiply, + four, + Token.Divide, + five + }; + //Act + List returnedValue = Tokeniser.Tokenise(testString); + //Assert + Assert.IsTrue(expectedValue.SequenceEqual(returnedValue)); + } + } +} \ No newline at end of file diff --git a/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenTests.cs b/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenTests.cs new file mode 100644 index 0000000..5227fe8 --- /dev/null +++ b/MathEngine/EngineTests/Parser Tests/Tokeniser/TokenTests.cs @@ -0,0 +1,323 @@ +using MathEngine.Parser.Tokeniser; +using Newtonsoft.Json.Linq; + +namespace EngineTests.Parser_Tests.Tokeniser +{ + /// + /// Class for testing the Token + /// + [TestClass] + public class TokenTests + { + /// + /// Test that Token constructor returns valid token + /// + [TestMethod] + public void TestTokenConstructorReturnsToken() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + Token token = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Assert.IsNotNull(token); + Assert.AreEqual(token.TokenValue, testTokenValue); + Assert.AreEqual(token.Token_Type, testTokenType); + Assert.AreEqual(token.NumericalType, testNumericType); + Assert.AreEqual(token.FunctionArity, testArityValue); + } + +#if DEBUG + /// + /// Test ToString returns expected string format + /// + [TestMethod] + public void TestToStringReturnsExpetedStringFormat() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + + string token_string = token1.ToString(); + Assert.AreEqual(token_string, "123,Numeric,Integer,0"); + } +#endif + /// + /// Test for == operator comparing two equal Tokens returns true + /// + [TestMethod] + public void TestTokenEqualOperatorReturnsTrueOnEqualTokens() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + string testTokenValue2 = "123"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + Assert.AreEqual(token1 == token2, true); + } + + /// + /// Test for == operator comparing unequal Tokens returns false + /// + [TestMethod] + public void TestTokenEqualOperatorReturnsFalseOnUnequalTokens() + { + string testTokenValue1 = "123"; + Token.Type testTokenType1 = Token.Type.Numeric; + Token.NumericType testNumericType1 = Token.NumericType.Integer; + uint testArityValue1 = 0; + + string testTokenValue2 = "125"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + string testTokenValue3 = "123"; + Token.Type testTokenType3 = Token.Type.Operator; + Token.NumericType testNumericType3 = Token.NumericType.Integer; + uint testArityValue3 = 0; + + string testTokenValue4 = "123"; + Token.Type testTokenType4 = Token.Type.Numeric; + Token.NumericType testNumericType4 = Token.NumericType.Decimal; + uint testArityValue4 = 0; + + string testTokenValue5 = "123"; + Token.Type testTokenType5 = Token.Type.Numeric; + Token.NumericType testNumericType5 = Token.NumericType.Integer; + uint testArityValue5 = 1; + + Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3); + Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4); + Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5); + + Assert.AreEqual(token1 == token2, false); + Assert.AreEqual(token1 == token3, false); + Assert.AreEqual(token1 == token4, false); + Assert.AreEqual(token1 == token5, false); + } + + /// + /// Test for != operator comparing two equal Tokens returns true + /// + [TestMethod] + public void TestTokenUnEqualOperatorReturnsFalseOnEqualTokens() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Assert.AreEqual(token1 != token2, false); + } + + /// + /// Test for != operator comparing unequal Tokens returns True + /// + [TestMethod] + public void TestTokenUnEqualOperatorReturnsTrueOnUnequalTokens() + { + string testTokenValue1 = "123"; + Token.Type testTokenType1 = Token.Type.Numeric; + Token.NumericType testNumericType1 = Token.NumericType.Integer; + uint testArityValue1 = 0; + + string testTokenValue2 = "125"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + string testTokenValue3 = "123"; + Token.Type testTokenType3 = Token.Type.Operator; + Token.NumericType testNumericType3 = Token.NumericType.Integer; + uint testArityValue3 = 0; + + string testTokenValue4 = "123"; + Token.Type testTokenType4 = Token.Type.Numeric; + Token.NumericType testNumericType4 = Token.NumericType.Decimal; + uint testArityValue4 = 0; + + string testTokenValue5 = "123"; + Token.Type testTokenType5 = Token.Type.Numeric; + Token.NumericType testNumericType5 = Token.NumericType.Integer; + uint testArityValue5 = 1; + + Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3); + Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4); + Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5); + + Assert.AreEqual(token1 != token2, true); + Assert.AreEqual(token1 != token3, true); + Assert.AreEqual(token1 != token4, true); + Assert.AreEqual(token1 != token5, true); + } + + /// + /// Test Equals method returns True when Tokens are equal + /// + [TestMethod] + public void TestTokenEqualsMethodWithTokenObjectsReturnsTrueWhenEqual() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + string testTokenValue2 = "123"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + Assert.AreEqual(token1.Equals(token2), true); + } + + /// + /// Test Equals method returns False when Tokens are unequal + /// + [TestMethod] + public void TestTokenEqualsMethodWithTokenObjectsReturnsFalseWhenUnequal() + { + string testTokenValue1 = "123"; + Token.Type testTokenType1 = Token.Type.Numeric; + Token.NumericType testNumericType1 = Token.NumericType.Integer; + uint testArityValue1 = 0; + + string testTokenValue2 = "125"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + string testTokenValue3 = "123"; + Token.Type testTokenType3 = Token.Type.Operator; + Token.NumericType testNumericType3 = Token.NumericType.Integer; + uint testArityValue3 = 0; + + string testTokenValue4 = "123"; + Token.Type testTokenType4 = Token.Type.Numeric; + Token.NumericType testNumericType4 = Token.NumericType.Decimal; + uint testArityValue4 = 0; + + string testTokenValue5 = "123"; + Token.Type testTokenType5 = Token.Type.Numeric; + Token.NumericType testNumericType5 = Token.NumericType.Integer; + uint testArityValue5 = 1; + + Token token1 = new(testTokenValue1, testTokenType1, testNumericType1, testArityValue1); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + Token token3 = new(testTokenValue3, testTokenType3, testNumericType3, testArityValue3); + Token token4 = new(testTokenValue4, testTokenType4, testNumericType4, testArityValue4); + Token token5 = new(testTokenValue5, testTokenType5, testNumericType5, testArityValue5); + + Assert.AreEqual(token1.Equals(token2), false); + Assert.AreEqual(token1.Equals(token3), false); + Assert.AreEqual(token1.Equals(token4), false); + Assert.AreEqual(token1.Equals(token5), false); + } + + /// + /// Test Equals method checks for Token equality when object is a token + /// + [TestMethod] + public void TestTokenEqualsMethodWithObjectsThatIsATokenComparesForTokenEquality() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + string testTokenValue2 = "123"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + object token_obj = token2; + Assert.AreEqual(token1.Equals(token_obj), true); + } + + /// + /// Test Equals method checks for returns false when object is not a token + /// + [TestMethod] + public void TestTokenEqualsMethodWithObjectsThatIsNotATokenReturnsFalse() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + int non_token = 5; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Assert.AreEqual(token1.Equals(non_token), false); + } + + /// + /// Test GetHashCode on two tokens with same values is the same + /// + [TestMethod] + public void TestTokenGetHashCodeOnTwoTokensWhichHaveSameValuesAreEqual() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + string testTokenValue2 = "123"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + + int hash1 = token1.GetHashCode(); + int hash2 = token2.GetHashCode(); + Assert.AreEqual(hash1, hash2); + } + + /// + /// Test GetHashCode on two tokens with different values are different + /// + [TestMethod] + public void TestTokenGetHashCodeOnTwoTokensWhichHaveDifferentValuesAreUnequal() + { + string testTokenValue = "123"; + Token.Type testTokenType = Token.Type.Numeric; + Token.NumericType testNumericType = Token.NumericType.Integer; + uint testArityValue = 0; + + string testTokenValue2 = "125"; + Token.Type testTokenType2 = Token.Type.Numeric; + Token.NumericType testNumericType2 = Token.NumericType.Integer; + uint testArityValue2 = 0; + + Token token1 = new(testTokenValue, testTokenType, testNumericType, testArityValue); + Token token2 = new(testTokenValue2, testTokenType2, testNumericType2, testArityValue2); + + int hash1 = token1.GetHashCode(); + int hash2 = token2.GetHashCode(); + Assert.AreNotEqual(hash1, hash2); + } + } +} diff --git a/MathEngine/MathEngine/Parser/Nodes/BaseNode.cs b/MathEngine/MathEngine/Parser/Nodes/BaseNode.cs new file mode 100644 index 0000000..2390a8e --- /dev/null +++ b/MathEngine/MathEngine/Parser/Nodes/BaseNode.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace MathEngine.Parser.Parser +{ + /// + /// Abstract class representing a Node in a Tree structure + /// + internal abstract class BaseNode + { + /// + /// Reference to any child Nodes + /// + protected List? Children; + + /// + /// Base method for adding two nodes, returning another BaseNode object + /// + /// The node to be added to the current instance + /// + /// + protected virtual BaseNode Add(BaseNode otherNode) + { + throw new InvalidOperationException("Attempted to call BaseNode _add, which is invalid!"); + } + + /// + /// Base operator for adding two Base Nodes + /// + /// The left BaseNode + /// The right BaseNode + /// The addition of two BaseNodes, as defined by the calling type + public static BaseNode operator +(BaseNode lhs, BaseNode rhs) + { + return lhs.Add(rhs); + } + + /// + /// Base method for subtracting two nodes, returning another BaseNode object + /// + /// The node to be subtract from the current instance + /// + /// + protected virtual BaseNode Subtract(BaseNode otherNode) + { + throw new InvalidOperationException("Attempted to call BaseNode Subtract, which is invalid!"); + } + + /// + /// Base operator for subtracting two Base Nodes + /// + /// The left BaseNode + /// The right BaseNode + /// The subtraction of two BaseNodes, as defined by the calling type + public static BaseNode operator -(BaseNode lhs, BaseNode rhs) + { + return lhs.Subtract(rhs); + } + + /// + /// Base method for multiplying two nodes, returning another BaseNode object + /// + /// The node multiply the current instance by + /// + /// + protected virtual BaseNode Multiply(BaseNode otherNode) + { + throw new InvalidOperationException("Attempted to call BaseNode Multiply, which is invalid!"); + } + + /// + /// Base operator for multiplying two Base Nodes + /// + /// The left BaseNode + /// The right BaseNode + /// The product of two BaseNodes, as defined by the calling type + public static BaseNode operator *(BaseNode lhs, BaseNode rhs) + { + return lhs.Multiply(rhs); + } + + /// + /// Base method for dividing two nodes, returning another BaseNode object + /// + /// The node which will divide the current instance + /// + /// + protected virtual BaseNode Divide(BaseNode otherNode) + { + throw new InvalidOperationException("Attempted to call BaseNode _add, which is invalid!"); + } + + /// + /// Base operator for dividing two Base Nodes + /// + /// The left BaseNode + /// The right BaseNode + /// The division of two BaseNodes, as defined by the calling type + public static BaseNode operator /(BaseNode lhs, BaseNode rhs) + { + return lhs.Divide(rhs); + } + + /// + /// Abstract Base method that evaluates the current Node + /// + /// + public abstract BaseNode Evaluate(); + } +} diff --git a/MathEngine/MathEngine/Parser/Nodes/BinaryNode.cs b/MathEngine/MathEngine/Parser/Nodes/BinaryNode.cs new file mode 100644 index 0000000..74e0cd9 --- /dev/null +++ b/MathEngine/MathEngine/Parser/Nodes/BinaryNode.cs @@ -0,0 +1,36 @@ + +using System.Numerics; + +namespace MathEngine.Parser.Parser.Nodes +{ + internal class BinaryNode:BaseNode + { + private BaseNode left; + private BaseNode right; + private Func op; + + /// + /// Initialises A BinaryNode with the given left and right branches and the operation to perform + /// + /// The left branch + /// The right branch + /// The oepration to perform on evaluation + public BinaryNode(BaseNode left, BaseNode right, Func op) + { + this.left = left; + this.right = right; + this.op = op; + } + + /// + /// Evalutes the binary node based on the operator given + /// + /// + public override BaseNode Evaluate() + { + BaseNode lhs_val = this.left.Evaluate(); + BaseNode rhs_val = this.right.Evaluate(); + return op(lhs_val, rhs_val); + } + } +} diff --git a/MathEngine/MathEngine/Parser/Nodes/NodeFactory.cs b/MathEngine/MathEngine/Parser/Nodes/NodeFactory.cs new file mode 100644 index 0000000..d631bc1 --- /dev/null +++ b/MathEngine/MathEngine/Parser/Nodes/NodeFactory.cs @@ -0,0 +1,56 @@ +using MathEngine.Parser.Parser.Nodes; +using MathEngine.Parser.Tokeniser; +namespace MathEngine.Parser.Parser +{ + /// + /// Factory that creates a TreeNode + /// + internal class NodeFactory + { + /// + /// Creates a binary TreeNode, that is a node with a root value and two children + /// + /// The token to be the root node of the TreeNode + /// TreeNode that is the left branch of the current node + /// TreeNode that is the right branch of the current node + /// A TreeNode with CurrentToken as the root value and LeftBranch and RightBranch as Children + public static BaseNode CreateBinaryNode(Token CurrentToken, BaseNode LeftBranch, BaseNode RightBranch) + { + switch (CurrentToken.Token_Type) + { + case Token.Type.Addition: + return new BinaryNode(LeftBranch, RightBranch, (a, b) => a + b); + case Token.Type.Subtraction: + return new BinaryNode(LeftBranch, RightBranch, (a, b) => a - b); + case Token.Type.Multiplication: + return new BinaryNode(LeftBranch, RightBranch, (a, b) => a * b); + case Token.Type.Division: + return new BinaryNode(LeftBranch, RightBranch, (a, b) => a / b); + case Token.Type.Exponentiation: + throw new NotImplementedException("Exponentiation is not implemented at this time"); + default: + throw new NotImplementedException("Attempted to create a BinaryNode with an invalid operation!"); + } + } + + /// + /// Returns a Node that holds a numerical value + /// + /// The token that holds the numeric value + /// + public static BaseNode CreateNumericNode(Token CurrentToken) + { + switch (CurrentToken.NumericalType) + { + case Token.NumericType.Integer: + return new NumericNode(Int64.Parse(CurrentToken.TokenValue)); + case Token.NumericType.Decimal: + return new NumericNode(Decimal.Parse(CurrentToken.TokenValue)); + case Token.NumericType.Complex: + throw new NotImplementedException("Complex Numbers are not implemented at this time"); + default: + throw new InvalidDataException("Attempted to create a NumericNode with non numeric data!"); + } + } + } +} diff --git a/MathEngine/MathEngine/Parser/Nodes/NumericNode.cs b/MathEngine/MathEngine/Parser/Nodes/NumericNode.cs new file mode 100644 index 0000000..0319948 --- /dev/null +++ b/MathEngine/MathEngine/Parser/Nodes/NumericNode.cs @@ -0,0 +1,77 @@ +using System.Numerics; + +namespace MathEngine.Parser.Parser.Nodes +{ + /// + /// Represents a Tree node that can store a numeric value + /// + internal class NumericNode : BaseNode where T: INumber + { + private readonly T Value; + + /// + /// Initialises a new instance of a NumericNode with a given Token + /// + /// The token for the nodes value + public NumericNode(T value) + { + this.Children = null; + this.Value = value; + } + + protected override BaseNode Add(BaseNode otherNode) + { + if (otherNode is NumericNode) + { + NumericNode rhs = (NumericNode)otherNode; + return new NumericNode(Value + rhs.Value); + } + throw new InvalidOperationException("Attempted Invalid operation"); + } + + protected override BaseNode Subtract(BaseNode otherNode) + { + if (otherNode is NumericNode) + { + NumericNode rhs = (NumericNode)otherNode; + return new NumericNode(Value - rhs.Value); + } + throw new InvalidOperationException("Attempted Invalid operation"); + } + + protected override BaseNode Multiply(BaseNode otherNode) + { + if (otherNode is NumericNode) + { + NumericNode rhs = (NumericNode)otherNode; + return new NumericNode(Value * rhs.Value); + } + throw new InvalidOperationException("Attempted Invalid operation"); + } + + protected override BaseNode Divide(BaseNode otherNode) + { + if (otherNode is NumericNode) + { + NumericNode rhs = (NumericNode)otherNode; + return new NumericNode(Value / rhs.Value); + } + throw new InvalidOperationException("Attempted Invalid operation"); + } + + /// + /// Evaluates the Numeric Node by simply returning the current instance + /// + /// + public override BaseNode Evaluate() + { + return this; + } + + public override string ToString() + { + return Value.ToString(); + } + + } +}