⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stringformulaparser.java

📁 jxtl API Java中Excel的生成与导入解析参考文档
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
*
*      Copyright (C) 2002 Andrew Khan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***************************************************************************/

package jxl.biff.formula;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;

import common.Logger;

import jxl.WorkbookSettings;
import jxl.biff.WorkbookMethods;

/**
 * Parses a string formula into a parse tree
 */
class StringFormulaParser implements Parser
{
  /**
   * The logger
   */
  private static Logger logger = Logger.getLogger(StringFormulaParser.class);

  /**
   * The formula string passed to this object
   */
  private String formula;

  /**
   * The parsed formula string, as retrieved from the parse tree
   */
  private String parsedFormula;

  /**
   * The parse tree
   */
  private ParseItem root;

  /**
   * The stack argument used when parsing a function in order to
   * pass multiple arguments back to the calling method
   */
  private Stack arguments;

  /**
   * The workbook settings
   */
  private WorkbookSettings settings;

  /**
   * A handle to the external sheet
   */
  private ExternalSheet externalSheet;

  /**
   * A handle to the name table
   */
  private WorkbookMethods nameTable;

  /**
   * Constructor
   * @param f
   * @param ws
   */
  public StringFormulaParser(String f, 
                             ExternalSheet es, 
                             WorkbookMethods nt, 
                             WorkbookSettings ws)
  {
    formula = f;
    settings = ws;
    externalSheet = es;
    nameTable = nt;
  }

  /**
   * Parses the list of tokens
   *
   * @exception FormulaException
   */
  public void parse() throws FormulaException
  {
    ArrayList tokens = getTokens();
    
    Iterator i = tokens.iterator();
    
    root = parseCurrent(i);
  }

  /**
   * Recursively parses the token array.  Recursion is used in order
   * to evaluate parentheses and function arguments
   *
   * @param i an iterator of tokens
   * @return the root node of the current parse stack
   * @exception FormulaException if an error occurs
   */
  private ParseItem parseCurrent(Iterator i) throws FormulaException
  {
    Stack stack = new Stack();
    Stack operators = new Stack();
    Stack args = null; // we usually don't need this

    boolean parenthesesClosed = false;
    ParseItem lastParseItem = null;
    
    while (i.hasNext() && !parenthesesClosed)
    {
      ParseItem pi = (ParseItem) i.next();

      if (pi instanceof Operand)
      {
        handleOperand((Operand) pi, stack);
      }
      else if (pi instanceof StringFunction)
      {
        handleFunction((StringFunction) pi, i, stack);
      }
      else if (pi instanceof Operator)
      {
        Operator op = (Operator) pi;

        // See if the operator is a binary or unary operator
        // It is a unary operator either if the stack is empty, or if
        // the last thing off the stack was another operator
        if (op instanceof StringOperator)
        {
          StringOperator sop = (StringOperator) op;
          if (stack.isEmpty() || lastParseItem instanceof Operator)
          {
            op = sop.getUnaryOperator();
          }
          else
          {
            op = sop.getBinaryOperator();
          }
        }

        if (operators.empty())
        {
          // nothing much going on, so do nothing for the time being
          operators.push(op);
        }
        else
        {
          Operator operator = (Operator) operators.peek();

          // If the last  operator has a higher precedence then add this to 
          // the operator stack and wait
          if (op.getPrecedence() <= operator.getPrecedence())
          {
            operators.push(op);
          }
          else
          {
            // The operator is a lower precedence so we can sort out
            // some of the items on the stack
            operators.pop(); // remove the operator from the stack
            operator.getOperands(stack);
            stack.push(operator);
            operators.push(op);
          }
        }
      }
      else if (pi instanceof ArgumentSeparator)
      {
        // Clean up any remaining items on this stack
        while (!operators.isEmpty())
        {
          Operator o = (Operator) operators.pop();
          o.getOperands(stack);
          stack.push(o);
        }
        
        // Add it to the argument stack.  Create the argument stack
        // if necessary.  Items will be stored on the argument stack in
        // reverse order
        if (args == null)
        {
          args = new Stack();
        }

        args.push(stack.pop());
        stack.clear();
      }
      else if (pi instanceof OpenParentheses)
      {
        ParseItem pi2 = parseCurrent(i);
        Parenthesis p = new Parenthesis();
        pi2.setParent(p);
        p.add(pi2);
        stack.push(p);
      }
      else if (pi instanceof CloseParentheses)
      {
        parenthesesClosed = true;
      }
      
      lastParseItem = pi;
    }

    while (!operators.isEmpty())
    {
      Operator o = (Operator) operators.pop();
      o.getOperands(stack);
      stack.push(o);
    }

    ParseItem rt = !stack.empty()? (ParseItem) stack.pop():null;

    // if the argument stack is not null, then add it to that stack
    // as well for good measure
    if (args != null && rt != null)
    {
      args.push(rt);
    }

    arguments = args;

    if (!stack.empty() || !operators.empty() )
    {
      logger.warn("Formula " + formula + 
                  " has a non-empty parse stack");
    }

    return rt;
  }

  /**
   * Gets the list of lexical tokens using the generated lexical analyzer
   *
   * @return the list of tokens
   * @exception FormulaException if an error occurs
   */
  private ArrayList getTokens() throws FormulaException
  {
    ArrayList tokens = new ArrayList();

    StringReader sr = new StringReader(formula);
    Yylex lex = new Yylex(sr);
    lex.setExternalSheet(externalSheet);
    lex.setNameTable(nameTable);
    try
    {
      ParseItem pi = lex.yylex();
      while (pi != null)
      {
        tokens.add(pi);
        pi = lex.yylex();
      }
    }
    catch (IOException e)
    {
      logger.warn(e.toString());
    }
    catch (Error e)
    {
      throw new FormulaException(FormulaException.LEXICAL_ERROR,
                                 formula + " at char  " + lex.getPos());
    }
      

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -