Пример #1
0
        /// <summary> Handles the case when parsing a string when a token is a function
        ///
        /// </summary>
        /// <param name="sf">the string function
        /// </param>
        /// <param name="i"> the token iterator
        /// </param>
        /// <param name="stack">the parse tree stack
        /// </param>
        /// <exception cref=""> FormulaException if an error occurs
        /// </exception>
        private void  handleFunction(StringFunction sf, ArrayList pis, Stack stack)
        {
            ParseItem pi2 = parseCurrent(pis);

            // If the function is unknown, then throw an error
            if (sf.getFunction(settings) == Function.UNKNOWN)
            {
                throw new FormulaException(FormulaException.unrecognizedFunction);
            }

            // First check for possible optimized functions and possible
            // use of the Attribute token
            if (sf.getFunction(settings) == Function.SUM && arguments == null)
            {
                // this is handled by an attribute
                Attribute a = new Attribute(sf, settings);
                a.add(pi2);
                stack.Push(a);
                return;
            }

            if (sf.getFunction(settings) == Function.IF)
            {
                // this is handled by an attribute
                Attribute a = new Attribute(sf, settings);

                // Add in the if conditions as a var arg function in
                // the correct order
                VariableArgFunction vaf = new VariableArgFunction(settings);

                // [TODO] TEST is the order the same as in Java?
                object[] argumentsArray = arguments.ToArray();
                for (int j = 0; j < argumentsArray.Length; j++)
                {
                    vaf.add((ParseItem)argumentsArray[j]);
                }


                a.IfConditions = vaf;
                stack.Push(a);
                return;
            }

            // Function cannot be optimized.  See if it is a variable argument
            // function or not
            if (sf.getFunction(settings).NumArgs == 0xff)
            {
                // If the arg stack has not been initialized, it means
                // that there was only one argument, which is the
                // returned parse item
                if (arguments == null)
                {
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings), 1, settings);
                    vaf.add(pi2);
                    stack.Push(vaf);
                }
                else
                {
                    // Add the args to the function in reverse order.  The
                    // VariableArgFunction will reverse these when it writes out the
                    // byte version as they are stored in the correct order
                    // within Excel
                    int numargs             = arguments.Count;
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings), numargs, settings);

                    for (int j = 0; j < numargs; j++)
                    {
                        ParseItem pi3 = (ParseItem)arguments.Pop();
                        vaf.add(pi3);
                    }
                    stack.Push(vaf);
                    // [TODO] - check it
                    //		arguments.empty();
                    arguments.Clear();
                    arguments = null;
                }
                return;
            }

            // Function is a standard built in function
            BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings), settings);

            int numargs2 = sf.getFunction(settings).NumArgs;

            if (numargs2 == 1)
            {
                // only one item which is the returned ParseItem
                bif.add(pi2);
            }
            else
            {
                if ((arguments == null && numargs2 != 0) || (arguments != null && numargs2 != arguments.Count))
                {
                    throw new FormulaException(FormulaException.incorrectArguments);
                }
                // multiple arguments so go to the arguments stack.
                // Unlike the variable argument function, the args are
                // stored in reverse order
                // [TODO] TEST is the order the same as in Java?
                object[] argumentsArray = arguments.ToArray();
                for (int j = 0; j < numargs2; j++)
                {
                    bif.add((ParseItem)argumentsArray[j]);
                }
            }
            stack.Push(bif);
        }
