Files
MathsEngine/MathEngine/MathEngine/AST/Nodes/NodeFactory.cs

95 lines
4.0 KiB
C#

using MathEngine.Functions.BuiltIns;
using MathEngine.Tokenizer;
using MathEngine.Types;
using MathEngine.Types.Interfaces;
using System.Runtime.Intrinsics.X86;
using Xunit.Sdk;
using static MathEngine.Tokenizer.Token;
namespace MathEngine.AST.Nodes
{
/// <summary>
/// Factory that creates a TreeNode
/// </summary>
internal class NodeFactory
{
/// <summary>
/// Creates a binary TreeNode, that is a node with a root value and two children
/// </summary>
/// <param name="CurrentToken">The token to be the root node of the TreeNode</param>
/// <param name="LeftToken">TreeNode that is the left branch of the current node</param>
/// <param name="RightToken">TreeNode that is the right branch of the current node</param>
/// <returns>A TreeNode with CurrentToken as the root value and LeftBranch and RightBranch as Children</returns>
public static BaseNode CreateBinaryNode(Token CurrentToken, BaseNode LeftBranch, BaseNode RightBranch)
{
switch (CurrentToken.Type)
{
case TokenType.Addition:
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a + b);
case TokenType.Subtraction:
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a - b);
case TokenType.Multiplication:
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a * b);
case TokenType.Division:
return new BinaryNode(LeftBranch, RightBranch, (a, b) => a / b);
case TokenType.Exponentiation:
throw new NotImplementedException("Exponentiation is not supported at this time!");
// return new BinaryNode(LeftBranch, RightBranch, (a, b) => a ^ b);
default:
throw new NotImplementedException("Attempted to create a BinaryNode with an invalid operation!");
}
}
/// <summary>
/// Creates a Function Node, that is a node that operates a number of arguments
/// </summary>
/// <param name="FunctionToken">The function to create the node for</param>
/// <param name="ArgumentStack">Reference to Stack of BaseNode objects to take the arguments from</param>
/// <returns></returns>
public static BaseNode CreateFunctionNode(Token FunctionToken, Stack<BaseNode> ArgumentStack)
{
int argc = (int)FunctionToken.Arity;
INumericNode[] argsv = new INumericNode[argc];
for (int i = argc; i > 0; i--)
{
// TODO: Update so either INumeric or function nodes are allowed
// this will enable nested functions
if (ArgumentStack.Peek() is INumericNode numericNode)
{
argsv[i - 1] = numericNode;
ArgumentStack.Pop();
}
else
{
throw new InvalidOperationException("Function arguments implement INumericNode.");
}
}
return new FunctionNode(BuiltIns.GetFunction(FunctionToken.Value), argsv);
}
/// <summary>
/// Creates a Function Node, that is a node that operates a number of arguments
/// </summary>
/// <param name="FunctionToken">The function to create the node for</param>
/// <param name="ArgumentStack">Reference to Stack of BaseNode objects to take the arguments from</param>
/// <returns></returns>
public static BaseNode CreateNumericNode(Token NumericToken)
{
if (NumericToken.Type != TokenType.Numeric)
{
throw new ArgumentException("Token is not of a numeric type");
}
if (!(decimal.TryParse(NumericToken.Value, out decimal res)))
{
throw new ArgumentException("Failure to parse number");
}
return new NumericallyOrderableNode<DecimalValue>(new DecimalValue(res));
}
}
}