Formula Parser fixes with tests, by Peter M Murray

Bug 25457.
PR:
Obtained from:
Submitted by:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353474 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Avik Sengupta 2004-01-01 07:49:16 +00:00
parent a297ae284c
commit 8d576a6466
3 changed files with 70 additions and 45 deletions

View File

@ -80,6 +80,7 @@ import org.apache.poi.hssf.record.formula.*;
* @author Andrew C. oliver (acoliver at apache dot org) * @author Andrew C. oliver (acoliver at apache dot org)
* @author Eric Ladner (eladner at goldinc dot com) * @author Eric Ladner (eladner at goldinc dot com)
* @author Cameron Riley (criley at ekmail.com) * @author Cameron Riley (criley at ekmail.com)
* @author Peter M. Murray (pete at quantrix dot com)
*/ */
public class FormulaParser { public class FormulaParser {
@ -228,13 +229,31 @@ public class FormulaParser {
/** Get an Identifier */ /** Get an Identifier */
private String GetName() { private String GetName() {
StringBuffer Token = new StringBuffer(); StringBuffer Token = new StringBuffer();
if (!IsAlpha(look)) { if (!IsAlpha(look) && look != '\'') {
Expected("Name"); Expected("Name");
} }
while (IsAlNum(look)) { if(look == '\'')
Token = Token.append(Character.toUpperCase(look)); {
GetChar(); Match('\'');
boolean done = look == '\'';
while(!done)
{
Token.append(Character.toUpperCase(look));
GetChar();
if(look == '\'')
{
Match('\'');
done = look != '\'';
}
}
} }
else
{
while (IsAlNum(look)) {
Token.append(Character.toUpperCase(look));
GetChar();
}
}
SkipWhite(); SkipWhite();
return Token.toString(); return Token.toString();
} }
@ -478,12 +497,18 @@ public class FormulaParser {
/** Parse and Translate a Math Factor */ /** Parse and Translate a Math Factor */
private void Factor() { private void Factor() {
if (look == '(' ) { if (look == '-')
{
Match('-');
Factor();
tokens.add(new UnaryMinusPtg());
}
else if (look == '(' ) {
Match('('); Match('(');
Expression(); Expression();
Match(')'); Match(')');
tokens.add(new ParenthesisPtg()); tokens.add(new ParenthesisPtg());
} else if (IsAlpha(look)){ } else if (IsAlpha(look) || look == '\''){
Ident(); Ident();
} else if(look == '"') { } else if(look == '"') {
StringLiteral(); StringLiteral();
@ -501,26 +526,42 @@ public class FormulaParser {
} }
} }
private void StringLiteral() { private void StringLiteral()
Match('"'); {
StringBuffer Token = new StringBuffer(); // Can't use match here 'cuz it consumes whitespace
for(;;) { // which we need to preserve inside the string.
if(look == '"') { // - pete
GetChar(); // Match('"');
SkipWhite(); //potential white space here since it doesnt matter up to the operator if (look != '"')
if(look == '"') Expected("\"");
Token.append("\""); else
else {
break; GetChar();
} else if(look == 0) { StringBuffer Token = new StringBuffer();
break; for (;;)
} else { {
Token.append(look); if (look == '"')
GetChar(); {
} 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()));
} }
tokens.add(new StringPtg(Token.toString())); }
}
/** Recognize and Translate a Multiply */ /** Recognize and Translate a Multiply */
private void Multiply(){ private void Multiply(){
@ -590,11 +631,7 @@ public class FormulaParser {
/** Parse and Translate an Expression */ /** Parse and Translate an Expression */
private void Expression() { private void Expression() {
if (IsAddop(look)) { Term();
EmitLn("CLR D0"); //unaryAdd ptg???
} else {
Term();
}
while (IsAddop(look)) { while (IsAddop(look)) {
if (look == '+' ) Add(); if (look == '+' ) Add();
else if (look == '-') Subtract(); else if (look == '-') Subtract();
@ -725,7 +762,7 @@ end;
private void setRootLevelRVA(Node n, int formulaType) { private void setRootLevelRVA(Node n, int formulaType) {
//Pg 16, excelfileformat.pdf @ openoffice.org //Pg 16, excelfileformat.pdf @ openoffice.org
Ptg p = (Ptg) n.getValue(); Ptg p = (Ptg) n.getValue();
if (formulaType == this.FORMULA_TYPE_NAMEDRANGE) { if (formulaType == FormulaParser.FORMULA_TYPE_NAMEDRANGE) {
if (p.getDefaultOperandClass() == Ptg.CLASS_REF) { if (p.getDefaultOperandClass() == Ptg.CLASS_REF) {
setClass(n,Ptg.CLASS_REF); setClass(n,Ptg.CLASS_REF);
} else { } else {

View File

@ -536,7 +536,7 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
functionData[25][0]=new Byte(Ptg.CLASS_VALUE);functionData[25][1]=new byte[] {Ptg.CLASS_VALUE};functionData[25][2]=new Integer(1); functionData[25][0]=new Byte(Ptg.CLASS_VALUE);functionData[25][1]=new byte[] {Ptg.CLASS_VALUE};functionData[25][2]=new Integer(1);
functionData[26][0]=new Byte(Ptg.CLASS_VALUE);functionData[26][1]=new byte[] {Ptg.CLASS_VALUE};functionData[26][2]=new Integer(1); functionData[26][0]=new Byte(Ptg.CLASS_VALUE);functionData[26][1]=new byte[] {Ptg.CLASS_VALUE};functionData[26][2]=new Integer(1);
functionData[27][0]=new Byte(Ptg.CLASS_VALUE);functionData[27][1]=new byte[] {Ptg.CLASS_VALUE};functionData[27][2]=new Integer(2); functionData[27][0]=new Byte(Ptg.CLASS_VALUE);functionData[27][1]=new byte[] {Ptg.CLASS_VALUE};functionData[27][2]=new Integer(2);
functionData[28][0]=new Byte(Ptg.CLASS_VALUE);functionData[28][1]=new byte[] {Ptg.CLASS_REF};functionData[28][2]=new Integer(-1); functionData[28][0]=new Byte(Ptg.CLASS_VALUE);functionData[28][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[28][2]=new Integer(-1);
functionData[29][0]=new Byte(Ptg.CLASS_VALUE);functionData[29][1]=new byte[] {Ptg.CLASS_REF};functionData[29][2]=new Integer(-1); functionData[29][0]=new Byte(Ptg.CLASS_VALUE);functionData[29][1]=new byte[] {Ptg.CLASS_REF};functionData[29][2]=new Integer(-1);
functionData[30][0]=new Byte(Ptg.CLASS_VALUE);functionData[30][1]=new byte[] {Ptg.CLASS_VALUE};functionData[30][2]=new Integer(2); functionData[30][0]=new Byte(Ptg.CLASS_VALUE);functionData[30][1]=new byte[] {Ptg.CLASS_VALUE};functionData[30][2]=new Integer(2);
functionData[31][0]=new Byte(Ptg.CLASS_VALUE);functionData[31][1]=new byte[] {Ptg.CLASS_VALUE};functionData[31][2]=new Integer(3); functionData[31][0]=new Byte(Ptg.CLASS_VALUE);functionData[31][1]=new byte[] {Ptg.CLASS_VALUE};functionData[31][2]=new Integer(3);
@ -571,7 +571,7 @@ public abstract class AbstractFunctionPtg extends OperationPtg {
functionData[61][0]=new Byte(Ptg.CLASS_VALUE);functionData[61][1]=new byte[] {Ptg.CLASS_VALUE};functionData[61][2]=new Integer(3); functionData[61][0]=new Byte(Ptg.CLASS_VALUE);functionData[61][1]=new byte[] {Ptg.CLASS_VALUE};functionData[61][2]=new Integer(3);
functionData[62][0]=new Byte(Ptg.CLASS_VALUE);functionData[62][1]=new byte[] {Ptg.CLASS_REF};functionData[62][2]=new Integer(-1); functionData[62][0]=new Byte(Ptg.CLASS_VALUE);functionData[62][1]=new byte[] {Ptg.CLASS_REF};functionData[62][2]=new Integer(-1);
functionData[63][0]=new Byte(Ptg.CLASS_VALUE);functionData[63][1]=new byte[] {Ptg.CLASS_REF};functionData[63][2]=new Integer(1); functionData[63][0]=new Byte(Ptg.CLASS_VALUE);functionData[63][1]=new byte[] {Ptg.CLASS_REF};functionData[63][2]=new Integer(1);
functionData[64][0]=new Byte(Ptg.CLASS_VALUE);functionData[64][1]=new byte[] {Ptg.CLASS_REF};functionData[64][2]=new Integer(-1); functionData[64][0]=new Byte(Ptg.CLASS_VALUE);functionData[64][1]=new byte[] {Ptg.CLASS_VALUE, Ptg.CLASS_REF};functionData[64][2]=new Integer(-1);
functionData[65][0]=new Byte(Ptg.CLASS_VALUE);functionData[65][1]=new byte[] {Ptg.CLASS_VALUE};functionData[65][2]=new Integer(3); functionData[65][0]=new Byte(Ptg.CLASS_VALUE);functionData[65][1]=new byte[] {Ptg.CLASS_VALUE};functionData[65][2]=new Integer(3);
functionData[66][0]=new Byte(Ptg.CLASS_VALUE);functionData[66][1]=new byte[] {Ptg.CLASS_VALUE};functionData[66][2]=new Integer(3); functionData[66][0]=new Byte(Ptg.CLASS_VALUE);functionData[66][1]=new byte[] {Ptg.CLASS_VALUE};functionData[66][2]=new Integer(3);
functionData[67][0]=new Byte(Ptg.CLASS_VALUE);functionData[67][1]=new byte[] {Ptg.CLASS_VALUE};functionData[67][2]=new Integer(1); functionData[67][0]=new Byte(Ptg.CLASS_VALUE);functionData[67][1]=new byte[] {Ptg.CLASS_VALUE};functionData[67][2]=new Integer(1);

View File

@ -186,18 +186,6 @@ public class HSSFDateUtil
case 0x2d: case 0x2d:
case 0x2e: case 0x2e:
case 0x2f: case 0x2f:
// Additional internal date formats found by inspection
// Using Excel v.X 10.1.0 (Mac)
case 0xa4:
case 0xa5:
case 0xa6:
case 0xa7:
case 0xa8:
case 0xa9:
case 0xaa:
case 0xab:
case 0xac:
case 0xad:
retval = true; retval = true;
break; break;