示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#4
0
 protected override CalcExpression VisitFunctionExpression(CalcFunctionExpression expr, int baseRow, int baseColumn)
 {
     return(expr);
 }
示例#5
0
        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);
            }
        }
示例#6
0
        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);
        }
示例#7
0
        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));
        }
示例#8
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);
        }