Example #1
0
        public override TreeNode FactoryMethod(string expression)
        {
            OpNodeFactory opNodeFactory = new ConcreteOpNodeFactory();
            OperatorNode  @operator     = opNodeFactory.FactoryMethod(expression);

            if (@operator != null)
            {
                return(@operator);
            }
            else
            {
                bool int_success    = Int32.TryParse(expression, out int int_result),
                     double_success = Double.TryParse(expression, out double double_result);
                if (int_success)
                {
                    return(new ValueNode(int_result));
                }
                else if (double_success)
                {
                    return(new ValueNode(double_result));
                }
                else
                {
                    return(new CellReferenceNode(expression));
                }
            }
        }
        public double Evaluate()
        {
            // If the node is a constantNode(a number), then simply return its value
            ConstantNode constantNode = this.Root as ConstantNode;

            if (constantNode != null)
            {
                return(constantNode.Value);
            }

            // If the node is a variableNode then return the value in the dictionary correspondingly
            VariableNode variableNode = this.Root as VariableNode;

            if (variableNode != null)
            {
                return(this.Variables[variableNode.Name]);
            }

            // it is an operator node if we came here
            OperatorNode operatorNode = this.Root as OperatorNode;

            if (operatorNode != null)
            {
                OperatorNode op = this.Root as OperatorNode;
                if (op != null)
                {
                    return(op.Evaluate());
                }
            }

            throw new NotSupportedException();
        }
        public string ShuntingYard(string expression)
        {
            Stack <string> stack  = new Stack <string>();
            string         result = string.Empty;
            char           c;

            for (int i = 0; i < expression.Length; i++)
            {
                c = expression[i];
                if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^') // Incoming symbols is an operator
                {
                    OperatorNode op = new OperatorNode(c);
                    if (stack.Count == 0 || stack.Peek() == "(") // 4. Stack is empty or stack top = Left parenthesis
                    {
                        stack.Push(c.ToString());
                    }
                    else if (stack.Count != 0)
                    {
                        OperatorNode stackOp = new OperatorNode(stack.Peek().ToCharArray()[0]);
                        if ((op.Precedence > stackOp.Precedence) || (op.Precedence == stackOp.Precedence && stackOp.Associativity == "Right")) // 5.
                        {
                            stack.Push(c.ToString());
                        }
                        else if ((op.Precedence < stackOp.Precedence) || (op.Precedence == stackOp.Precedence && stackOp.Associativity == "Left")) // 6.
                        {
                            while (stack.Count != 0 && ((op.Precedence < stackOp.Precedence) || (op.Precedence == stackOp.Precedence && stackOp.Associativity == "Left")))
                            {
                                result += stack.Pop();
                            }

                            stack.Push(c.ToString());
                        }
                    }
                }
                else if (c == '(') // 2. Incoming symbols is a left parenthesis
                {
                    stack.Push(c.ToString());
                }
                else if (c == ')') // 3. Incoming symbols is a right parenthesis
                {
                    while (stack.Peek() != "(")
                    {
                        result += stack.Pop();
                    }

                    stack.Pop();
                }
                else // 1. Incoming symbols is an operand
                {
                    result += c;
                }
            }

            while (stack.Count != 0)
            {
                result += stack.Pop();
            }

            return(result);
        }
        /************************************************************
        * This is a recursive function which builds the entire
        * expression tree from the bottom to the top.
        * Here's how the general idea of how the function works:
        * 1. Segment the expression with "+" and "-" being
        * the delimiters then either construct a node with
        * those segments or build a tree out of it (by calling this
        * recursive function) depending on which one's the
        * appropriate option and connect those nodes/trees together
        * appropriately but don't segment anything within parenthesis.
        * 2. Repeat #1 but use "*" and "/" as the delimiters.
        * 3. If an sub_expression with paranthesis as the first
        * and last element get passed to this function, go back
        * to #1.
        * 4. Eventually a tree will be constructed from the
        * bottom to the top.
        ************************************************************/
        private Node ConstructTree(string sub_expression, bool using_multiply_divide_operators)
        {
            List <string> expression_pieces = new List <string>();

            char[] contents = sub_expression.ToCharArray();
            char   operator1 = '+', operator2 = '-';

            if ('(' == contents[0] && ')' == contents[contents.Length - 1])
            {
                sub_expression = sub_expression.Substring(1, sub_expression.Length - 2);
                contents       = sub_expression.ToCharArray();
                using_multiply_divide_operators = false;
            }

            if (using_multiply_divide_operators)
            {
                operator1 = '*';
                operator2 = '/';
            }

            /************************************************************
            * Base Case: Expression has no parenthesis and has
            * no + or - operators
            ************************************************************/
            if (!sub_expression.Contains("+") &&
                !sub_expression.Contains("-") &&
                !sub_expression.Contains("("))
            {
                string[]      split_pieces_from_multiply_operator      = sub_expression.Split('*');
                List <string> split_pieces_from_multiply_operator_list = new List <string>();
                for (int i = 0; i < split_pieces_from_multiply_operator.Length; i++)
                {
                    split_pieces_from_multiply_operator_list.Add(split_pieces_from_multiply_operator[i]);
                    split_pieces_from_multiply_operator_list.Add("*");
                }
                split_pieces_from_multiply_operator_list.RemoveAt(split_pieces_from_multiply_operator_list.Count - 1);
                for (int i = 0; i < split_pieces_from_multiply_operator_list.Count; i++)
                {
                    if (split_pieces_from_multiply_operator_list[i].Contains("/"))
                    {
                        string[]      split_pieces_from_divide_operator      = split_pieces_from_multiply_operator_list[i].Split('/');
                        List <string> split_pieces_from_divide_operator_list = new List <string>();
                        for (int j = 0; j < split_pieces_from_divide_operator.Length; j++)
                        {
                            expression_pieces.Add(split_pieces_from_divide_operator[j]);
                            expression_pieces.Add("/");
                        }
                        expression_pieces.RemoveAt(expression_pieces.Count - 1);
                    }
                    else
                    {
                        expression_pieces.Add(split_pieces_from_multiply_operator_list[i]);
                    }
                }
            }
            else
            {
                int cut_start_i = 0;
                for (int i = 0; i < contents.Length; i++)
                {
                    if ('(' == contents[i])
                    {
                        int parenthesis_start_i = i;
                        int parenthesis_count   = 1;
                        while (0 != parenthesis_count)
                        {
                            i++;
                            if ('(' == contents[i])
                            {
                                parenthesis_count++;
                            }
                            else if (')' == contents[i])
                            {
                                parenthesis_count--;
                            }
                        }
                    }
                    else if (operator1 == contents[i] || operator2 == contents[i])
                    {
                        expression_pieces.Add(sub_expression.Substring(cut_start_i, i - cut_start_i));
                        expression_pieces.Add(Convert.ToString(contents[i]));
                        cut_start_i = i + 1;
                    }
                }
                expression_pieces.Add(sub_expression.Substring(cut_start_i, sub_expression.Length - cut_start_i));
            }

            Node current_left_node = MakeNodeWithValue(expression_pieces[0]);

            if (null == current_left_node)
            {
                current_left_node = ConstructTree(expression_pieces[0], true);
            }
            for (int i = 1; i < expression_pieces.Count; i += 2)
            {
                OperatorNode current_operator   = new OperatorNode(expression_pieces[i]);
                Node         current_right_node = MakeNodeWithValue(expression_pieces[i + 1]);
                if (null == current_right_node)
                {
                    current_right_node = ConstructTree(expression_pieces[i + 1], true);
                }
                current_operator.Left  = current_left_node;
                current_operator.Right = current_right_node;
                current_left_node      = current_operator;
            }

            return(current_left_node);
        }
        public Node ConstructTree(string pre_expression)
        {
            // This block is responsible for finding all the variables in the expression
            List <string> temp = new List <string>();
            string        m    = string.Empty;
            char          p;

            for (int k = 0; k < pre_expression.Length; k++)
            {
                p = pre_expression[k];
                if (p == '(' || p == ')')
                {
                }
                else if (p != '+' && p != '-' && p != '*' && p != '/')
                {
                    m += p;
                }
                else
                {
                    temp.Add(m);
                    m = "";
                }
            }
            temp.Add(m);

            // Take the original expression
            string expression = ShuntingYard(pre_expression); // Get its postfix notation

            // This block is responsible for building the tree
            Stack <Node> stack = new Stack <Node>();
            Node         n     = this.Root;
            char         c;
            string       x = "";
            int          y = 0;

            // Read until there is nothing left to read
            for (int i = 0; i < expression.Length; i++)
            {
                c = expression[i]; // Read char by char

                // If char read is an operator
                if (c == '+' || c == '-' || c == '*' || c == '/')
                {
                    Node tree1 = null;
                    if (stack.Count != 0)
                    {
                        tree1 = stack.Pop();
                    }
                    Node tree2 = null;
                    if (stack.Count != 0)
                    {
                        tree2 = stack.Pop();
                    }

                    OperatorNode op = new OperatorNode(c);
                    op.Right = tree1;
                    op.Left  = tree2;
                    n        = op;
                    stack.Push(op);
                }
                else
                {
                    // If its any other things (variables)
                    x += c; // Keep making the string until it is one of the variables we need
                    if (x == temp[y])
                    {
                        y++;
                        // This part is where we deal with single expressions without Operators
                        // So automatically, we know that it will either be a ConstantNode(a number) or a VariableNode(a name)
                        double number;

                        // If the expression is a ConstantNode
                        if (double.TryParse(x, out number))
                        {
                            // Insert the expression into the dictionary
                            //if (!this.Variables.ContainsKey(x))
                            //{
                            //    this.Variables.Add(x, number);
                            //}
                            ConstantNode cn = new ConstantNode();
                            cn.Value = number;
                            n        = cn;
                            stack.Push(n);
                        }

                        // If the expression is VariableNode
                        else
                        {
                            // Insert the expression into the dictionary
                            if (!this.Variables.ContainsKey(x))
                            {
                                this.Variables.Add(x, 0.0);
                            }
                            VariableNode vn = new VariableNode(Variables);
                            vn.Name = x;
                            n       = vn;
                            stack.Push(n);
                        }
                        x = "";
                    }
                }
            }
            return(n);
        }