Exemplo n.º 1
0
        /// <summary>
        /// Builds the tree also has a stack that we'll use to
        /// keep track of the list's items. Shunting algorithm and precedence
        /// will now be applied right away before items are read/to tree.
        /// Observe the following algorithm. We use a regular expression to store the possible combinations (-,/,+,*,(,))
        /// Symbols are partitoned out using the regular expression. Then we throw the entire list through shunting algorithm
        /// We then iterate through the list returned and use the stack to push,pop out items accordingly.
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private Node BuildTree(string expression)
        {
            var    nodeStack = new Stack <Node>();
            string pattern   = @"([-/\+\*\(\)])";
            var    tokens    = Regex.Split(expression, pattern).Where(s => s != String.Empty).ToList <string>();

            foreach (var tok in ShuntingAlgo(tokens))
            {
                if (Char.IsLetter(tok[0]))
                {
                    nodeStack.Push(new VariableNode(tok));
                }
                else if (Char.IsDigit(tok[0]))
                {
                    nodeStack.Push(new ValueNode(Double.Parse(tok)));
                }
                else
                {
                    var on = new OperatorNode(tok[0]);
                    on.right = nodeStack.Pop();
                    on.left  = nodeStack.Pop();
                    nodeStack.Push(on);
                }
            }
            root = nodeStack.Pop();
            return(root);
        }
