// Syntax analysis of reverse polish notation expression
    private Stack <double> SyntaxAnalysisRPN(Stack <double> stack, string token)
    {
        // if it's operand then just push to stack
        if (token[0] == NumberMarker[0])
        {
            stack.Push(double.Parse(token.Remove(0, 1)));
        }

        // otherwise apply operator or funtion to elements in stack
        else if (NumberOfArguments(token) == 1)
        {
            double        argument = stack.Pop();
            NumExpression arg      = new NumExpression(argument);
            if (!isRadians)
            {
                argument = argument * Math.PI / 180; // Convert value to degree
            }
            NumExpression trigArg = new NumExpression(argument);
            double        result;

            switch (token)
            {
            case UnaryPlus:
                result = arg.evaluate();
                break;

            case UnaryMinus:
                NegateExpresion neg = new NegateExpresion(arg);
                result = neg.evaluate();
                break;

            case Sqrt:
                SqrtExpression sqrt = new SqrtExpression(arg);
                result = sqrt.evaluate();
                break;

            case Log:
                LogarithmExpression log = new LogarithmExpression(arg);
                result = log.evaluate();
                break;

            case Ln:
                LnExpression ln = new LnExpression(arg);
                result = ln.evaluate();
                break;

            case Sin:
                SinExpression sin = new SinExpression(trigArg);
                result = sin.evaluate();
                break;

            case Cos:
                CosExpression cos = new CosExpression(trigArg);
                result = cos.evaluate();
                break;

            case Tan:
                TanExpression tan = new TanExpression(trigArg);
                result = tan.evaluate();
                break;

            case Csc:
                CscExpression csc = new CscExpression(trigArg);
                result = csc.evaluate();
                break;

            case Sec:
                SecExpression sec = new SecExpression(trigArg);
                result = sec.evaluate();
                break;

            case Cot:
                CotExpression cot = new CotExpression(trigArg);
                result = cot.evaluate();
                break;

            default:
                throw new ArgumentException("Unknown operator");
            }
            stack.Push(result);
        }
        else
        {
            // otherwise operator's number of arguments equal to 2
            double        argument2 = stack.Pop();
            double        argument1 = stack.Pop();
            NumExpression arg1      = new NumExpression(argument1);
            NumExpression arg2      = new NumExpression(argument2);
            double        result;

            switch (token)
            {
            case Plus:
                AdditionExpression add = new AdditionExpression(arg1, arg2);
                result = add.evaluate();
                break;

            case Minus:
                MinusExpression minus = new MinusExpression(arg1, arg2);
                result = minus.evaluate();
                break;

            case Multiply:
                MultiplyExpression multiply = new MultiplyExpression(arg1, arg2);
                result = multiply.evaluate();
                break;

            case Divide:
                if (argument2 == 0)
                {
                    throw new DivideByZeroException("Second argument is zero");
                }
                DivideExpression divide = new DivideExpression(arg1, arg2);
                result = divide.evaluate();
                break;

            case Mod:
                ModExpression mod = new ModExpression(arg1, arg2);
                result = mod.evaluate();
                break;

            case Exponent:
                ExpononetExpression exp = new ExpononetExpression(arg1, arg2);
                result = exp.evaluate();
                break;

            default: throw new ArgumentException("Unknown operator");
            }
            stack.Push(result);
        }
        return(stack);
    }
    public override List <TestResult> run()
    {
        //Do some tests, make results, pass back a list

        List <TestResult> results = new List <TestResult>();

        double     expected = 5.0;
        Expression expr     = new AtomicExpression(expected);
        double     actual   = expr.evaluate();
        TestResult res      = new TestResult("Atomic Positive Int", expected, actual, compare(expected, actual));

        results.Add(res);

        expected = -5.0;
        expr     = new AtomicExpression(expected);
        actual   = expr.evaluate();
        res      = new TestResult("Atomic Negative Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 0;
        expr     = new AtomicExpression(expected);
        actual   = expr.evaluate();
        res      = new TestResult("Atomic 0 Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 5.0;
        expr     = new ParenExpression(new AtomicExpression(expected));
        actual   = expr.evaluate();
        res      = new TestResult("Paren Positive Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = -5.0;
        expr     = new ParenExpression(new AtomicExpression(expected));
        actual   = expr.evaluate();
        res      = new TestResult("Paren Positive Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 0;
        expr     = new ParenExpression(new AtomicExpression(expected));
        actual   = expr.evaluate();
        res      = new TestResult("Paren 0 Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 7;
        expr     = new AddExpression(new AtomicExpression(5), new AtomicExpression(2));
        actual   = expr.evaluate();
        res      = new TestResult("Add Positive Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 3;
        expr     = new SubtractExpression(new AtomicExpression(5), new AtomicExpression(2));
        actual   = expr.evaluate();
        res      = new TestResult("Subtract Postive Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 10;
        expr     = new MultiplyExpression(new AtomicExpression(5), new AtomicExpression(2));
        actual   = expr.evaluate();
        res      = new TestResult("Multiply Positive Int", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 2.5;
        expr     = new DivideExpression(new AtomicExpression(5), new AtomicExpression(2));
        actual   = expr.evaluate();
        res      = new TestResult("Divide Positive Float", expected, actual, compare(expected, actual));
        results.Add(res);

        expected = 25;
        expr     = new ExponentExpression(new AtomicExpression(5), new AtomicExpression(2));
        actual   = expr.evaluate();
        res      = new TestResult("Exponent Positive Float", expected, actual, compare(expected, actual));
        results.Add(res);

        return(results); //I can be reasonably certain they won't mess up in different circumstances. It's just wrappers for primitive expressions.
    }