Exemplo n.º 1
0
        /// <summary>
        /// Gets Associvity for respective operator from dictionary using Reflection
        /// </summary>
        /// <param name="op">Operator Character</param>
        /// <returns>Associativity enum Left or Right</returns>
        public OperatorExpressionTreeNode.Associativity GetAssociativity(char op)
        {
            OperatorExpressionTreeNode.Associativity associativityValue = OperatorExpressionTreeNode.Associativity.COUNT;
            if (validOperators.ContainsKey(op))
            {
                Type         type         = validOperators[op];
                PropertyInfo propertyInfo = type.GetProperty("Associativity");
                if (propertyInfo != null)
                {
                    object propertyValue = propertyInfo.GetValue(type);
                    if (propertyValue is OperatorExpressionTreeNode.Associativity)
                    {
                        associativityValue = (OperatorExpressionTreeNode.Associativity)propertyValue;
                    }
                }
            }

            return(associativityValue);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Converts infix expression to postfix expression
        /// </summary>
        /// <param name="expression">infix expression</param>
        /// <returns>Postfix expression as list of strings</returns>
        private List <string> ConvertToPostfix(string expression)
        {
            // Dijkstra's Shunting Yard Algorithm

            // Save output as a list of substrings in postfix notation
            List <string> postfixExpression = new List <string>();
            Stack <char>  operatorStack     = new Stack <char>();

            // Remove whitespace from infix expression
            expression = expression.Replace(" ", string.Empty);

            // Set start point for new operand
            int operandStartIndex = -1;

            // Iterate per character to decide what to do
            for (int i = 0; i < expression.Length; i++)
            {
                // If character belongs to a new operand, set the starting point
                if (!this.IsOperatorOrParenthesis(expression[i]))
                {
                    if (operandStartIndex == -1)
                    {
                        operandStartIndex = i;
                    }
                }
                else
                {
                    // If character is an operator or parenthesis push any started operand to the list
                    if (operandStartIndex != -1)
                    {
                        // Operand has ended and should be added to the list from start point to current position
                        postfixExpression.Add(expression.Substring(operandStartIndex, i - operandStartIndex));

                        // Reset start point for next operand
                        operandStartIndex = -1;
                    }

                    // If character is left parenthesis, push to the stack
                    if (this.IsLeftParenthesis(expression[i]))
                    {
                        operatorStack.Push(expression[i]);
                    }

                    // If character is a right parenthesis
                    else if (this.IsRightParenthesis(expression[i]))
                    {
                        // Discard right parenthesis and pop from stack until left parenthesis is reached
                        while (!this.IsLeftParenthesis(operatorStack.Peek()))
                        {
                            // Add popped operators as substrings to the list
                            postfixExpression.Add(operatorStack.Pop().ToString());
                        }

                        // Discard the matching left parenthesis
                        operatorStack.Pop();
                    }

                    // If character is an operator
                    else if (operatorFactory.IsValidOperator(expression[i]))
                    {
                        // If the stack is empty or top is left parenthesis
                        if (!operatorStack.Any() || this.IsLeftParenthesis(operatorStack.Peek()))
                        {
                            operatorStack.Push(expression[i]);
                        }

                        // If top of stack is an operator
                        else if (operatorFactory.IsValidOperator(operatorStack.Peek()))
                        {
                            ushort expressionPrecedence = operatorFactory.GetPrecedence(expression[i]);
                            ushort stackPrecedence      = operatorFactory.GetPrecedence(operatorStack.Peek());
                            OperatorExpressionTreeNode.Associativity expressionAssociativity = operatorFactory.GetAssociativity(expression[i]);

                            // If incoming operator has higher precdence OR equal precedence AND is Right Associative: push the incoming operator to the stack
                            if (expressionPrecedence < stackPrecedence || (expressionPrecedence == stackPrecedence && expressionAssociativity == OperatorExpressionTreeNode.Associativity.RIGHT))
                            {
                                operatorStack.Push(expression[i]);
                            }
                            else
                            {
                                // If the incoming operator has lower precedence OR equal precedence AND is Left Associative pop from the stack until this is no longer true
                                while (operatorStack.Any() &&
                                       ((operatorFactory.IsValidOperator(operatorStack.Peek()) &&
                                         expressionPrecedence > operatorFactory.GetPrecedence(operatorStack.Peek())) ||
                                        (expressionPrecedence == operatorFactory.GetPrecedence(operatorStack.Peek()) &&
                                         expressionAssociativity == OperatorExpressionTreeNode.Associativity.LEFT)))
                                {
                                    // Add popped operators as substrings to the list
                                    postfixExpression.Add(operatorStack.Pop().ToString());
                                }

                                // Push the incoming operator after the stack has been adjusted
                                operatorStack.Push(expression[i]);
                            }
                        }
                    }
                }
            }

            // If at the end of the expression an operand was started, push it to the output list
            if (operandStartIndex != -1)
            {
                postfixExpression.Add(expression.Substring(operandStartIndex, expression.Length - operandStartIndex));
            }

            // At the end of the expression, pop all remaining symbols from the stack
            while (operatorStack.Count > 0)
            {
                postfixExpression.Add(operatorStack.Pop().ToString());
            }

            // Returns postfix expression as a list of substrings
            return(postfixExpression);
        }