private FactoryResult TryGetFunction(string equationString, IEquationMember previousMember)
        {
            FactoryResult result = RegularExpressionParser(
                Function.RegularExpression,
                equationString,
                (x) => new Function(x));

            return(result);
        }
        /*
         * https://en.wikipedia.org/wiki/Shunting-yard_algorithm
         * http://wcipeg.com/wiki/Shunting_yard_algorithm#Unary_operators
         * http://tutplusplus.blogspot.com/2011/12/c-tutorial-arithmetic-expression.html
         * http://tutplusplus.blogspot.com/2010/12/c-tutorial-equation-calculator.html
         */
        /// <summary>
        /// Using Shunting yard algorithm
        /// </summary>
        /// <param name="equationString"></param>
        /// <param name="varFinder"></param>
        /// <returns></returns>
        private Queue <IEquationMember> CreateReversePolishNotationQueue(string equationString, IList <string> parameterNames)
        {
            if (string.IsNullOrEmpty(equationString))
            {
                throw new ArgumentNullException(nameof(equationString));
            }
            Stack <IPrecedenceMember> precedenceStack = new Stack <IPrecedenceMember>();
            Stack <Function>          functionStack   = new Stack <Function>();
            Queue <IEquationMember>   outputQueue     = new Queue <IEquationMember>();
            IEquationMember           previousToken   = null;
            int totalNumbers    = 0;
            int totalBinaryOpts = 0;

            while (equationString.Length > 0 && !string.IsNullOrWhiteSpace(equationString))
            {
                int startingLength = equationString.Length;

                FactoryResult result = EquationMemberFactory.CreateEquationMember(equationString, previousToken, parameterNames);
                previousToken  = result?.Member;
                equationString = result?.RemainingString;
                if (previousToken is Number || previousToken is Variable)
                {
                    totalNumbers++;
                }
                if (previousToken is BinaryOperator)
                {
                    totalBinaryOpts++;
                }
                previousToken = HandleToken(precedenceStack, functionStack, outputQueue, previousToken);

                // if we didn't do anything in a loop, then there are unsupported strings
                if (equationString == null || startingLength == equationString.Length)
                {
                    throw new ArgumentException();
                }
            }

            if (totalNumbers != totalBinaryOpts + 1 && totalBinaryOpts > 0)
            {
                throw new ArgumentException("Binary Operators must have at 2 numbers to interact with");
            }

            while (precedenceStack.Count > 0)
            {
                if (precedenceStack.Peek() is Bracket)
                {
                    throw new ArgumentException();
                }
                outputQueue.Enqueue(precedenceStack.Pop());
            }
            EquationArguments = (IReadOnlyList <string>)parameterNames;
            return(outputQueue);
        }
 private FactoryResult TryToExtractVariable(string equationString,
                                            IEquationMember previousMember, IList <string> parameterNames)
 {
     return(RegularExpressionParser(
                Variable.RegularExpression,
                Variable.ReplaceRegularExpression,
                equationString,
                (x) =>
     {
         if (!parameterNames.Contains(x))
         {
             parameterNames.Add(x);
             parameterNames.OrderBy(name => name);
         }
         return new Variable(parameterNames.IndexOf(x));
     }));
 }
        private FactoryResult TryToExtractANumber(string equationString, IEquationMember previousMember)
        {
            FactoryResult result = RegularExpressionParser(
                Number.RegularExpression,
                equationString,
                (x) => new Number(double.Parse(x)));

            if (result != null)
            {
                return(result);
            }

            return(RegularExpressionParser(
                       @"^\s*PI",
                       equationString,
                       (x) => new Number(Math.PI)));
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="charArr">Changes only if a this method returns true</param>
 /// <param name="previousMember"></param>
 /// <param name="opt">null if BinaryOperator cannot be made</param>
 /// <returns>True if object can be created</returns>
 private FactoryResult TryGetBinaryOperator(string equationString, IEquationMember previousMember)
 {
     if (BinaryOperatorHasValidPreviousOperator(previousMember))
     {
         foreach (IOperatorMember obj in BinaryOperator.AllOperators)
         {
             FactoryResult result = RegularExpressionParser(
                 obj.RegularExpression,
                 equationString,
                 (x) => obj);
             if (result != null)
             {
                 return(result);
             }
         }
     }
     return(null);
 }
        internal FactoryResult CreateEquationMember(
            string equationString,
            IEquationMember previousMember,
            IList <string> parameterNames)
        {
            FactoryResult result          = null;
            string        refinedEquation = new Regex(@"\s").Replace(equationString, "");

            foreach (var fun in GetParsers(parameterNames))
            {
                result = fun(refinedEquation, previousMember);
                if (result != null)
                {
                    break;
                }
            }
            return(result);
        }
 private IEquationMember HandleToken(
     Stack <IPrecedenceMember> precedenceStack, Stack <Function> functionStack,
     Queue <IEquationMember> outputQueue, IEquationMember previousToken)
 {
     if (previousToken is Number num)
     {
         outputQueue.Enqueue(num);
     }
     else if (previousToken is Variable mVar)
     {
         outputQueue.Enqueue(mVar);
     }
     else if (previousToken is Function fun)
     {
         precedenceStack.Push(fun);
         functionStack.Push(fun);
     }
     else if (previousToken is IOperatorMember opt)
     {
         while (TopOfStackHasHigherPriorityOperator(precedenceStack, opt))
         {
             outputQueue.Enqueue(precedenceStack.Pop());
         }
         precedenceStack.Push(opt);
     }
     else if (previousToken is Bracket bracket)
     {
         BracketHelper(precedenceStack, outputQueue, functionStack, bracket);
     }
     else if (previousToken is FunctionArgumentSeparator funSep)
     {
         if (functionStack.Count() < 1)
         {
             throw new ArgumentException();
         }
         functionStack.Peek().TotalParameters++;
         previousToken = null;
     }
     return(previousToken);
 }
        public double Evaluate(params double[] args)
        {
            Stack <double>          numStack = new Stack <double>();
            Queue <IEquationMember> newQueue = new Queue <IEquationMember>();

            while (ReversePolishNotationQueue.Count > 0)
            {
                IEquationMember curMember = ReversePolishNotationQueue.Dequeue();
                newQueue.Enqueue(curMember);
                if (curMember is IOperatorMember opt)
                {
                    numStack.Push(opt.Evaluate(numStack));
                }
                else if (curMember is Number num)
                {
                    numStack.Push(num.Value);
                }
                else if (curMember is Variable variable)
                {
                    if (args == null || variable.Index > args.Length - 1)
                    {
                        throw new ArgumentException($"This equation requires at least {variable.Index + 1} arguments");
                    }
                    numStack.Push(args[variable.Index]);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            if (numStack.Count != 1)
            {
                throw new ArgumentException();
            }
            ReversePolishNotationQueue = newQueue;
            return(numStack.Peek());
        }
 /// <summary>
 /// true if the previous is valid for a unary operator
 /// </summary>
 /// <param name="previousMember"></param>
 /// <returns></returns>
 private bool UnaryOperatorHasValidPreviousOperator(IEquationMember previousMember)
 {
     return(!BinaryOperatorHasValidPreviousOperator(previousMember));
 }
 /// <summary>
 /// true if the previous is valid for a binary operator
 /// </summary>
 /// <param name="previousToken"></param>
 /// <returns></returns>
 private bool BinaryOperatorHasValidPreviousOperator(IEquationMember previousMember)
 {
     return(previousMember != null &&
            (!(previousMember is IOperatorMember) ||
             previousMember.Equals(Bracket.RightBracket)));
 }