I hope to work on this later today.  Scanning it, it looks really good! 
 Far better than my messing around for sure.  This shows the most 
promise of anything I've seen yet.

I'd like to see the javacc aproach as well but I remain unconvinced that 
it will adequately work both directions.  I'd rather be able to 
read/write/modify only a small subset of the formulas in Excel then be 
able to read all of the formulas.  Obviously for 2.0 the goal is all 
non-obsolecent formula pieces.  I'd still like to see a prototype of 
that.  (and any other approaches someone may have).  I think we're well 
on our way to finding the best approach and I think excellent formula 
support will fall out from there.

-Andy

Avik Sengupta wrote:

>This contains all that i have mailed to the list in the last few days, diffed 
>against the latest cvs. 
>
>this has the functionality to create a RPN ptg array from a string, and back. 
>
>try java org.apache.poi.hssf.record.formula.FormulaParser <formula>
>
>after compiling and setting the classpath. 
>
>I will now look at handling some basic cell references and also integrating all 
>the stuff so that we get some level of access from usermodel. 
>
>
>------------------------------------------------------------------------
>
>? formula.patch
>? tmp.txt
>? src/java/org/apache/poi/hssf/record/formula/.nbattrs
>? src/java/org/apache/poi/hssf/record/formula/DummyFunctionPtg.java
>? tools/antipede/lib/temp
>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    24 Apr 2002 10:37:07 
>-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   24 Apr 2002 10:37:16 
>-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 24 Apr 2002 10:37:23 
>-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     24 Apr 2002 
>10:37:38 -0000
>@@ -61,55 +61,62 @@
> import java.util.Stack;
> 
> /**
>- * EXPERIMENTAL code to parse formulas back and forth between RPN and not
>+ * EXPERIMENTAL 
>  *
>- * @author Avik Sengupta <[EMAIL PROTECTED]>
>+ * @author Avik Sengupta <avik AT Avik Sengupta DOT com>
>+ *
>+ * 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 +124,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 +175,8 @@
>     }
>     
>     
>-    //{--------------------------------------------------------------}
>-    //{ Match a Specific Input Character }
>-    
>+
>+    /** Match a Specific Input Character */
>     private void Match(char x) {
>         if (Look != x) {
>             Expected("" + x + "");
>@@ -192,9 +187,7 @@
>     }
>     
>     
>-    //{--------------------------------------------------------------}
>-    //{ Get an Identifier }
>-    
>+    /** Get an Identifier */
>     private String GetName() {
>         String Token;
>         Token = "";
>@@ -211,9 +204,7 @@
>     }
>     
>     
>-    //{--------------------------------------------------------------}
>-    //{ Get a Number }
>-    
>+    /** Get a Number */
>     private String GetNum() {
>         String Value ="";
>         if  (!IsDigit(Look)) Expected("Integer");
>@@ -224,63 +215,64 @@
>         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(); //Expression() -- add this!
>             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());
>+            //tokens.add(new ParenthesisPtg());
>             Expression();
>             Match(')');
>-            operationsList.add(new ParenthesisPtg());
>+            //tokens.add(new ParenthesisPtg());
>             return;
>         } else if (IsAlpha(Look)){
>             Ident();
>@@ -288,38 +280,32 @@
>             //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());
>+        tokens.add(new MultiplyPtg());
>         //EmitLn("MULS (SP)+,D0");
>     }
>     
>     
>-    //{-------------------------------------------------------------}
>-    //{ Recognize and Translate a Divide }
>-    
>+    /** Recognize and Translate a Divide */
>     private void Divide() {
>         Match('/');
>         Factor();
>-        operationsList.add(new DividePtg());
>+        tokens.add(new DividePtg());
>         //EmitLn("MOVE (SP)+,D1");
>         //EmitLn("EXS.L D0");
>         //EmitLn("DIVS D1,D0");
>     }
>     
>     
>-    //{---------------------------------------------------------------}
>-    //{ Parse and Translate a Math Term }
>-    
>+    /** Parse and Translate a Math Term */
>     private void  Term(){
>         Factor();
>         while (Look == '*' || Look == '/' ) {
>@@ -330,33 +316,23 @@
>         }
>     }
>     
>-    
>-    //{--------------------------------------------------------------}
>-    //{ 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 +340,10 @@
>             Term();
>         }
>         while (IsAddop(Look)) {
>-            EmitLn("MOVE D0,-(SP)");
>             if ( Look == '+' )  Add();
>             if (Look == '-') Subtract();
>+            // if (Look == '*') Multiply();
>+           // if (Look == '/') Divide();
>         }
>     }
>     
>@@ -380,71 +357,88 @@
>    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
>-            }
>-            
>-            
>-            for (numOper = op.getNumberOfOperands();numOper>0;numOper--) {
>-                if (numOnStack==0) {
>-                    result.add(operandsList.pop());//numOnStack++;
>-                } else {
>-                    numOnStack--;
>-                }
>+    /** 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());
>             }
>-            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()));
>         
>         //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       24 Apr 2002 
>10:37:45 -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      24 Apr 2002 
>10:37:50 -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    24 Apr 2002 
>10:37:55 -0000
>@@ -99,11 +99,19 @@
> 
>     public String toFormulaString(Ptg [] operands)
>     {
>-        return "(";
>+        return "";
>     }
>     
>     public void manipulate(List source, List results, int pos) {
>     }
>+    
>+    public String toFormulaString(String[] operands) {
>+        return "";
>+    }    
>+    
>+    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  24 Apr 2002 10:38:00 
>-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       24 Apr 2002 10:38:10 
>-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       24 Apr 2002 
>10:38:17 -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  24 Apr 
>2002 10:38:22 -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;
>+    }    
>+    
>+    
>+
> }
>



Reply via email to