/// <summary> /// Static version of the Expression Evaluator /// </summary> /// <param name="expression">expression to be evaluated</param> /// <param name="handler">attach a custom function handler</param> /// <returns></returns> public static object Evaluate(string expression, AdditionalFunctionEventHandler handler) { ExpressionEval expr = new ExpressionEval(expression); expr.AdditionalFunctionEventHandler += handler; return(expr.Evaluate()); }
/// <summary> /// Executes the function based upon the name of the function /// </summary> /// <param name="name">name of the function to execute</param> /// <param name="p">parameter list</param> /// <returns>returned value of executed function</returns> //[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] private object ExecuteFunction(string name, object[] p) { object[] parameters = null; if (p != null) { parameters = (object[])p.Clone(); for (int x = 0; x < parameters.Length; x++) { if (parameters[x] is IExpression) { parameters[x] = ((IExpression)parameters[x]).Evaluate(); } } } switch (name.ToLower(CultureInfo.CurrentCulture)) { // Math functions case "sin": return(Math.Sin(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "cos": return(Math.Cos(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "tan": return(Math.Tan(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "sec": return(1 / Math.Cos(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "csc": return(1 / Math.Sin(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "cot": return(1 / Math.Tan(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "asin": return(Math.Asin(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "acos": return(Math.Acos(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "atan": return(Math.Atan(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "sinh": return(Math.Sinh(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "cosh": return(Math.Cosh(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "tanh": return(Math.Tanh(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "abs": return(Math.Abs(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "sqrt": return(Math.Sqrt(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "ciel": return(Math.Ceiling(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "floor": return(Math.Floor(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "exp": return(Math.Exp(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "log10": return(Math.Log10(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "log": return((parameters.Length > 1) ? Math.Log(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture), Convert.ToDouble(parameters[1], CultureInfo.CurrentCulture)) : Math.Log(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); case "max": return(Math.Max(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture), Convert.ToDouble(parameters[1], CultureInfo.CurrentCulture))); case "min": return(Math.Min(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture), Convert.ToDouble(parameters[1], CultureInfo.CurrentCulture))); case "pow": return(Math.Pow(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture), Convert.ToDouble(parameters[1], CultureInfo.CurrentCulture))); case "round": return((parameters.Length > 1) ? Math.Round(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture), Convert.ToInt32(parameters[1], CultureInfo.CurrentCulture)) : Math.Round(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture))); //case "trunc": return Math.Truncate(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture)); case "e": return(Math.E); case "pi": return(Math.PI); //DateTime functions case "now": return(DateTime.Now); case "today": return(DateTime.Today); case "mindate": return(DateTime.MinValue); case "maxdate": return(DateTime.MaxValue); case "monthname": return((new DateTime(2000, Convert.ToInt32(parameters[0]), 1)).ToString("MMMM")); case "adddays": return(Convert.ToDateTime(parameters[0]).AddDays(Convert.ToInt32(parameters[1]))); case "addmonths": return(Convert.ToDateTime(parameters[0]).AddMonths(Convert.ToInt32(parameters[1]))); case "addyears": return(Convert.ToDateTime(parameters[0]).AddYears(Convert.ToInt32(parameters[1]))); case "addhours": return(Convert.ToDateTime(parameters[0]).AddHours(Convert.ToInt32(parameters[1]))); case "addminutes": return(Convert.ToDateTime(parameters[0]).AddMinutes(Convert.ToInt32(parameters[1]))); case "addseconds": return(Convert.ToDateTime(parameters[0]).AddSeconds(Convert.ToInt32(parameters[1]))); //Formatting Functions case "fmtnum": return(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture).ToString("" + parameters[1], CultureInfo.CurrentCulture)); case "fmtdate": return(Convert.ToDateTime(parameters[0], CultureInfo.CurrentCulture).ToString("" + parameters[1], CultureInfo.CurrentCulture)); //Numerical Expression Evaluation case "expr": { ExpressionEval eval = new ExpressionEval("" + parameters[0]); eval.AdditionalFunctionEventHandler += this.AdditionalFunctionEventHandler; eval._variables = this._variables; return(eval.Evaluate()); } //Casting Functions case "cdbl": return(Convert.ToDouble(parameters[0], CultureInfo.CurrentCulture)); case "cint": return(Convert.ToInt32(parameters[0], CultureInfo.CurrentCulture)); case "clong": return(Convert.ToInt64(parameters[0], CultureInfo.CurrentCulture)); case "cuint": return(Convert.ToUInt32(parameters[0], CultureInfo.CurrentCulture)); case "culong": return(Convert.ToUInt64(parameters[0], CultureInfo.CurrentCulture)); case "cdatetime": return(Convert.ToDateTime(parameters[0], CultureInfo.CurrentCulture)); case "str": return(parameters[0].ToString()); //Logical Functions case "iif": return(Iif(parameters)); case "case": return(Case(parameters)); //security fucntions case "currentuserid": return(WindowsIdentity.GetCurrent().Name.ToLower()); default: return(AdditionalFunctionHelper(name, parameters)); } }
/// <summary> /// returns the parameters of a function /// </summary> /// <param name="m">regex math value</param> /// <returns></returns> private object [] GetParameters(Match m) { string strParams = ""; int nIdx = m.Index + m.Length; int nDepth = 1; int nLast = 0; bool bInQuotes = false; ArrayList ret = new ArrayList(); //Get the parameter string while (nDepth > 0) { if (nIdx >= Expression.Length) { throw new ArgumentException("Missing ')' in Expression"); } if (!bInQuotes && Expression[nIdx] == ')') { nDepth--; } if (!bInQuotes && Expression[nIdx] == '(') { nDepth++; } if (Expression[nIdx] == '"' && (nIdx == 0 || Expression[nIdx - 1] != '\\')) { bInQuotes = !bInQuotes; } if (nDepth > 0) { nIdx++; } } strParams = Expression.Substring(m.Index + m.Length, nIdx - (m.Index + m.Length)); if ("" + strParams == "") { return(null); } bInQuotes = false; for (nIdx = 0; nIdx < strParams.Length; nIdx++) { if (!bInQuotes && strParams[nIdx] == ')') { nDepth--; } if (!bInQuotes && strParams[nIdx] == '(') { nDepth++; } if (strParams[nIdx] == '"' && (nIdx == 0 || strParams[nIdx - 1] != '\\')) { bInQuotes = !bInQuotes; } if (!bInQuotes && nDepth == 0 && strParams[nIdx] == ',') { ret.Add(strParams.Substring(nLast, nIdx - nLast)); nLast = nIdx + 1; } } ret.Add(strParams.Substring(nLast, nIdx - nLast)); for (nIdx = 0; nIdx < ret.Count; nIdx++) { ExpressionEval eval = new ExpressionEval(ret[nIdx].ToString()); eval.AdditionalFunctionEventHandler += AdditionalFunctionEventHandler; eval._variables = this._variables; ret[nIdx] = eval; } return(ret.ToArray()); }
/// <summary> /// This will search the expression for the next token (operand, operator, etc) /// </summary> /// <param name="nIdx">Start Position of Search</param> /// <returns>First character index after token.</returns> //[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] private int NextToken(int nIdx) { Match mRet = null; int nRet = nIdx; object val = null; //Check for preceeding white space from last token index Match m = DefinedRegex.WhiteSpace.Match(Expression, nIdx); if (m.Success && m.Index == nIdx) { return(nIdx + m.Length); } //Check Parenthesis m = DefinedRegex.Parenthesis.Match(Expression, nIdx); if (m.Success) { mRet = m; } //Check Function if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.Function.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; } } //Check Variable if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.Variable.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = new Variable(m.Groups["Variable"].Value, _variables); } } //Check Unary Operator if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.UnaryOp.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = new UnaryOp(m.Value); } } //Check Hexadecimal if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.Hexadecimal.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = Convert.ToInt32(m.Value, 16); } } //Check Boolean if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.Boolean.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = bool.Parse(m.Value); } } //Check DateTime if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.DateTime.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = Convert.ToDateTime(m.Groups["DateString"].Value, CultureInfo.CurrentCulture); } } //Check Timespan if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.TimeSpan.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = new TimeSpan( int.Parse("0" + m.Groups["Days"].Value), int.Parse(m.Groups["Hours"].Value), int.Parse(m.Groups["Minutes"].Value), int.Parse("0" + m.Groups["Seconds"].Value), int.Parse("0" + m.Groups["Milliseconds"].Value) ); } } //Check Numeric if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.Numeric.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { while (m.Success && ("" + m.Value == "")) { m = m.NextMatch(); } if (m.Success) { mRet = m; val = double.Parse(m.Value, CultureInfo.CurrentCulture); } } } if (mRet == null || mRet.Index > nIdx) { //Check String m = DefinedRegex.String.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = m.Groups["String"].Value.Replace("\\\"", "\""); } } //Check Binary Operator if (mRet == null || mRet.Index > nIdx) { m = DefinedRegex.BinaryOp.Match(Expression, nIdx); if (m.Success && (mRet == null || m.Index < mRet.Index)) { mRet = m; val = new BinaryOp(m.Value); } } if (mRet == null) { throw new ArgumentException("Invalid expression construction: \"" + Expression + "\"."); } if (mRet.Index != nIdx) { throw new ArgumentException( "Invalid token in expression: [" + Expression.Substring(nIdx, mRet.Index - nIdx).Trim() + "]" ); } if (mRet.Value == "(" || mRet.Value.StartsWith("$")) { nRet = mRet.Index + mRet.Length; int nDepth = 1; bool bInQuotes = false; while (nDepth > 0) { if (nRet >= Expression.Length) { throw new ArgumentException("Missing " + (bInQuotes ? "\"" : ")") + " in Expression"); } if (!bInQuotes && Expression[nRet] == ')') { nDepth--; } if (!bInQuotes && Expression[nRet] == '(') { nDepth++; } if (Expression[nRet] == '"' && (nRet == 0 || Expression[nRet - 1] != '\\')) { bInQuotes = !bInQuotes; } nRet++; } if (mRet.Value == "(") { ExpressionEval expr = new ExpressionEval( Expression.Substring(mRet.Index + 1, nRet - mRet.Index - 2) ); if (this.AdditionalFunctionEventHandler != null) { expr.AdditionalFunctionEventHandler += this.AdditionalFunctionEventHandler; } expr._variables = this._variables; _expressionlist.Add(expr); } else { FunctionEval func = new FunctionEval( Expression.Substring(mRet.Index, (nRet) - mRet.Index) ); if (this.AdditionalFunctionEventHandler != null) { func.AdditionalFunctionEventHandler += this.AdditionalFunctionEventHandler; } func._variables = this._variables; _expressionlist.Add(func); } } else { nRet = mRet.Index + mRet.Length; _expressionlist.Add(val); } return(nRet); }
public BinaryOp(string strOp) { _strOp = strOp; _nPrecedence = ExpressionEval.OperatorPrecedence(strOp); }
/// <summary> /// Static version of the Expression Evaluator /// </summary> /// <param name="expression">expression to be evaluated</param> /// <returns></returns> public static object Evaluate(string expressionString) { ExpressionEval expression = new ExpressionEval(expressionString); return(expression.Evaluate()); }