Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/xlwt/ExcelFormulaParser.py: 13%
396 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1### $ANTLR 2.7.7 (20060930): "xlwt/excel-formula.g" -> "ExcelFormulaParser.py"$
2### import antlr and other modules ..
3from . import antlr
5### header action >>>
6import struct
7from . import Utils
8from .UnicodeUtils import upack1
9from .ExcelMagic import *
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}
16class FormulaParseException(Exception):
17 """
18 An exception indicating that a Formula could not be successfully parsed.
19 """
20### header action <<<
21### preamble action>>>
23### preamble action <<<
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
65class Parser(antlr.LLkParser):
66 ### user action >>>
67 ### user action <<<
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 <<<
78 def formula(self):
80 pass
81 self.expr("V")
83 def expr(self,
84 arg_type
85 ):
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())
122 self.prec0_expr(arg_type)
123 self.rpn += op
124 else:
125 break
128 def prec0_expr(self,
129 arg_type
130 ):
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
146 def prec1_expr(self,
147 arg_type
148 ):
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())
169 self.prec2_expr(arg_type)
170 self.rpn += op;
171 # print "**prec1_expr4 %s" % arg_type
172 else:
173 break
176 def prec2_expr(self,
177 arg_type
178 ):
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())
199 self.prec3_expr(arg_type)
200 self.rpn += op
201 else:
202 break
205 def prec3_expr(self,
206 arg_type
207 ):
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
223 def prec4_expr(self,
224 arg_type
225 ):
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())
242 def prec5_expr(self,
243 arg_type
244 ):
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())
261 def primary(self,
262 arg_type
263 ):
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())
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())
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())
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())
374 rpn_chunks.append(self.rpn[mark:])
375 ref_markers.append(len(self.sheet_references))
376 else:
377 break
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())
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())
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())
533 def sheet(self):
534 ref = None
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())
560 return ref
562 def expr_list(self,
563 arg_type_list, min_argc, max_argc
564 ):
565 arg_cnt = None
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())
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())
611 arg_cnt += 1
612 else:
613 break
615 elif la1 and la1 in [RP]:
616 pass
617 else:
618 raise antlr.NoViableAltException(self.LT(1), self.getFilename())
620 return arg_cnt
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]
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())