Made POI follow the rules for encoding unary +/- operators more closely.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@887028 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
484dc9fe5a
commit
e55e9044aa
@ -1091,10 +1091,10 @@ public final class FormulaParser {
|
||||
return new ParseNode(ErrPtg.valueOf(parseErrorLiteral()));
|
||||
case '-':
|
||||
Match('-');
|
||||
return new ParseNode(UnaryMinusPtg.instance, powerFactor());
|
||||
return parseUnary(false);
|
||||
case '+':
|
||||
Match('+');
|
||||
return new ParseNode(UnaryPlusPtg.instance, powerFactor());
|
||||
return parseUnary(true);
|
||||
case '(':
|
||||
Match('(');
|
||||
ParseNode inside = comparisonExpression();
|
||||
@ -1118,6 +1118,35 @@ public final class FormulaParser {
|
||||
}
|
||||
|
||||
|
||||
private ParseNode parseUnary(boolean isPlus) {
|
||||
|
||||
boolean numberFollows = IsDigit(look) || look=='.';
|
||||
ParseNode factor = powerFactor();
|
||||
|
||||
if (numberFollows) {
|
||||
// + or - directly next to a number is parsed with the number
|
||||
|
||||
Ptg token = factor.getToken();
|
||||
if (token instanceof NumberPtg) {
|
||||
if (isPlus) {
|
||||
return factor;
|
||||
}
|
||||
token = new NumberPtg(-((NumberPtg)token).getValue());
|
||||
return new ParseNode(token);
|
||||
}
|
||||
if (token instanceof IntPtg) {
|
||||
if (isPlus) {
|
||||
return factor;
|
||||
}
|
||||
int intVal = ((IntPtg)token).getValue();
|
||||
// note - cannot use IntPtg for negatives
|
||||
token = new NumberPtg(-intVal);
|
||||
return new ParseNode(token);
|
||||
}
|
||||
}
|
||||
return new ParseNode(isPlus ? UnaryPlusPtg.instance : UnaryMinusPtg.instance, factor);
|
||||
}
|
||||
|
||||
private ParseNode parseArray() {
|
||||
List<Object[]> rowsData = new ArrayList<Object[]>();
|
||||
while(true) {
|
||||
|
@ -187,6 +187,43 @@ public final class TestFormulaParser extends TestCase {
|
||||
confirmTokenClasses("+A1", RefPtg.class, UnaryPlusPtg.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* There may be multiple ways to encode an expression involving {@link UnaryPlusPtg}
|
||||
* or {@link UnaryMinusPtg}. These may be perfectly equivalent from a formula
|
||||
* evaluation perspective, or formula rendering. However, differences in the way
|
||||
* POI encodes formulas may cause unnecessary confusion. These non-critical tests
|
||||
* check that POI follows the same encoding rules as Excel.
|
||||
*/
|
||||
public void testExactEncodingOfUnaryPlusAndMinus() {
|
||||
// as tested in Excel:
|
||||
confirmUnary("-3", -3, NumberPtg.class);
|
||||
confirmUnary("--4", -4, NumberPtg.class, UnaryMinusPtg.class);
|
||||
confirmUnary("+++5", 5, IntPtg.class, UnaryPlusPtg.class, UnaryPlusPtg.class);
|
||||
confirmUnary("++-6", -6, NumberPtg.class, UnaryPlusPtg.class, UnaryPlusPtg.class);
|
||||
|
||||
// Spaces muck things up a bit. It would be clearer why the following cases are
|
||||
// reasonable if POI encoded tAttrSpace in the right places.
|
||||
// Otherwise these differences look capricious.
|
||||
confirmUnary("+ 12", 12, IntPtg.class, UnaryPlusPtg.class);
|
||||
confirmUnary("- 13", 13, IntPtg.class, UnaryMinusPtg.class);
|
||||
}
|
||||
|
||||
private static void confirmUnary(String formulaText, double val, Class<?>...expectedTokenTypes) {
|
||||
Ptg[] ptgs = parseFormula(formulaText);
|
||||
confirmTokenClasses(ptgs, expectedTokenTypes);
|
||||
Ptg ptg0 = ptgs[0];
|
||||
if (ptg0 instanceof IntPtg) {
|
||||
IntPtg intPtg = (IntPtg) ptg0;
|
||||
assertEquals((int)val, intPtg.getValue());
|
||||
} else if (ptg0 instanceof NumberPtg) {
|
||||
NumberPtg numberPtg = (NumberPtg) ptg0;
|
||||
assertEquals(val, numberPtg.getValue(), 0.0);
|
||||
} else {
|
||||
fail("bad ptg0 " + ptg0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testLeadingSpaceInString() {
|
||||
String value = " hi ";
|
||||
Ptg[] ptgs = parseFormula("\"" + value + "\"");
|
||||
@ -325,7 +362,7 @@ public final class TestFormulaParser extends TestCase {
|
||||
|
||||
cell.setCellFormula("+.1");
|
||||
formula = cell.getCellFormula();
|
||||
assertEquals("+0.1", formula);
|
||||
assertEquals("0.1", formula);
|
||||
|
||||
cell.setCellFormula("-.1");
|
||||
formula = cell.getCellFormula();
|
||||
|
Loading…
Reference in New Issue
Block a user