1 19 20 package jxl.biff.formula; 21 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 import java.util.Stack ; 25 import java.io.StringReader ; 26 import java.io.IOException ; 27 28 import common.Assert; 29 import common.Logger; 30 31 import jxl.Cell; 32 import jxl.WorkbookSettings; 33 import jxl.biff.WorkbookMethods; 34 35 38 class StringFormulaParser implements Parser 39 { 40 43 private static Logger logger = Logger.getLogger(StringFormulaParser.class); 44 45 48 private String formula; 49 50 53 private String parsedFormula; 54 55 58 private ParseItem root; 59 60 64 private Stack arguments; 65 66 69 private WorkbookSettings settings; 70 71 74 private ExternalSheet externalSheet; 75 76 79 private WorkbookMethods nameTable; 80 81 86 public StringFormulaParser(String f, ExternalSheet es, WorkbookMethods nt, 87 WorkbookSettings ws) 88 { 89 formula = f; 90 settings = ws; 91 externalSheet = es; 92 nameTable = nt; 93 } 94 95 100 public void parse() throws FormulaException 101 { 102 ArrayList tokens = getTokens(); 103 104 Iterator i = tokens.iterator(); 105 106 root = parseCurrent(i); 107 } 108 109 117 private ParseItem parseCurrent(Iterator i) throws FormulaException 118 { 119 Stack stack = new Stack (); 120 Stack operators = new Stack (); 121 Stack args = null; 123 boolean parenthesesClosed = false; 124 ParseItem lastParseItem = null; 125 126 while (i.hasNext() && !parenthesesClosed) 127 { 128 ParseItem pi = (ParseItem) i.next(); 129 130 if (pi instanceof Operand) 131 { 132 handleOperand((Operand) pi, stack); 133 } 134 else if (pi instanceof StringFunction) 135 { 136 handleFunction((StringFunction) pi, i, stack); 137 } 138 else if (pi instanceof Operator) 139 { 140 Operator op = (Operator) pi; 141 142 if (op instanceof StringOperator) 146 { 147 StringOperator sop = (StringOperator) op; 148 if (stack.isEmpty() || lastParseItem instanceof Operator) 149 { 150 op = sop.getUnaryOperator(); 151 } 152 else 153 { 154 op = sop.getBinaryOperator(); 155 } 156 } 157 158 if (operators.empty()) 159 { 160 operators.push(op); 162 } 163 else 164 { 165 Operator operator = (Operator) operators.peek(); 166 167 if (op.getPrecedence() < operator.getPrecedence()) 170 { 171 operators.push(op); 172 } 173 else 174 { 175 operators.pop(); operator.getOperands(stack); 179 stack.push(operator); 180 operators.push(op); 181 } 182 } 183 } 184 else if (pi instanceof ArgumentSeparator) 185 { 186 while (!operators.isEmpty()) 188 { 189 Operator o = (Operator) operators.pop(); 190 o.getOperands(stack); 191 stack.push(o); 192 } 193 194 if (args == null) 198 { 199 args = new Stack (); 200 } 201 202 args.push(stack.pop()); 203 stack.clear(); 204 } 205 else if (pi instanceof OpenParentheses) 206 { 207 ParseItem pi2 = parseCurrent(i); 208 Parenthesis p = new Parenthesis(); 209 pi2.setParent(p); 210 p.add(pi2); 211 stack.push(p); 212 } 213 else if (pi instanceof CloseParentheses) 214 { 215 parenthesesClosed = true; 216 } 217 218 lastParseItem = pi; 219 } 220 221 while (!operators.isEmpty()) 222 { 223 Operator o = (Operator) operators.pop(); 224 o.getOperands(stack); 225 stack.push(o); 226 } 227 228 ParseItem rt = !stack.empty()? (ParseItem) stack.pop():null; 229 230 if (args != null && rt != null) 233 { 234 args.push(rt); 235 } 236 237 arguments = args; 238 239 if (!stack.empty() || !operators.empty() ) 240 { 241 logger.warn("Formula " + formula + 242 " has a non-empty parse stack"); 243 } 244 245 return rt; 246 } 247 248 254 private ArrayList getTokens() throws FormulaException 255 { 256 ArrayList tokens = new ArrayList (); 257 258 StringReader sr = new StringReader (formula); 259 Yylex lex = new Yylex(sr); 260 lex.setExternalSheet(externalSheet); 261 lex.setNameTable(nameTable); 262 try 263 { 264 ParseItem pi = lex.yylex(); 265 while (pi != null) 266 { 267 tokens.add(pi); 268 pi = lex.yylex(); 269 } 270 } 271 catch (IOException e) 272 { 273 logger.warn(e.toString()); 274 } 275 catch (Error e) 276 { 277 throw new FormulaException(FormulaException.lexicalError, 278 formula + " at char " + lex.getPos()); 279 } 280 281 return tokens; 282 } 283 284 288 public String getFormula() 289 { 290 if (parsedFormula == null) 291 { 292 StringBuffer sb = new StringBuffer (); 293 root.getString(sb); 294 parsedFormula = sb.toString(); 295 } 296 297 return parsedFormula; 298 } 299 300 305 public byte[] getBytes() 306 { 307 byte[] bytes = root.getBytes(); 308 309 if (root.isVolatile()) 310 { 311 byte[] newBytes = new byte[bytes.length + 4]; 312 System.arraycopy(bytes, 0, newBytes, 4, bytes.length); 313 newBytes[0] = Token.ATTRIBUTE.getCode(); 314 newBytes[1] = (byte) 0x1; 315 bytes = newBytes; 316 } 317 318 return bytes; 319 } 320 321 329 private void handleFunction(StringFunction sf, Iterator i, 330 Stack stack) 331 throws FormulaException 332 { 333 ParseItem pi2 = parseCurrent(i); 334 335 if (sf.getFunction(settings) == Function.UNKNOWN) 337 { 338 throw new FormulaException(FormulaException.unrecognizedFunction); 339 } 340 341 if (sf.getFunction(settings) == Function.SUM && arguments == null) 344 { 345 Attribute a = new Attribute(sf, settings); 347 a.add(pi2); 348 stack.push(a); 349 return; 350 } 351 352 if (sf.getFunction(settings) == Function.IF) 353 { 354 Attribute a = new Attribute(sf, settings); 356 357 VariableArgFunction vaf = new VariableArgFunction(settings); 360 int numargs = arguments.size(); 361 for (int j = 0 ; j < numargs; j++) 362 { 363 ParseItem pi3 = (ParseItem) arguments.get(j); 364 vaf.add(pi3); 365 } 366 367 a.setIfConditions(vaf); 368 stack.push(a); 369 return; 370 } 371 372 if (sf.getFunction(settings).getNumArgs() == 0xff) 375 { 376 if (arguments == null) 380 { 381 VariableArgFunction vaf = new VariableArgFunction 382 (sf.getFunction(settings), 1, settings); 383 vaf.add(pi2); 384 stack.push(vaf); 385 } 386 else 387 { 388 int numargs = arguments.size(); 390 VariableArgFunction vaf = new VariableArgFunction 391 (sf.getFunction(settings), numargs, settings); 392 393 ParseItem[] args = new ParseItem[numargs]; 394 for (int j = 0 ; j < numargs; j++) 395 { 396 ParseItem pi3 = (ParseItem) arguments.pop(); 397 args[numargs-j-1] = pi3; 398 } 399 400 for (int j = 0 ; j < args.length ; j++) 401 { 402 vaf.add(args[j]); 403 } 404 stack.push(vaf); 405 arguments.clear(); 406 arguments = null; 407 } 408 return; 409 } 410 411 BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings), 413 settings); 414 415 int numargs = sf.getFunction(settings).getNumArgs(); 416 if (numargs == 1) 417 { 418 bif.add(pi2); 420 } 421 else 422 { 423 if ((arguments == null && numargs != 0) || 424 (arguments != null && numargs != arguments.size())) 425 { 426 throw new FormulaException(FormulaException.incorrectArguments); 427 } 428 for (int j = 0; j < numargs ; j++) 432 { 433 ParseItem pi3 = (ParseItem) arguments.get(j); 434 bif.add(pi3); 435 } 436 } 437 stack.push(bif); 438 } 439 440 446 public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) 447 { 448 root.adjustRelativeCellReferences(colAdjust, rowAdjust); 449 } 450 451 461 public void columnInserted(int sheetIndex, int col, boolean currentSheet) 462 { 463 root.columnInserted(sheetIndex, col, currentSheet); 464 } 465 466 467 477 public void columnRemoved(int sheetIndex, int col, boolean currentSheet) 478 { 479 root.columnRemoved(sheetIndex, col, currentSheet); 480 } 481 482 492 public void rowInserted(int sheetIndex, int row, boolean currentSheet) 493 { 494 root.rowInserted(sheetIndex, row, currentSheet); 495 } 496 497 507 public void rowRemoved(int sheetIndex, int row, boolean currentSheet) 508 { 509 root.rowRemoved(sheetIndex, row, currentSheet); 510 } 511 512 518 private void handleOperand(Operand o, Stack stack) 519 { 520 if (!(o instanceof IntegerValue)) 521 { 522 stack.push(o); 523 return; 524 } 525 526 if (o instanceof IntegerValue) 527 { 528 IntegerValue iv = (IntegerValue) o; 529 if (!iv.isOutOfRange()) 530 { 531 stack.push(iv); 532 } 533 else 534 { 535 DoubleValue dv = new DoubleValue(iv.getValue()); 537 stack.push(dv); 538 } 539 } 540 } 541 542 } 543 | Popular Tags |