private bool TryGetFunction(CalcFunctionExpression expr, CalcEvaluatorContext context, out CalcFunction func, out object error) { func = expr.Function; int argCount = expr.ArgCount; if (object.ReferenceEquals(func, null)) { if (object.ReferenceEquals(context, null)) { error = CalcErrors.Name; return(false); } func = context.GetFunction(expr.FunctionName); if (object.ReferenceEquals(func, null)) { error = CalcErrors.Name; return(false); } if ((argCount < func.MinArgs) || (func.MaxArgs < argCount)) { error = CalcErrors.Value; return(false); } } error = null; return(true); }
protected virtual CalcExpression VisitFunctionExpression(CalcFunctionExpression expr, int baseRow, int baseColumn) { int argCount = expr.ArgCount; CalcExpression[] args = new CalcExpression[argCount]; bool flag = false; for (int i = 0; i < argCount; i++) { CalcExpression arg = expr.GetArg(i); args[i] = this.Visit(arg, baseRow, baseColumn); if (arg != args[i]) { flag = true; } } if (!flag) { return(expr); } if (object.ReferenceEquals(expr.Function, null)) { return(new CalcFunctionExpression(expr.FunctionName, args)); } return(new CalcFunctionExpression(expr.Function, args)); }
CalcExpression ParseAtom() { string id; CalcExpression x = null; FunctionDefinition fnDef = null; switch (_token.Type) { case Tktype.LITERAL: //字面量,不用处理,作为CalcExpression返回即可 x = new CalcExpression(_token); break; case Tktype.IDENTIFIER: //标识,可能来自功能、外部数据源 id = (string)_token.Value; if (_fns.TryGetValue(id, out fnDef)) { var p = GetParameters(); //检查参数个数是否符合功能定义 var pCnt = p == null ? 0 : p.Count; if (fnDef.ParmMin != -1 && pCnt < fnDef.ParmMin) { Throw("Too few parameters."); } if (fnDef.ParmMax != -1 && pCnt > fnDef.ParmMax) { Throw("Too many parameters."); } x = new CalcFunctionExpression(fnDef, p); break; } if (_inData.Variables.ContainsKey(id)) { x = new CalcVariableExpression(_inData, id); break; } var xObj = GetExternalObject(id); if (xObj != null) { x = new CalcXObjectExpression(xObj); break; } if (_inData != null) { var list = new List <BindingInfo>(); for (var t = _token; t != null; t = GetMember()) { list.Add(new BindingInfo((string)t.Value, GetParameters())); } x = new CalcBindingExpression(_inData, list, _ci); break; } Throw("Unexpected identifier"); break; case Tktype.GROUP: if (_token.Id != Tkid.OPEN) { Throw("Expression expected."); } GetToken(); x = ParseCompare(); if (_token.Id != Tkid.CLOSE) { Throw("Unbalanced parenthesis."); } break; } // make sure we got something... if (x == null) { Throw(); } GetToken(); return(x); }
protected override CalcExpression VisitFunctionExpression(CalcFunctionExpression expr, int baseRow, int baseColumn) { return(expr); }
public static void ExtractAllReferenceExpression(ICalcEvaluator evaluator, CalcExpression root, List <CalcReferenceExpression> nodes) { if (root is CalcBinaryOperatorExpression) { CalcBinaryOperatorExpression expression = root as CalcBinaryOperatorExpression; ExtractAllReferenceExpression(evaluator, expression.Left, nodes); ExtractAllReferenceExpression(evaluator, expression.Right, nodes); } else if (root is CalcParenthesesExpression) { CalcParenthesesExpression expression2 = root as CalcParenthesesExpression; ExtractAllReferenceExpression(evaluator, expression2.Arg, nodes); } else if (root is CalcExternalNameExpression) { CalcExternalNameExpression expression3 = root as CalcExternalNameExpression; ICalcSource source = expression3.Source; if (source != null) { CalcExpression expression4 = source.GetDefinedName(expression3.Name, -1, -1); if (expression4 != null) { ExtractAllReferenceExpression(evaluator, expression4, nodes); } } } else if (root is CalcFunctionExpression) { CalcFunctionExpression expr = root as CalcFunctionExpression; Worksheet worksheet = evaluator as Worksheet; if (worksheet != null) { CalcEvaluatorContext context = new CalcEvaluatorContext(worksheet, false, worksheet.ActiveRowIndex, worksheet.ActiveColumnIndex, 1, 1); object obj2 = new CalcEvaluator().Evaluate(expr, context, true, true); if (obj2 is CalcReference) { CalcReference reference = obj2 as CalcReference; int row = reference.GetRow(0); int rowCount = reference.GetRowCount(0); int column = reference.GetColumn(0); int columnCount = reference.GetColumnCount(0); ICalcSource source2 = null; CalcReference reference2 = reference.GetSource(); // hdt MethodInfo info = reference2.GetType().GetRuntimeMethod("GetContext", null); if (info != null) { source2 = info.Invoke(reference2, null) as ICalcSource; } if (source2 == null) { source2 = worksheet; } CalcExternalRangeExpression expression6 = CreateExternalRangeExpressionByCount(source2, row, column, rowCount, columnCount, false, false, false, false); nodes.Add(expression6); } } } else if (root is CalcReferenceExpression) { nodes.Add(root as CalcReferenceExpression); } }
private bool PrepareFunctionArguments(CalcFunctionExpression expr, CalcEvaluatorContext context, out CalcFunction func, out object[] args, out List <int> expandArrayArgIndex, out object error) { if (!this.TryGetFunction(expr, context, out func, out error)) { args = null; expandArrayArgIndex = null; return(false); } expandArrayArgIndex = new List <int>(); int argCount = expr.ArgCount; args = new object[argCount]; error = null; if (func.IsBranch) { int i = func.FindTestArgument(); if ((i >= 0) && (i < argCount)) { object obj2; if (!this.EvaluateFunctionArgument(expr.GetArg(i), context, func.AcceptsArray(i), func.AcceptsReference(i), func.AcceptsError(i), func.AcceptsMissingArgument(i), out obj2)) { error = obj2; expandArrayArgIndex = null; return(false); } if ((context != null) && !context.ArrayFormulaMode) { if (obj2 is CalcReference) { obj2 = this.ExtractValueFromReference(obj2 as CalcReference, context.Row, context.Column); if (!func.AcceptsError(i) && (obj2 is CalcError)) { error = obj2; expandArrayArgIndex = null; return(false); } if (!func.AcceptsMissingArgument(i) && (obj2 is CalcMissingArgument)) { obj2 = null; } } else if ((obj2 is CalcArray) && !func.AcceptsArray(i)) { if (!context.ExpandArrayToMultiCall) { obj2 = CalcHelper.GetArrayValue(obj2 as CalcArray, 0, 0); if (!func.AcceptsError(i) && (obj2 is CalcError)) { error = obj2; expandArrayArgIndex = null; return(false); } if (!func.AcceptsMissingArgument(i) && (obj2 is CalcMissingArgument)) { obj2 = null; } } else { expandArrayArgIndex.Add(i); } } } args[i] = obj2; } List <int> list = new List <int>(); CalcArray array = CalcConvert.ToArray(args[i]); for (int j = 0; j < array.RowCount; j++) { for (int k = 0; k < array.ColumnCount; k++) { int item = -1; try { item = func.FindBranchArgument(array.GetValue(j, k)); } catch (InvalidCastException) { } if (item != -1) { if (!list.Contains(item)) { list.Add(item); } if (list.Count >= (func.MaxArgs - 1)) { break; } } } } if (list.Count == 0) { error = CalcErrors.Value; expandArrayArgIndex = null; return(false); } foreach (int num6 in list) { if ((num6 >= 0) && (num6 < argCount)) { object obj3; if (!this.EvaluateFunctionArgument(expr.GetArg(num6), context, func.AcceptsArray(num6), func.AcceptsReference(num6), func.AcceptsError(num6), func.AcceptsMissingArgument(num6), out obj3)) { error = obj3; expandArrayArgIndex = null; return(false); } if (((context != null) && !context.ArrayFormulaMode) && ((obj3 is CalcArray) && !func.AcceptsArray(num6))) { if (!context.ExpandArrayToMultiCall) { obj3 = CalcHelper.GetArrayValue(obj3 as CalcArray, 0, 0); if (!func.AcceptsError(num6) && (obj3 is CalcError)) { error = obj3; expandArrayArgIndex = null; return(false); } if (!func.AcceptsMissingArgument(num6) && (obj3 is CalcMissingArgument)) { obj3 = null; } } else { expandArrayArgIndex.Add(num6); } } args[num6] = obj3; } } if (expandArrayArgIndex.Count > 0) { expandArrayArgIndex.Sort(); } } else { for (int m = 0; m < argCount; m++) { object obj4; if (!this.EvaluateFunctionArgument(expr.GetArg(m), context, func.AcceptsArray(m), func.AcceptsReference(m), func.AcceptsError(m), func.AcceptsMissingArgument(m), out obj4)) { error = obj4; expandArrayArgIndex = null; return(false); } if (((context != null) && !context.ArrayFormulaMode) && ((obj4 is CalcArray) && !func.AcceptsArray(m))) { if (!context.ExpandArrayToMultiCall) { obj4 = CalcHelper.GetArrayValue(obj4 as CalcArray, 0, 0); if (!func.AcceptsError(m) && (obj4 is CalcError)) { error = obj4; expandArrayArgIndex = null; return(false); } if (!func.AcceptsMissingArgument(m) && (obj4 is CalcMissingArgument)) { obj4 = null; } } else { expandArrayArgIndex.Add(m); } } args[m] = obj4; } } return(true); }
private object EvaluateFunction(CalcFunctionExpression expr, CalcEvaluatorContext context, bool acceptsArray, bool acceptsReference) { CalcFunction function; object[] objArray; object obj2; List <int> list; if (!this.PrepareFunctionArguments(expr, context, out function, out objArray, out list, out obj2)) { return(obj2); } int argCount = expr.ArgCount; if ((context != null) && context.ArrayFormulaMode) { if (argCount > 0) { return(this.EvaluateFunctionWithArrayFormulaMode(function, objArray, context, acceptsArray, acceptsReference)); } return(this.EvaluateFunction(function, objArray, context, acceptsArray, acceptsReference, 0, 0)); } if (((context != null) && context.ExpandArrayToMultiCall) && (list.Count > 0)) { Dictionary <int, object> dictionary = new Dictionary <int, object>(argCount); bool[] flagArray = new bool[argCount]; bool flag = true; for (int i = 0; i < argCount; i++) { if (list.Contains(i)) { CalcArray array = objArray[i] as CalcArray; if (array == null) { dictionary[i] = null; flagArray[i] = true; } else if (array.Length == 1) { dictionary[i] = array.GetValue(0); flagArray[i] = true; } else { dictionary[i] = array; flag = false; } } else { flagArray[i] = true; } } if (!flag) { int[] numArray = new int[argCount]; int[] numArray2 = new int[argCount]; for (int j = 0; j < argCount; j++) { CalcArray array2 = dictionary.ContainsKey(j) ? (dictionary[j] as CalcArray) : null; numArray[j] = (flagArray[j] || (array2 == null)) ? -1 : array2.RowCount; numArray2[j] = (flagArray[j] || (array2 == null)) ? -1 : array2.ColumnCount; } int num4 = -1; int num5 = -1; if (!flagArray[0]) { num4 = numArray[0]; num5 = numArray2[0]; } for (int k = 1; k < argCount; k++) { if (!flagArray[k]) { int num7 = numArray[k]; int num8 = numArray2[k]; num4 = (num4 == -1) ? num7 : ((num7 > 1) ? ((num4 > 1) ? Math.Min(num7, num4) : num7) : num4); num5 = (num5 == -1) ? num8 : ((num8 > 1) ? ((num5 > 1) ? Math.Min(num8, num5) : num8) : num5); } } object[,] values = new object[num4, num5]; object[] objArray3 = new object[objArray.Length]; objArray.CopyTo(objArray3, 0); using (context.EnterExpandArrayToMultiCallMode()) { for (int m = 0; m < num4; m++) { for (int n = 0; n < num5; n++) { foreach (KeyValuePair <int, object> pair in dictionary) { objArray3[pair.Key] = flagArray[pair.Key] ? pair.Value : CalcHelper.GetArrayValue(pair.Value as CalcArray, m, n); } values[m, n] = this.EvaluateFunction(function, objArray3, context, acceptsArray, acceptsReference, m, n); } } return(new ConcreteArray <object>(values)); } } foreach (KeyValuePair <int, object> pair2 in dictionary) { objArray[pair2.Key] = pair2.Value; } } return(this.EvaluateFunction(function, objArray, context, acceptsArray, acceptsReference, 0, 0)); }
public virtual CalcExpression Visit(CalcExpression expr, int baseRow, int baseColumn) { CalcConstantExpression expression = expr as CalcConstantExpression; if (expression != null) { return(this.VisitConstantExpression(expression)); } CalcCellExpression expression2 = expr as CalcCellExpression; if (expression2 != null) { return(this.VisitCellExpression(expression2, baseRow, baseColumn)); } CalcRangeExpression expression3 = expr as CalcRangeExpression; if (expression3 != null) { return(this.VisitRangeExpression(expression3, baseRow, baseColumn)); } CalcUnaryOperatorExpression expression4 = expr as CalcUnaryOperatorExpression; if (expression4 != null) { return(this.VisitUnaryOperatorExpression(expression4, baseRow, baseColumn)); } CalcBinaryOperatorExpression expression5 = expr as CalcBinaryOperatorExpression; if (expression5 != null) { return(this.VisitBinaryOperatorExpression(expression5, baseRow, baseColumn)); } CalcFunctionExpression expression6 = expr as CalcFunctionExpression; if (expression6 != null) { return(this.VisitFunctionExpression(expression6, baseRow, baseColumn)); } CalcExternalCellExpression expression7 = expr as CalcExternalCellExpression; if (expression7 != null) { return(this.VisitExternalCellExpression(expression7, baseRow, baseColumn)); } CalcExternalRangeExpression expression8 = expr as CalcExternalRangeExpression; if (expression8 != null) { return(this.VisitExternalRangeExpression(expression8, baseRow, baseColumn)); } if (expr is CalcSharedExpression) { CalcExpression expression9 = (expr as CalcSharedExpression).Expression; CalcExpression expression10 = this.Visit(expression9, baseRow, baseColumn); if (expression10 == expression9) { return(expr); } return(new CalcSharedExpression(expression10)); } CalcParenthesesExpression expression11 = expr as CalcParenthesesExpression; if (expression11 != null) { return(this.VisitParenthesesExpression(expression11, baseRow, baseColumn)); } CalcNameExpression expression12 = expr as CalcNameExpression; if (expression12 != null) { return(this.VisitNameExpression(expression12, baseRow, baseColumn)); } CalcExternalNameExpression expression13 = expr as CalcExternalNameExpression; if (expression13 != null) { return(this.VisitExternalNameExpression(expression13, baseRow, baseColumn)); } CalcSheetRangeExpression expression14 = expr as CalcSheetRangeExpression; if (expression14 != null) { return(this.VisitSheetRangeExpression(expression14, baseRow, baseColumn)); } return(expr); }