Пример #2
0
        /// <summary> Parses the sublist of tokens.  In most cases this will equate to
        /// the full list
        ///
        /// </summary>
        /// <param name="len">the .Length of the subexpression to parse
        /// </param>
        /// <exception cref=""> FormulaException
        /// </exception>
        private void  parseSubExpression(int len)
        {
            int   tokenVal = 0;
            Token t        = null;

            // Indicates that we are parsing the incredibly complicated and
            // hacky if construct that MS saw fit to include, the gits
            Stack ifStack = new Stack();

            // The end position of the sub-expression
            int endpos = pos + len;

            while (pos < endpos)
            {
                tokenVal = tokenData[pos];
                pos++;

                t = Token.getToken(tokenVal);

                if (t == Token.UNKNOWN)
                {
                    throw new FormulaException(FormulaException.unrecognizedToken, tokenVal);
                }

                Assert.verify(t != Token.UNKNOWN);

                // Operands
                if (t == Token.REF)
                {
                    CellReference cr = new CellReference(relativeTo);
                    pos += cr.read(tokenData, pos);
                    tokenStack.Push(cr);
                }
                else if (t == Token.REFV)
                {
                    SharedFormulaCellReference cr = new SharedFormulaCellReference(relativeTo);
                    pos += cr.read(tokenData, pos);
                    tokenStack.Push(cr);
                }
                else if (t == Token.REF3D)
                {
                    CellReference3d cr = new CellReference3d(relativeTo, workbook);
                    pos += cr.read(tokenData, pos);
                    tokenStack.Push(cr);
                }
                else if (t == Token.AREA)
                {
                    Area a = new Area();
                    pos += a.read(tokenData, pos);
                    tokenStack.Push(a);
                }
                else if (t == Token.AREAV)
                {
                    SharedFormulaArea a = new SharedFormulaArea(relativeTo);
                    pos += a.read(tokenData, pos);
                    tokenStack.Push(a);
                }
                else if (t == Token.AREA3D)
                {
                    Area3d a = new Area3d(workbook);
                    pos += a.read(tokenData, pos);
                    tokenStack.Push(a);
                }
                else if (t == Token.NAME)
                {
                    Name n = new Name();
                    pos += n.read(tokenData, pos);
                    tokenStack.Push(n);
                }
                else if (t == Token.NAMED_RANGE)
                {
                    NameRange nr = new NameRange(nameTable);
                    pos += nr.read(tokenData, pos);
                    tokenStack.Push(nr);
                }
                else if (t == Token.INTEGER)
                {
                    IntegerValue i = new IntegerValue();
                    pos += i.read(tokenData, pos);
                    tokenStack.Push(i);
                }
                else if (t == Token.DOUBLE)
                {
                    DoubleValue d = new DoubleValue();
                    pos += d.read(tokenData, pos);
                    tokenStack.Push(d);
                }
                else if (t == Token.BOOL)
                {
                    BooleanValue bv = new BooleanValue();
                    pos += bv.read(tokenData, pos);
                    tokenStack.Push(bv);
                }
                else if (t == Token.STRING)
                {
                    StringValue sv = new StringValue(settings);
                    pos += sv.read(tokenData, pos);
                    tokenStack.Push(sv);
                }
                else if (t == Token.MISSING_ARG)
                {
                    MissingArg ma = new MissingArg();
                    pos += ma.read(tokenData, pos);
                    tokenStack.Push(ma);
                }
                // Unary Operators
                else if (t == Token.UNARY_PLUS)
                {
                    UnaryPlus up = new UnaryPlus();
                    pos += up.read(tokenData, pos);
                    addOperator(up);
                }
                else if (t == Token.UNARY_MINUS)
                {
                    UnaryMinus um = new UnaryMinus();
                    pos += um.read(tokenData, pos);
                    addOperator(um);
                }
                else if (t == Token.PERCENT)
                {
                    Percent p = new Percent();
                    pos += p.read(tokenData, pos);
                    addOperator(p);
                }
                // Binary Operators
                else if (t == Token.SUBTRACT)
                {
                    Subtract s = new Subtract();
                    pos += s.read(tokenData, pos);
                    addOperator(s);
                }
                else if (t == Token.ADD)
                {
                    Add s = new Add();
                    pos += s.read(tokenData, pos);
                    addOperator(s);
                }
                else if (t == Token.MULTIPLY)
                {
                    Multiply s = new Multiply();
                    pos += s.read(tokenData, pos);
                    addOperator(s);
                }
                else if (t == Token.DIVIDE)
                {
                    Divide s = new Divide();
                    pos += s.read(tokenData, pos);
                    addOperator(s);
                }
                else if (t == Token.CONCAT)
                {
                    Concatenate c = new Concatenate();
                    pos += c.read(tokenData, pos);
                    addOperator(c);
                }
                else if (t == Token.POWER)
                {
                    Power p = new Power();
                    pos += p.read(tokenData, pos);
                    addOperator(p);
                }
                else if (t == Token.LESS_THAN)
                {
                    LessThan lt = new LessThan();
                    pos += lt.read(tokenData, pos);
                    addOperator(lt);
                }
                else if (t == Token.LESS_EQUAL)
                {
                    LessEqual lte = new LessEqual();
                    pos += lte.read(tokenData, pos);
                    addOperator(lte);
                }
                else if (t == Token.GREATER_THAN)
                {
                    GreaterThan gt = new GreaterThan();
                    pos += gt.read(tokenData, pos);
                    addOperator(gt);
                }
                else if (t == Token.GREATER_EQUAL)
                {
                    GreaterEqual gte = new GreaterEqual();
                    pos += gte.read(tokenData, pos);
                    addOperator(gte);
                }
                else if (t == Token.NOT_EQUAL)
                {
                    NotEqual ne = new NotEqual();
                    pos += ne.read(tokenData, pos);
                    addOperator(ne);
                }
                else if (t == Token.EQUAL)
                {
                    Equal e = new Equal();
                    pos += e.read(tokenData, pos);
                    addOperator(e);
                }
                else if (t == Token.PARENTHESIS)
                {
                    Parenthesis p = new Parenthesis();
                    pos += p.read(tokenData, pos);
                    addOperator(p);
                }
                // Functions
                else if (t == Token.ATTRIBUTE)
                {
                    Attribute a = new Attribute(settings);
                    pos += a.read(tokenData, pos);

                    if (a.Sum)
                    {
                        addOperator(a);
                    }
                    else if (a.isIf())
                    {
                        // Add it to a special stack for ifs
                        ifStack.Push(a);
                    }
                }
                else if (t == Token.FUNCTION)
                {
                    BuiltInFunction bif = new BuiltInFunction(settings);
                    pos += bif.read(tokenData, pos);

                    addOperator(bif);
                }
                else if (t == Token.FUNCTIONVARARG)
                {
                    VariableArgFunction vaf = new VariableArgFunction(settings);
                    pos += vaf.read(tokenData, pos);

                    if (vaf.Function != Function.ATTRIBUTE)
                    {
                        addOperator(vaf);
                    }
                    else
                    {
                        // This is part of an IF function.  Get the operands, but then
                        // add it to the top of the if stack
                        vaf.getOperands(tokenStack);

                        Attribute ifattr = null;
                        if (ifStack.Count <= 0)
                        {
                            ifattr = new Attribute(settings);
                        }
                        else
                        {
                            ifattr = (Attribute)ifStack.Pop();
                        }

                        ifattr.IfConditions = vaf;
                        tokenStack.Push(ifattr);
                    }
                }
                // Other things
                else if (t == Token.MEM_FUNC)
                {
                    MemFunc memFunc = new MemFunc();
                    pos += memFunc.read(tokenData, pos);

                    // Create new tokenStack for the sub expression
                    Stack oldStack = tokenStack;
                    tokenStack = new Stack();

                    parseSubExpression(memFunc.Length);

                    ParseItem[] subexpr = new ParseItem[tokenStack.Count];
                    int         i       = 0;
                    while (tokenStack.Count > 0)
                    {
                        subexpr[i] = (ParseItem)tokenStack.Pop();
                        i++;
                    }

                    memFunc.SubExpression = subexpr;

                    tokenStack = oldStack;
                    tokenStack.Push(memFunc);
                }
            }
        }