]> source.dussan.org Git - poi.git/commitdiff
FormulaParser patch to address:
authorDanny Mui <dmui@apache.org>
Wed, 7 May 2003 03:40:52 +0000 (03:40 +0000)
committerDanny Mui <dmui@apache.org>
Wed, 7 May 2003 03:40:52 +0000 (03:40 +0000)
1) embedded ifs
2) GreaterEqual, LessEqual, NotEqual
3) Refactored stringliteral detection
BR: 19079
Submitted By: fred at stsci dot edu

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353089 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/model/FormulaParser.java
src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java [new file with mode: 0755]
src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java [new file with mode: 0755]
src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java [new file with mode: 0755]
src/java/org/apache/poi/hssf/record/formula/Ptg.java
src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java

index 6d7ff6f700d4eb47b60ccba3bf0195d4a48f9c39..b41f084873244aa8c20099bf138a88cd6c198c6f 100644 (file)
@@ -457,6 +457,7 @@ public class FormulaParser {
         if (look != ')')  {
             numArgs++; 
             Expression();
+                          addArgumentPointer();
         }
         while (look == ','  || look == ';') { //TODO handle EmptyArgs
             if(look == ',') {
@@ -466,6 +467,7 @@ public class FormulaParser {
               Match(';');
             }
             Expression();
+                          addArgumentPointer();
             numArgs++;
         }
         return numArgs;
@@ -478,7 +480,6 @@ public class FormulaParser {
             Expression();
             Match(')');
             tokens.add(new ParenthesisPtg());
-            return;
         } else if (IsAlpha(look)){
             Ident();
         } else if(look == '"') {
@@ -499,9 +500,23 @@ public class FormulaParser {
     
     private void StringLiteral() {
         Match('"');
-        String name= GetNameAsIs();
-        Match('"');
-        tokens.add(new StringPtg(name));
+                 StringBuffer Token = new StringBuffer();
+                 for(;;) {
+                            if(look == '"') {
+                       GetChar();
+                       SkipWhite(); //potential white space here since it doesnt matter up to the operator
+                       if(look == '"')
+                           Token.append("\"");
+                       else
+                           break;
+                   } else if(look == 0) {
+                       break;
+                   } else {
+                       Token.append(look);
+                       GetChar();
+                   }
+               }
+               tokens.add(new StringPtg(Token.toString()));        
     }
     
     /** Recognize and Translate a Multiply */
@@ -525,16 +540,13 @@ public class FormulaParser {
     /** Parse and Translate a Math Term */
     private void  Term(){
         Factor();
-        while (look == '*' || look == '/' || look == '^' || look == '&' || 
-               look == '=' || look == '>' || look == '<' ) {
+                while (look == '*' || look == '/' || look == '^' || look == '&') {
+        
             ///TODO do we need to do anything here??
             if (look == '*') Multiply();
-            if (look == '/') Divide();
-            if (look == '^') Power();
-            if (look == '&') Concat();
-            if (look == '=') Equal();
-            if (look == '>') GreaterThan();
-            if (look == '<') LessThan();
+            else if (look == '/') Divide();
+            else if (look == '^') Power();
+            else if (look == '&') Concat();
         }
     }
     
@@ -555,7 +567,7 @@ public class FormulaParser {
     /** Recognize and Translate a test for Equality  */
     private void Equal() {
         Match('=');
-        Term();
+        Expression();
         tokens.add(new EqualPtg());
     }
     
@@ -581,31 +593,80 @@ public class FormulaParser {
             Term();
         }
         while (IsAddop(look)) {
-            if ( look == '+' )  Add();
-            if (look == '-') Subtract();
-            if (look == '*') Multiply();
-            if (look == '/') Divide();
-            if (look == '>') GreaterThan();
-            if (look == '<') LessThan();
+            if (look == '+' )  Add();
+            else if (look == '-') Subtract();
         }
-        addArgumentPointer();
+        
+               /*
+                * This isn't quite right since it would allow multiple comparison operators.
+                */
+               
+                 if(look == '=' || look == '>' || look == '<') {
+                               if (look == '=') Equal();
+                     else if (look == '>') GreaterThan();
+                     else if (look == '<') LessThan();
+                     return;
+                 }        
+        
         
     }
     
     /** Recognize and Translate a Greater Than  */
     private void GreaterThan() {
-        Match('>');
-        Term();
-        tokens.add(new GreaterThanPtg());
+               Match('>');
+               if(look == '=')
+                   GreaterEqual();
+               else {
+                   Expression();
+                   tokens.add(new GreaterThanPtg());
+               }
     }
     
     /** Recognize and Translate a Less Than  */
     private void LessThan() {
-        Match('<');
-        Term();
-        tokens.add(new LessThanPtg());
-    }   
-    
+               Match('<');
+               if(look == '=')
+                   LessEqual();
+               else if(look == '>')
+                   NotEqual();
+               else {
+                   Expression();
+                   tokens.add(new LessThanPtg());
+               }
+
+       }  
+   
+   /**
+    * Recognize and translate Greater than or Equal
+    *
+    */ 
+       private void GreaterEqual() {
+           Match('=');
+           Expression();
+           tokens.add(new GreaterEqualPtg());
+       }    
+
+       /**
+        * Recognize and translate Less than or Equal
+        *
+        */ 
+
+       private void LessEqual() {
+           Match('=');
+           Expression();
+           tokens.add(new LessEqualPtg());
+       }
+       
+       /**
+        * Recognize and not Equal
+        *
+        */ 
+
+       private void NotEqual() {
+           Match('>');
+           Expression();
+           tokens.add(new NotEqualPtg());
+       }    
     
     //{--------------------------------------------------------------}
     //{ Parse and Translate an Assignment Statement }
diff --git a/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/GreaterEqualPtg.java
new file mode 100755 (executable)
index 0000000..de0b623
--- /dev/null
@@ -0,0 +1,121 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 apache@apache.org.
+ *
+ * 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 org.apache.poi.hssf.util.SheetReferences;
+
+/**
+ * PTG class to implement greater or equal to
+ * @author  fred at stsci dot edu
+ */
+public class GreaterEqualPtg
+    extends OperationPtg
+{
+    public final static int  SIZE = 1;
+    public final static byte sid  = 0x0c;
+
+    /** Creates new AddPtg */
+
+   public GreaterEqualPtg()
+    {
+    }
+
+    public GreaterEqualPtg(byte [] data, int offset)
+    {
+
+        // doesn't need anything
+    }
+
+    public void writeBytes(byte [] array, int offset)
+    {
+        array[ offset + 0 ] = sid;
+    }
+
+    public int getSize()
+    {
+        return SIZE;
+    }
+
+    public int getType()
+    {
+        return TYPE_BINARY;
+    }
+
+    public int getNumberOfOperands()
+    {
+        return 2;
+    }
+
+    public String toFormulaString(SheetReferences refs)
+    {
+        return ">=";
+    }
+    public String toFormulaString(String[] operands) {
+         StringBuffer buffer = new StringBuffer();
+
+        
+        buffer.append(operands[ 0 ]);
+        buffer.append(toFormulaString((SheetReferences)null));
+        buffer.append(operands[ 1 ]);
+        return buffer.toString();
+    }       
+
+    public Object clone() {
+      return new GreaterEqualPtg();
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/LessEqualPtg.java
new file mode 100755 (executable)
index 0000000..0c8165f
--- /dev/null
@@ -0,0 +1,122 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 apache@apache.org.
+ *
+ * 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 org.apache.poi.hssf.util.SheetReferences;
+
+
+/**
+ * Ptg class to implement less than or equal
+ * @author  fred at stsci dot edu
+ */
+
+public class LessEqualPtg
+        extends OperationPtg
+{
+        public final static int  SIZE = 1;
+        public final static byte sid  = 0x0a;
+
+        /** Creates new AddPtg */
+
+       public LessEqualPtg()
+        {
+        }
+
+        public LessEqualPtg(byte [] data, int offset)
+        {
+
+                 // doesn't need anything
+        }
+
+        public void writeBytes(byte [] array, int offset)
+        {
+                 array[ offset + 0 ] = sid;
+        }
+
+        public int getSize()
+        {
+                 return SIZE;
+        }
+
+        public int getType()
+        {
+                 return TYPE_BINARY;
+        }
+
+        public int getNumberOfOperands()
+        {
+                 return 2;
+        }
+
+        public String toFormulaString(SheetReferences refs)
+        {
+                 return "<=";
+        }
+        public String toFormulaString(String[] operands) {
+                       StringBuffer buffer = new StringBuffer();
+
+        
+                 buffer.append(operands[ 0 ]);
+                 buffer.append(toFormulaString((SheetReferences)null));
+                 buffer.append(operands[ 1 ]);
+                 return buffer.toString();
+        }       
+
+        public Object clone() {
+               return new LessEqualPtg();
+        }
+
+
+}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java b/src/java/org/apache/poi/hssf/record/formula/NotEqualPtg.java
new file mode 100755 (executable)
index 0000000..c43c196
--- /dev/null
@@ -0,0 +1,124 @@
+/* ====================================================================
+ * 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 apache@apache.org.
+ *
+ * 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 org.apache.poi.hssf.util.SheetReferences;
+
+/**
+ * Ptg class to implement not equal
+ * @author  fred at stsci dot edu
+ */
+
+public class NotEqualPtg
+        extends OperationPtg
+{
+        public final static int  SIZE = 1;
+        public final static byte sid  = 0x0e;
+
+        /** Creates new AddPtg */
+
+       public NotEqualPtg()
+        {
+        }
+
+        public NotEqualPtg(byte [] data, int offset)
+        {
+
+                 // doesn't need anything
+        }
+
+        public void writeBytes(byte [] array, int offset)
+        {
+                 array[ offset + 0 ] = sid;
+        }
+
+        public int getSize()
+        {
+                 return SIZE;
+        }
+
+        public int getType()
+        {
+                 return TYPE_BINARY;
+        }
+
+        public int getNumberOfOperands()
+        {
+                 return 2;
+        }
+
+        public String toFormulaString(SheetReferences refs)
+        {
+                 return "<>";
+        }
+        public String toFormulaString(String[] operands) {
+                       StringBuffer buffer = new StringBuffer();
+
+        
+                 buffer.append(operands[ 0 ]);
+                 buffer.append(toFormulaString((SheetReferences)null));
+                 buffer.append(operands[ 1 ]);
+                 return buffer.toString();
+        }       
+
+        public Object clone() {
+               return new NotEqualPtg();
+        }
+
+
+}
\ No newline at end of file
index 1e4a5c397033a24923715206a78de7e72e765c73..3787d0056e1a6d0a6d9873f6c009c61e6e9cf67b 100644 (file)
@@ -184,7 +184,19 @@ public abstract class Ptg
             case LessThanPtg.sid:
                 retval = new LessThanPtg(data, offset);
                 break;
-                
+
+                          case LessEqualPtg.sid:
+                              retval = new LessEqualPtg(data, offset);
+                              break;
+                                       
+                          case GreaterEqualPtg.sid:
+                              retval = new GreaterEqualPtg(data, offset);
+                              break;
+                              
+                          case NotEqualPtg.sid:
+                        retval = new NotEqualPtg(data, offset);
+                        break;
+                              
             case ConcatPtg.sid :
                 retval = new ConcatPtg(data, offset);
                 break;
index 339fdcd8645c94dcee3168b3aefe531dffc76a40..c4722a9a73479ff22da5edb554cf0333c1c0ba95 100644 (file)
@@ -251,16 +251,39 @@ public class TestFormulaParser extends TestCase {
                                        
        }
         
-        public void testSimpleLogical() {
-            FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
-            fp.parse();
-            Ptg[] ptgs = fp.getRPNPtg();
-            assertTrue("Ptg array should not be null", ptgs !=null);
-            assertEquals("Ptg array length", 9, ptgs.length);
-            assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
+       public void testSimpleLogical() {
+               FormulaParser fp=new FormulaParser("IF(A1<A2,B1,B2)",null);
+               fp.parse();
+      Ptg[] ptgs = fp.getRPNPtg();
+      assertTrue("Ptg array should not be null", ptgs !=null);
+      assertEquals("Ptg array length", 9, ptgs.length);
+      assertEquals("3rd Ptg is less than",LessThanPtg.class,ptgs[2].getClass());
             
            
-        }
+       }
+        
+       public void testParenIf() {
+               FormulaParser fp=new FormulaParser("IF((A1+A2)<=3,\"yes\",\"no\")",null);
+               fp.parse();
+               Ptg[] ptgs = fp.getRPNPtg();
+               assertTrue("Ptg array should not be null", ptgs !=null);
+               assertEquals("Ptg array length", 12, ptgs.length);
+               assertEquals("6th Ptg is less than equal",LessEqualPtg.class,ptgs[5].getClass());
+               assertEquals("11th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[10].getClass());
+       }
+       
+       public void testEmbeddedIf() {
+               FormulaParser fp=new FormulaParser("IF(3>=1,\"*\",IF(4<>1,\"first\",\"second\"))",null);
+               fp.parse();
+               Ptg[] ptgs = fp.getRPNPtg();
+               assertTrue("Ptg array should not be null", ptgs !=null);
+               assertEquals("Ptg array length", 17, ptgs.length);
+               
+               assertEquals("6th Ptg is not a goto (Attr) ptg",AttrPtg.class,ptgs[5].getClass());
+               assertEquals("9th Ptg is not a not equal ptg",NotEqualPtg.class,ptgs[8].getClass());
+               assertEquals("15th Ptg is not the inner IF variable function ptg",FuncVarPtg.class,ptgs[14].getClass());
+               
+       }
            
      public static void main(String [] args) {
         System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");