acoliver    02/04/17 16:06:49

  Added:       src/java/org/apache/poi/hssf/record/formula
                        FormulaParser.java
  Log:
  added new class from Avik Sengupta
  
  Revision  Changes    Path
  1.1                  
jakarta-poi/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java
  
  Index: FormulaParser.java
  ===================================================================
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache POI" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache POI", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  package org.apache.poi.hssf.record.formula;
  
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Stack;
  
  /**
   * EXPERIMENTAL code to parse formulas back and forth between RPN and not
   *
   * @author Avik Sengupta <[EMAIL PROTECTED]>
   */
  public class FormulaParser {
      
      private String formulaString;
      private int pointer=0;
      
      private Stack operationsList = new java.util.Stack();
      private Stack operandsList = new java.util.Stack();
      private List result = new ArrayList();
      private int numParen;
      
      //{--------------------------------------------------------------}
      //{ Constant Declarations }
      
      private static char TAB = '\t';
      private static char CR = '\n';
      
      //{--------------------------------------------------------------}
      //{ Variable Declarations }
      
      private char Look;              //{ Lookahead Character }
      
      public FormulaParser(String formula){
          formulaString = formula;
          pointer=0;
      }
      
      //{--------------------------------------------------------------}
      //{ Read New Character From Input Stream }
      
      private void GetChar() {
          Look=formulaString.charAt(pointer++);
          System.out.println("Got char: "+Look);
      }
      
      //{--------------------------------------------------------------}
      //{ Report an Error }
      
      private void Error(String s) {
          System.out.println("Error: "+s);
      }
      
      
      //{--------------------------------------------------------------}
      //{ Report Error and Halt }
      
      private void Abort(String s) {
          Error(s);
          //System.exit(1);  //throw exception??
          throw new RuntimeException("Cannot Parse, sorry");
      }
      
      
      //{--------------------------------------------------------------}
      //{ Report What Was Expected }
      
      private void Expected(String s) {
          Abort(s + " Expected");
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize an Alpha Character }
      
      private boolean IsAlpha(char c) {
          return Character.isLetter(c);
          //return  UpCase(c) in ['A'..'Z'];
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize a Decimal Digit }
      
      private boolean IsDigit(char c) {
          System.out.println("Checking digit for"+c);
          return Character.isDigit(c);
          
          //return ("0123456789".indexOf( (int) c) != 0)//c in ['0'..'9'];
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize an Alphanumeric }
      
      private boolean  IsAlNum(char c) {
          return  (IsAlpha(c) || IsDigit(c));
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize an Addop }
      
      private boolean IsAddop( char c) {
          return (c =='+' || c =='-');
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize White Space }
      
      private boolean IsWhite( char c) {
          return  (c ==' ' || c== TAB);
      }
      
      
      //{--------------------------------------------------------------}
      //{ Skip Over Leading White Space }
      
      private void SkipWhite() {
          while (IsWhite(Look)) {
              GetChar();
          }
      }
      
      
      //{--------------------------------------------------------------}
      //{ Match a Specific Input Character }
      
      private void Match(char x) {
          if (Look != x) {
              Expected("" + x + "");
          }else {
              GetChar();
              SkipWhite();
          }
      }
      
      
      //{--------------------------------------------------------------}
      //{ Get an Identifier }
      
      private String GetName() {
          String Token;
          Token = "";
          if (!IsAlpha(Look)) {
              Expected("Name");
          }
          while (IsAlNum(Look)) {
              Token = Token + Character.toUpperCase(Look);
              GetChar();
          }
          
          SkipWhite();
          return Token;
      }
      
      
      //{--------------------------------------------------------------}
      //{ Get a Number }
      
      private String GetNum() {
          String Value ="";
          if  (!IsDigit(Look)) Expected("Integer");
          while (IsDigit(Look)){
              Value = Value + Look;
              GetChar();
          }
          SkipWhite();
          return Value;
      }
      
      
      //{--------------------------------------------------------------}
      //{ Output a String with Tab }
      
      private void  Emit(String s){
          System.out.print(TAB+s);
      }
      
      
      //{--------------------------------------------------------------}
      //{ Output a String with Tab and CRLF }
      
      private void EmitLn(String s) {
          Emit(s);
          System.out.println();;
      }
      
      
      //{---------------------------------------------------------------}
      //{ Parse and Translate a Identifier }
      
      private void Ident() {
          String Name;
          Name = GetName();
          if (Look == '('){
              Match('(');
              //Expression() -- add this!
              Match(')');
              //this is the end of the function
              //EmitLn("BSR " + Name);
          } else {
              //EmitLn("MOVE " + Name + "(PC),D0b");
              //this can be either a cell ref or a named range !!
              
              boolean cellRef = true ; //we should probably do it with reg exp??
              if (cellRef) {
                  operationsList.add(new ValueReferencePtg()); //TODO we need to pass 
in Name somewhere
              }else {
                  //handle after named range is integrated!!
              }
          }
      }
  
      
      //{---------------------------------------------------------------}
      //{ Parse and Translate a Math Factor }
      
      //procedure Expression; Forward;
      
      private void Factor() {
          if (Look == '(' ) {
              Match('(');
              operationsList.add(new ParenthesisPtg());
              Expression();
              Match(')');
              operationsList.add(new ParenthesisPtg());
              return;
          } else if (IsAlpha(Look)){
              Ident();
          }else{
              //EmitLn("MOVE #" + GetNum() + ",D0");
              IntPtg p = new IntPtg();
              p.setValue(Short.parseShort(GetNum()));
              operandsList.add(p);
          }
      }
  
      
      //{--------------------------------------------------------------}
      //{ Recognize and Translate a Multiply }
      
      private void Multiply(){
          Match('*');
          Factor();
          operationsList.add(new MultiplyPtg());
          //EmitLn("MULS (SP)+,D0");
      }
      
      
      //{-------------------------------------------------------------}
      //{ Recognize and Translate a Divide }
      
      private void Divide() {
          Match('/');
          Factor();
          operationsList.add(new DividePtg());
          //EmitLn("MOVE (SP)+,D1");
          //EmitLn("EXS.L D0");
          //EmitLn("DIVS D1,D0");
      }
      
      
      //{---------------------------------------------------------------}
      //{ Parse and Translate a Math Term }
      
      private void  Term(){
          Factor();
          while (Look == '*' || Look == '/' ) {
              //EmitLn("MOVE D0,-(SP)");
              ///TODO do we need to do anything here??
              if (Look == '*') Multiply();
              if (Look == '/') Divide();
          }
      }
      
      
      //{--------------------------------------------------------------}
      //{ Recognize and Translate an Add }
      
      private void Add() {
          Match('+');
          Term();
          //EmitLn("ADD (SP)+,D0");
          operationsList.add(new AddPtg());
      }
      
      
      //{-------------------------------------------------------------}
      //{ Recognize and Translate a Subtract }
      
      private void Subtract() {
          Match('-');
          Term();
          operationsList.add(new SubtractPtg());
          //EmitLn("SUB (SP)+,D0");
          //EmitLn("NEG D0");
      }
      
      
      //{---------------------------------------------------------------}
      //{ Parse and Translate an Expression }
      
      private void Expression() {
          if (IsAddop(Look)) {
              EmitLn("CLR D0");  //unaryAdd ptg???
          } else {
              Term();
          }
          while (IsAddop(Look)) {
              EmitLn("MOVE D0,-(SP)");
              if ( Look == '+' )  Add();
              if (Look == '-') Subtract();
          }
      }
      
      
      //{--------------------------------------------------------------}
      //{ Parse and Translate an Assignment Statement }
      /**
  procedure Assignment;
  var Name: string[8];
  begin
     Name := GetName;
     Match('=');
     Expression;
     EmitLn('LEA ' + Name + '(PC),A0');
     EmitLn('MOVE D0,(A0)')
  end;
       **/
      
      //{--------------------------------------------------------------}
      //{ Initialize }
      
      private void  Init() {
          GetChar();
          SkipWhite();
      }
      
      public void parse() {
          Init();
          Expression();
          //now tokenisation is done .. convert to RPN!!
          tokenToRPN();
      }
      
      private void tokenToRPN() {
          OperationPtg op;
          Ptg operand;
          int numOper = 0;
          int numOnStack = 0;
          result.add(operandsList.pop()); numOnStack++;
          
          while (!operationsList.isEmpty()) {
              op = (OperationPtg) operationsList.pop();
              if (op instanceof ParenthesisPtg) {
                  // do something smart
              }
              
              
              for (numOper = op.getNumberOfOperands();numOper>0;numOper--) {
                  if (numOnStack==0) {
                      result.add(operandsList.pop());//numOnStack++;
                  } else {
                      numOnStack--;
                  }
              }
              result.add(op);
              numOnStack++;
          }
      }
      
      public String toString() {
          StringBuffer buf = new StringBuffer();
             for (int i=0;i<result.size();i++) {
              buf.append( ( (Ptg)result.get(i)).toFormulaString());
              buf.append(' ');
          } 
          return buf.toString();
      }
      
      
      //{--------------------------------------------------------------}
      //{ Main Program for testing}
      public static void main(String[] argv) {
          FormulaParser fp = new FormulaParser(argv[0]+";");
          fp.parse();
          System.out.println(fp.toString());
          
          //If Look <> CR then Expected('NewLine');
      }
      //{--------------------------------------------------------------}
      
  } 
  
  


Reply via email to