mirror of https://github.com/apache/poi.git
bug 25457, formula parser fixes by Peter M Murray
sync to head git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353475 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
47541ff2e8
commit
a521770323
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue