public PostfixItem(PostfixItem NewItem)
 {
     this.state = NewItem.state;
     this.constant = NewItem.constant;
     this.functions = NewItem.functions;
     this.vars = NewItem.vars;
     this.knownconst = NewItem.knownconst;
 }
예제 #2
0
        /// <summary>
        /// Validate postfix representation of the arithmetic expression
        /// </summary>
        private void ValidatePostfix()
        {
            PostfixItem[] copy = new PostfixItem[postfix.Length];
            postfix.CopyTo(copy, 0);

            int i;

            for (i = copy.Length - 1; i >= 0; i--)
            {
                if (copy[i] is Operator)
                {
                    int i2 = FindFirstUsableIndex(copy, i);
                    int i1 = FindFirstUsableIndex(copy, i2);

                    // Probably shouldn't happen...
                    if (i1 == -1 || i2 == -1)
                    {
                        throw new FormatException();
                    }

                    copy[i]  = new Constant();
                    copy[i1] = null;
                    copy[i2] = null;
                }
                else if (copy[i] is OperatorUnary)
                {
                    int i1 = FindFirstUsableIndex(copy, i);

                    // Probably shouldn't happen...
                    if (i1 == -1)
                    {
                        throw new FormatException();
                    }

                    copy[i]  = new Constant();
                    copy[i1] = null;
                }
            }

            int numberCount = 0;

            while (++i < copy.Length)
            {
                if (copy[i] is Constant || copy[i] is Variable)
                {
                    numberCount++;
                }
            }

            // Probably shouldn't happen...
            if (numberCount != 1)
            {
                throw new FormatException();
            }
        }
예제 #3
0
        /// <summary>
        /// Parses operator
        /// </summary>
        /// <param name="input">Input character</param>
        /// <param name="precedingItem">Preceding item type</param>
        /// <param name="postfixStack">Postfix stack</param>
        /// <param name="operatorsStack">Operators stack</param>
        /// <returns>Returns true if successful; false, otherwise</returns>
        private bool ParseOperator(char input, ref PrecedingItem precedingItem, Stack <PostfixItem> postfixStack, Stack <PostfixItem> operatorsStack)
        {
            string name = char.ToString(input);

            OperatorCallbacks.OperatorFunction function = ResolveOperator(name);
            if (function != null)
            {
                if (precedingItem == PrecedingItem.Operator || precedingItem == PrecedingItem.OperatorUnary ||
                    precedingItem == PrecedingItem.ParenthesesStart)
                {
                    return(false);
                }

                while (operatorsStack.Count > 0)
                {
                    PostfixItem current = operatorsStack.Peek();

                    if (current is InternalCommandBlock)
                    {
                        break;
                    }

                    Operator op;
                    if ((op = current as Operator) != null && IsHigherPrecedence(op.Name, name))
                    {
                        break;
                    }

                    OperatorUnary opu;
                    if ((opu = current as OperatorUnary) != null && IsHigherPrecedence(opu.Name, name))
                    {
                        break;
                    }

                    operatorsStack.Pop();
                    postfixStack.Push(current);
                }

                operatorsStack.Push(new Operator {
                    Name     = name,
                    Function = function
                });

                precedingItem = PrecedingItem.Operator;
                return(true);
            }

            return(false);
        }
예제 #4
0
        /// <summary>
        /// Resolves value of given constant or variable
        /// </summary>
        /// <param name="item">Item to resolve</param>
        /// <param name="x">Value of variable</param>
        /// <returns>Value</returns>
        private static double GetValue(PostfixItem item, double x)
        {
            if (item is Variable)
            {
                return(x);
            }

            Constant c;

            if ((c = item as Constant) != null)
            {
                return(c.Value);
            }
            return(double.NaN);
        }
예제 #5
0
        public double Evaluate(double x)
        {
            PostfixItem[] copy = new PostfixItem[postfix.Length];
            postfix.CopyTo(copy, 0);

            int i;

            for (i = copy.Length - 1; i >= 0; i--)
            {
                Operator      op;
                OperatorUnary opu;

                if ((op = copy[i] as Operator) != null)
                {
                    int i2 = FindFirstUsableIndex(copy, i);
                    int i1 = FindFirstUsableIndex(copy, i2);

                    // (i1 == -1 || i2 == -1) is already validated

                    double value1 = GetValue(copy[i1], x);
                    double value2 = GetValue(copy[i2], x);

                    double value = op.Function(value1, value2);

                    copy[i] = new Constant {
                        Value = value
                    };

                    copy[i1] = null;
                    copy[i2] = null;
                }
                else if ((opu = copy[i] as OperatorUnary) != null)
                {
                    int i1 = FindFirstUsableIndex(copy, i);

                    // (i1 == -1) is already validated

                    double value1 = GetValue(copy[i1], x);

                    double value = opu.Function(value1);

                    copy[i] = new Constant {
                        Value = value
                    };

                    copy[i1] = null;
                }
            }

            while (++i < copy.Length)
            {
                Constant c;
                if ((c = copy[i] as Constant) != null)
                {
                    return(c.Value);
                }

                if (copy[i] is Variable)
                {
                    return(x);
                }
            }

            return(double.NaN);
        }
