/// <summary>
        /// Returns an expression that can be compiled into a function to be called dynamically.
        /// </summary>
        /// <returns></returns>
        private Expression ParseDynamicExpression(ref Dictionary <string, ParameterExpression> discoveredParameters, string expression = null)
        {
            if (string.IsNullOrEmpty(expression))
            {
                // this is the final text to be parsed.
                expression = this.ToString();
            }

            bool NegativeExpression = false;

            if (expression.StartsWith("-"))
            {
                NegativeExpression = true;
                expression         = expression.TrimStart('-'); // remove any trailing minuses
            }


            char[] separators = { '^', '*', '/', '+', '-', '(', '<', '>', '=' };

            char[] operators = { '^', '*', '/', '+', '-' };


            expression = expression.Replace(" ", "");

            // simple parsing
            // obeys the rules of priorities

            // Priorities
            //    ^  Power
            //    *  multiplication
            //    /  division
            //    +  Addition
            //    -  Subtraction



            // Tokenization is done by separating with operators
            DynamicExpressionOperator Root = new DynamicExpressionOperator();
            DynamicExpressionOperator ep   = Root;

            StringBuilder TokenBuilder    = new StringBuilder();
            Stack <int>   PLevels         = new Stack <int>();
            bool          Inner           = false;
            bool          FunctionContext = false;

            #region method that will be reused
            Action <Dictionary <string, ParameterExpression> > redundantFunction = (parameters) =>
            {
                // Last pass that escaped from the loop.
                if (Inner)
                {
                    ep.DynamicExpression = ParseDynamicExpression(ref parameters, TokenBuilder.ToString());

                    Inner = false;
                }
                else
                {
                    double constant;
                    if (TokenBuilder.ToString().Equals("Infinity", StringComparison.OrdinalIgnoreCase) || TokenBuilder.ToString().Equals("inf", StringComparison.OrdinalIgnoreCase))
                    {
                        ep.DynamicExpression = Expression.Constant(double.PositiveInfinity, typeof(double));
                    }
                    else if (TokenBuilder.ToString().Equals("NaN", StringComparison.OrdinalIgnoreCase))
                    {
                        ep.DynamicExpression = Expression.Constant(double.NaN, typeof(double));
                    }
                    else if (TokenBuilder[0] == '%')
                    {
                        // constant
                        ep.DynamicExpression = Expression.Constant(MathConstants.Constant(TokenBuilder.ToString().TrimStart('%')), typeof(double));
                    }
                    else if (double.TryParse(TokenBuilder.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out constant))
                    {
                        ep.DynamicExpression = Expression.Constant(constant, typeof(double));
                    }
                    else
                    {
                        var pname = TokenBuilder.ToString();

                        var FMatch = FunctionRegex.Match(pname);
                        // test if the parameter is a function
                        if (FMatch.Success)
                        {
                            // take the function name and search for it
                            // if you found it take the inner parameters and parse it independently
                            var fname = FMatch.Groups["function"].Value;

                            // search for the function in the math class
                            MethodInfo targetfunction;

                            if (CoMath.AvailableFunctions.Contains(fname, StringComparer.OrdinalIgnoreCase))
                            {
                                targetfunction = typeof(CoMath).GetMethod(
                                    fname
                                    , System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static
                                    );
                            }
                            else if (fname.Equals("log", StringComparison.OrdinalIgnoreCase))
                            {
                                targetfunction = typeof(Math).GetMethod("Log", new Type[] { typeof(double) });
                            }
                            else if (fname.Equals("iif", StringComparison.OrdinalIgnoreCase))
                            {
                                targetfunction = typeof(CoLogic).GetMethod("IIF", new Type[] { typeof(bool), typeof(double), typeof(double) });
                            }
                            else
                            {
                                targetfunction = typeof(Math).GetMethod(
                                    fname
                                    , System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static
                                    );
                            }

                            if (targetfunction != null)
                            {
                                // for now take the
                                var          fps      = FMatch.Groups["parameters"].Value;
                                string[]     pss      = TextTools.ComaSplit(fps);
                                Expression[] tfparams = new Expression[pss.Length];
                                for (int ixf = 0; ixf < pss.Length; ixf++)
                                {
                                    tfparams[ixf] = ParseDynamicExpression(ref parameters, pss[ixf]);
                                }
                                ep.DynamicExpression = Expression.Call(targetfunction, tfparams);
                            }
                            else
                            {
                                var fn = Functions.Keys.FirstOrDefault(cc => cc.StartsWith(fname));
                                if (!string.IsNullOrEmpty(fn))
                                {
                                    // this is good  because we have a body.
                                    ep.DynamicExpression = Functions[fn].ParseDynamicExpression(ref parameters);
                                }
                                else
                                {
                                    throw new SymbolicException(string.Format("The target function {0} couldn't be found", fname));
                                }
                            }
                        }
                        else
                        {
                            // this is an ordinary parameter based on our test.
                            ParameterExpression pe;
                            if (parameters.TryGetValue(pname, out pe))
                            {
                                ep.DynamicExpression = pe;
                            }
                            else
                            {
                                pe = Expression.Parameter(typeof(double), pname);

                                ep.DynamicExpression = pe;

                                parameters.Add(pname, pe);
                            }
                        }
                    }
                }
            };


            #endregion

            for (int ix = 0; ix < expression.Length; ix++)
            {
                if (PLevels.Count == 0)
                {
                    // include the normal parsing when we are not in parenthesis group
                    if (separators.Contains(expression[ix]))
                    {
                        if ((expression[ix] == '-' || expression[ix] == '+') && ix == 0)
                        {
                            // add first character if - or +
                            TokenBuilder.Append(expression[ix]);
                        }
                        else if (ix > 1 &&
                                 char.ToUpper(expression[ix - 1]) == 'E' && char.IsDigit(expression[ix - 2]) &&
                                 (expression[ix] == '-' || expression[ix] == '+'))
                        {
                            // test previous charachter if E    and charachter before it to be digit and current character is - or +
                            //    then we are in sceintific representation of number

                            // case of 3e+2 4e-2  all cases with e in it.

                            TokenBuilder.Append(expression[ix]);
                        }
                        else if (expression[ix] == '(')
                        {
                            // either we reached a function of expression group.
                            PLevels.Push(1);

                            // test for something other than separator in previous charachter
                            var OperatorBehind = ix > 0 ? separators.Contains(expression[ix - 1]) : true;

                            if (!OperatorBehind)
                            {
                                //the previous charachter is normal word which indicates we reached a function
                                FunctionContext = true;
                                TokenBuilder.Append(expression[ix]);
                            }
                        }
                        else if (operators.Contains(expression[ix - 1]) && (expression[ix] == '-' || expression[ix] == '+'))
                        {
                            // the case in which last charachter was another operator and followed by current (-) or (+)
                            TokenBuilder.Append(expression[ix]);
                        }
                        else
                        {
                            // tokenize   when we reach any operator  or open '(' parenthesis

                            redundantFunction(discoveredParameters);

                            TokenBuilder = new StringBuilder();

                            ep.Operation = expression[ix].ToString();

                            if (expression[ix] == '<' || expression[ix] == '>')
                            {
                                // check for equal sign after this
                                if (expression[ix + 1] == '=')
                                {
                                    ep.Operation += "=";
                                    ix++;
                                }
                            }

                            ep.Next = new DynamicExpressionOperator();
                            ep      = ep.Next;      // advance the reference to the next node to make the linked list.
                        }
                    }
                    else
                    {
                        TokenBuilder.Append(expression[ix]);
                    }
                }
                else
                {
                    // we are in group
                    if (expression[ix] == '(')
                    {
                        PLevels.Push(1);
                    }
                    if (expression[ix] == ')')
                    {
                        PLevels.Pop();

                        if (PLevels.Count == 0)
                        {
                            Inner = true;
                            if (FunctionContext)
                            {
                                TokenBuilder.Append(expression[ix]);
                                FunctionContext = false;
                                Inner           = false; // because i am taking the function body as a whole in this parse pass.
                                // then inner parameters of the function will be parsed again
                            }
                        }
                        else
                        {
                            TokenBuilder.Append(expression[ix]);
                        }
                    }
                    else
                    {
                        TokenBuilder.Append(expression[ix]);
                    }
                }
            }

            redundantFunction(discoveredParameters);

            TokenBuilder = null;


            string[] Group = { "^"    /* Power for normal product '*' */
            };


            string[] Group1 = { "*" /* normal multiplication */,
                                "/" /* normal division */,
                                "%" /* modulus */ };


            string[] Group2 = { "+", "-" };

            string[] Group3 = { "<", "<=", ">", ">=" };

            string[] Group4 = { "=", "<>" };

            /// Operator Groups Ordered by Priorities.
            string[][] OperatorGroups = { Group, Group1, Group2, Group3, Group4 };

            foreach (var opg in OperatorGroups)
            {
                DynamicExpressionOperator eop = Root;

                //Pass for '[op]' and merge it  but from top to child :)  {forward)
                while (eop.Next != null)
                {
                    //if the operator in node found in the opg (current operator group) then execute the logic

                    if (opg.Count(c => c.Equals(eop.Operation, StringComparison.OrdinalIgnoreCase)) > 0)
                    {
                        short skip;
                        eop.DynamicExpression = ArithExpression(eop, out skip);

                        //drop eop.Next
                        if (eop.Next.Next != null)
                        {
                            while (skip > 0)
                            {
                                eop.Operation = eop.Next.Operation;

                                eop.Next = eop.Next.Next;

                                skip--;
                            }
                        }
                        else
                        {
                            //no more nodes exit the loop

                            eop.Next      = null; //last item were processed.
                            eop.Operation = string.Empty;
                        }
                    }
                    else
                    {
                        eop = eop.Next;
                    }
                }
            }

            Expression FinalExpression;

            if (NegativeExpression)
            {
                FinalExpression = Expression.Multiply(Expression.Constant(-1.0, typeof(double)), Root.DynamicExpression);
            }
            else
            {
                FinalExpression = Root.DynamicExpression;
            }

            return(FinalExpression);
        }
        private static Expression ArithExpression(DynamicExpressionOperator eop, out short skip)
        {
            Expression left  = eop.DynamicExpression;
            string     op    = eop.Operation;
            Expression right = eop.Next.DynamicExpression;

            skip = 1;


            if (op == "^")
            {
                // This will be right associative operator
                // which means if more than one power appeared like this 3^2^4  then it will be processed like this 3^(2^4)

                if (eop.Next.Next != null)
                {
                    if (eop.Next.Operation == "^")
                    {
                        short iskip;
                        var   powerResult = Expression.Power(
                            left
                            , ArithExpression(eop.Next, out iskip)
                            );

                        skip += iskip;
                        return(powerResult);
                    }
                    else
                    {
                        return(Expression.Power(left, right));
                    }
                }
                else
                {
                    return(Expression.Power(left, right));
                }
            }

            if (op == "*")
            {
                return(Expression.Multiply(left, right));
            }
            if (op == "/")
            {
                return(Expression.Divide(left, right));
            }
            if (op == "+")
            {
                return(Expression.Add(left, right));
            }
            if (op == "-")
            {
                return(Expression.Subtract(left, right));
            }

            if (op == "<")
            {
                return(Expression.LessThan(left, right));
            }
            if (op == ">")
            {
                return(Expression.GreaterThan(left, right));
            }
            if (op == "<=")
            {
                return(Expression.LessThanOrEqual(left, right));
            }
            if (op == ">=")
            {
                return(Expression.GreaterThanOrEqual(left, right));
            }
            if (op == "=")
            {
                return(Expression.Equal(left, right));
            }
            if (op == "<>")
            {
                return(Expression.NotEqual(left, right));
            }


            throw new NotSupportedException("Not Supported Operator '" + op + "'");
        }