/// <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(); }
private static bool performComparison(string[] values) { string comparisonString = ""; string tempVar; bool errorFlag = false; for (int i = 0; i < values.Length; i++) { //Console.WriteLine(values[i]); if (values[i].Equals(".lt.")) { values[i] = " < "; } else if (values[i].Equals(".gt.")) { values[i] = " > "; } else if (values[i].Equals(".eq.")) { values[i] = " == "; } else if (values[i].Equals(".le.")) { values[i] = " <= "; } else if (values[i].Equals(".ge.")) { values[i] = " >= "; } else if (values[i].Equals(".ne.")) { values[i] = " != "; } else if (values[i].Equals(".and.")) { values[i] = " && "; } else if (values[i].Equals(".or.")) { values[i] = " || "; } else if (values[i].Equals(".not.")) { values[i] = " ! "; } else if (isVariableName(values[i])) { if (variables.ContainsKey(values[i])) { variables.TryGetValue(values[i], out tempVar); values[i] = tempVar; } else { errorFlag = true; } } else if (isString(values[i])) { values[i] = values[i].Replace('"', '\''); } //.Trim('\'') //Console.WriteLine(values[i]); } foreach (string s in values) { comparisonString += s; } //Console.WriteLine(comparisonString); if (!errorFlag) { ExpressionEval expr = new ExpressionEval(comparisonString); object result = expr.Evaluate(); //Console.WriteLine(result); return (bool)result; } else { return false; } }
/// <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); } }
public bool IsScheduling(string cronExpression) { string buildExpression = ""; int p = 0; while (p < cronExpression.Length) { char token = cronExpression[p]; if (token == '(' || token == ')' || token == ';' || token == ':') { buildExpression += token; p++; continue; } string currentExpression = token.ToString(); p++; while (p < cronExpression.Length) { token = cronExpression[p]; if (token != '(' && token != ')' && token != ';' && token != ':') { currentExpression += token; p++; } else { break; } } currentExpression = currentExpression.Trim(new char[] { ' ', '\t' }); if (String.IsNullOrEmpty(currentExpression)) continue; bool isEntryActive = false; if (currentExpression.StartsWith("@")) { // Check expresion from scheduled item with a given name var eventItem = Get(currentExpression.Substring(1)); isEntryActive = (eventItem != null && eventItem.IsEnabled && EvaluateCronEntry(eventItem.CronExpression)); } else { isEntryActive = EvaluateCronEntry(currentExpression); } buildExpression += (isEntryActive ? "1" : "0"); } buildExpression = buildExpression.Replace(":", "+"); buildExpression = buildExpression.Replace(";", "*"); bool success = false; try { ExpressionEval eval = new ExpressionEval(); eval.Expression = buildExpression; success = eval.EvaluateBool(); } catch (Exception ex) { masterControlProgram.HomeGenie.LogBroadcastEvent( Domains.HomeAutomation_HomeGenie_Scheduler, cronExpression, "Scheduler Expression", Properties.SCHEDULER_ERROR, JsonConvert.SerializeObject(ex.Message)); } return success; }
public bool IsScheduling(DateTime date, string cronExpression) { string buildExpression = ""; int p = 0; while (p < cronExpression.Length) { char token = cronExpression[p]; if (token == '(' || token == ')' || token == ';' || token == ':') { buildExpression += token; p++; continue; } string currentExpression = token.ToString(); p++; while (p < cronExpression.Length) { token = cronExpression[p]; if (token != '(' && token != ')' && token != ';' && token != ':') { currentExpression += token; p++; } else { break; } } currentExpression = currentExpression.Trim(new char[] { ' ', '\t' }); if (String.IsNullOrEmpty(currentExpression)) continue; bool isEntryActive = false; if (currentExpression.StartsWith("@")) { // Check expresion from scheduled item with a given name var eventItem = Get(currentExpression.Substring(1)); if (eventItem == null) { masterControlProgram.HomeGenie.MigService.RaiseEvent( this, Domains.HomeAutomation_HomeGenie, SourceModule.Scheduler, cronExpression, Properties.SchedulerError, JsonConvert.SerializeObject("Unknown event name '"+currentExpression+"'")); } else if (recursionCount >= MAX_EVAL_RECURSION) { recursionCount = 0; masterControlProgram.HomeGenie.MigService.RaiseEvent( this, Domains.HomeAutomation_HomeGenie, SourceModule.Scheduler, cronExpression, Properties.SchedulerError, JsonConvert.SerializeObject("Too much recursion in expression '"+currentExpression+"'")); eventItem.IsEnabled = false; } else { recursionCount++; try { isEntryActive = (eventItem.IsEnabled && IsScheduling(date, eventItem.CronExpression)); } catch{ } recursionCount--; if (recursionCount < 0) recursionCount = 0; } } else { isEntryActive = EvaluateCronEntry(date, currentExpression); } buildExpression += (isEntryActive ? "1" : "0"); } buildExpression = buildExpression.Replace(":", "+"); buildExpression = buildExpression.Replace(";", "*"); bool success = false; try { ExpressionEval eval = new ExpressionEval(); eval.Expression = buildExpression; success = eval.EvaluateBool(); } catch (Exception ex) { masterControlProgram.HomeGenie.MigService.RaiseEvent( this, Domains.HomeAutomation_HomeGenie, // before v1.1 it was: Domains.HomeAutomation_HomeGenie_Automation, SourceModule.Scheduler, // before v1.1 it was: cronExpression, cronExpression, // before v1.1 it was: "Scheduler Expression", Properties.SchedulerError, JsonConvert.SerializeObject(ex.Message)); } return success; }
/// <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> /// 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(); }
/// <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; }