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();
+ }
+
+ }
+}