FormulaParser patch to address:

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
This commit is contained in:
Danny Muid 2003-05-07 03:40:52 +00:00
parent ffe20f3e80
commit b693562626
6 changed files with 500 additions and 37 deletions

View File

@ -457,6 +457,7 @@ public class FormulaParser {
if (look != ')') { if (look != ')') {
numArgs++; numArgs++;
Expression(); Expression();
addArgumentPointer();
} }
while (look == ',' || look == ';') { //TODO handle EmptyArgs while (look == ',' || look == ';') { //TODO handle EmptyArgs
if(look == ',') { if(look == ',') {
@ -466,6 +467,7 @@ public class FormulaParser {
Match(';'); Match(';');
} }
Expression(); Expression();
addArgumentPointer();
numArgs++; numArgs++;
} }
return numArgs; return numArgs;
@ -478,7 +480,6 @@ public class FormulaParser {
Expression(); Expression();
Match(')'); Match(')');
tokens.add(new ParenthesisPtg()); tokens.add(new ParenthesisPtg());
return;
} else if (IsAlpha(look)){ } else if (IsAlpha(look)){
Ident(); Ident();
} else if(look == '"') { } else if(look == '"') {
@ -499,9 +500,23 @@ public class FormulaParser {
private void StringLiteral() { private void StringLiteral() {
Match('"'); Match('"');
String name= GetNameAsIs(); StringBuffer Token = new StringBuffer();
Match('"'); for(;;) {
tokens.add(new StringPtg(name)); 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 */ /** Recognize and Translate a Multiply */
@ -525,16 +540,13 @@ public class FormulaParser {
/** Parse and Translate a Math Term */ /** Parse and Translate a Math Term */
private void Term(){ private void Term(){
Factor(); Factor();
while (look == '*' || look == '/' || look == '^' || look == '&' || while (look == '*' || look == '/' || look == '^' || look == '&') {
look == '=' || look == '>' || look == '<' ) {
///TODO do we need to do anything here?? ///TODO do we need to do anything here??
if (look == '*') Multiply(); if (look == '*') Multiply();
if (look == '/') Divide(); else if (look == '/') Divide();
if (look == '^') Power(); else if (look == '^') Power();
if (look == '&') Concat(); else if (look == '&') Concat();
if (look == '=') Equal();
if (look == '>') GreaterThan();
if (look == '<') LessThan();
} }
} }
@ -555,7 +567,7 @@ public class FormulaParser {
/** Recognize and Translate a test for Equality */ /** Recognize and Translate a test for Equality */
private void Equal() { private void Equal() {
Match('='); Match('=');
Term(); Expression();
tokens.add(new EqualPtg()); tokens.add(new EqualPtg());
} }
@ -581,31 +593,80 @@ public class FormulaParser {
Term(); Term();
} }
while (IsAddop(look)) { while (IsAddop(look)) {
if ( look == '+' ) Add(); if (look == '+' ) Add();
if (look == '-') Subtract(); else if (look == '-') Subtract();
if (look == '*') Multiply();
if (look == '/') Divide();
if (look == '>') GreaterThan();
if (look == '<') LessThan();
} }
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 */ /** Recognize and Translate a Greater Than */
private void GreaterThan() { private void GreaterThan() {
Match('>'); Match('>');
Term(); if(look == '=')
GreaterEqual();
else {
Expression();
tokens.add(new GreaterThanPtg()); tokens.add(new GreaterThanPtg());
} }
}
/** Recognize and Translate a Less Than */ /** Recognize and Translate a Less Than */
private void LessThan() { private void LessThan() {
Match('<'); Match('<');
Term(); if(look == '=')
LessEqual();
else if(look == '>')
NotEqual();
else {
Expression();
tokens.add(new LessThanPtg()); 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 } //{ Parse and Translate an Assignment Statement }

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -185,6 +185,18 @@ public abstract class Ptg
retval = new LessThanPtg(data, offset); retval = new LessThanPtg(data, offset);
break; 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 : case ConcatPtg.sid :
retval = new ConcatPtg(data, offset); retval = new ConcatPtg(data, offset);
break; break;

View File

@ -262,6 +262,29 @@ public class TestFormulaParser extends TestCase {
} }
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) { public static void main(String [] args) {
System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser"); System.out.println("Testing org.apache.poi.hssf.record.formula.FormulaParser");
junit.textui.TestRunner.run(TestFormulaParser.class); junit.textui.TestRunner.run(TestFormulaParser.class);