1### $ANTLR 2.7.7 (20060930): "xlwt/excel-formula.g" -> "ExcelFormulaParser.py"$ 2### import antlr and other modules .. 3from . import antlr 4 5### header action >>> 6import struct 7from . import Utils 8from .UnicodeUtils import upack1 9from .ExcelMagic import * 10 11_RVAdelta = {"R": 0, "V": 0x20, "A": 0x40} 12_RVAdeltaRef = {"R": 0, "V": 0x20, "A": 0x40, "D": 0x20} 13_RVAdeltaArea = {"R": 0, "V": 0x20, "A": 0x40, "D": 0} 14 15 16class FormulaParseException(Exception): 17 """ 18 An exception indicating that a Formula could not be successfully parsed. 19 """ 20### header action <<< 21### preamble action>>> 22 23### preamble action <<< 24 25### >>>The Known Token Types <<< 26SKIP = antlr.SKIP 27INVALID_TYPE = antlr.INVALID_TYPE 28EOF_TYPE = antlr.EOF_TYPE 29EOF = antlr.EOF 30NULL_TREE_LOOKAHEAD = antlr.NULL_TREE_LOOKAHEAD 31MIN_USER_TYPE = antlr.MIN_USER_TYPE 32TRUE_CONST = 4 33FALSE_CONST = 5 34STR_CONST = 6 35NUM_CONST = 7 36INT_CONST = 8 37FUNC_IF = 9 38FUNC_CHOOSE = 10 39NAME = 11 40QUOTENAME = 12 41EQ = 13 42NE = 14 43GT = 15 44LT = 16 45GE = 17 46LE = 18 47ADD = 19 48SUB = 20 49MUL = 21 50DIV = 22 51POWER = 23 52PERCENT = 24 53LP = 25 54RP = 26 55LB = 27 56RB = 28 57COLON = 29 58COMMA = 30 59SEMICOLON = 31 60REF2D = 32 61REF2D_R1C1 = 33 62BANG = 34 63CONCAT = 35 64 65class Parser(antlr.LLkParser): 66 ### user action >>> 67 ### user action <<< 68 69 def __init__(self, *args, **kwargs): 70 antlr.LLkParser.__init__(self, *args, **kwargs) 71 self.tokenNames = _tokenNames 72 ### __init__ header action >>> 73 self.rpn = b"" 74 self.sheet_references = [] 75 self.xcall_references = [] 76 ### __init__ header action <<< 77 78 def formula(self): 79 80 pass 81 self.expr("V") 82 83 def expr(self, 84 arg_type 85 ): 86 87 pass 88 self.prec0_expr(arg_type) 89 while True: 90 if ((self.LA(1) >= EQ and self.LA(1) <= LE)): 91 pass 92 la1 = self.LA(1) 93 if False: 94 pass 95 elif la1 and la1 in [EQ]: 96 pass 97 self.match(EQ) 98 op = struct.pack('B', ptgEQ) 99 elif la1 and la1 in [NE]: 100 pass 101 self.match(NE) 102 op = struct.pack('B', ptgNE) 103 elif la1 and la1 in [GT]: 104 pass 105 self.match(GT) 106 op = struct.pack('B', ptgGT) 107 elif la1 and la1 in [LT]: 108 pass 109 self.match(LT) 110 op = struct.pack('B', ptgLT) 111 elif la1 and la1 in [GE]: 112 pass 113 self.match(GE) 114 op = struct.pack('B', ptgGE) 115 elif la1 and la1 in [LE]: 116 pass 117 self.match(LE) 118 op = struct.pack('B', ptgLE) 119 else: 120 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 121 122 self.prec0_expr(arg_type) 123 self.rpn += op 124 else: 125 break 126 127 128 def prec0_expr(self, 129 arg_type 130 ): 131 132 pass 133 self.prec1_expr(arg_type) 134 while True: 135 if (self.LA(1)==CONCAT): 136 pass 137 pass 138 self.match(CONCAT) 139 op = struct.pack('B', ptgConcat) 140 self.prec1_expr(arg_type) 141 self.rpn += op 142 else: 143 break 144 145 146 def prec1_expr(self, 147 arg_type 148 ): 149 150 pass 151 self.prec2_expr(arg_type) 152 while True: 153 if (self.LA(1)==ADD or self.LA(1)==SUB): 154 pass 155 la1 = self.LA(1) 156 if False: 157 pass 158 elif la1 and la1 in [ADD]: 159 pass 160 self.match(ADD) 161 op = struct.pack('B', ptgAdd) 162 elif la1 and la1 in [SUB]: 163 pass 164 self.match(SUB) 165 op = struct.pack('B', ptgSub) 166 else: 167 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 168 169 self.prec2_expr(arg_type) 170 self.rpn += op; 171 # print "**prec1_expr4 %s" % arg_type 172 else: 173 break 174 175 176 def prec2_expr(self, 177 arg_type 178 ): 179 180 pass 181 self.prec3_expr(arg_type) 182 while True: 183 if (self.LA(1)==MUL or self.LA(1)==DIV): 184 pass 185 la1 = self.LA(1) 186 if False: 187 pass 188 elif la1 and la1 in [MUL]: 189 pass 190 self.match(MUL) 191 op = struct.pack('B', ptgMul) 192 elif la1 and la1 in [DIV]: 193 pass 194 self.match(DIV) 195 op = struct.pack('B', ptgDiv) 196 else: 197 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 198 199 self.prec3_expr(arg_type) 200 self.rpn += op 201 else: 202 break 203 204 205 def prec3_expr(self, 206 arg_type 207 ): 208 209 pass 210 self.prec4_expr(arg_type) 211 while True: 212 if (self.LA(1)==POWER): 213 pass 214 pass 215 self.match(POWER) 216 op = struct.pack('B', ptgPower) 217 self.prec4_expr(arg_type) 218 self.rpn += op 219 else: 220 break 221 222 223 def prec4_expr(self, 224 arg_type 225 ): 226 227 pass 228 self.prec5_expr(arg_type) 229 la1 = self.LA(1) 230 if False: 231 pass 232 elif la1 and la1 in [PERCENT]: 233 pass 234 self.match(PERCENT) 235 self.rpn += struct.pack('B', ptgPercent) 236 elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,RP,COMMA,SEMICOLON,CONCAT]: 237 pass 238 else: 239 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 240 241 242 def prec5_expr(self, 243 arg_type 244 ): 245 246 la1 = self.LA(1) 247 if False: 248 pass 249 elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,LP,REF2D]: 250 pass 251 self.primary(arg_type) 252 elif la1 and la1 in [SUB]: 253 pass 254 self.match(SUB) 255 self.primary(arg_type) 256 self.rpn += struct.pack('B', ptgUminus) 257 else: 258 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 259 260 261 def primary(self, 262 arg_type 263 ): 264 265 str_tok = None 266 int_tok = None 267 num_tok = None 268 ref2d_tok = None 269 ref2d1_tok = None 270 ref2d2_tok = None 271 ref3d_ref2d = None 272 ref3d_ref2d2 = None 273 name_tok = None 274 func_tok = None 275 la1 = self.LA(1) 276 if False: 277 pass 278 elif la1 and la1 in [TRUE_CONST]: 279 pass 280 self.match(TRUE_CONST) 281 self.rpn += struct.pack("2B", ptgBool, 1) 282 elif la1 and la1 in [FALSE_CONST]: 283 pass 284 self.match(FALSE_CONST) 285 self.rpn += struct.pack("2B", ptgBool, 0) 286 elif la1 and la1 in [STR_CONST]: 287 pass 288 str_tok = self.LT(1) 289 self.match(STR_CONST) 290 self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1].replace("\"\"", "\"")) 291 elif la1 and la1 in [NUM_CONST]: 292 pass 293 num_tok = self.LT(1) 294 self.match(NUM_CONST) 295 self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text)) 296 elif la1 and la1 in [FUNC_IF]: 297 pass 298 self.match(FUNC_IF) 299 self.match(LP) 300 self.expr("V") 301 la1 = self.LA(1) 302 if False: 303 pass 304 elif la1 and la1 in [SEMICOLON]: 305 pass 306 self.match(SEMICOLON) 307 elif la1 and la1 in [COMMA]: 308 pass 309 self.match(COMMA) 310 else: 311 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 312 313 self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0) # tAttrIf 314 pos0 = len(self.rpn) - 2 315 self.expr(arg_type) 316 la1 = self.LA(1) 317 if False: 318 pass 319 elif la1 and la1 in [SEMICOLON]: 320 pass 321 self.match(SEMICOLON) 322 elif la1 and la1 in [COMMA]: 323 pass 324 self.match(COMMA) 325 else: 326 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 327 328 self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0) # tAttrSkip 329 pos1 = len(self.rpn) - 2 330 self.rpn = self.rpn[:pos0] + struct.pack("<H", pos1-pos0) + self.rpn[pos0+2:] 331 self.expr(arg_type) 332 self.match(RP) 333 self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3) # tAttrSkip 334 self.rpn += struct.pack("<BBH", ptgFuncVarR, 3, 1) # 3 = nargs, 1 = IF func 335 pos2 = len(self.rpn) 336 self.rpn = self.rpn[:pos1] + struct.pack("<H", pos2-(pos1+2)-1) + self.rpn[pos1+2:] 337 elif la1 and la1 in [FUNC_CHOOSE]: 338 pass 339 self.match(FUNC_CHOOSE) 340 arg_type = "R" 341 rpn_chunks = [] 342 self.match(LP) 343 self.expr("V") 344 rpn_start = len(self.rpn) 345 ref_markers = [len(self.sheet_references)] 346 while True: 347 if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON): 348 pass 349 la1 = self.LA(1) 350 if False: 351 pass 352 elif la1 and la1 in [SEMICOLON]: 353 pass 354 self.match(SEMICOLON) 355 elif la1 and la1 in [COMMA]: 356 pass 357 self.match(COMMA) 358 else: 359 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 360 361 mark = len(self.rpn) 362 la1 = self.LA(1) 363 if False: 364 pass 365 elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]: 366 pass 367 self.expr(arg_type) 368 elif la1 and la1 in [RP,COMMA,SEMICOLON]: 369 pass 370 self.rpn += struct.pack("B", ptgMissArg) 371 else: 372 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 373 374 rpn_chunks.append(self.rpn[mark:]) 375 ref_markers.append(len(self.sheet_references)) 376 else: 377 break 378 379 self.match(RP) 380 self.rpn = self.rpn[:rpn_start] 381 nc = len(rpn_chunks) 382 chunklens = [len(chunk) for chunk in rpn_chunks] 383 skiplens = [0] * nc 384 skiplens[-1] = 3 385 for ic in xrange(nc-1, 0, -1): 386 skiplens[ic-1] = skiplens[ic] + chunklens[ic] + 4 387 jump_pos = [2 * nc + 2] 388 for ic in xrange(nc): 389 jump_pos.append(jump_pos[-1] + chunklens[ic] + 4) 390 chunk_shift = 2 * nc + 6 # size of tAttrChoose 391 for ic in xrange(nc): 392 for refx in xrange(ref_markers[ic], ref_markers[ic+1]): 393 ref = self.sheet_references[refx] 394 self.sheet_references[refx] = (ref[0], ref[1], ref[2] + chunk_shift) 395 chunk_shift += 4 # size of tAttrSkip 396 choose_rpn = [] 397 choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04, nc)) # 0x04 is tAttrChoose 398 choose_rpn.append(struct.pack("<%dH" % (nc+1), *jump_pos)) 399 for ic in xrange(nc): 400 choose_rpn.append(rpn_chunks[ic]) 401 choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x08, skiplens[ic])) # 0x08 is tAttrSkip 402 choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc+1, 100)) # 100 is CHOOSE fn 403 self.rpn += "".join(choose_rpn) 404 elif la1 and la1 in [LP]: 405 pass 406 self.match(LP) 407 self.expr(arg_type) 408 self.match(RP) 409 self.rpn += struct.pack("B", ptgParen) 410 else: 411 if (self.LA(1)==INT_CONST) and (_tokenSet_0.member(self.LA(2))): 412 pass 413 int_tok = self.LT(1) 414 self.match(INT_CONST) 415 # print "**int_const", int_tok.text 416 int_value = int(int_tok.text) 417 if int_value <= 65535: 418 self.rpn += struct.pack("<BH", ptgInt, int_value) 419 else: 420 self.rpn += struct.pack("<Bd", ptgNum, float(int_value)) 421 elif (self.LA(1)==REF2D) and (_tokenSet_0.member(self.LA(2))): 422 pass 423 ref2d_tok = self.LT(1) 424 self.match(REF2D) 425 # print "**ref2d %s %s" % (ref2d_tok.text, arg_type) 426 r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text) 427 ptg = ptgRefR + _RVAdeltaRef[arg_type] 428 self.rpn += struct.pack("<B2H", ptg, r, c) 429 elif (self.LA(1)==REF2D) and (self.LA(2)==COLON): 430 pass 431 ref2d1_tok = self.LT(1) 432 self.match(REF2D) 433 self.match(COLON) 434 ref2d2_tok = self.LT(1) 435 self.match(REF2D) 436 r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text) 437 r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text) 438 ptg = ptgAreaR + _RVAdeltaArea[arg_type] 439 self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2) 440 elif (self.LA(1)==INT_CONST or self.LA(1)==NAME or self.LA(1)==QUOTENAME) and (self.LA(2)==COLON or self.LA(2)==BANG): 441 pass 442 sheet1=self.sheet() 443 sheet2 = sheet1 444 la1 = self.LA(1) 445 if False: 446 pass 447 elif la1 and la1 in [COLON]: 448 pass 449 self.match(COLON) 450 sheet2=self.sheet() 451 elif la1 and la1 in [BANG]: 452 pass 453 else: 454 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 455 456 self.match(BANG) 457 ref3d_ref2d = self.LT(1) 458 self.match(REF2D) 459 ptg = ptgRef3dR + _RVAdeltaRef[arg_type] 460 rpn_ref2d = "" 461 r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text) 462 rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1) 463 la1 = self.LA(1) 464 if False: 465 pass 466 elif la1 and la1 in [COLON]: 467 pass 468 self.match(COLON) 469 ref3d_ref2d2 = self.LT(1) 470 self.match(REF2D) 471 ptg = ptgArea3dR + _RVAdeltaArea[arg_type] 472 r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text) 473 rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2) 474 elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,PERCENT,RP,COMMA,SEMICOLON,CONCAT]: 475 pass 476 else: 477 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 478 479 self.rpn += struct.pack("<B", ptg) 480 self.sheet_references.append((sheet1, sheet2, len(self.rpn))) 481 self.rpn += rpn_ref2d 482 elif (self.LA(1)==NAME) and (_tokenSet_0.member(self.LA(2))): 483 pass 484 name_tok = self.LT(1) 485 self.match(NAME) 486 raise Exception("[formula] found unexpected NAME token (%r)" % name_tok.txt) 487 # #### TODO: handle references to defined names here 488 elif (self.LA(1)==NAME) and (self.LA(2)==LP): 489 pass 490 func_tok = self.LT(1) 491 self.match(NAME) 492 func_toku = func_tok.text.upper() 493 if func_toku in all_funcs_by_name: 494 (opcode, 495 min_argc, 496 max_argc, 497 func_type, 498 arg_type_str) = all_funcs_by_name[func_toku] 499 arg_type_list = list(arg_type_str) 500 else: 501 raise Exception("[formula] unknown function (%s)" % func_tok.text) 502 # print "**func_tok1 %s %s" % (func_toku, func_type) 503 xcall = opcode < 0 504 if xcall: 505 # The name of the add-in function is passed as the 1st arg 506 # of the hidden XCALL function 507 self.xcall_references.append((func_toku, len(self.rpn) + 1)) 508 self.rpn += struct.pack("<BHHH", 509 ptgNameXR, 510 0xadde, # ##PATCHME## index to REF entry in EXTERNSHEET record 511 0xefbe, # ##PATCHME## one-based index to EXTERNNAME record 512 0x0000) # unused 513 self.match(LP) 514 arg_count=self.expr_list(arg_type_list, min_argc, max_argc) 515 self.match(RP) 516 if arg_count > max_argc or arg_count < min_argc: 517 raise Exception("%d parameters for function: %s" % (arg_count, func_tok.text)) 518 if xcall: 519 func_ptg = ptgFuncVarR + _RVAdelta[func_type] 520 self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1, 255) # 255 is magic XCALL function 521 elif min_argc == max_argc: 522 func_ptg = ptgFuncR + _RVAdelta[func_type] 523 self.rpn += struct.pack("<BH", func_ptg, opcode) 524 elif arg_count == 1 and func_tok.text.upper() == "SUM": 525 self.rpn += struct.pack("<BBH", ptgAttr, 0x10, 0) # tAttrSum 526 else: 527 func_ptg = ptgFuncVarR + _RVAdelta[func_type] 528 self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode) 529 else: 530 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 531 532 533 def sheet(self): 534 ref = None 535 536 sheet_ref_name = None 537 sheet_ref_int = None 538 sheet_ref_quote = None 539 la1 = self.LA(1) 540 if False: 541 pass 542 elif la1 and la1 in [NAME]: 543 pass 544 sheet_ref_name = self.LT(1) 545 self.match(NAME) 546 ref = sheet_ref_name.text 547 elif la1 and la1 in [INT_CONST]: 548 pass 549 sheet_ref_int = self.LT(1) 550 self.match(INT_CONST) 551 ref = sheet_ref_int.text 552 elif la1 and la1 in [QUOTENAME]: 553 pass 554 sheet_ref_quote = self.LT(1) 555 self.match(QUOTENAME) 556 ref = sheet_ref_quote.text[1:-1].replace("''", "'") 557 else: 558 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 559 560 return ref 561 562 def expr_list(self, 563 arg_type_list, min_argc, max_argc 564 ): 565 arg_cnt = None 566 567 arg_cnt = 0 568 arg_type = arg_type_list[arg_cnt] 569 # print "**expr_list1[%d] req=%s" % (arg_cnt, arg_type) 570 la1 = self.LA(1) 571 if False: 572 pass 573 elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]: 574 pass 575 self.expr(arg_type) 576 arg_cnt += 1 577 while True: 578 if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON): 579 pass 580 if arg_cnt < len(arg_type_list): 581 arg_type = arg_type_list[arg_cnt] 582 else: 583 arg_type = arg_type_list[-1] 584 if arg_type == "+": 585 arg_type = arg_type_list[-2] 586 # print "**expr_list2[%d] req=%s" % (arg_cnt, arg_type) 587 la1 = self.LA(1) 588 if False: 589 pass 590 elif la1 and la1 in [SEMICOLON]: 591 pass 592 self.match(SEMICOLON) 593 elif la1 and la1 in [COMMA]: 594 pass 595 self.match(COMMA) 596 else: 597 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 598 599 la1 = self.LA(1) 600 if False: 601 pass 602 elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]: 603 pass 604 self.expr(arg_type) 605 elif la1 and la1 in [RP,COMMA,SEMICOLON]: 606 pass 607 self.rpn += struct.pack("B", ptgMissArg) 608 else: 609 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 610 611 arg_cnt += 1 612 else: 613 break 614 615 elif la1 and la1 in [RP]: 616 pass 617 else: 618 raise antlr.NoViableAltException(self.LT(1), self.getFilename()) 619 620 return arg_cnt 621 622 623_tokenNames = [ 624 "<0>", 625 "EOF", 626 "<2>", 627 "NULL_TREE_LOOKAHEAD", 628 "TRUE_CONST", 629 "FALSE_CONST", 630 "STR_CONST", 631 "NUM_CONST", 632 "INT_CONST", 633 "FUNC_IF", 634 "FUNC_CHOOSE", 635 "NAME", 636 "QUOTENAME", 637 "EQ", 638 "NE", 639 "GT", 640 "LT", 641 "GE", 642 "LE", 643 "ADD", 644 "SUB", 645 "MUL", 646 "DIV", 647 "POWER", 648 "PERCENT", 649 "LP", 650 "RP", 651 "LB", 652 "RB", 653 "COLON", 654 "COMMA", 655 "SEMICOLON", 656 "REF2D", 657 "REF2D_R1C1", 658 "BANG", 659 "CONCAT" 660] 661 662 663### generate bit set 664def mk_tokenSet_0(): 665 ### var1 666 data = [ 37681618946, 0] 667 return data 668_tokenSet_0 = antlr.BitSet(mk_tokenSet_0()) 669 670