예제 #1
0
        /// <summary>
        /// Parses an infix String expression and creates a parse tree of Node's.
        /// </summary>
        /// <remarks>
        /// This is the heart of the parser, it takes a normal expression and creates
        /// a datastructure we can easily recurse when evaluating.
        ///
        /// The datastructure is then evaluated by the toValue method.
        /// </remarks>
        /// <param name="exp">the infix string expression to process</param>
        /// <returns>A tree datastructure of Node objects representing the expression</returns>
        private Node parse( String exp )
        {
            int i , ma , len;
            String farg , sarg , fop;
            Node tree = null;

            farg = sarg = fop = "";
            ma = i = 0;

            len = exp.Length;

            if( len == 0  )
            {
                throw new System.Exception("Wrong number of arguments to operator");
            }
            else if( exp[ 0 ] == '(' && (( ma = match( exp , 0 ) ) == ( len - 1 ) ) )
            {
                return( parse( exp.Substring( 1 , ma - 1 ) ));
            }
            else if( isVariable( exp ) )
            {
                return( new Node( exp ) );
            }
            else if( isAllNumbers( exp ) )  // this is really the only place where isAllNumbers matters.
            {
                try
                {
                    return( new Node( DoubleParse( exp ) ) );
                }
                catch( FormatException )
                {
                    throw new System.Exception( "Syntax error-> " + exp + " (not using regional decimal separator?)" );
                }
            }

            while( i < len )
            {
                if( ( fop = getOp( exp , i ) ) == null )
                {
                    farg = arg( null, exp, i );
                    fop  = getOp( exp, i + farg.Length );

                    if( fop == null ) throw new Exception( "Missing operator" );

                    if( isTwoArgOp( fop ) )
                    {
                        sarg = arg( fop , exp, i + farg.Length + fop.Length );
                        if( sarg.Equals( "" ) ) throw new Exception( "Wrong number of arguments to operator " + fop );
                        tree = new Node( fop , parse( farg ) , parse( sarg ) );
                        i += farg.Length + fop.Length + sarg.Length;
                    }
                    else
                    {
                        if( farg.Equals( "" ) ) throw new Exception( "Wrong number of arguments to operator " + fop );
                        tree = new Node( fop , parse( farg ) );
                        i += farg.Length + fop.Length;
                    }

                }
                else
                {
                    if( isTwoArgOp( fop ) )
                    {
                        farg = arg( fop, exp, i + fop.Length );
                        if( farg.Equals( "" ) ) throw new Exception( "Wrong number of arguments to operator " + fop );
                        if( tree == null )
                        {
                            if( fop.Equals( "+" ) || fop.Equals( "-" ) )
                            {
                                tree = new Node( 0D );
                            }
                            else
                            {
                                throw new Exception( "Wrong number of arguments to operator " + fop );
                            }
                        }
                        tree = new Node( fop, tree, parse( farg ) );
                        i += farg.Length + fop.Length;

                    }
                    else
                    {
                        farg = arg( fop, exp, i + fop.Length );
                        if( farg.Equals( "" ) ) throw new Exception( "Wrong number of arguments to operator " + fop );
                        tree = new Node( fop , parse( farg ) );
                        i += farg.Length + fop.Length;

                    }
                }

            }

            return tree;
        }