예제 #6
0
        /// <summary>
        /// Parse infix representation to postfix representation
        /// </summary>
        /// <param name="input">Infix representation of arithmetic expression</param>
        private unsafe void ParseToPostfix(string input)
        {
            variableName = null;

            Stack <PostfixItem> postfixStack   = new Stack <PostfixItem>();
            Stack <PostfixItem> operatorsStack = new Stack <PostfixItem>();

            int           level     = 0;
            PrecedingItem preceding = PrecedingItem.ParenthesesStart;

            int length = input.Length;

            fixed(char *ptr = input)
            {
                for (int i = 0; i < length; i++)
                {
                    if (char.IsDigit(ptr[i]) || ptr[i] == '.' ||
                        ((preceding == PrecedingItem.Operator || preceding == PrecedingItem.ParenthesesStart) && (ptr[i] == '-' || ptr[i] == '+')))
                    {
                        // Number
                        if (preceding == PrecedingItem.Number || preceding == PrecedingItem.OperatorUnary || preceding == PrecedingItem.ParenthesesEnd)
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                        }

                        double number = ExtractNumber(ptr, length, ref i);
                        if (double.IsNaN(number))
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.InvalidNumber);
                        }

                        postfixStack.Push(new Constant {
                            Value = number
                        });

                        preceding = PrecedingItem.Number;
                    }
                    else if (char.IsLetter(ptr[i]))
                    {
                        // Function/constant/variable
                        string name = ExtractName(ptr, length, ref i);
                        OperatorCallbacks.OperatorUnaryFunction function = ResolveOperatorUnary(name);
                        if (function != null)
                        {
                            if (preceding == PrecedingItem.OperatorUnary || preceding == PrecedingItem.ParenthesesEnd)
                            {
                                throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                            }

                            // Insert multiply between number and function
                            if (preceding == PrecedingItem.Number)
                            {
                                ParseOperator('*', ref preceding, postfixStack, operatorsStack);
                            }

                            operatorsStack.Push(new OperatorUnary {
                                Name     = name,
                                Function = function
                            });

                            preceding = PrecedingItem.OperatorUnary;
                        }
                        else
                        {
                            if (preceding == PrecedingItem.OperatorUnary || preceding == PrecedingItem.ParenthesesEnd)
                            {
                                throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                            }

                            // Insert multiply between number and constant/variable
                            if (preceding == PrecedingItem.Number)
                            {
                                ParseOperator('*', ref preceding, postfixStack, operatorsStack);
                            }

                            if (name == "e" || name == "E")
                            {
                                postfixStack.Push(new Constant {
                                    Value = callbacks.E
                                });
                            }
                            else if (name == "pi" || name == "PI")
                            {
                                postfixStack.Push(new Constant {
                                    Value = callbacks.PI
                                });
                            }
                            else
                            {
                                if (variableName != null && variableName != name)
                                {
                                    throw new SyntaxException(input, i - name.Length + 1, SyntaxException.Type.DistinctVariableCountExceeded);
                                }

                                postfixStack.Push(new Variable());

                                variableName = name;
                            }

                            preceding = PrecedingItem.Number;
                        }
                    }
                    else if (ptr[i] == '(')
                    {
                        // Open parenthesis
                        if (preceding == PrecedingItem.Number || preceding == PrecedingItem.ParenthesesEnd)
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                        }

                        operatorsStack.Push(new InternalCommandBlock {
                            Value = "("
                        });

                        preceding = PrecedingItem.ParenthesesStart;
                        level++;
                    }
                    else if (ptr[i] == ')')
                    {
                        // Close parenthesis
                        if (preceding == PrecedingItem.Operator || preceding == PrecedingItem.OperatorUnary ||
                            preceding == PrecedingItem.ParenthesesStart)
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                        }

                        while (operatorsStack.Count > 0)
                        {
                            InternalCommandBlock commandBlock = operatorsStack.Peek() as InternalCommandBlock;
                            if (commandBlock != null && commandBlock.Value == "(")
                            {
                                break;
                            }

                            PostfixItem item = operatorsStack.Pop();
                            postfixStack.Push(item);
                        }

                        if (operatorsStack.Count == 0)
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.ParenthesesCountMismatch);
                        }

                        operatorsStack.Pop();

                        preceding = PrecedingItem.ParenthesesEnd;
                        level--;
                    }
                    else if (ptr[i] == '#')
                    {
                        // Comment
                        break;
                    }
                    else if (ptr[i] != ' ')
                    {
                        // Operator
                        if (!ParseOperator(ptr[i], ref preceding, postfixStack, operatorsStack))
                        {
                            throw new SyntaxException(input, i, SyntaxException.Type.Unknown);
                        }
                    }
                }
            }

            // Check proper ending of arithmetic expression
            if (level > 0)
            {
                throw new SyntaxException(input, input.Length - 1, SyntaxException.Type.ParenthesesCountMismatch);
            }
            if (preceding == PrecedingItem.Operator || preceding == PrecedingItem.OperatorUnary || preceding == PrecedingItem.ParenthesesStart)
            {
                throw new SyntaxException(input, input.Length - 1, SyntaxException.Type.Unknown);
            }

            // Empty "operators" stack
            while (operatorsStack.Count > 0)
            {
                PostfixItem item = operatorsStack.Pop();
                postfixStack.Push(item);
            }

            postfix = postfixStack.ToArray();
        }