Exemplo n.º 2
0
        // recursively evaluates tree
        private double RecursiveEvaluate(Node root)
        {
            OperatorNode operatorHolder = new OperatorNode(' ');
            ConstantNode constantHolder = new ConstantNode(0);
            VariableNode variableHolder = new VariableNode(string.Empty);
            double       num            = 0;

            if (root is OperatorNode)
            {
                // if node is operator, evaluate left and right subtrees
                operatorHolder = (OperatorNode)root;
                return(Operation(RecursiveEvaluate(root.Left), RecursiveEvaluate(root.Right), operatorHolder.Op));
            }
            else if (root is VariableNode)
            {
                // if node is variable, return value stored in variable
                variableHolder = (VariableNode)root;
                num            = Variables[variableHolder.Name];
                return(num);
            }
            else
            {
                // if node is constant, return value of constant
                constantHolder = (ConstantNode)root;
                num            = constantHolder.Value;
                return(num);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Builds the tree and has cases that it'll watch out for
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        Node BuildTree(string expression)
        {
            double val;

            for (int i = expression.Length - 1; i >= 0; i--)
            {
                switch (expression[i])
                {
                case '+':
                case '-':
                case '*':
                case '/':
                    OperatorNode newbie = new OperatorNode(expression[i]);
                    if (root == null)
                    {
                        root = newbie;
                    }
                    newbie.left  = BuildTree(expression.Substring(0, i));
                    newbie.right = BuildTree(expression.Substring(i + 1));
                    return(newbie);
                }
            }
            if (Double.TryParse(expression, out val))
            {
                return(new ValueNode(val));
            }
            else
            {
                return(new VariableNode(expression));
            }
        }
Exemplo n.º 4
0
        private double Evaluate(Node node)
        {
            if (node != null)
            {
                if (node is OperatorNode)
                {
                    OperatorNode opNode     = node as OperatorNode;
                    double       evaluation = opNode.Evaluate();
                    return(evaluation);
                }

                if (node is ConstantNode)
                {
                    ConstantNode constNode = node as ConstantNode;
                    return(constNode.Value);
                }

                if (node is VariableNode)
                {
                    VariableNode varNode = node as VariableNode;
                    return(this.Variables[varNode.Name]);
                }
            }

            return(0);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Places a new node into the expression tree from the currentNode in either the left or right branches.
        /// </summary>
        /// <param name="newNode"> The node being inserted. </param>
        /// <param name="currentNode"> The current position in the expression tree. </param>
        /// <returns> True of false depending on if the node could be inserted. Helps TraverseTree() with recursion. </returns>
        private bool InsertNode(Node newNode, Node currentNode)
        {
            OperatorNode positionNode = currentNode as OperatorNode;
            ConstantNode constNode    = newNode as ConstantNode;
            OperatorNode opNode       = newNode as OperatorNode;
            VariableNode varNode      = newNode as VariableNode;

            // Right first to match the order of the expression stack.
            if (positionNode.Right == null)
            {
                if (opNode != null)
                {
                    // Making sure nothing is in the new branches as the tree is being made.
                    opNode.Left        = null;
                    opNode.Right       = null;
                    positionNode.Right = opNode;
                }
                else
                {
                    if (varNode != null)
                    {
                        constNode = new ConstantNode()
                        {
                            Value = this.Variables[varNode.Name]
                        };
                    }

                    positionNode.Right = constNode;
                }

                return(true);
            }
            else if (positionNode.Left == null)
            {
                if (opNode != null)
                {
                    // Making sure nothing is in the new branches as the tree is being made.
                    opNode.Left       = null;
                    opNode.Right      = null;
                    positionNode.Left = opNode;
                }
                else
                {
                    if (varNode != null)
                    {
                        constNode = new ConstantNode()
                        {
                            Value = this.Variables[varNode.Name]
                        };
                    }

                    positionNode.Left = constNode;
                }

                return(true);
            }

            return(false);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Evaluate:
        ///     This function is used to evaluate the expression tree. This logic is given to
        ///     us in our Etree.c lecture notes. It takes in an ExpressionTreeBaseNode param.
        ///     then tries to cast it as a ConstantNode, VariableNode, or OperatorNode. Based
        ///     on what the node type is (see ExpressionTreeNodeFactory) it will return a value
        ///     to be evaluated. (all root nodes should be operators)
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private double Evaluate(ExpressionTreeBaseNode node)
        {
            ConstantNode constantNode = node as ConstantNode;

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

            // as a variable
            VariableNode variableNode = node as VariableNode;

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

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

            if (operatorNode != null)
            {
                // but which one?
                switch (operatorNode.Operator)
                {
                case '+':
                    return(Evaluate(operatorNode.Left) + Evaluate(operatorNode.Right));

                case '-':
                    return(Evaluate(operatorNode.Left) - Evaluate(operatorNode.Right));

                case '*':
                    return(Evaluate(operatorNode.Left) * Evaluate(operatorNode.Right));

                case '/':

                    try
                    {
                        return(Evaluate(operatorNode.Left) / Evaluate(operatorNode.Right));
                    }
                    catch (DivideByZeroException e)
                    {
                        Console.Write(e.Message);
                        Console.ReadLine();
                    }
                    break;

                case '^':
                    return(Math.Pow(Evaluate(operatorNode.Left), Evaluate(operatorNode.Right)));

                default:     // if it is not any of the operators that we support, throw an exception:
                    throw new NotSupportedException(
                              "Operator " + operatorNode.Operator.ToString() + " not supported.");
                }
            }

            throw new NotSupportedException();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Finds where to insert a new node into the expression tree and calls InsertNode().
        /// </summary>
        /// <param name="newNode"> The node being inserted. </param>
        /// <param name="currentNode"> The current position in the expression tree. </param>
        /// <returns> True or false depending on if the node could be inserted. Helps with recursion of the tree. </returns>
        private bool TraverseTree(Node newNode, Node currentNode)
        {
            OperatorNode positionNode = currentNode as OperatorNode;
            OperatorNode rightNode    = positionNode.Right as OperatorNode;

            // Right first to match the order of the expression stack.
            if (positionNode.Right != null && rightNode != null)
            {
                if (!this.TraverseTree(newNode, rightNode))
                {
                    if (positionNode.Left is OperatorNode leftNode)
                    {
                        if (this.TraverseTree(newNode, leftNode))
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(this.InsertNode(newNode, currentNode));
                    }
                }
            }
            else if (positionNode.Left != null)
            {
                if (positionNode.Left is OperatorNode leftNode)
                {
                    if (this.TraverseTree(newNode, leftNode))
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    return(this.InsertNode(newNode, currentNode));
                }
            }

            return(this.InsertNode(newNode, currentNode));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Evaluates the expression tree's arithmetic.
        /// </summary>
        /// <returns>Returns the arithmetic calculation of the expression tree.</returns>
        public double Evaluate()
        {
            if (this.head == null)
            {
                if (this.singleNodeString != null)
                {
                    return(this.variables[this.singleNodeString]);
                }
                else
                {
                    return(this.singleNodeDouble);
                }
            }

            OperatorNode current = this.head;     // A reference to the head of this expression tree.

            return(this.EvaluateHelper(current)); // Return the result of the helper method.
        }
Exemplo n.º 9
0
        private double Eval(BaseNode node)
        {
            //Evaluate based on the kind of node

            ConstantNode constnode = node as ConstantNode;

            if (constnode != null)
            {
                return(constnode.OpValue);
            }

            VariableNode varnode = node as VariableNode;

            if (varnode != null)
            {
                // used to be a try/catch, but now we set every new variable to 0 when the tree is made, so there will always be a value to obtain.
                return(variableDict[varnode.Name]);
            }

            OperatorNode opnode = node as OperatorNode;

            if (opnode != null)
            {
                switch (opnode.Op)
                {
                case '+':
                    return(Eval(opnode.Left) + Eval(opnode.Right));

                case '-':
                    return(Eval(opnode.Left) - Eval(opnode.Right));

                case '*':
                    return(Eval(opnode.Left) * Eval(opnode.Right));

                case '/':
                    return(Eval(opnode.Left) / Eval(opnode.Right));
                }
            }

            return(0);
        }
        /// <summary>
        /// Builds an expression tree from expression string.
        /// Returns the root node of the expression tree.
        /// </summary>
        /// <param name="expression">Expression string.</param>
        /// <returns>Root of built expression tree.</returns>
        private ExpressionTreeNode BuildExpressionTree(string expression)
        {
            List <ExpressionTreeNode>  postfixList = this.GetPostfixList(expression);
            Stack <ExpressionTreeNode> stack       = new Stack <ExpressionTreeNode>();

            foreach (ExpressionTreeNode currNode in postfixList)
            {
                if (this.IsConstantNode(currNode) || this.IsVariableNode(currNode))
                {
                    stack.Push(currNode);
                }
                else
                {
                    OperatorNode currOpNode = currNode as OperatorNode;
                    currOpNode.Right = stack.Pop();
                    currOpNode.Left  = stack.Pop();
                    stack.Push(currOpNode);
                }
            }

            return(stack.Pop());
        }
Exemplo n.º 11
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
                {
                    return(new ValueNode(double_result));
                }
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Prints the content of the expression tree to the console.
        /// </summary>
        /// <param name="node">The head of the expression tree.</param>
        /// <param name="result">The resultant string.</param>
        private void PrintTreeHelper(OperatorNode node, string result)
        {
            // In-order traversal algorithm.
            if (node.Left != null && node.Right != null)
            {
                // Check for OperatorNode or other node on left.
                if (!this.IsOperatorNode(node.Left))
                {
                    Console.Write(node.Left.Value);
                    result += node.Left.Value;
                }
                else
                {
                    this.PrintTreeHelper((OperatorNode)node.Left, result);
                }

                // Print current node value.
                Console.Write(node.Value);
                result += node.Value;

                // Check for OperatorNode or other node on right.
                if (!this.IsOperatorNode(node.Right))
                {
                    Console.Write(node.Right.Value);
                }
                else
                {
                    this.PrintTreeHelper((OperatorNode)node.Right, result);
                }
            }
            else
            {
                // Print the leaf's value.
                Console.WriteLine(node.Value);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// GetNode:
        ///   returns a ExpressionTreeNode such based off of client specified parameters. Only supports
        ///   Constant, Variable, and Operator Nodes. All of which inherit from ExpressionTreeBaseNode.
        /// </summary>
        /// <param name="nodeType">
        ///   nodeType string will specify which kind of ExpressionTree Node the client wishes to instantiate
        /// </param>
        /// <param name="operation">
        ///   operation char specifies the operation the client wishes to pass into OperationNode constructor.
        ///   (Optional) If passed in with "C" or "V" it will not be used.
        /// </param>
        /// <returns> ExpressionTreeBaseNode </returns>
        public ExpressionTreeBaseNode GetNode(string nodeType, string operation = "\0")
        {
            ExpressionTreeBaseNode node;

            switch (nodeType)
            {
            case "C":      /*constant*/
                ConstantNode constantNode = new ConstantNode();
                double       result;


                if (double.TryParse(operation, out result))
                {
                    constantNode.Value = result;
                }

                node = constantNode;

                return(node);

            case "V":      /*variable*/
                VariableNode variableNode = new VariableNode();

                variableNode.Name = operation;
                node = variableNode;

                return(node);

            case "O":      /*operator*/
                char op = operation[0];
                node = new OperatorNode(op);
                return(node);

            default: return(null);
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Better implementation that checks and evaluates off dict right away.
        /// Evaluate is self explained that returns the value (new or assigned)
        /// </summary>
        /// <returns></returns>
        private double Evaluate(Node node)
        {
            ValueNode constnode = node as ValueNode;

            if (constnode != null)
            {
                return(constnode.OpValue);
            }
            VariableNode varnode = node as VariableNode;

            if (varnode != null)
            {
                return(variableDict[varnode.Name]);
            }
            OperatorNode opnode = node as OperatorNode;

            if (opnode != null)
            {
                switch (opnode.Op)
                {
                case '+':
                    return(Evaluate(opnode.Left) + Evaluate(opnode.Right));

                case '-':
                    return(Evaluate(opnode.Left) - Evaluate(opnode.Right));

                case '*':
                    return(Evaluate(opnode.Left) * Evaluate(opnode.Right));

                case '/':
                    return(Evaluate(opnode.Left) / Evaluate(opnode.Right));
                }
            }

            return(0);
        }
        /// <summary>
        /// Takes a valid string expression and returns a postfix ordered list of expression tree nodes.
        /// Uses Dijkstra's Shunting Yard algorithm.
        /// </summary>
        /// <param name="expression">Valid expression string.</param>
        /// <returns>Postfix ordered expression tree node list.</returns>
        private List <ExpressionTreeNode> GetPostfixList(string expression)
        {
            Stack <char> stack = new Stack <char>();
            List <ExpressionTreeNode> postfixList = new List <ExpressionTreeNode>();
            OperatorNodeFactory       opFact      = new OperatorNodeFactory();

            char[] expressionArray = expression.ToArray <char>();

            // loops over each char in expression string
            for (int i = 0; i < expressionArray.Length; i++)
            {
                char currChar = expressionArray[i];

                // if the current char is a left parenthesis, push to stack
                if (currChar.Equals('('))
                {
                    stack.Push(currChar);
                }

                // if the current char is a right parenthesis
                else if (currChar.Equals(')'))
                {
                    // while the top of the stack is not a left parenthesis, pop and add to list
                    while (!stack.Peek().Equals('('))
                    {
                        OperatorNode newOpNode = opFact.CreateOperatorNode(stack.Pop());
                        postfixList.Add(newOpNode);
                    }

                    stack.Pop(); // pop the left parenthesis from the top of the stack
                }

                // If the current char is a valid operator
                else if (opFact.IsValidOperator(currChar))
                {
                    // if the stack is empty or the next char is a left parenthesis
                    if (stack.Count <= 0 || stack.Peek().Equals('('))
                    {
                        stack.Push(currChar);
                    }

                    // otherwise the next char on the stack is an operator
                    else
                    {
                        OperatorNode currOpNode = opFact.CreateOperatorNode(currChar);
                        OperatorNode nextOpNode = opFact.CreateOperatorNode(stack.Peek());

                        // if curr operator has > precedence than the next operator, or equal precedence and right associativity
                        if (currOpNode.Precedence > nextOpNode.Precedence ||
                            (currOpNode.Precedence == nextOpNode.Precedence && currOpNode.Associativity == OperatorNode.Associative.Right))
                        {
                            stack.Push(currChar); // push the current operator on the stack
                        }

                        // if curr operator has < precedence than the next operator, or equal precedence and left associativity
                        else
                        {
                            // add the next operator to the list
                            stack.Pop();
                            postfixList.Add(nextOpNode);
                            i--;
                        }
                    }
                }

                // if the current char is a digit (0-9)
                else if (char.IsDigit(currChar))
                {
                    string constantString = currChar.ToString();
                    for (int j = i + 1; j < expressionArray.Length; j++)
                    {
                        currChar = expressionArray[j];

                        // if the next char is a digit, append to constant string
                        if (char.IsDigit(currChar))
                        {
                            constantString += currChar.ToString();
                            i++;
                        }

                        // otherwise the next char is not part of this number
                        else
                        {
                            break;
                        }
                    }

                    postfixList.Add(new ConstantNode(double.Parse(constantString))); // add the complete number to the list
                }

                // if the current char is a variable
                else
                {
                    string variable = currChar.ToString();
                    for (int j = i + 1; j < expressionArray.Length; j++)
                    {
                        currChar = expressionArray[j];

                        // if the next char is not an operator
                        if (!opFact.IsValidOperator(currChar))
                        {
                            variable += expressionArray[j].ToString();
                            i++;
                        }

                        // otherwise the next char is not part of this variable
                        else
                        {
                            break;
                        }
                    }

                    // add the complete variable to the list
                    postfixList.Add(new VariableNode(variable, ref this.variables));

                    // Add the name to variabelNames list if it is not already in it.
                    if (!this.variableNames.Contains(variable))
                    {
                        this.variableNames.Add(variable);
                    }
                }
            }

            // pop and add the rest of the stack to the list
            while (stack.Count > 0)
            {
                OperatorNode newOpNode = opFact.CreateOperatorNode(stack.Pop());
                postfixList.Add(newOpNode);
            }

            return(postfixList);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ExpressionTree"/> class.
        /// </summary>
        /// <param name="expression">The arithmetic expression to be generated.</param>
        public ExpressionTree(string expression)
        {
            bool isSingleNodeTree = true;

            foreach (char op in this.Operators)
            {
                if (expression.Contains(op))
                {
                    isSingleNodeTree = false;
                    break;
                }
            }

            if (isSingleNodeTree)
            {
                try
                {
                    this.singleNodeDouble = Convert.ToDouble(expression);
                }
                catch (Exception)
                {
                    this.singleNodeString = expression;
                }

                return;
            }

            // Generate the postfix notation for the expression.
            string[] postfixArray = this.ConvertToPostfix(expression);

            // Declare local variables.
            Node                  left, right;
            OperatorNode          center;
            Stack <Node>          nodeStack = new Stack <Node>();
            ExpressionTreeFactory etf       = new ExpressionTreeFactory();

            // Iterate through each string in the postfix expression.
            for (int i = 0; i < postfixArray.Length; i++)
            {
                string s = postfixArray[i];

                // Check for an empty string.
                if (s == string.Empty)
                {
                    continue;
                }

                // Operator found!
                if (s.Length == 1 && this.Operators.Contains(s[0]))
                {
                    // Create a new node with the top two nodes of the stack
                    // as children and push it onto the top of the stack.
                    center       = (OperatorNode)etf.CreateNode(s);
                    right        = nodeStack.Pop();
                    left         = nodeStack.Pop();
                    center.Left  = left;
                    center.Right = right;
                    nodeStack.Push(center);
                }
                else
                {
                    nodeStack.Push(etf.CreateNode(s)); // Push a non-operator node onto the stack.
                }
            }

            // Set the new head of the expression tree.
            this.head = (OperatorNode)nodeStack.Peek();
            nodeStack.Pop();
        }
Exemplo n.º 17
0
        /// <summary>
        /// Evaluates the arithmetic logic of an expression tree.
        /// </summary>
        /// <param name="current">The head of the tree to be evaluated.</param>
        /// <returns>Returns the evaluation of the expression tree.</returns>
        private double EvaluateHelper(OperatorNode current)
        {
            // Both children are leaves.
            if (!this.IsOperatorNode(current.Left) && !this.IsOperatorNode(current.Right))
            {
                double leftVal, rightVal;
                if (this.IsVariableNode(current.Left))
                {
                    leftVal = this.variables[current.Left.Value]; // Get left value from dictionary.
                }
                else
                {
                    leftVal = Convert.ToDouble(current.Left.Value); // Get left value from left node.
                }

                if (this.IsVariableNode(current.Right))
                {
                    rightVal = this.variables[current.Right.Value]; // Get right value from dictionary.
                }
                else
                {
                    rightVal = Convert.ToDouble(current.Right.Value); // Get right value from right node.
                }

                return(current.Evaluate(leftVal, rightVal));
            }
            else if (!this.IsOperatorNode(current.Left))
            {
                // Only the right node is an operator node.
                double leftVal;
                if (this.IsVariableNode(current.Left))
                {
                    leftVal = this.variables[current.Left.Value]; // Get left value from dictionary.
                }
                else
                {
                    leftVal = Convert.ToDouble(current.Left.Value); // Get left value from left node.
                }

                return(current.Evaluate(leftVal, this.EvaluateHelper((OperatorNode)current.Right)));
            }
            else if (!this.IsOperatorNode(current.Right))
            {
                // Only the left node is an operator node.
                double rightVal;
                if (this.IsVariableNode(current.Right))
                {
                    rightVal = this.variables[current.Right.Value]; // Get right value from dictionary.
                }
                else
                {
                    rightVal = Convert.ToDouble(current.Right.Value); // Get right value from right node.
                }

                return(current.Evaluate(this.EvaluateHelper((OperatorNode)current.Left), rightVal));
            }
            else
            {
                // Both children are operator nodes.
                OperatorNode leftNode = (OperatorNode)current.Left, rightNode = (OperatorNode)current.Right;
                return(current.Evaluate(this.EvaluateHelper(leftNode), this.EvaluateHelper(rightNode)));
            }
        }
Exemplo n.º 18
0
        private ExpressionTreeBaseNode CreateExpressionTree(string expression)
        {
            Stack <ExpressionTreeBaseNode> operandStack = new Stack <ExpressionTreeBaseNode>();
            int precidence = -1;
            /**********************************************************************/
            // we will parse the expression string into the expression tree here! //
            /**********************************************************************/
            int expressionIndex = 0;

            for (; expressionIndex < expression.Length; expressionIndex++)
            {
                char currentChar = expression[expressionIndex];
                //not an operator
                if (!CheckOperatorPrecidence(currentChar, ref precidence))
                {
                    switch (currentChar)
                    {
                    //Constant (double)
                    case ':':
                        string constantValue = "";
                        expressionIndex++;

                        //traverse expression to grab the entire constant (double), and store in constantValue
                        while (expressionIndex < expression.Length && expression[expressionIndex] != ':')
                        {
                            constantValue += expression[expressionIndex];
                            expressionIndex++;
                        }

                        //create new ConstantNode and pass in the corresponding Value prop.
                        ExpressionTreeBaseNode constantNode = nodeFactory.GetNode("C", constantValue);

                        //convert type to constant node to print the value

                        /*
                         * ConstantNode node = (ConstantNode)constantNode;
                         * Console.WriteLine("constantNode.Value = " + node.Value);
                         */

                        operandStack.Push(constantNode);      //push to operand stack

                        break;

                    //Variable (string)
                    case '{':
                        string variableName = "";
                        expressionIndex++;

                        //traverse expression to grab the entire constant (double), and store in constantValue
                        while (expressionIndex < expression.Length && expression[expressionIndex] != '}')
                        {
                            variableName += expression[expressionIndex];
                            expressionIndex++;
                        }

                        //create new VariableNode and pass in the corresponding Name prop.
                        ExpressionTreeBaseNode variableNode = nodeFactory.GetNode("V", variableName);

                        //convert type to constant node to set the default value
                        VariableNode tempNode = (VariableNode)variableNode;
                        SetVariable(tempNode.Name, 0.0);

                        operandStack.Push(variableNode);     //push to operand stack

                        break;
                    }
                }
                //currentChar is an operator
                else
                {
                    //create new OperatorNode and pass in the corresponding operator prop.
                    ExpressionTreeBaseNode operatorNode = nodeFactory.GetNode("O", currentChar.ToString());

                    //convert type to constant node to print the value
                    OperatorNode tempNode = (OperatorNode)operatorNode;

                    //pop two operands off of the stack
                    ExpressionTreeBaseNode rightNode = operandStack.Pop();
                    ExpressionTreeBaseNode leftNode  = operandStack.Pop();

                    //set operatornode left and right nodes.
                    tempNode.Left  = leftNode;
                    tempNode.Right = rightNode;

                    operandStack.Push(tempNode); //push operator node onto stack
                }
            }

            ExpressionTreeBaseNode expressionTreeRoot = operandStack.Peek(); //expression tree root is top of stack

            operandStack.Pop();                                              //pop top of stack (root)

            return(expressionTreeRoot);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Edsger Dijkstra's Shunting Yard algorithm to convert an infix expression into postfix expression.
        /// </summary>
        /// <param name="infixExpression"> Infix expression. </param>
        /// <returns> Postfix expression. </returns>
        private Queue <Node> ShuntingYardAlgorithm(string infixExpression)
        {
            Queue <Node>         postfixExpression = new Queue <Node>();
            Stack <OperatorNode> operatorStack     = new Stack <OperatorNode>();

            for (int index = 0; index < infixExpression.Length;)
            {
                // Need to create substring until the first operator in the expression is reached.
                string substring = string.Empty;
                int    substringIndex;
                for (substringIndex = index; substringIndex < infixExpression.Length && !ExpressionTreeFactory.MatchesCharacter(infixExpression[substringIndex]); substringIndex++)
                {
                    substring += infixExpression[substringIndex];
                }

                // If the substring is a number then turn that substring into one.
                if (double.TryParse(substring, out double numSubstring))
                {
                    postfixExpression.Enqueue(new ConstantNode()
                    {
                        Value = numSubstring
                    });
                    index = substringIndex;
                }
                else
                {
                    if (ExpressionTreeFactory.MatchesOperator(infixExpression[index]))
                    {
                        OperatorNode op = ExpressionTreeFactory.CreateOperatorNode(infixExpression[index]);
                        try
                        {
                            // If there are operators on the operatorStack with higher precedence than op then they need to be removed from the stack and added to the postfixExpression first.
                            while (operatorStack.Peek().Precedence >= op.Precedence && operatorStack.Peek().Operator != '(')
                            {
                                postfixExpression.Enqueue(operatorStack.Pop());
                            }
                        }
                        catch
                        {
                            // Possible for there to be an empty operatorStack. In that case, nothing happens.
                        }

                        operatorStack.Push(op);
                    }
                    else if (infixExpression[index] == '(')
                    {
                        operatorStack.Push(new OperatorNode('(')
                        {
                            Precedence = 4
                        });
                    }
                    else if (infixExpression[index] == ')')
                    {
                        try
                        {
                            while (operatorStack.Peek().Operator != '(')
                            {
                                postfixExpression.Enqueue(operatorStack.Pop());
                            }
                        }
                        catch
                        {
                            throw new ArgumentException("Missing a left parenthesis");
                        }

                        operatorStack.Pop();
                    }
                    else
                    {
                        // If the substring cannot be parsed as a double (constant) or parentheses then it's a variable.
                        postfixExpression.Enqueue(new VariableNode()
                        {
                            Name = substring
                        });
                        if (!this.Variables.ContainsKey(substring))
                        {
                            this.SetVariable(substring, 0);
                        }

                        index = substringIndex - 1;
                    }

                    index++;
                }
            }

            // End of the expression, popping all operators onto the queue
            while (operatorStack.Count != 0)
            {
                if (operatorStack.Peek().Operator != '(')
                {
                    postfixExpression.Enqueue(operatorStack.Pop());
                }
                else
                {
                    throw new ArgumentException("Missing a right parenthesis");
                }
            }

            return(postfixExpression);
        }
Exemplo n.º 20
0
        public ExpressionTree(string expression)
        {
            this.expression = expression;
            List <Node>         postfixExpression = new List <Node>();
            List <OperatorNode> operatorStack     = new List <OperatorNode>();
            string       variable         = string.Empty;
            string       integer          = string.Empty;
            string       expressionString = string.Empty;
            OperatorNode opNode;

            // create postfix expression from given expression

            // begin by building postfixExpression and operatorStack lists
            for (int i = 0; i < expression.Length; i++)
            {
                if (variable != string.Empty && Char.IsLetterOrDigit(expression[i]))
                {
                    variable += expression[i];
                }
                else if (Char.IsLetter(expression[i]))
                {
                    variable += expression[i];
                }
                else if (variable == string.Empty && Char.IsDigit(expression[i]))
                {
                    integer += expression[i];
                }
                else if (integer != string.Empty && Char.IsDigit(expression[i]))
                {
                    integer += expression[i];
                }
                else if (!Char.IsLetterOrDigit(expression[i]) && (expression[i] != ')') && variable != string.Empty)
                {
                    postfixExpression.Add(new VariableNode(variable));                     // add variable to postfix expression

                    opNode = new OperatorNode(expression[i]);

                    // only do if operator stack is not empty
                    if (operatorStack.Count > 0)
                    {
                        bool overPrecedence = true;

                        // encountered operator or parenthesis, determine what happens next
                        while (overPrecedence == true && operatorStack.Count != 0)
                        {
                            // pop operators from operator stack and push onto list expression if precedence is greater than or equal to operator being pushed onto operator stack
                            if (operatorStack[operatorStack.Count - 1].Precedence <= opNode.Precedence)
                            {
                                postfixExpression.Add(operatorStack[operatorStack.Count - 1]);
                                operatorStack.RemoveAt(operatorStack.Count - 1);
                            }
                            else
                            {
                                overPrecedence = false;
                            }
                        }
                    }

                    operatorStack.Add(opNode);                   // push operator onto operator stack
                    variables.Add(variable, 0);                  // add variable to dictionary, initialize to 0
                    variable = string.Empty;                     // reset variable string to empty, prepare for new variable entry
                }
                else if (!Char.IsLetterOrDigit(expression[i]) && (expression[i] != ')') && integer != string.Empty)
                {
                    postfixExpression.Add(new ConstantNode(double.Parse(integer)));                     // add integer to postfix expression

                    opNode = new OperatorNode(expression[i]);

                    if (operatorStack.Count > 0)
                    {
                        bool overPrecedence = true;

                        // encountered operator or parenthesis, determine what happens next
                        while (overPrecedence == true && operatorStack.Count != 0)
                        {
                            // pop operators from operator stack and push onto list expression if precedence is greater than or equal to operator being pushed onto operator stack
                            if (operatorStack[operatorStack.Count - 1].Precedence <= opNode.Precedence)
                            {
                                postfixExpression.Add(operatorStack[operatorStack.Count - 1]);
                                operatorStack.RemoveAt(operatorStack.Count - 1);
                            }
                            else
                            {
                                overPrecedence = false;
                            }
                        }
                    }

                    operatorStack.Add(opNode);                  // push operator onto operator stack
                    integer = string.Empty;                     // reset integer string to empty, prepare for new integer entry
                }
                else if (expression[i] == '(')
                {
                    operatorStack.Add(new OperatorNode('('));
                }
                else if (expression[i] == ')' && variable != string.Empty)
                {
                    postfixExpression.Add(new VariableNode(variable));                     // add variable to postfix expression

                    if (!variables.ContainsKey(variable))
                    {
                        variables.Add(variable, 0);                         // add variable to dictionary, initialize to 0
                    }

                    variable = string.Empty;                     // reset variable string to empty, prepare for new variable entry

                    // while no left bracket found, pop operators from operator stack onto expression
                    while (operatorStack[operatorStack.Count - 1].Op != '(')
                    {
                        postfixExpression.Add(operatorStack[operatorStack.Count - 1]);
                        operatorStack.RemoveAt(operatorStack.Count - 1);
                    }

                    operatorStack.RemoveAt(operatorStack.Count - 1);                     // remove left bracket from operator stack
                }
                else if (expression[i] == ')' && integer != string.Empty)
                {
                    postfixExpression.Add(new ConstantNode(double.Parse(integer))); // add integer to postfix expression
                    integer = string.Empty;                                         // reset integer string to empty, prepare for new integer entry

                    // while no left bracket found, pop operators from operator stack onto expression
                    while (operatorStack[operatorStack.Count - 1].Op != '(')
                    {
                        postfixExpression.Add(operatorStack[operatorStack.Count - 1]);
                        operatorStack.RemoveAt(operatorStack.Count - 1);
                    }

                    operatorStack.RemoveAt(operatorStack.Count - 1);                     // remove left bracket from operator stack
                }
                else if (expression[i] == ')')
                {
                    // while no left bracket found, pop operators from operator stack onto expression
                    while (operatorStack[operatorStack.Count - 1].Op != '(')
                    {
                        postfixExpression.Add(operatorStack[operatorStack.Count - 1]);
                        operatorStack.RemoveAt(operatorStack.Count - 1);
                    }

                    operatorStack.RemoveAt(operatorStack.Count - 1);                     // remove left bracket from operator stack
                }
                else if (expression[i] == '*' || expression[i] == '+' || expression[i] == '-' || expression[i] == '/')
                {
                    operatorStack.Add(new OperatorNode(expression[i]));                     // adds operator to stack, only used when an operator appears after a ')'
                }

                // takes into account an expression of only one variable or one constant  (ex. "x" or "12")
                if ((i + 1) == expression.Length && variable != string.Empty)
                {
                    variables.Add(variable, 0);
                    postfixExpression.Add(new VariableNode(variable));
                }
                else if ((i + 1) == expression.Length && integer != string.Empty)
                {
                    postfixExpression.Add(new ConstantNode(double.Parse(integer)));
                }
            }

            int operands = postfixExpression.Count;             // keeps track of how many operands in expression

            // pop the rest of the operators off of the operator stack
            for (int j = 0; j < operatorStack.Count; j++)
            {
                int index = operatorStack.Count - 1;

                postfixExpression.Add(operatorStack[index - j]);
            }

            Node        curr      = null; // used to keep track of what node we are on
            int         postIndex = postfixExpression.Count - 1;
            List <Node> markers   = new List <Node>();

            // build tree based on postfixExpression
            while (postIndex >= 0)
            {
                // setting first node
                if (root == null)
                {
                    root = postfixExpression[postIndex]; // set root to first node encountered in list

                    curr = root;                         // set tracker to root after it is created

                    postIndex -= 1;
                }
                else
                {
                    if (postIndex >= 0)
                    {
                        // determine where next node needs to go based on positional criteria
                        if ((curr.Left != null) && (curr.Right != null) && markers.Count != 0 && postIndex == 0)
                        {
                            // Condition: if both left and right nodes are full, there are still markers in marker list, and we are now at the beginning of the postfixExpression
                            // Do: then work back through markers until we've reached needed position and place last node
                            while (curr.Left != null && curr.Right != null)
                            {
                                curr = markers[markers.Count - 1];
                                markers.RemoveAt(markers.Count - 1);
                            }

                            if (curr.Right == null)
                            {
                                curr.Right = postfixExpression[postIndex];
                            }
                            else if (curr.Left == null)
                            {
                                curr.Left = postfixExpression[postIndex];
                            }

                            postIndex -= 1;
                        }
                        else if (!(curr.Left is OperatorNode) && !(curr.Right is OperatorNode) && (curr.Left != null) && (curr.Right != null) && markers.Count != 0)
                        {
                            // Condition: if both left and right nodes are not operators, are not null, and there are markers still in marker list
                            // Do: then move back to the last node that has an open left or right and place next node in open position
                            while (curr.Left != null && curr.Right != null)
                            {
                                curr = markers[markers.Count - 1];
                                markers.RemoveAt(markers.Count - 1);
                            }

                            if (curr.Right == null)
                            {
                                curr.Right = postfixExpression[postIndex];
                                if (curr.Right is OperatorNode)
                                {
                                    curr = curr.Right;
                                }
                            }
                            else if (curr.Left == null)
                            {
                                curr.Left = postfixExpression[postIndex];
                                if (curr.Left is OperatorNode)
                                {
                                    curr = curr.Left;
                                }
                            }

                            postIndex -= 1;
                        }
                        else if (curr is OperatorNode && !(postfixExpression[postIndex] is OperatorNode) && !(postfixExpression[postIndex - 1] is OperatorNode))
                        {
                            // Condition: if we are currently on an operator node, and the next two nodes on postfixExpression are not operators
                            // Do: then add these two nodes to the right and left of our current node
                            curr.Right = postfixExpression[postIndex];
                            curr.Left  = postfixExpression[postIndex - 1];
                            postIndex -= 2;
                        }
                        else if (curr is OperatorNode && postfixExpression[postIndex] is OperatorNode && curr.Right == null)
                        {
                            // Condition: if we are currently on an operator node, and the next node in the expression is an operator, and the current node's right is empty
                            // Do: then add a marker to marker list that tracks current node, add node from expression to right of current node, and move current to the node we just placed
                            markers.Add(curr);                             // drop marker to come back to
                            curr.Right = postfixExpression[postIndex];
                            curr       = curr.Right;
                            postIndex -= 1;
                        }
                        else if ((curr is OperatorNode) && (postfixExpression[postIndex] is OperatorNode) && (curr.Left == null))
                        {
                            // Condition: if our current node is an operator, and the next node in expression is an operator, and the current node's left is empty
                            // Do: then add a marker to marker list that tracks current node, add node from expression to left of current node, and move current to the node we just placed
                            markers.Add(curr);
                            curr.Left  = postfixExpression[postIndex];
                            curr       = curr.Left;
                            postIndex -= 1;
                        }
                        else
                        {
                            // Condition: if none of the other conditional statements matched with conditions
                            // Do: then place the next node in expression to the right of our current node
                            curr.Right = postfixExpression[postIndex];
                            postIndex -= 1;
                        }
                    }
                    else
                    {
                        curr.Right = postfixExpression[postIndex];                         // add node to right
                        postIndex -= 1;
                    }
                }
            }
        }