On Fri, 2002-04-05 at 02:59, Avik Sengupta wrote:
> Ok, this turned out to be simple. An updated patch (against latest cvs) that 
> solves the parenthesis display problem i mentioned earlier. (Parenthesis Ptgs 
> ARE written, even tho its not required for RPN calc)
> 
> Have a good weekend folks. 
> 
> Cheers
> -
> Avik
> 
> PS. Does the formula viewer work? I cant seem to get it to. 
> 

Probably not.  All the existing formula stuff (before we started on this
again recently) was from my first wack at it back in October I think. 
And well, I'd absolutely no idea what I was doing as far as formulas go
back then.  Feel free to make it work.  I envisioend it being to
formulas what BiffViewer is to HSSF in general. But it needs a bit more
work to be useful.  (actually BiffViewer...well ... IS the original HSSF
;-) )

> PPS. Anybody have any idea on section  3.12 of the openoffice excel doc 
> (predefined sheet formulas) which at the moment is blank? I could do with only 
> a few example id's so that i could test. 
> ----
> 

> ? formula3.patch
> ? src/documentation/xdocs/.nbattrs
> ? src/documentation/xdocs/hdf/.nbattrs
> ? src/documentation/xdocs/hpsf/.nbattrs
> ? src/documentation/xdocs/hssf/.nbattrs
> ? src/documentation/xdocs/news/.nbattrs
> ? src/documentation/xdocs/plan/.nbattrs
> ? src/documentation/xdocs/poifs/.nbattrs
> ? src/documentation/xdocs/resolutions/.nbattrs
> ? src/documentation/xdocs/utils/.nbattrs
> ? src/java/org/apache/poi/hssf/model/.nbattrs
> ? src/java/org/apache/poi/hssf/record/.nbattrs
> ? src/java/org/apache/poi/hssf/record/formula/.nbattrs
> ? src/java/org/apache/poi/hssf/record/formula/DummyFunctionPtg.java
> ? src/java/org/apache/poi/hssf/usermodel/.nbattrs
> ? tools/antipede/lib/temp
> Index: .cvsignore
> ===================================================================
> RCS file: /home/cvspublic/jakarta-poi/.cvsignore,v
> retrieving revision 1.7
> diff -u -r1.7 .cvsignore
> --- .cvsignore        15 Apr 2002 08:07:45 -0000      1.7
> +++ .cvsignore        26 Apr 2002 16:17:14 -0000
> @@ -6,3 +6,4 @@
>  log*.*
>  *.log
>  build
> +.nbattrs
> Index: src/documentation/xdocs/plan/POI20Vision.xml
> ===================================================================
> RCS file: /home/cvspublic/jakarta-poi/src/documentation/xdocs/plan/POI20Vision.xml,v
> retrieving revision 1.5
> diff -u -r1.5 POI20Vision.xml
> --- src/documentation/xdocs/plan/POI20Vision.xml      6 Apr 2002 13:36:06 -0000      
> 1.5
> +++ src/documentation/xdocs/plan/POI20Vision.xml      26 Apr 2002 16:17:52 -0000
> @@ -17,12 +17,12 @@
>   <section title="Preface">
>          <p>
>                  This is the POI 2.0 cycle vision document.  Although the vision
> -                has not changed and this document is certainly not out of date and 
> -                the vision has not changed, the structure of the project has
> +                has not changed and this document is certainly not out of date, 
> +                the structure of the project has
>                  changed a bit.  We're not going to change the vision document to
>                  reflect this (however proper that may be) because it would only
>                  involve deletion.  There is no purpose in providing less
> -                information provided we give clarification.
> +                information, provided we give clarification.
>          </p>
>          <p>
>                  This document was created before the POI components for 
> @@ -94,7 +94,7 @@
>                  </li>
>                  <li>
>                          Refactor HSSF for greater
> -                     performance as well as an event-driven API for reading
> +                     performance as well as provide an event-driven API for reading
>                  </li>
>                  <li>
>                          Extend HSSF by adding the ability to read and write 
>formulas.
> @@ -116,7 +116,7 @@
>                          POIFSSerializer and HSSFSerializer
>                  </li>
>                  <li>
> -                        Providing the create excel charts. (write only)
> +                        Providing the ability to create excel charts. (write only)
>                  </li>
>          </ul>
>    </section>
> Index: src/java/org/apache/poi/hssf/record/FormulaRecord.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/FormulaRecord.java,v
> retrieving revision 1.5
> diff -u -r1.5 FormulaRecord.java
> --- src/java/org/apache/poi/hssf/record/FormulaRecord.java    18 Apr 2002 12:00:53 
>-0000      1.5
> +++ src/java/org/apache/poi/hssf/record/FormulaRecord.java    26 Apr 2002 16:18:20 
>-0000
> @@ -78,7 +78,7 @@
>      implements CellValueRecordInterface, Comparable
>  {
>      
> -    public static final boolean EXPERIMENTAL_FORMULA_SUPPORT_ENABLED=false;
> +    public static final boolean EXPERIMENTAL_FORMULA_SUPPORT_ENABLED=true;
>      
>      public static final short sid =
>          0x06;   // docs say 406...because of a bug Microsoft support site article 
>#Q184647)
> @@ -359,11 +359,10 @@
>          LittleEndian.putShort(data, 18 + offset, getOptions());
>          LittleEndian.putInt(data, 20 + offset, field_6_zero);
>          LittleEndian.putShort(data, 24 + offset, getExpressionLength());
> +        serializePtgs(data, 26+offset);
>          } else {
>              System.arraycopy(all_data,0,data,offset,all_data.length);
>          }
> -
> -        // serializePtgs(data, 26+offset);
>          return getRecordSize();
>      }
>  
> Index: src/java/org/apache/poi/hssf/record/formula/AddPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/AddPtg.java,v
> retrieving revision 1.3
> diff -u -r1.3 AddPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/AddPtg.java   23 Apr 2002 23:56:46 
>-0000      1.3
> +++ src/java/org/apache/poi/hssf/record/formula/AddPtg.java   26 Apr 2002 16:18:32 
>-0000
> @@ -141,6 +141,7 @@
>          return buffer.toString();
>      }
>      
> +    
>      public int getPrecedence() {
>          return 5;
>      }
> @@ -148,6 +149,18 @@
>      public int getStringLength() {
>          return 1;
>      }
> +
> +    
> +    public String toFormulaString(String[] operands) {
> +        StringBuffer buffer = new StringBuffer();
> +
> +        buffer.append(operands[ 0 ]);
> +        buffer.append("+");
> +        buffer.append(operands[ 1 ]);
> +        return buffer.toString();
> +    }
> +    
> +
>      
>      public void manipulate(List source, List results, int pos) {
>          standardBinaryManipulation(source,results,pos);
> Index: src/java/org/apache/poi/hssf/record/formula/AttrPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/AttrPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 AttrPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/AttrPtg.java  23 Apr 2002 23:56:46 
>-0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/AttrPtg.java  26 Apr 2002 16:18:40 
>-0000
> @@ -210,5 +210,12 @@
>      public void manipulate(List source, List results, int pos) {
>      }
>      
> +    public String toFormulaString(String[] operands) {
> +        return "SUM(" + operands[ 0 ] + ")";
> +    }    
> +    
> +    public int getPrecedence() {
> +        return 1;
> +    }    
>      
>  }
> Index: src/java/org/apache/poi/hssf/record/formula/DividePtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/DividePtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 DividePtg.java
> --- src/java/org/apache/poi/hssf/record/formula/DividePtg.java        23 Apr 2002 
>23:56:46 -0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/DividePtg.java        26 Apr 2002 
>16:18:46 -0000
> @@ -119,7 +119,25 @@
>          buffer.append(operands[ 1 ].toFormulaString());
>          return buffer.toString();
>      }
> +
> +     public int getPrecedence() {
> +        return 4;
> +    }
>      
> +    public int getStringLength() {
> +        return 1;
> +    }
> +    
> +    public String toFormulaString(String[] operands) {
> +        StringBuffer buffer = new StringBuffer();
> +
> +        buffer.append(operands[ 0 ]);
> +        buffer.append("/");
> +        buffer.append(operands[ 1 ]);
> +        return buffer.toString();
> +    }
> +    
> +
>      public void manipulate(List source, List results, int pos) {
>      }
>      
> Index: src/java/org/apache/poi/hssf/record/formula/FormulaParser.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/FormulaParser.java,v
> retrieving revision 1.1
> diff -u -r1.1 FormulaParser.java
> --- src/java/org/apache/poi/hssf/record/formula/FormulaParser.java    17 Apr 2002 
>23:06:49 -0000      1.1
> +++ src/java/org/apache/poi/hssf/record/formula/FormulaParser.java    26 Apr 2002 
>16:19:03 -0000
> @@ -60,56 +60,66 @@
>  import java.util.ArrayList;
>  import java.util.Stack;
>  
> +import org.apache.poi.hssf.usermodel.*;
> +import java.io.FileOutputStream;
> +
>  /**
> - * EXPERIMENTAL code to parse formulas back and forth between RPN and not
> + * EXPERIMENTAL 
> + *
> + * @author Avik Sengupta <avik AT Avik Sengupta DOT com>
>   *
> - * @author Avik Sengupta <[EMAIL PROTECTED]>
> + * This class parses a formula string into a List of tokens in RPN order
> + * Inspired by 
> + *           Lets Build a Compiler, by Jack Crenshaw
> + * BNF for the formula expression is :
> + * <expression> ::= <term> [<addop> <term>]*
> + * <term> ::= <factor>  [ <mulop> <factor ]*
> + * <factor> ::= <number> | (<expression>) | <cellRef> 
>   */
>  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 tokens = new java.util.Stack();
> +    //private Stack tokens = 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 
>      
> -    private char Look;              //{ Lookahead Character }
>      
> +    /** create the parser with the string that is to be parsed
> +     *    later call the parse() method to return ptg list in rpn order
> +     *    then call the getRPNPtg() to retrive the parse results
> +     *  This class is recommended only for single threaded use
> +     *  The parse and getPRNPtg are internally synchronized for safety, thus
> +     *  while it is safe to use in a multithreaded environment, you will get long 
>lock waits.  
> +     */
>      public FormulaParser(String formula){
>          formulaString = formula;
>          pointer=0;
>      }
>      
> -    //{--------------------------------------------------------------}
> -    //{ Read New Character From Input Stream }
> -    
> +
> +    /** Read New Character From Input Stream */
>      private void GetChar() {
>          Look=formulaString.charAt(pointer++);
> -        System.out.println("Got char: "+Look);
> +        //System.out.println("Got char: "+Look);
>      }
>      
> -    //{--------------------------------------------------------------}
> -    //{ Report an Error }
> -    
> +
> +    /** Report an Error */
>      private void Error(String s) {
>          System.out.println("Error: "+s);
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Report Error and Halt }
> -    
> + 
> +    /** Report Error and Halt */
>      private void Abort(String s) {
>          Error(s);
>          //System.exit(1);  //throw exception??
> @@ -117,61 +127,50 @@
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Report What Was Expected }
> -    
> +
> +    /** Report What Was Expected */
>      private void Expected(String s) {
>          Abort(s + " Expected");
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Recognize an Alpha Character }
> -    
> + 
> +    /** Recognize an Alpha Character */
>      private boolean IsAlpha(char c) {
>          return Character.isLetter(c);
> -        //return  UpCase(c) in ['A'..'Z'];
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Recognize a Decimal Digit }
> -    
> + 
> +    /** Recognize a Decimal Digit */
>      private boolean IsDigit(char c) {
> -        System.out.println("Checking digit for"+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 }
> -    
> +
> +    /** Recognize an Alphanumeric */
>      private boolean  IsAlNum(char c) {
>          return  (IsAlpha(c) || IsDigit(c));
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Recognize an Addop }
> -    
> +
> +    /** Recognize an Addop */
>      private boolean IsAddop( char c) {
>          return (c =='+' || c =='-');
>      }
>      
> -    
> -    //{--------------------------------------------------------------}
> -    //{ Recognize White Space }
> -    
> +
> +    /** Recognize White Space */
>      private boolean IsWhite( char c) {
>          return  (c ==' ' || c== TAB);
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Skip Over Leading White Space }
> -    
> +
> +    /** Skip Over Leading White Space */
>      private void SkipWhite() {
>          while (IsWhite(Look)) {
>              GetChar();
> @@ -179,9 +178,8 @@
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Match a Specific Input Character }
> -    
> +
> +    /** Match a Specific Input Character */
>      private void Match(char x) {
>          if (Look != x) {
>              Expected("" + x + "");
> @@ -192,9 +190,7 @@
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Get an Identifier }
> -    
> +    /** Get an Identifier */
>      private String GetName() {
>          String Token;
>          Token = "";
> @@ -211,9 +207,7 @@
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Get a Number }
> -    
> +    /** Get a Number */
>      private String GetNum() {
>          String Value ="";
>          if  (!IsDigit(Look)) Expected("Integer");
> @@ -224,139 +218,120 @@
>          SkipWhite();
>          return Value;
>      }
> -    
> -    
> -    //{--------------------------------------------------------------}
> -    //{ Output a String with Tab }
> -    
> +
> +    /** Output a String with Tab */
>      private void  Emit(String s){
>          System.out.print(TAB+s);
>      }
> -    
> -    
> -    //{--------------------------------------------------------------}
> -    //{ Output a String with Tab and CRLF }
> -    
> +
> +    /** Output a String with Tab and CRLF */
>      private void EmitLn(String s) {
>          Emit(s);
>          System.out.println();;
>      }
>      
> -    
> -    //{---------------------------------------------------------------}
> -    //{ Parse and Translate a Identifier }
> -    
> +    /** Parse and Translate a Identifier */
>      private void Ident() {
>          String Name;
>          Name = GetName();
>          if (Look == '('){
> +            //This is a function 
>              Match('(');
> -            //Expression() -- add this!
> +            int numArgs = Arguments(); 
>              Match(')');
>              //this is the end of the function
> -            //EmitLn("BSR " + Name);
> +            tokens.add(new DummyFunctionPtg(Name,numArgs));
>          } 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
> +                tokens.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;
>      
> +    /** get arguments to a function */
> +    private int Arguments() {
> +        int numArgs = 0;
> +        if (Look != ')')  {
> +            numArgs++; 
> +            Expression();
> +        }
> +        while (Look == ',') {
> +            Match(',');
> +            Expression();
> +            numArgs++;
> +        }
> +        return numArgs;
> +    }
> +
> +   /** Parse and Translate a Math Factor  */
>      private void Factor() {
>          if (Look == '(' ) {
>              Match('(');
> -            operationsList.add(new ParenthesisPtg());
>              Expression();
>              Match(')');
> -            operationsList.add(new ParenthesisPtg());
> +            tokens.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);
> +            tokens.add(p);
>          }
>      }
>  
>      
> -    //{--------------------------------------------------------------}
> -    //{ Recognize and Translate a Multiply }
> -    
> +    /** Recognize and Translate a Multiply */
>      private void Multiply(){
>          Match('*');
>          Factor();
> -        operationsList.add(new MultiplyPtg());
> -        //EmitLn("MULS (SP)+,D0");
> +        tokens.add(new MultiplyPtg());
> +  
>      }
>      
>      
> -    //{-------------------------------------------------------------}
> -    //{ Recognize and Translate a Divide }
> -    
> +    /** 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");
> +        tokens.add(new DividePtg());
> +
>      }
>      
>      
> -    //{---------------------------------------------------------------}
> -    //{ Parse and Translate a Math Term }
> -    
> +    /** 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 }
> -    
> +    /** Recognize and Translate an Add */
>      private void Add() {
>          Match('+');
>          Term();
> -        //EmitLn("ADD (SP)+,D0");
> -        operationsList.add(new AddPtg());
> +        tokens.add(new AddPtg());
>      }
>      
>      
> -    //{-------------------------------------------------------------}
> -    //{ Recognize and Translate a Subtract }
> -    
> +    /** Recognize and Translate a Subtract */
>      private void Subtract() {
>          Match('-');
>          Term();
> -        operationsList.add(new SubtractPtg());
> -        //EmitLn("SUB (SP)+,D0");
> -        //EmitLn("NEG D0");
> +        tokens.add(new SubtractPtg());
>      }
>      
>      
> -    //{---------------------------------------------------------------}
> -    //{ Parse and Translate an Expression }
> -    
> +    /** Parse and Translate an Expression */
>      private void Expression() {
>          if (IsAddop(Look)) {
>              EmitLn("CLR D0");  //unaryAdd ptg???
> @@ -364,9 +339,10 @@
>              Term();
>          }
>          while (IsAddop(Look)) {
> -            EmitLn("MOVE D0,-(SP)");
>              if ( Look == '+' )  Add();
>              if (Look == '-') Subtract();
> +            // if (Look == '*') Multiply();
> +           // if (Look == '/') Divide();
>          }
>      }
>      
> @@ -380,71 +356,104 @@
>     Name := GetName;
>     Match('=');
>     Expression;
> -   EmitLn('LEA ' + Name + '(PC),A0');
> -   EmitLn('MOVE D0,(A0)')
> +
>  end;
>       **/
>      
> -    //{--------------------------------------------------------------}
> -    //{ Initialize }
> + 
> +    /** Initialize */
>      
>      private void  Init() {
>          GetChar();
>          SkipWhite();
>      }
>      
> +    /** API call to execute the parsing of the formula
> +     *
> +     */
>      public void parse() {
> -        Init();
> -        Expression();
> -        //now tokenisation is done .. convert to RPN!!
> -        tokenToRPN();
> +        synchronized (tokens) {
> +            Init();
> +            Expression();
> +        }
>      }
>      
> -    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
> +    /** API call to retrive the array of Ptgs created as 
> +     * a result of the parsing
> +     */
> +    public Ptg[] getRPNPtg() {
> +       synchronized (tokens) {
> +            if (tokens == null) throw new IllegalStateException("Please parse a 
>string before trying to access the parse result");
> +            Ptg[] retval = new Ptg[tokens.size()];
> +            return (Ptg[]) tokens.toArray(retval);
> +       }
> +    }
> +    
> +    /** Static method to convert an array of Ptgs in RPN order 
> +     *  to a human readable string format in infix mode
> +     *  TODO - extra brackets might appear, but string will be semantically 
>correct. 
> +     */
> +    public static String toFormulaString(Ptg[] ptgs) {
> +        java.util.Stack stack = new java.util.Stack();
> +        int numPtgs = ptgs.length;
> +        OperationPtg o;
> +        int numOperands;
> +        String[] operands;
> +        for (int i=0;i<numPtgs;i++) {
> +            if (ptgs[i] instanceof OperationPtg) {
> +                o = (OperationPtg) ptgs[i];
> +                numOperands = o.getNumberOfOperands();
> +                operands = new String[numOperands];
> +                for (int j=0;j<numOperands;j++) {
> +                    operands[numOperands-j-1] = (String) stack.pop(); //TODO: catch 
>stack underflow and throw parse exception. 
> +                    
> +                }  
> +                String result = o.toFormulaString(operands);
> +                //if (! (o instanceof DummyFunctionPtg) ) result = "("+result+")" ;
> +                stack.push(result);
> +            } else {
> +                stack.push(ptgs[i].toFormulaString());
>              }
> -            
> -            
> -            for (numOper = op.getNumberOfOperands();numOper>0;numOper--) {
> -                if (numOnStack==0) {
> -                    result.add(operandsList.pop());//numOnStack++;
> -                } else {
> -                    numOnStack--;
> -                }
> -            }
> -            result.add(op);
> -            numOnStack++;
>          }
> +        return (String) stack.pop(); //TODO: catch stack underflow and throw parse 
>exception. 
>      }
> -    
> +   
>      public String toString() {
>          StringBuffer buf = new StringBuffer();
> -           for (int i=0;i<result.size();i++) {
> -            buf.append( ( (Ptg)result.get(i)).toFormulaString());
> +           for (int i=0;i<tokens.size();i++) {
> +            buf.append( ( (Ptg)tokens.get(i)).toFormulaString());
>              buf.append(' ');
>          } 
>          return buf.toString();
>      }
>      
>      
> -    //{--------------------------------------------------------------}
> -    //{ Main Program for testing}
> +    /** Main Program for testing*/
>      public static void main(String[] argv) {
>          FormulaParser fp = new FormulaParser(argv[0]+";");
> +        System.out.println("\nFormula is: ");
>          fp.parse();
> -        System.out.println(fp.toString());
> +        System.out.println("RPN Form is: " +fp.toString());
> +        
> +        System.out.println("Converted Text form is : 
>"+fp.toFormulaString(fp.getRPNPtg()));
> +        try {
> +        short            rownum = 0;
> +        FileOutputStream out    = new FileOutputStream("test.xls");
> +        HSSFWorkbook     wb     = new HSSFWorkbook();
> +        HSSFSheet        s      = wb.createSheet();
> +        HSSFRow          r      = null;
> +        HSSFCell         c      = null;
> +        
> +        r = s.createRow((short) 0);
> +        c = r.createCell((short) 0);
> +        c.setCellFormula(argv[0]);
>          
> +        wb.write(out);
> +        out.close();
> +        } catch (java.io.IOException ioe) {
> +            ioe.printStackTrace();
> +        }
>          //If Look <> CR then Expected('NewLine');
>      }
> -    //{--------------------------------------------------------------}
>      
>  } 
> Index: src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 MultiplyPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java      23 Apr 2002 
>23:56:46 -0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/MultiplyPtg.java      26 Apr 2002 
>16:19:09 -0000
> @@ -132,6 +132,16 @@
>          return buffer.toString();
>      }
>      
> +    public String toFormulaString(String[] operands) {
> +        StringBuffer buffer = new StringBuffer();
> +
> +        buffer.append(operands[ 0 ]);
> +        buffer.append("*");
> +        buffer.append(operands[ 1 ]);
> +        return buffer.toString();
> +    }
> +    
> +    
>      public void manipulate(List source, List results, int pos) {
>          standardBinaryManipulation(source, results, pos);
>      }
> @@ -155,4 +165,5 @@
>      }
>      
>      
> +
>  }
> Index: src/java/org/apache/poi/hssf/record/formula/OperationPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/OperationPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 OperationPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/OperationPtg.java     23 Apr 2002 
>23:56:46 -0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/OperationPtg.java     26 Apr 2002 
>16:19:15 -0000
> @@ -74,6 +74,10 @@
>      public final static int TYPE_FUNCTION = 2;
>  
>      public abstract int getType();
> +    
> +    public abstract String toFormulaString(String[] operands);
> +    
> +    public abstract int getPrecedence();
>  
>      public abstract int getNumberOfOperands();
>      
> Index: src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java,v
> retrieving revision 1.3
> diff -u -r1.3 ParenthesisPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java   23 Apr 2002 
>23:56:46 -0000      1.3
> +++ src/java/org/apache/poi/hssf/record/formula/ParenthesisPtg.java   26 Apr 2002 
>16:19:20 -0000
> @@ -58,9 +58,9 @@
>  import java.util.List;
>  
>  /**
> - * Dummy class, we want it only for for the parsing process
> - * does not actually get into the file  -- note by andy...there is a parenthesis PTG
> - * that can be written and is sometimes!
> + * While formula tokens are stored in RPN order and thus do not need parenthesis 
>for 
> + * precedence reasons, Parenthesis tokens ARE written to ensure that user entered
> + * parenthesis are displayed as-is on reading back
>   *
>   * Avik Sengupta <[EMAIL PROTECTED]>
>   * Andrew C. Oliver (acoliver at apache dot org)
> @@ -69,17 +69,18 @@
>      extends OperationPtg
>  {
>     
> -
> +    private final static int SIZE = 1;
> +    public final static byte sid  = 0x15;
>     
>  
>      public void writeBytes(byte [] array, int offset)
>      {
> -        //do nothing
> +        array[ offset + 0 ] = sid;
>      }
>  
>      public int getSize()
>      {
> -        return 0;
> +        return SIZE;
>      }
>  
>      public int getType()
> @@ -89,21 +90,29 @@
>  
>      public int getNumberOfOperands()
>      {
> -        return 0;
> +        return 1;
>      }
>  
>      public String toFormulaString()
>      {
> -        return "(";
> +        return "()";
>      }
>  
>      public String toFormulaString(Ptg [] operands)
>      {
> -        return "(";
> +        return "";
>      }
>      
>      public void manipulate(List source, List results, int pos) {
>      }
> +    
> +    public String toFormulaString(String[] operands) {
> +        return "("+operands[0]+")";
> +    }    
> +    
> +    public int getPrecedence() {
> +        return 2;
> +    }    
>      
>  }
>  
> Index: src/java/org/apache/poi/hssf/record/formula/PowerPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/PowerPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 PowerPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/PowerPtg.java 23 Apr 2002 23:56:46 
>-0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/PowerPtg.java 26 Apr 2002 16:19:26 
>-0000
> @@ -109,6 +109,10 @@
>      {
>          return "^";
>      }
> +    
> +    public int getPrecedence() {
> +        return 3;
> +    }
>  
>      public String toFormulaString(Ptg [] operands)
>      {
> @@ -119,8 +123,21 @@
>          buffer.append(operands[ 0 ].toFormulaString());
>          return buffer.toString();
>      }
> +        
> +    
> +    public String toFormulaString(String[] operands) {
> +         StringBuffer buffer = new StringBuffer();
> +
> +        buffer.append(operands[ 1 ]);
> +        buffer.append("^");
> +        buffer.append(operands[ 0 ]);
> +        return buffer.toString();
> +    }
> +    
> +
>      
>      public void manipulate(List source, List results, int pos) {
>      }
>      
> +
>  }
> Index: src/java/org/apache/poi/hssf/record/formula/Ptg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/Ptg.java,v
> retrieving revision 1.4
> diff -u -r1.4 Ptg.java
> --- src/java/org/apache/poi/hssf/record/formula/Ptg.java      23 Apr 2002 22:24:41 
>-0000      1.4
> +++ src/java/org/apache/poi/hssf/record/formula/Ptg.java      26 Apr 2002 16:19:37 
>-0000
> @@ -77,6 +77,54 @@
>      {
>      }
>      
> +    /** convert infix order ptg list to rpn order ptg list
> +     * @return List ptgs in RPN order
> +     * @param infixPtgs List of ptgs in infix order
> +     */
> +    public static List ptgsToRpn(List infixPtgs) {
> +        java.util.Stack operands = new java.util.Stack();
> +        java.util.List retval = new java.util.Stack();
> +        
> +        java.util.ListIterator i = infixPtgs.listIterator();
> +        Object p;
> +        OperationPtg o ;
> +        boolean weHaveABracket = false;
> +        while (i.hasNext()) {
> +            p=i.next();
> +            if (p instanceof OperationPtg) {
> +                if (p instanceof ParenthesisPtg) {
> +                    if (!weHaveABracket) {
> +                        operands.push(p);
> +                        weHaveABracket = true;
> +                    } else {
> +                        o = (OperationPtg) operands.pop();
> +                        while (!(o instanceof ParenthesisPtg)) { 
> +                            retval.add(o);
> +                        }
> +                        weHaveABracket = false;
> +                    }
> +                } else {
> +                    
> +                    while  (!operands.isEmpty() && ((OperationPtg) 
>operands.peek()).getPrecedence() >= ((OperationPtg) p).getPrecedence() ) { //TODO 
>handle ^ since it is right associative
> +                        retval.add(operands.pop());
> +                    }
> +                    operands.push(p);
> +                }
> +            } else {
> +                retval.add(p);
> +            }
> +        }
> +        while (!operands.isEmpty()) {
> +            if (operands.peek() instanceof ParenthesisPtg ){
> +                //throw some error
> +            } else {
> +                retval.add(operands.pop());
> +            }   
> +        }
> +        return retval;
> +    }
> +    
> +
>      
>      
>      /*
> Index: src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 SubtractPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java      23 Apr 2002 
>23:56:46 -0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/SubtractPtg.java      26 Apr 2002 
>16:19:44 -0000
> @@ -119,9 +119,27 @@
>          buffer.append(operands[ 1 ].toFormulaString());
>          return buffer.toString();
>      }
> +
> +     public int getPrecedence() {
> +        return 5;
> +    }
>      
> -    public void manipulate(List source, List results, int pos) {
> +    public int getStringLength() {
> +        return 1;
> +    }
> +    
> +    public String toFormulaString(String[] operands) {
> +        StringBuffer buffer = new StringBuffer();
> +
> +        buffer.append(operands[ 0 ]);
> +        buffer.append("-");
> +        buffer.append(operands[ 1 ]);
> +        return buffer.toString();
>      }
>      
> +   
> +    public void manipulate(List source, List results, int pos) {
> +    }
>      
> +
>  }
> Index: src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java,v
> retrieving revision 1.2
> diff -u -r1.2 ValueVariableFunctionPtg.java
> --- src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java 23 Apr 
>2002 23:56:46 -0000      1.2
> +++ src/java/org/apache/poi/hssf/record/formula/ValueVariableFunctionPtg.java 26 Apr 
>2002 16:19:49 -0000
> @@ -128,8 +128,20 @@
>      {
>          return toFormulaString();
>      }
> +
>      
> +    public String toFormulaString(String[] operands) {
> +        return toFormulaString();
> +    }
> +    
> +   
>      public void manipulate(List source, List results, int pos) {
>      }
>      
> +    public int getPrecedence() {
> +        return 1;
> +    }    
> +    
> +    
> +
>  }
> Index: src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
> ===================================================================
> RCS file: 
>/home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java,v
> retrieving revision 1.5
> diff -u -r1.5 HSSFCell.java
> --- src/java/org/apache/poi/hssf/usermodel/HSSFCell.java      15 Mar 2002 12:15:59 
>-0000      1.5
> +++ src/java/org/apache/poi/hssf/usermodel/HSSFCell.java      26 Apr 2002 16:20:26 
>-0000
> @@ -70,6 +70,9 @@
>  import org.apache.poi.hssf.record.BlankRecord;
>  import org.apache.poi.hssf.record.BoolErrRecord;
>  import org.apache.poi.hssf.record.ExtendedFormatRecord;
> +import org.apache.poi.hssf.record.formula.Ptg;
> +
> +import org.apache.poi.hssf.record.formula.FormulaParser;
>  
>  import java.util.Date;
>  import java.util.Calendar;
> @@ -684,6 +687,32 @@
>          }
>      }
>  
> +    public void setCellFormula(String formula) {
> +        if (formula==null) {
> +            setCellType(CELL_TYPE_BLANK,false);
> +        } else {
> +            
> +            setCellType(CELL_TYPE_FORMULA,false);
> +            FormulaRecord rec = (FormulaRecord) record;
> +            rec.setOptions(( short ) 2);
> +            rec.setValue(0);
> +            rec.setXFIndex(( short ) 0x0f);
> +            FormulaParser fp = new FormulaParser(formula+";");
> +            fp.parse();
> +            Ptg[] ptg  = fp.getRPNPtg();
> +            int   size = 0;
> +            System.out.println("got Ptgs " + ptg.length);
> +            for (int k = 0; k < ptg.length; k++) {
> +                size += ptg[ k ].getSize();
> +                rec.pushExpressionToken(ptg[ k ]);
> +            }
> +            rec.setExpressionLength(( short ) size);
> +            //return rec;
> +            
> +        }
> +    }
> +    
> +    
>      /**
>       * get the value of the cell as a number.  For strings we throw an exception.
>       * For blank cells we return a 0.
-- 
http://www.superlinksoftware.com
http://jakarta.apache.org/poi - port of Excel/Word/OLE 2 Compound
Document 
                            format to java
http://developer.java.sun.com/developer/bugParade/bugs/4487555.html 
                        - fix java generics!
The avalanche has already started. It is too late for the pebbles to
vote.
-Ambassador Kosh

Reply via email to