예제 #2
0
        /// <summary>
        /// Parses the datastructure created by the parse method.
        /// </summary>
        /// <remarks>
        /// This is where the actual evaluation of the expression is made,
        /// the Node tree structure created by the parse method is recursed and evaluated
        /// to a double value.
        /// </remarks>
        /// <param name="tree">A Node representing a tree datastructure</param>
        /// <returns>A double value</returns>
        private double toValue( Node tree )
        {
            Node arg1, arg2;
            double val;
            String op, tmp;

            if( tree.getType() == Node.TYPE_CONSTANT )
            {
                return( tree.getValue() );
            }
            else if( tree.getType() == Node.TYPE_VARIABLE )
            {
                tmp = tree.getVariable();

                // check if PI, Euler....etc
                if( spconst.ContainsKey( tmp ) )
                {
                    return( (double)spconst[ tmp ] );
                }

                // normal variable, get value
                return GetVariable( tmp );

            //				if( isConstant( tmp ) )
            //				{
            //					return( Double.Parse( tmp ) );
            //				}
            //				else
            //				{
            //					Syntax( tmp );
            //					return( toValue( parse( putMult( parseE( tmp ) ) ) ) );
            //				}
            }

            op   = tree.getOperator();
            arg1 = tree.arg1();

            if( tree.arguments() == 2 )
            {
                arg2 = tree.arg2();

                if( op.Equals( "+" ) )
                    return( toValue(arg1) + toValue(arg2));
                else if( op.Equals( "-" ) )
                    return( toValue(arg1) - toValue(arg2));
                else if( op.Equals( "*" ) )
                    return( toValue(arg1) * toValue(arg2));
                else if( op.Equals( "/" ) )
                    return( toValue(arg1) / toValue(arg2));
                else if( op.Equals( "^" ) )
                    return( Math.Pow(toValue(arg1),toValue(arg2)));
                else if( op.Equals( "log" ) )
                    return( Math.Log(toValue(arg2)) / Math.Log(toValue(arg1)) );
                else if( op.Equals( "%" ) )
                    return( toValue(arg1) % toValue(arg2));
                else if( op.Equals( "==" ) )
                    return( toValue(arg1) == toValue(arg2) ? 1.0 : 0.0 );
                else if( op.Equals( "!=" ) )
                    return( toValue(arg1) != toValue(arg2) ? 1.0 : 0.0  );
                else if( op.Equals( "<" ) )
                    return( toValue(arg1) < toValue(arg2) ? 1.0 : 0.0 );
                else if( op.Equals( ">" ) )
                    return( toValue(arg1) > toValue(arg2) ? 1.0 : 0.0 );
                else if( op.Equals( "&&" ) )
                    return( ( toValue(arg1) == 1.0 ) && ( toValue(arg2) == 1.0 ) ? 1.0 : 0.0 );
                else if( op.Equals( "||" ) )
                    return( ( toValue(arg1) == 1.0 ) || ( toValue(arg2) == 1.0 ) ? 1.0 : 0.0 );
                else if( op.Equals( ">=" ) )
                    return( toValue(arg1) >= toValue(arg2) ? 1.0 : 0.0 );
                else if( op.Equals( "<=" ) )
                    return( toValue(arg1) <= toValue(arg2) ? 1.0 : 0.0 );

            }
            else
            {
                if( op.Equals( "sqrt" ) )
                    return( Math.Sqrt(toValue(arg1)));
                else if( op.Equals( "sin" ) )
                    return( Math.Sin(toValue(arg1)));
                else if( op.Equals( "cos" ) )
                    return( Math.Cos(toValue(arg1)));
                else if( op.Equals( "tan" ) )
                    return( Math.Tan(toValue(arg1)));
                else if( op.Equals( "asin" ) )
                    return( Math.Asin(toValue(arg1)));
                else if( op.Equals( "acos" ) )
                    return( Math.Acos(toValue(arg1)));
                else if( op.Equals( "atan" ) )
                    return( Math.Atan(toValue(arg1)));
                else if( op.Equals( "ln" ) )
                    return( Math.Log(toValue(arg1)));
                else if( op.Equals( "exp" ) )
                    return( Math.Exp(toValue(arg1)));
                else if( op.Equals( "cotan" ) )
                    return(1 / Math.Tan(toValue(arg1)));
                else if( op.Equals( "acotan" ) )
                    return( Math.PI / 2 - Math.Atan(toValue(arg1)));
                else if( op.Equals( "ceil" ) )
                    return((double)Math.Ceiling(toValue(arg1)));
                else if( op.Equals( "round" ) )
                    return((double)Math.Round(toValue(arg1)));
                else if( op.Equals( "floor" ) )
                    return((double)Math.Floor(toValue(arg1)));
                else if( op.Equals( "fac" ) )
                    return(fac(toValue(arg1)));
                else if( op.Equals( "abs" ) )
                    return( Math.Abs(toValue(arg1)));
                else if( op.Equals( "fpart" ) )
                    return( fpart(toValue(arg1)) );
                else if( op.Equals( "sfac" ) )
                    return( sfac(toValue(arg1)));
                else if( op.Equals( "sinh" ) )
                {
                    val = toValue(arg1);
                    return( ( Math.Exp(val) - ( 1 / Math.Exp(val))) / 2);
                }
                else if( op.Equals( "cosh" ) )
                {
                    val = toValue(arg1);
                    return( ( Math.Exp(val) + ( 1 / Math.Exp(val))) / 2);
                }
                else if( op.Equals( "tanh" ) )
                {
                    val = toValue(arg1);
                    return( ( ( Math.Exp(val) - ( 1 / Math.Exp(val))) / 2) / ((Math.Exp(val) + ( 1 / Math.Exp(val))) / 2) );
                }
                else if( op.Equals( "!" ) )
                {
                    return( ( ! ( toValue(arg1) == 1.0 ) ) ? 1.0 : 0.0 );
                }
            }

            throw new System.Exception( "Unknown operator" );
        }
예제 #3
0
 /// <summary>
 /// Creates a Node containing the specified Operator and argument.
 /// This will automatically mark this Node as a TYPE_EXPRESSION
 /// </summary>
 /// <param name="_operator">the string representing an operator</param>
 /// <param name="_arg1">the argument to the specified operator</param>
 public Node( String _operator, Node _arg1 )
 {
     this._arg1	= _arg1;
     this._operator	= _operator;
     this.args	= 1;
     this.type	= TYPE_EXPRESSION;
 }