using System; using System.Collections; using System.Text.RegularExpressions; using IwbZero.ExprFunctions; using IwbZero.IwbBase; using IwbZero.ToolCommon.StringModel; namespace IwbZero.Expr { public class EvalExpr { // Fields private static IdCollection _functions; private static IdCollection _operators; private static Regex _RegexDate = new Regex("[0-9]{1,2}/[0-9]{1,2}/[0-9]{2,4}( [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}[ ]*(AM|PM)?)?", RegexOptions.IgnoreCase); private static Regex _RegexDateAdd = new Regex("[0-9]+(d|m|y)", RegexOptions.IgnoreCase); private static Regex _RegexDecimal = new Regex(@"-?[0-9]*\.[0-9]*", RegexOptions.IgnoreCase); private static Regex _RegexInt = new Regex("-?[0-9]+", RegexOptions.IgnoreCase); private static Regex _RegexVariable = new Regex("[_@a-zA-Z][_@a-zA-Z0-9.$]*", RegexOptions.IgnoreCase); // Methods public static string Evaluate(ExprObject exprObj) { string str = ""; if (exprObj.ChildCount == 0) { return exprObj.Expr; } EvaluateAllChildren(exprObj); ExprObject expr = null; for (int i = 0; i < exprObj.ChildCount; i++) { ExprObject child = exprObj.GetChild(i); if (child.IsOperator) { var @operator = child.GetOperator(); ExprObject expr3 = exprObj.GetChild(i + 1); if (expr3 != null) { expr = @operator.Calculate(expr, expr3); i++; } } else if (expr == null) { expr = child; } } if (expr != null) str = expr.Expr; return str; } public static string Evaluate(string exprStr) { string str = exprStr; try { ExprObject exprObj = new ExprObject(exprStr, ExprElements.Expression); if (Parse(exprObj, true)) { str = Evaluate(exprObj); } } catch (Exception) { // ignored } return str; } public static string Evaluate(string exprStr, Hashtable variableValueDic) { var exprStr2 = TransVariable(exprStr, variableValueDic); var str = Evaluate(exprStr2); return str; } #region Methods public static ExprElements GetElementType(string expression) { ExprElements variable = ExprElements.Value; expression = expression.Trim(); Match match = _RegexVariable.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { variable = ExprElements.Variable; } return variable; } public static ExprTypes GetExprTypes(string expression) { ExprTypes date = ExprTypes.String; expression = expression.Trim(); if ((expression.UAndT() == "TRUE") || (expression.UAndT() == "FALSE")) { return ExprTypes.Bool; } Match match = _RegexVariable.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { return ExprTypes.Variable; } match = _RegexDecimal.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { return ExprTypes.Decimal; } match = _RegexInt.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { return ExprTypes.Integer; } match = _RegexDateAdd.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { return ExprTypes.DateAdd; } match = _RegexDate.Match(expression); if (((match.Index == 0)) && (match.Length == expression.Length)) { date = ExprTypes.Date; } return date; } public static ExprTypes GetExprTypes(ExprObject exprObj) { ExprTypes @bool = ExprTypes.String; if (exprObj.ElementType != ExprElements.String) { string str = exprObj.Expr.Trim(); if ((str.UAndT() == "TRUE") || (str.UAndT() == "FALSE")) { @bool = ExprTypes.Bool; str = ""; } if (str == "") { return @bool; } Match match = _RegexDecimal.Match(str); if (((match.Index == 0)) && (match.Length == str.Length)) { return ExprTypes.Decimal; } match = _RegexInt.Match(str); if (((match.Index == 0)) && (match.Length == str.Length)) { return ExprTypes.Integer; } match = _RegexDateAdd.Match(str); if (((match.Index == 0)) && (match.Length == str.Length)) { return ExprTypes.DateAdd; } match = _RegexDate.Match(str); if (((match.Index == 0)) && (match.Length == str.Length)) { @bool = ExprTypes.Date; } } return @bool; } public static DateTime GetLastDayOfMonth(DateTime datetime) { int year = datetime.Year; int month = datetime.Month + 1; if (month > 12) { year++; month = 1; } int day = 1; return (new DateTime(year, month, day) - new TimeSpan(1, 0, 0, 0)); } public static DateTime AddDays(DateTime datetime, string toAdd) { DateTime time = datetime; toAdd = toAdd.UAndT(); int days = toAdd.ValI(); if (toAdd.IndexOf("D", StringComparison.Ordinal) >= 0) { return (time + new TimeSpan(days, 0, 0, 0)); } int year; int month = datetime.Month; int day = datetime.Day; if (toAdd.IndexOf("M", StringComparison.Ordinal) >= 0) { int num5 = ((datetime.Year * 12) + datetime.Month) + days; year = num5 / 12; month = num5 - (year * 12); } else { year = datetime.Year + days; } DateTime lastDayOfMonth = GetLastDayOfMonth(new DateTime(year, month, 1)); if (lastDayOfMonth.Day < day) { day = lastDayOfMonth.Day; } return new DateTime(year, month, day, datetime.Hour, datetime.Minute, datetime.Second, datetime.Millisecond); } public static string TransVariable(string exprStr, Hashtable variableValueDic) { string str = exprStr; var variables = GetVariablesInString(exprStr); if (variables != null) { foreach (string v in variables) { var value = GetVariableValue(v, variableValueDic); if (value != null) { str = str.Replace(v, value); } } } return str; } public static string TransGlobalVariable(string exprStr, Hashtable variableValueDic) { string str = exprStr; var variables = GetVariablesInString(exprStr); if (variables != null) { foreach (string v in variables) { var value = GetVariableValue(v, variableValueDic); str = str.Replace(v, value); } } return str; } private static void EvaluateAllChildren(ExprObject exprObj) { if (exprObj != null) { for (int i = 0; i < exprObj.ChildCount; i++) { ExprObject child = exprObj.GetChild(i); EvaluateAllChildren(child); if (child != null) { string str = null; switch (child.ElementType) { case ExprElements.Function: str = EvaluateFunction(child); break; case ExprElements.Variable: //str = TransSessionVariables(child.Expr); break; case ExprElements.Expression: str = Evaluate(child); break; } if (str != null) { child.Expr = str; child.ElementType = ExprElements.Value; } } } } } public static string EvaluateFunction(ExprObject exprObj) { string str = ""; string functionId = exprObj.Expr.UAndT(); if (_functions == null) { _functions = new IdCollection(); } IwbFunction function = (IwbFunction)_functions[functionId]; if (function == null) { function = IwbFunction.LoadById(functionId); if (function != null) { _functions.Add(function); } } if (function != null) { str = function.InvokeFunction(exprObj); } return str; } private static bool IsStartingParent(char pcChar) { return (pcChar == '('); } private static bool IsStartingQuote(char pcChar) { if (pcChar != '"') { return (pcChar == '\''); } return true; } private static int GetStaticString(string pcString, char pcQuote) { int length = pcString.Length; for (int i = 0; i < length; i++) { char ch = pcString[i]; if (ch == pcQuote) { return i; } if ((ch == '\\') && (i < (length - 1))) { switch (pcString[i + 1]) { case '"': case '\'': i++; break; } } } return -1; } private static int GetClosingParenthesis(string pcString) { int num = -1; int length = pcString.Length; int num3 = 0; for (int i = 0; i < length; i++) { char pcQuote = pcString[i]; if (((pcQuote == '"') || (pcQuote == '\'')) && (i < (length - 1))) { int staticString = GetStaticString(pcString.Substring(i + 1), pcQuote); if (staticString >= 0) { i += staticString + 1; } } if (pcQuote == '(') { num3++; } else if (pcQuote == ')') { if (num3 == 0) { num = i; } else { num3--; } } } return num; } #endregion #region 变量赋值 public static ArrayList GetVariablesInString(string pcString) { var arr1 = GetStringVariables(pcString) ?? new ArrayList(); var arr2 = GetStringVariables(pcString, IwbVariableType.Global) ?? new ArrayList(); arr1.AddRange(arr2); return arr1; } public static ArrayList GetStringVariables(string pcString, string variableHeader = IwbVariableType.Local) { int index; ArrayList poArrayList = new ArrayList(); for (int i = pcString.IndexOf(variableHeader, StringComparison.Ordinal); i >= 0; i = pcString.IndexOf(variableHeader, index, StringComparison.Ordinal)) { string pcName = variableHeader; for (index = i + variableHeader.Length; index < pcString.Length; index++) { char ch = pcString[index]; if ((((ch < 'a') || (ch > 'z')) && ((ch < 'A') || (ch > 'Z'))) && (((ch < '0') || (ch > '9')) && (ch != '_'))) { break; } pcName = pcName + ch; } poArrayList.InsertIdentifier(pcName); } return poArrayList; } public static string GetVariableValue(string pcVariable, Hashtable variableValueDic) { var key = pcVariable.UAndT(); foreach (DictionaryEntry dic in variableValueDic) { if (dic.Key.UAndT() == key) { return ((IwbRtVariable)dic.Value).GetStringValue(); } } return null; } #endregion 变量赋值 #region 表达式转换为ExprObject public static bool Parse(ExprObject exprObj, bool plThrowException) { bool flag = true; try { Parse(exprObj); } catch (Exception) { if (plThrowException) { throw; } flag = false; } return flag; } private static void Parse(ExprObject exprObj, string pcExpression = null) { pcExpression = (pcExpression ?? exprObj.Expr)?.Trim() ?? ""; switch (GetExprTypes(pcExpression)) { case ExprTypes.Integer: case ExprTypes.Decimal: case ExprTypes.Date: case ExprTypes.Bool: exprObj.AddChild(new ExprObject(pcExpression, ExprElements.Value)); return; case ExprTypes.Variable: exprObj.AddChild(new ExprObject(pcExpression, ExprElements.Variable)); return; } ExprObject exprObject = null; string str = ""; while (pcExpression != "") { var poNode = GetNextElement(ref pcExpression); if (poNode != null) { if (((poNode.ElementType != ExprElements.String) && (poNode.Expr == "-")) && ((exprObject == null) || exprObject.IsOperator)) { str = "-"; } else { poNode.Expr = str + poNode.Expr; exprObj.AddChild(poNode); str = ""; } exprObject = poNode; } } CollapseSyntaxTree(exprObj); } private static ExprObject GetNextElement(ref string pcString) { ExprObject exprObj = null; string pcExpr = ""; bool flag = false; int length = pcString.Length; for (int i = 0; i < length; i++) { char pcChar = pcString[i]; string str2 = ""; if (i < (length - 1)) { str2 = pcString.Substring(i + 1); } int closingParenthesis; if (IsStartingParent(pcChar)) { closingParenthesis = GetClosingParenthesis(str2); if (closingParenthesis < 0) { throw new Exception("No ending parenthesis."); } if (pcExpr != "") { string pcExpression = pcString.Substring(i + 1, closingParenthesis); exprObj = new ExprObject(pcExpr, ExprElements.Function); if (pcExpression != "") { Parse(exprObj, pcExpression); CollapseFunctionCall(exprObj); } } else { exprObj = new ExprObject(pcString.Substring(i + 1, closingParenthesis), ExprElements.Expression); Parse(exprObj, exprObj.Expr); } i = (i + closingParenthesis) + 2; flag = true; } else if (IsStartingQuote(pcChar)) { if (pcExpr != "") { throw new Exception("Operand required."); } closingParenthesis = GetStaticString(str2, pcChar); if (closingParenthesis < 0) { throw new Exception("No ending quote."); } exprObj = new ExprObject(pcString.Substring(i + 1, closingParenthesis), ExprElements.String); i = (i + closingParenthesis) + 2; flag = true; } else { ExprOperator @operator = GetOperator(pcString.Substring(i)); bool flag2 = true; if (i == (length - 1)) { pcString = ""; } if (((@operator != null) && (pcExpr != "")) && (GetExprTypes(pcExpr) == ExprTypes.String)) { @operator = null; } if (@operator != null) { if (pcExpr == "") { exprObj = new ExprObject(@operator.Id, ExprElements.Operator); i += @operator.Symbol.Length; } flag = true; flag2 = false; } else if ((pcExpr == "") && (pcChar == ' ')) { flag2 = false; } if (flag2) { pcExpr = pcExpr + pcChar.ToString(); } if ((pcExpr != "") && ((@operator != null) || (i == (length - 1)))) { ExprElements elementType = GetElementType(pcExpr); exprObj = new ExprObject(pcExpr, elementType); flag = true; } } if (flag) { if (i < pcString.Length) { pcString = pcString.Substring(i); return exprObj; } pcString = ""; return exprObj; } } return null; } private static ExprOperator GetOperator(string pcString) { foreach (ExprOperator operator2 in Operators) { if (operator2.IsSymbolMatched(pcString)) { return operator2; } } return null; } /// /// 构建表达式树 /// /// private static void CollapseSyntaxTree(ExprObject poExprObject) { int level = -1; int piStart = -1; int piLevel = 100; for (int i = 0; i < poExprObject.ChildCount; i++) { ExprOperator @operator = poExprObject.GetChild(i).GetOperator(); if (i == (poExprObject.ChildCount - 1)) { @operator = new ExprOperator("", "", piLevel, 0); i++; } if (@operator != null) { if (piLevel > @operator.Level) { piLevel = @operator.Level; } if (@operator.Level > level) { piStart = i - @operator.LeftOperands; } else if (@operator.Level < level) { CollapseSyntaxTree(poExprObject, piStart, i - 1); CollapseSyntaxTree(poExprObject); } level = @operator.Level; } } } /// /// 构建表达式树 /// /// /// /// private static void CollapseSyntaxTree(ExprObject poExprObject, int piStart, int piEnd) { if (piEnd > piStart) { ExprObject poNode = new ExprObject("", ExprElements.Expression); for (int i = piStart; i <= piEnd; i++) { ExprObject child = poExprObject.GetChild(piStart); poExprObject.RemoveChildAt(piStart); poNode.AddChild(child); poNode.Expr = poNode.Expr + " " + child.Expr; } poExprObject.InsertChildAt(poNode, piStart); } } private static void CollapseFunctionCall(ExprObject poExprObject) { if (poExprObject.ChildCount > 1) { bool flag = false; foreach (ExprObject expr in poExprObject.ChildNodes) { if (expr.IsOperator && (expr.Expr.Trim() == ",")) { flag = true; break; } } if (!flag) { ExprObject poNode = new ExprObject(poExprObject.Expr, ExprElements.Expression); foreach (ExprObject expr3 in poExprObject.ChildNodes) { poNode.AddChild(expr3); } poExprObject.ChildNodes.Clear(); poExprObject.AddChild(poNode); } } } public static IdCollection Operators => _operators ?? (_operators = new IdCollection { new ExprOperator("+", "+", 4, 1), new ExprOperator("-", "-", 4, 1), new ExprOperator(",", ",", 0, 0), new ExprOperator("and", " and ", 1, 1), new ExprOperator("&&", " && ", 1, 1), new ExprOperator("or", " or ", 1, 1), new ExprOperator("||", " || ", 1, 1), new ExprOperator("not", "not ", 2, 0), new ExprOperator("!", "! ", 2, 0), new ExprOperator("!=", "!=", 3, 1), new ExprOperator("=", "=", 3, 1), new ExprOperator(">=", ">=", 3, 1), new ExprOperator(">", ">", 3, 1), new ExprOperator("<=", "<=", 3, 1), new ExprOperator("<", "<", 3, 1), new ExprOperator("like", " like ", 3, 1), new ExprOperator("*", "*", 5, 1), new ExprOperator("/", "/", 5, 1), new ExprOperator("%", "%", 5, 1) }); #endregion 表达式转换为ExprObject } }