예제 #1
0
        static double SolveRPN(List <MathToken> RPN)    //pushes numbers onto the stack, resolves functions and operators with those numbers, pushes the result back on, and so forth,
        {                                               // until there's (hopefully) one number and no operators left
            Stack <double> operands = new Stack <double>();

            foreach (MathToken t in RPN)
            {
                if (t.GetType() == typeof(OperatorToken))
                {
                    OperatorToken o = (OperatorToken)t;
                    if (operands.Count >= 2) //binary operators need at least 2 numbers
                    {
                        double b      = operands.Pop();
                        double a      = operands.Pop();
                        double result = o.Operator(a, b);
                        operands.Push(result);
                    }
                    else
                    {
                        throw new SyntaxException("Not enough operands");
                    }
                }
                else if (t.GetType() == typeof(NumberToken))
                {
                    NumberToken n = (NumberToken)t;
                    operands.Push(n.NumberValue);
                }
                else if (t.GetType() == typeof(FunctionToken))
                {
                    FunctionToken f = (FunctionToken)t;
                    if (operands.Count >= 1) //this only rules out an empty stack
                    {
                        double a      = operands.Pop();
                        double result = f.Function(a);
                        operands.Push(result);
                    }
                    else
                    {
                        throw new SyntaxException("Not enough operands");
                    }
                }
            }
            if (operands.Count > 1) //if we're left with more than one number and no operators
            {
                throw new SyntaxException("Not enough operators");
            }
            else
            {
                return(operands.Pop());
            }
        }
예제 #2
0
        static List <MathToken> ShuntingYard(List <MathToken> calc) //algorithm by Edsger Dijkstra to turn (possibly) ambiguous infix notation into (much easier to parse) reverse Polish notation
        {
            List <MathToken>  output = new List <MathToken>();
            Stack <MathToken> stack  = new Stack <MathToken>();

            foreach (MathToken t in calc)
            {
                if (t.GetType() == typeof(NumberToken))
                {
                    output.Add(t);
                }
                else if (t.GetType() == typeof(FunctionToken))
                {
                    stack.Push(t);
                }
                else if (t.GetType() == typeof(OperatorToken))
                {
                    while (stack.Count > 0)
                    {
                        if (stack.Peek().GetType() == typeof(FunctionToken))
                        {
                            output.Add(stack.Pop());
                        }
                        else if (stack.Peek().GetType() == typeof(OperatorToken))
                        {
                            OperatorToken stackoper = (OperatorToken)stack.Peek();
                            OperatorToken inputoper = (OperatorToken)t;
                            if (stackoper.Precedence >= inputoper.Precedence)
                            {
                                output.Add(stack.Pop());
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    stack.Push(t);
                }
                else if (t.GetType() == typeof(BracketToken))
                {
                    BracketToken b = (BracketToken)t;
                    if (b.IsLeft)
                    {
                        stack.Push(t);
                    }
                    else
                    {
                        try
                        {
                            while (true)
                            {
                                if (stack.Peek().GetType() == typeof(BracketToken))
                                {
                                    BracketToken bracket = (BracketToken)stack.Peek();
                                    if (bracket.IsLeft)
                                    {
                                        stack.Pop();
                                        break;
                                    }
                                }
                                output.Add(stack.Pop());
                            }
                        }
                        catch (InvalidOperationException) //if it runs out of stack without finding an opening bracket
                        {
                            throw new SyntaxException("Mismatched parentheses");
                        }
                    }
                }
                else //this should probably go, since every type of token is accounted for
                {
                    throw new SyntaxException("Something went horribly wrong");
                }
            }
            while (stack.Count > 0) //when all input is read, move the stack to the output
            {
                MathToken t = stack.Pop();
                if (t.GetType() == typeof(BracketToken)) //if it finds an opening bracket that was never closed
                {
                    BracketToken b = (BracketToken)t;
                    if (b.IsLeft)
                    {
                        throw new SyntaxException("Mismatched parentheses");
                    }
                }
                else
                {
                    output.Add(t);
                }
            }
            if (output.Count == 0) //it looks like acceptable input, but once you take the brackets out, you're left with nothing
            {
                throw new SyntaxException("Nothing but parentheses?");
            }
            return(output);
        }