Ejemplo n.º 1
0
        public StaticStack<MathOperation> Convert(string expression)
        {
            StaticStack<MathOperation> Output = new StaticStack<MathOperation>();
            Stack<MathOperation> OperatorStack = new Stack<MathOperation>();
            NumberState NumberState = NumberState.None;

            float CommaMultiplier = 0;
            float minus = 1;
            bool useMinus = true;
            for (int i = 0; i < expression.Length; i++)
            {
                char token = expression[i];
                if (char.IsWhiteSpace(token))
                {
                    //fixes 5 2 = 52
                    //new bug: 5 2 + = 7 (infix)
                    NumberState = NumberState.None;
                    continue;
                }
                if(token == '-')
                {
                    if (useMinus)
                    {
                        minus = -1;
                        continue;
                    }
                }
                if (char.IsDigit(token))
                {
                    float numeric = (float)char.GetNumericValue(token);
                    switch (NumberState)
                    {
                        case NumberState.None:
                            Output.Push((Number)(numeric * minus));
                            NumberState = NumberState.Number;
                            break;
                        case NumberState.Number:
                            float num = (Number)Output.PopReal();
                            Output.Push((Number)(num * 10.0 + numeric * NonNullSign(num)));
                            break;
                        case NumberState.Comma:
                            float num2 = (Number)Output.PopReal();
                            Output.Push((Number)(num2 + numeric * CommaMultiplier * NonNullSign(num2)));
                            CommaMultiplier *= 0.1f;
                            break;
                        default:
                            throw new NotImplementedException();
                    }
                    minus = 1;
                    useMinus = false;
                }
                else if (token == '.')
                {
                    minus = 1;
                    NumberState = NumberState.Comma;
                    CommaMultiplier = 0.1f;
                }
                else if (token == ',')
                {
                    NumberState = NumberState.None;

                    if (OperatorStack.Count == 0)
                        throw new MismatchedParenthesisException("\"" + expression.Substring(i) + "\": Can't find opening parenthesis");
                    while (OperatorStack.Count > 0)
                    {
                        if (OperatorStack.Peek() is Parenthesis)
                            break;
                        Output.Push(OperatorStack.Pop());
                    }
                    if (OperatorStack.Count == 0 || !(OperatorStack.Peek() is Parenthesis))
                        throw new MismatchedParenthesisException("\"" + expression.Substring(i) + "\": Can't find opening parenthesis");

                }
                else if (token == ')')
                {
                    if (OperatorStack.Count == 0)
                        throw new MismatchedParenthesisException("\"" + expression.Substring(i) + "\": Can't find opening parenthesis");
                    while (OperatorStack.Count > 0)
                    {
                        MathOperation TopOperator = OperatorStack.Pop();
                        if (TopOperator is Parenthesis)
                            break;
                        else
                            Output.Push(TopOperator);
                        if (OperatorStack.Count == 0)
                            throw new MismatchedParenthesisException("\"" + expression.Substring(i) + "\": Can't find opening parenthesis");
                    }
                    if (OperatorStack.Count > 0 && OperatorStack.Peek() is Function)
                        Output.Push(OperatorStack.Pop());
                    useMinus = false;
                }
                else if (char.IsSymbol(token) || char.IsPunctuation(token))
                {
                    string fullname = "";
                    for (; i < expression.Length; i++)
                    {
                        char letter = expression[i];
                        if ((char.IsSymbol(letter) || char.IsPunctuation(letter)))
                            //we cant use letters or 5 + sin(x) is going to break
                            fullname += char.ToLower(letter);
                        else
                        {
                            --i;
                            break;
                        }
                        if (m_Operators.ContainsKey(fullname))
                            break;
                    }
                    if (m_Operators.ContainsKey(fullname))
                    {
                        MathOperation TokenOperator = m_Operators[fullname];
                        if (NumberState != MathState.NumberState.None)
                        {
                            NumberState = NumberState.None;
                            if (TokenOperator is Parenthesis)
                            {
                                // makes 5(x) possible
                                OperatorStack.Push(new MathOperations.Operators.Multiplication());
                            }
                        }
                        while (OperatorStack.Count > 0)
                        {
                            MathOperation TopOperator = OperatorStack.Peek();
                            if (TokenOperator.Association == Association.Left && TokenOperator.Precedence <= TopOperator.Precedence)
                                Output.Push(OperatorStack.Pop());
                            else if (TokenOperator.Association == Association.Right && TokenOperator.Precedence < TopOperator.Precedence)
                                Output.Push(OperatorStack.Pop());
                            else
                                break;
                        }
                        OperatorStack.Push(TokenOperator);
                    }
                    useMinus = true;
                }
                else if (char.IsLetter(token))
                {
                    minus = 1;
                    string fullname = "";
                    for (; i < expression.Length; i++)
                    {
                        char letter = expression[i];
                        if (char.IsLetter(letter))
                            fullname += char.ToLower(letter);
                        else
                        {
                            --i;
                            break;
                        }
                    }
                    if (NumberState != MathState.NumberState.None)
                    {
                        NumberState = NumberState.None;
                        OperatorStack.Push(new MathOperations.Operators.Multiplication());
                    }
                    if (m_Functions.ContainsKey(fullname))
                        OperatorStack.Push(m_Functions[fullname]);
                    else if (m_Variables.ContainsKey(fullname))
                    {
                        Output.Push(new Variable(fullname, m_Variables));
                    }
                    else if (m_Constants.ContainsKey(fullname))
                    {
                        Output.Push(new Constant(fullname, m_Constants[fullname]));
                    }
                    else if (DefineUnknownVariables)
                        Output.Push(new Variable(fullname,m_Variables));
                    else
                        throw new UndefinedFunctionException("Function \"" + fullname + "\" not defined");
                    useMinus = false;
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
            while (OperatorStack.Count > 0)
            {
                if (OperatorStack.Peek() is Parenthesis)
                    throw new MismatchedParenthesisException("Can't find closing parenthesis");
                Output.Push(OperatorStack.Pop());
            }
            return Output;
        }