Exemplo n.º 1
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.º 2
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);
        }