/// <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; }
/// <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" ); }
/// <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; }