first commit
This commit is contained in:
325
hrmsEjb/jxl/biff/formula/TokenFormulaParser.java
Normal file
325
hrmsEjb/jxl/biff/formula/TokenFormulaParser.java
Normal file
@@ -0,0 +1,325 @@
|
||||
package jxl.biff.formula;
|
||||
|
||||
import common.Assert;
|
||||
import common.Logger;
|
||||
import java.util.Stack;
|
||||
import jxl.Cell;
|
||||
import jxl.WorkbookSettings;
|
||||
import jxl.biff.WorkbookMethods;
|
||||
|
||||
class TokenFormulaParser implements Parser {
|
||||
private static Logger logger = Logger.getLogger(TokenFormulaParser.class);
|
||||
|
||||
private byte[] tokenData;
|
||||
|
||||
private Cell relativeTo;
|
||||
|
||||
private int pos;
|
||||
|
||||
private ParseItem root;
|
||||
|
||||
private Stack tokenStack;
|
||||
|
||||
private ExternalSheet workbook;
|
||||
|
||||
private WorkbookMethods nameTable;
|
||||
|
||||
private WorkbookSettings settings;
|
||||
|
||||
public TokenFormulaParser(byte[] data, Cell c, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) {
|
||||
this.tokenData = data;
|
||||
this.pos = 0;
|
||||
this.relativeTo = c;
|
||||
this.workbook = es;
|
||||
this.nameTable = nt;
|
||||
this.tokenStack = new Stack();
|
||||
this.settings = ws;
|
||||
}
|
||||
|
||||
public void parse() throws FormulaException {
|
||||
parseSubExpression(this.tokenData.length);
|
||||
this.root = this.tokenStack.pop();
|
||||
Assert.verify(this.tokenStack.empty());
|
||||
}
|
||||
|
||||
private void parseSubExpression(int len) throws FormulaException {
|
||||
int tokenVal = 0;
|
||||
Token t = null;
|
||||
Stack ifStack = new Stack();
|
||||
int endpos = this.pos + len;
|
||||
while (this.pos < endpos) {
|
||||
tokenVal = this.tokenData[this.pos];
|
||||
this.pos++;
|
||||
t = Token.getToken(tokenVal);
|
||||
if (t == Token.UNKNOWN)
|
||||
throw new FormulaException(FormulaException.unrecognizedToken, tokenVal);
|
||||
Assert.verify((t != Token.UNKNOWN));
|
||||
if (t == Token.REF) {
|
||||
CellReference cr = new CellReference(this.relativeTo);
|
||||
this.pos += cr.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(cr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.REF) {
|
||||
CellReferenceError cr = new CellReferenceError();
|
||||
this.pos += cr.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(cr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.REFV) {
|
||||
SharedFormulaCellReference cr = new SharedFormulaCellReference(this.relativeTo);
|
||||
this.pos += cr.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(cr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.REF3D) {
|
||||
CellReference3d cr = new CellReference3d(this.relativeTo, this.workbook);
|
||||
this.pos += cr.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(cr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.AREA) {
|
||||
Area a = new Area();
|
||||
this.pos += a.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(a);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.AREAV) {
|
||||
SharedFormulaArea a = new SharedFormulaArea(this.relativeTo);
|
||||
this.pos += a.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(a);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.AREA3D) {
|
||||
Area3d a = new Area3d(this.workbook);
|
||||
this.pos += a.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(a);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.NAME) {
|
||||
Name n = new Name();
|
||||
this.pos += n.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(n);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.NAMED_RANGE) {
|
||||
NameRange nr = new NameRange(this.nameTable);
|
||||
this.pos += nr.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(nr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.INTEGER) {
|
||||
IntegerValue i = new IntegerValue();
|
||||
this.pos += i.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(i);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.DOUBLE) {
|
||||
DoubleValue d = new DoubleValue();
|
||||
this.pos += d.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(d);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.BOOL) {
|
||||
BooleanValue bv = new BooleanValue();
|
||||
this.pos += bv.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(bv);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.STRING) {
|
||||
StringValue sv = new StringValue(this.settings);
|
||||
this.pos += sv.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(sv);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.MISSING_ARG) {
|
||||
MissingArg ma = new MissingArg();
|
||||
this.pos += ma.read(this.tokenData, this.pos);
|
||||
this.tokenStack.push(ma);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.UNARY_PLUS) {
|
||||
UnaryPlus up = new UnaryPlus();
|
||||
this.pos += up.read(this.tokenData, this.pos);
|
||||
addOperator(up);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.UNARY_MINUS) {
|
||||
UnaryMinus um = new UnaryMinus();
|
||||
this.pos += um.read(this.tokenData, this.pos);
|
||||
addOperator(um);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.PERCENT) {
|
||||
Percent p = new Percent();
|
||||
this.pos += p.read(this.tokenData, this.pos);
|
||||
addOperator(p);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.SUBTRACT) {
|
||||
Subtract s = new Subtract();
|
||||
this.pos += s.read(this.tokenData, this.pos);
|
||||
addOperator(s);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.ADD) {
|
||||
Add s = new Add();
|
||||
this.pos += s.read(this.tokenData, this.pos);
|
||||
addOperator(s);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.MULTIPLY) {
|
||||
Multiply s = new Multiply();
|
||||
this.pos += s.read(this.tokenData, this.pos);
|
||||
addOperator(s);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.DIVIDE) {
|
||||
Divide s = new Divide();
|
||||
this.pos += s.read(this.tokenData, this.pos);
|
||||
addOperator(s);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.CONCAT) {
|
||||
Concatenate c = new Concatenate();
|
||||
this.pos += c.read(this.tokenData, this.pos);
|
||||
addOperator(c);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.POWER) {
|
||||
Power p = new Power();
|
||||
this.pos += p.read(this.tokenData, this.pos);
|
||||
addOperator(p);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.LESS_THAN) {
|
||||
LessThan lt = new LessThan();
|
||||
this.pos += lt.read(this.tokenData, this.pos);
|
||||
addOperator(lt);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.LESS_EQUAL) {
|
||||
LessEqual lte = new LessEqual();
|
||||
this.pos += lte.read(this.tokenData, this.pos);
|
||||
addOperator(lte);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.GREATER_THAN) {
|
||||
GreaterThan gt = new GreaterThan();
|
||||
this.pos += gt.read(this.tokenData, this.pos);
|
||||
addOperator(gt);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.GREATER_EQUAL) {
|
||||
GreaterEqual gte = new GreaterEqual();
|
||||
this.pos += gte.read(this.tokenData, this.pos);
|
||||
addOperator(gte);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.NOT_EQUAL) {
|
||||
NotEqual ne = new NotEqual();
|
||||
this.pos += ne.read(this.tokenData, this.pos);
|
||||
addOperator(ne);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.EQUAL) {
|
||||
Equal e = new Equal();
|
||||
this.pos += e.read(this.tokenData, this.pos);
|
||||
addOperator(e);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.PARENTHESIS) {
|
||||
Parenthesis p = new Parenthesis();
|
||||
this.pos += p.read(this.tokenData, this.pos);
|
||||
addOperator(p);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.ATTRIBUTE) {
|
||||
Attribute a = new Attribute(this.settings);
|
||||
this.pos += a.read(this.tokenData, this.pos);
|
||||
if (a.isSum()) {
|
||||
addOperator(a);
|
||||
continue;
|
||||
}
|
||||
if (a.isIf())
|
||||
ifStack.push(a);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.FUNCTION) {
|
||||
BuiltInFunction bif = new BuiltInFunction(this.settings);
|
||||
this.pos += bif.read(this.tokenData, this.pos);
|
||||
addOperator(bif);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.FUNCTIONVARARG) {
|
||||
VariableArgFunction vaf = new VariableArgFunction(this.settings);
|
||||
this.pos += vaf.read(this.tokenData, this.pos);
|
||||
if (vaf.getFunction() != Function.ATTRIBUTE) {
|
||||
addOperator(vaf);
|
||||
continue;
|
||||
}
|
||||
vaf.getOperands(this.tokenStack);
|
||||
Attribute ifattr = null;
|
||||
if (ifStack.empty()) {
|
||||
ifattr = new Attribute(this.settings);
|
||||
} else {
|
||||
ifattr = ifStack.pop();
|
||||
}
|
||||
ifattr.setIfConditions(vaf);
|
||||
this.tokenStack.push(ifattr);
|
||||
continue;
|
||||
}
|
||||
if (t == Token.MEM_FUNC) {
|
||||
MemFunc memFunc = new MemFunc();
|
||||
this.pos += memFunc.read(this.tokenData, this.pos);
|
||||
Stack oldStack = this.tokenStack;
|
||||
this.tokenStack = new Stack();
|
||||
parseSubExpression(memFunc.getLength());
|
||||
ParseItem[] subexpr = new ParseItem[this.tokenStack.size()];
|
||||
int i = 0;
|
||||
while (!this.tokenStack.isEmpty()) {
|
||||
subexpr[i] = this.tokenStack.pop();
|
||||
i++;
|
||||
}
|
||||
memFunc.setSubExpression(subexpr);
|
||||
this.tokenStack = oldStack;
|
||||
this.tokenStack.push(memFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addOperator(Operator o) {
|
||||
o.getOperands(this.tokenStack);
|
||||
this.tokenStack.push(o);
|
||||
}
|
||||
|
||||
public String getFormula() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
this.root.getString(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) {
|
||||
this.root.adjustRelativeCellReferences(colAdjust, rowAdjust);
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return this.root.getBytes();
|
||||
}
|
||||
|
||||
public void columnInserted(int sheetIndex, int col, boolean currentSheet) {
|
||||
this.root.columnInserted(sheetIndex, col, currentSheet);
|
||||
}
|
||||
|
||||
public void columnRemoved(int sheetIndex, int col, boolean currentSheet) {
|
||||
this.root.columnRemoved(sheetIndex, col, currentSheet);
|
||||
}
|
||||
|
||||
public void rowInserted(int sheetIndex, int row, boolean currentSheet) {
|
||||
this.root.rowInserted(sheetIndex, row, currentSheet);
|
||||
}
|
||||
|
||||
public void rowRemoved(int sheetIndex, int row, boolean currentSheet) {
|
||||
this.root.rowRemoved(sheetIndex, row, currentSheet);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user