/// <summary> /// 计算两个表达式的值 /// </summary> public static object ComputeTwo(InnerExpression lExp, InnerOperate op, InnerExpression rExp) { object oRet = ""; object lValue = lExp.GetValue(); object rValue = rExp.GetValue(); //OleDbHelper.AppendToFile("~/debug.txt", "\n" + "Left:" + lValue.GetType().ToString() // + " Right:" + rValue.GetType().ToString()); //Util.Debug(false, lValue.GetType(), rValue.GetType()); //return ""; if (lValue.GetType() != rValue.GetType()) { try { rValue = Convert.ChangeType(rValue, lValue.GetType()); } catch (Exception) { throw new InvalidOperationException(string.Format("{0}与{1}不支持运算,且类型不兼容!", lValue, rValue)); } } string opDef = op.OperatorDefine; #region 处理比较操作 if (ReservedWords.IsStringInRange(opDef, ">", "<", ">=", "<=", "!=", "==", "<>")) { if (!(lValue is IComparable) || !(rValue is IComparable)) { throw new InvalidOperationException(string.Format("{0}与{1}不支持比较!", lValue, rValue)); } IComparable ica = lValue as IComparable; IComparable icb = rValue as IComparable; switch (opDef) { case ">": oRet = (ica.CompareTo(icb) > 0); break; case "<": oRet = (ica.CompareTo(icb) < 0); break; case ">=": oRet = (ica.CompareTo(icb) >= 0); break; case "<=": oRet = (ica.CompareTo(icb) <= 0); break; case "!=": oRet = (ica.CompareTo(icb) != 0); break; case "<>": oRet = (ica.CompareTo(icb) != 0); break; case "==": oRet = (ica.CompareTo(icb) == 0); break; default: break; } } #endregion #region 双目基本运算 if (ReservedWords.IsStringInRange(opDef, "*", "/", "%", "+", "-")) { if (lValue.GetType() == typeof(string)) { #region 字符型 if (op.OperatorDefine == "+") { oRet = String.Concat(lValue.ToString(), rValue.ToString()); } else { oRet = lValue.ToString().Replace(rValue.ToString(), ""); } #endregion } else { #region 数字型 double dba = Convert.ToDouble(lValue); double dbb = Convert.ToDouble(rValue); switch (opDef) { case "*": oRet = (dba * dbb); break; case "/": oRet = (dba / dbb); break; case "%": oRet = (dba % dbb); break; case "+": oRet = (dba + dbb); break; case "-": oRet = (dba - dbb); break; default: break; } #endregion } } #endregion //return string.Format("{0}{1}{2}", lExp.GetValue(), op.OperatorDefine , rExp.GetValue()); return oRet; }
/// <summary> /// 获取最高运算优先级的索引/索引列表(同级左结合式) /// </summary> public static List<int> GetMaxPriorityExpIndexes(List<InnerExpression> exps) { List<int> oResList = new List<int>(); int iPriority = 20, iCurPriority = 0; InnerOperate op = null; for (int i = 0, j = exps.Count; i < j; i++) { //Util.Debug(false, string.Concat(i, " : [", exps[i].GetValue(), "] OP:" , exps[i].IsOperator())); if (exps[i].IsOperator()) { op = new InnerOperate(exps[i].GetValue().ToString()); iCurPriority = op.GetPriority(); //输出当前优先级 //Util.Debug(false, string.Concat( "[" , exps[i].GetValue().ToString().Trim(), "] = ", iCurPriority)); if (iCurPriority <= iPriority) { if (iCurPriority < iPriority) { iPriority = iCurPriority; oResList.Clear(); oResList.Add(i); } else { oResList.Add(i); } } } } return oResList; }
/// <summary> /// 计算一个表达式的值 /// </summary> /// <param name="exp">The exp.</param> /// <param name="op">The op.</param> /// <returns></returns> public static object ComputeOne(InnerExpression exp, InnerOperate op) { //"!", "~", "++", "--", "true", "false" object oRet = exp.GetValue(); if (op.OperatorDefine == "!") { return !(Convert.ToBoolean(oRet)); } else if (op.OperatorDefine == "~") { return ~Convert.ToChar(oRet); } else if (op.OperatorDefine == "++" || op.OperatorDefine == "--") { if (!Regex.IsMatch(oRet.ToString(), @"^(\+|\-)?[\d\.]+$", RegexOptions.Compiled)) { throw new InvalidOperationException("数据不支持自增/减运算!"); } else { double odb = double.Parse(oRet.ToString()); return (op.OperatorDefine == "++") ? odb++ : odb--; } } return oRet; }
/// <summary> /// 计算表达式 /// </summary> public static object ExecExpressions(List<InnerExpression> exps) { if (exps.Count == 0) return ""; while (exps.Count > 1) { List<int> priIdxes = GetMaxPriorityExpIndexes(exps); int total = exps.Count; int offSet = 0, cIdx = 0; InnerExpression tempExp = null; InnerOperate op = null; if (priIdxes.Count == 0) { #region 没有操作符号的数学运算 while (exps.Count >= 2) { tempExp = new InnerExpression(); if (Regex.IsMatch(exps[1].TagDefinition, InnerExpression.ArrayIndexFetchPattern, RegexOptions.Compiled)) { #region 数组下标直接获取 "ab"[0] = "a" string strExpValue = exps[0].GetValue().ToString(); int arrIdx = Convert.ToInt32(exps[1].TagDefinition.Trim('[', ']')); tempExp.TagDefinition = (arrIdx < strExpValue.Length) ? strExpValue[arrIdx].ToString() : strExpValue; tempExp.IsString = true; #endregion } else { tempExp.TagDefinition = InnerExpression.ComputeTwo(exps[0], new InnerOperate("+"), exps[1]).ToString(); tempExp.IsString = exps[0].IsString; } tempExp.IsEntity = true; exps[0] = tempExp; exps.RemoveAt(1); } #endregion } else { #region 处理同级运算 foreach (int idx in priIdxes) { cIdx = idx + offSet; //Util.Debug(false, cIdx); op = new InnerOperate(exps[cIdx].GetValue().ToString()); if (op.IsUnary()) { #region 一元 自增/减操作 直接运算 // ++i if ((idx + 1) < total) { tempExp = new InnerExpression(); tempExp.TagDefinition = InnerExpression.ComputeOne(exps[cIdx + 1], op).ToString(); tempExp.IsEntity = true; exps[cIdx + 1] = tempExp; exps.RemoveAt(cIdx); offSet -= 1; } else { //i++ if (idx > 0) { tempExp = new InnerExpression(); tempExp.TagDefinition = InnerExpression.ComputeOne(exps[cIdx - 1], op).ToString(); tempExp.IsEntity = true; exps[cIdx - 1] = tempExp; exps.RemoveAt(cIdx); offSet -= 1; } } #endregion } else if (op.IsTernary()) { //最低优先级 ? a : b #region 三目条件运算符 if (idx + 3 < total) { tempExp = new InnerExpression(); tempExp.TagDefinition = (Convert.ToBoolean(exps[cIdx - 1].GetValue()) ? exps[cIdx + 1].GetValue() : exps[cIdx + 3].GetValue()).ToString(); tempExp.IsEntity = true; exps[cIdx - 1] = tempExp; exps.RemoveAt(cIdx); exps.RemoveAt(cIdx); exps.RemoveAt(cIdx); exps.RemoveAt(cIdx); offSet -= 4; } #endregion } else { #region 双目运算 if (exps.Count >= 3) { tempExp = new InnerExpression(); tempExp.TagDefinition = InnerExpression.ComputeTwo(exps[cIdx - 1], op, exps[cIdx + 1]).ToString(); tempExp.IsString = exps[cIdx - 1].IsString; tempExp.IsEntity = true; exps[cIdx - 1] = tempExp; exps.RemoveAt(cIdx); exps.RemoveAt(cIdx); offSet -= 2; } else { //无效运算操作 exps.RemoveAt(cIdx); offSet -= 1; } #endregion } } #endregion } //Util.Debug(false, "当前还剩余:" + exps.Count.ToString()); //foreach (InnerExpression tex in exps) //{ // Util.Debug(false, tex.GetValue()); //} } return exps[0].GetValue(); }