Beispiel #1
0
 def add_sheet(self, sheetname, cell_overwrite_ok=False):
     from arelle import Worksheet, Utils
     if not isinstance(sheetname, str):
         sheetname = sheetname.decode(self.encoding)
     if not Utils.valid_sheet_name(sheetname):
         raise Exception("invalid worksheet name %r" % sheetname)
     lower_name = sheetname.lower()
     if lower_name in self.__worksheet_idx_from_name:
         raise Exception("duplicate worksheet name %r" % sheetname)
     self.__worksheet_idx_from_name[lower_name] = len(self.__worksheets)
     self.__worksheets.append(Worksheet(sheetname, self, cell_overwrite_ok))
     return self.__worksheets[-1]
Beispiel #2
0
    def primary(self,
        arg_type
    ):

        str_tok = None
        int_tok = None
        num_tok = None
        ref2d_tok = None
        ref2d1_tok = None
        ref2d2_tok = None
        ref3d_ref2d = None
        ref3d_ref2d2 = None
        name_tok = None
        func_tok = None
        la1 = self.LA(1)
        if False:
            pass
        elif la1 and la1 in [TRUE_CONST]:
            pass
            self.match(TRUE_CONST)
            self.rpn += struct.pack("2B", ptgBool, 1)
        elif la1 and la1 in [FALSE_CONST]:
            pass
            self.match(FALSE_CONST)
            self.rpn += struct.pack("2B", ptgBool, 0)
        elif la1 and la1 in [STR_CONST]:
            pass
            str_tok = self.LT(1)
            self.match(STR_CONST)
            self.rpn += struct.pack("B", ptgStr) + upack1(str_tok.text[1:-1].replace("\"\"", "\""))
        elif la1 and la1 in [NUM_CONST]:
            pass
            num_tok = self.LT(1)
            self.match(NUM_CONST)
            self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
        elif la1 and la1 in [FUNC_IF]:
            pass
            self.match(FUNC_IF)
            self.match(LP)
            self.expr("V")
            la1 = self.LA(1)
            if False:
                pass
            elif la1 and la1 in [SEMICOLON]:
                pass
                self.match(SEMICOLON)
            elif la1 and la1 in [COMMA]:
                pass
                self.match(COMMA)
            else:
                    raise antlr.NoViableAltException(self.LT(1), self.getFilename())

            self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0) # tAttrIf
            pos0 = len(self.rpn) - 2
            self.expr(arg_type)
            la1 = self.LA(1)
            if False:
                pass
            elif la1 and la1 in [SEMICOLON]:
                pass
                self.match(SEMICOLON)
            elif la1 and la1 in [COMMA]:
                pass
                self.match(COMMA)
            else:
                    raise antlr.NoViableAltException(self.LT(1), self.getFilename())

            self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0) # tAttrSkip
            pos1 = len(self.rpn) - 2
            self.rpn = self.rpn[:pos0] + struct.pack("<H", pos1-pos0) + self.rpn[pos0+2:]
            self.expr(arg_type)
            self.match(RP)
            self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3) # tAttrSkip
            self.rpn += struct.pack("<BBH", ptgFuncVarR, 3, 1) # 3 = nargs, 1 = IF func
            pos2 = len(self.rpn)
            self.rpn = self.rpn[:pos1] + struct.pack("<H", pos2-(pos1+2)-1) + self.rpn[pos1+2:]
        elif la1 and la1 in [FUNC_CHOOSE]:
            pass
            self.match(FUNC_CHOOSE)
            arg_type = b"R"
            rpn_chunks = []
            self.match(LP)
            self.expr("V")
            rpn_start = len(self.rpn)
            ref_markers = [len(self.sheet_references)]
            while True:
                if (self.LA(1)==COMMA or self.LA(1)==SEMICOLON):
                    pass
                    la1 = self.LA(1)
                    if False:
                        pass
                    elif la1 and la1 in [SEMICOLON]:
                        pass
                        self.match(SEMICOLON)
                    elif la1 and la1 in [COMMA]:
                        pass
                        self.match(COMMA)
                    else:
                            raise antlr.NoViableAltException(self.LT(1), self.getFilename())

                    mark = len(self.rpn)
                    la1 = self.LA(1)
                    if False:
                        pass
                    elif la1 and la1 in [TRUE_CONST,FALSE_CONST,STR_CONST,NUM_CONST,INT_CONST,FUNC_IF,FUNC_CHOOSE,NAME,QUOTENAME,SUB,LP,REF2D]:
                        pass
                        self.expr(arg_type)
                    elif la1 and la1 in [RP,COMMA,SEMICOLON]:
                        pass
                        self.rpn += struct.pack("B", ptgMissArg)
                    else:
                            raise antlr.NoViableAltException(self.LT(1), self.getFilename())

                    rpn_chunks.append(self.rpn[mark:])
                    ref_markers.append(len(self.sheet_references))
                else:
                    break

            self.match(RP)
            self.rpn = self.rpn[:rpn_start]
            nc = len(rpn_chunks)
            chunklens = [len(chunk) for chunk in rpn_chunks]
            skiplens = [0] * nc
            skiplens[-1] = 3
            for ic in range(nc-1, 0, -1):
                skiplens[ic-1] = skiplens[ic] + chunklens[ic] + 4
            jump_pos = [2 * nc + 2]
            for ic in range(nc):
                jump_pos.append(jump_pos[-1] + chunklens[ic] + 4)
            chunk_shift = 2 * nc + 6 # size of tAttrChoose
            for ic in range(nc):
                for refx in range(ref_markers[ic], ref_markers[ic+1]):
                    ref = self.sheet_references[refx]
                    self.sheet_references[refx] = (ref[0], ref[1], ref[2] + chunk_shift)
                chunk_shift += 4 # size of tAttrSkip
            choose_rpn = []
            choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04, nc)) # 0x04 is tAttrChoose
            choose_rpn.append(struct.pack("<%dH" % (nc+1), *jump_pos))
            for ic in range(nc):
                choose_rpn.append(rpn_chunks[ic])
                choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x08, skiplens[ic])) # 0x08 is tAttrSkip
            choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc+1, 100)) # 100 is CHOOSE fn
            self.rpn += b"".join(choose_rpn)
        elif la1 and la1 in [LP]:
            pass
            self.match(LP)
            self.expr(arg_type)
            self.match(RP)
            self.rpn += struct.pack("B", ptgParen)
        else:
            if (self.LA(1)==INT_CONST) and (_tokenSet_0.member(self.LA(2))):
                pass
                int_tok = self.LT(1)
                self.match(INT_CONST)
                # print "**int_const", int_tok.text
                int_value = int(int_tok.text)
                if int_value <= 65535:
                    self.rpn += struct.pack("<BH", ptgInt, int_value)
                else:
                    self.rpn += struct.pack("<Bd", ptgNum, float(int_value))
            elif (self.LA(1)==REF2D) and (_tokenSet_0.member(self.LA(2))):
                pass
                ref2d_tok = self.LT(1)
                self.match(REF2D)
                # print "**ref2d %s %s" % (ref2d_tok.text, arg_type)
                r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
                ptg = ptgRefR + _RVAdeltaRef[arg_type]
                self.rpn += struct.pack("<B2H", ptg, r, c)
            elif (self.LA(1)==REF2D) and (self.LA(2)==COLON):
                pass
                ref2d1_tok = self.LT(1)
                self.match(REF2D)
                self.match(COLON)
                ref2d2_tok = self.LT(1)
                self.match(REF2D)
                r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
                r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
                ptg = ptgAreaR + _RVAdeltaArea[arg_type]
                self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2)
            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):
                pass
                sheet1=self.sheet()
                sheet2 = sheet1
                la1 = self.LA(1)
                if False:
                    pass
                elif la1 and la1 in [COLON]:
                    pass
                    self.match(COLON)
                    sheet2=self.sheet()
                elif la1 and la1 in [BANG]:
                    pass
                else:
                        raise antlr.NoViableAltException(self.LT(1), self.getFilename())

                self.match(BANG)
                ref3d_ref2d = self.LT(1)
                self.match(REF2D)
                ptg = ptgRef3dR + _RVAdeltaRef[arg_type]
                rpn_ref2d = b""
                r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text)
                rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1)
                la1 = self.LA(1)
                if False:
                    pass
                elif la1 and la1 in [COLON]:
                    pass
                    self.match(COLON)
                    ref3d_ref2d2 = self.LT(1)
                    self.match(REF2D)
                    ptg = ptgArea3dR + _RVAdeltaArea[arg_type]
                    r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text)
                    rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2)
                elif la1 and la1 in [EOF,EQ,NE,GT,LT,GE,LE,ADD,SUB,MUL,DIV,POWER,PERCENT,RP,COMMA,SEMICOLON,CONCAT]:
                    pass
                else:
                    raise antlr.NoViableAltException(self.LT(1), self.getFilename())

                self.rpn += struct.pack("<B", ptg)
                self.sheet_references.append((sheet1, sheet2, len(self.rpn)))
                self.rpn += rpn_ref2d
            elif (self.LA(1)==NAME) and (_tokenSet_0.member(self.LA(2))):
                name_tok = self.LT(1)
                self.match(NAME)
                raise Exception("[formula] found unexpected NAME token (%r)" % name_tok.txt)
                # #### TODO: handle references to defined names here
            elif (self.LA(1)==NAME) and (self.LA(2)==LP):
                func_tok = self.LT(1)
                self.match(NAME)
                func_toku = func_tok.text.upper()
                if func_toku in all_funcs_by_name:
                    (opcode,
                    min_argc,
                    max_argc,
                    func_type,
                    arg_type_str) = all_funcs_by_name[func_toku]
                    arg_type_list = list(arg_type_str)
                else:
                    raise Exception("[formula] unknown function (%s)" % func_tok.text)
                # print "**func_tok1 %s %s" % (func_toku, func_type)
                xcall = opcode < 0
                if xcall:
                    # The name of the add-in function is passed as the 1st arg
                    # of the hidden XCALL function
                    self.xcall_references.append((func_toku, len(self.rpn) + 1))
                    self.rpn += struct.pack("<BHHH",
                        ptgNameXR,
                        0xadde, # ##PATCHME## index to REF entry in EXTERNSHEET record
                        0xefbe, # ##PATCHME## one-based index to EXTERNNAME record
                        0x0000) # unused
                self.match(LP)
                arg_count=self.expr_list(arg_type_list, min_argc, max_argc)
                self.match(RP)
                if arg_count > max_argc or arg_count < min_argc:
                    raise Exception("%d parameters for function: %s" % (arg_count, func_tok.text))
                if xcall:
                    func_ptg = ptgFuncVarR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1, 255) # 255 is magic XCALL function
                elif min_argc == max_argc:
                    func_ptg = ptgFuncR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<BH", func_ptg, opcode)
                elif arg_count == 1 and func_tok.text.upper() == "SUM":
                    self.rpn += struct.pack("<BBH", ptgAttr, 0x10, 0) # tAttrSum
                else:
                    func_ptg = ptgFuncVarR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<2BH", func_ptg, arg_count, opcode)
            else:
                raise antlr.NoViableAltException(self.LT(1), self.getFilename())
Beispiel #3
0
    def primary(self, arg_type):

        str_tok = None
        int_tok = None
        num_tok = None
        ref2d_tok = None
        ref2d1_tok = None
        ref2d2_tok = None
        ref3d_ref2d = None
        ref3d_ref2d2 = None
        name_tok = None
        func_tok = None
        la1 = self.LA(1)
        if False:
            pass
        elif la1 and la1 in [TRUE_CONST]:
            pass
            self.match(TRUE_CONST)
            self.rpn += struct.pack("2B", ptgBool, 1)
        elif la1 and la1 in [FALSE_CONST]:
            pass
            self.match(FALSE_CONST)
            self.rpn += struct.pack("2B", ptgBool, 0)
        elif la1 and la1 in [STR_CONST]:
            pass
            str_tok = self.LT(1)
            self.match(STR_CONST)
            self.rpn += struct.pack("B", ptgStr) + upack1(
                str_tok.text[1:-1].replace("\"\"", "\""))
        elif la1 and la1 in [NUM_CONST]:
            pass
            num_tok = self.LT(1)
            self.match(NUM_CONST)
            self.rpn += struct.pack("<Bd", ptgNum, float(num_tok.text))
        elif la1 and la1 in [FUNC_IF]:
            pass
            self.match(FUNC_IF)
            self.match(LP)
            self.expr("V")
            la1 = self.LA(1)
            if False:
                pass
            elif la1 and la1 in [SEMICOLON]:
                pass
                self.match(SEMICOLON)
            elif la1 and la1 in [COMMA]:
                pass
                self.match(COMMA)
            else:
                raise antlr.NoViableAltException(self.LT(1),
                                                 self.getFilename())

            self.rpn += struct.pack("<BBH", ptgAttr, 0x02, 0)  # tAttrIf
            pos0 = len(self.rpn) - 2
            self.expr(arg_type)
            la1 = self.LA(1)
            if False:
                pass
            elif la1 and la1 in [SEMICOLON]:
                pass
                self.match(SEMICOLON)
            elif la1 and la1 in [COMMA]:
                pass
                self.match(COMMA)
            else:
                raise antlr.NoViableAltException(self.LT(1),
                                                 self.getFilename())

            self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 0)  # tAttrSkip
            pos1 = len(self.rpn) - 2
            self.rpn = self.rpn[:pos0] + struct.pack(
                "<H", pos1 - pos0) + self.rpn[pos0 + 2:]
            self.expr(arg_type)
            self.match(RP)
            self.rpn += struct.pack("<BBH", ptgAttr, 0x08, 3)  # tAttrSkip
            self.rpn += struct.pack("<BBH", ptgFuncVarR, 3,
                                    1)  # 3 = nargs, 1 = IF func
            pos2 = len(self.rpn)
            self.rpn = self.rpn[:pos1] + struct.pack(
                "<H", pos2 - (pos1 + 2) - 1) + self.rpn[pos1 + 2:]
        elif la1 and la1 in [FUNC_CHOOSE]:
            pass
            self.match(FUNC_CHOOSE)
            arg_type = b"R"
            rpn_chunks = []
            self.match(LP)
            self.expr("V")
            rpn_start = len(self.rpn)
            ref_markers = [len(self.sheet_references)]
            while True:
                if (self.LA(1) == COMMA or self.LA(1) == SEMICOLON):
                    pass
                    la1 = self.LA(1)
                    if False:
                        pass
                    elif la1 and la1 in [SEMICOLON]:
                        pass
                        self.match(SEMICOLON)
                    elif la1 and la1 in [COMMA]:
                        pass
                        self.match(COMMA)
                    else:
                        raise antlr.NoViableAltException(
                            self.LT(1), self.getFilename())

                    mark = len(self.rpn)
                    la1 = self.LA(1)
                    if False:
                        pass
                    elif la1 and la1 in [
                            TRUE_CONST, FALSE_CONST, STR_CONST, NUM_CONST,
                            INT_CONST, FUNC_IF, FUNC_CHOOSE, NAME, QUOTENAME,
                            SUB, LP, REF2D
                    ]:
                        pass
                        self.expr(arg_type)
                    elif la1 and la1 in [RP, COMMA, SEMICOLON]:
                        pass
                        self.rpn += struct.pack("B", ptgMissArg)
                    else:
                        raise antlr.NoViableAltException(
                            self.LT(1), self.getFilename())

                    rpn_chunks.append(self.rpn[mark:])
                    ref_markers.append(len(self.sheet_references))
                else:
                    break

            self.match(RP)
            self.rpn = self.rpn[:rpn_start]
            nc = len(rpn_chunks)
            chunklens = [len(chunk) for chunk in rpn_chunks]
            skiplens = [0] * nc
            skiplens[-1] = 3
            for ic in range(nc - 1, 0, -1):
                skiplens[ic - 1] = skiplens[ic] + chunklens[ic] + 4
            jump_pos = [2 * nc + 2]
            for ic in range(nc):
                jump_pos.append(jump_pos[-1] + chunklens[ic] + 4)
            chunk_shift = 2 * nc + 6  # size of tAttrChoose
            for ic in range(nc):
                for refx in range(ref_markers[ic], ref_markers[ic + 1]):
                    ref = self.sheet_references[refx]
                    self.sheet_references[refx] = (ref[0], ref[1],
                                                   ref[2] + chunk_shift)
                chunk_shift += 4  # size of tAttrSkip
            choose_rpn = []
            choose_rpn.append(struct.pack("<BBH", ptgAttr, 0x04,
                                          nc))  # 0x04 is tAttrChoose
            choose_rpn.append(struct.pack("<%dH" % (nc + 1), *jump_pos))
            for ic in range(nc):
                choose_rpn.append(rpn_chunks[ic])
                choose_rpn.append(
                    struct.pack("<BBH", ptgAttr, 0x08,
                                skiplens[ic]))  # 0x08 is tAttrSkip
            choose_rpn.append(struct.pack("<BBH", ptgFuncVarV, nc + 1,
                                          100))  # 100 is CHOOSE fn
            self.rpn += b"".join(choose_rpn)
        elif la1 and la1 in [LP]:
            pass
            self.match(LP)
            self.expr(arg_type)
            self.match(RP)
            self.rpn += struct.pack("B", ptgParen)
        else:
            if (self.LA(1) == INT_CONST) and (_tokenSet_0.member(self.LA(2))):
                pass
                int_tok = self.LT(1)
                self.match(INT_CONST)
                # print "**int_const", int_tok.text
                int_value = int(int_tok.text)
                if int_value <= 65535:
                    self.rpn += struct.pack("<BH", ptgInt, int_value)
                else:
                    self.rpn += struct.pack("<Bd", ptgNum, float(int_value))
            elif (self.LA(1) == REF2D) and (_tokenSet_0.member(self.LA(2))):
                pass
                ref2d_tok = self.LT(1)
                self.match(REF2D)
                # print "**ref2d %s %s" % (ref2d_tok.text, arg_type)
                r, c = Utils.cell_to_packed_rowcol(ref2d_tok.text)
                ptg = ptgRefR + _RVAdeltaRef[arg_type]
                self.rpn += struct.pack("<B2H", ptg, r, c)
            elif (self.LA(1) == REF2D) and (self.LA(2) == COLON):
                pass
                ref2d1_tok = self.LT(1)
                self.match(REF2D)
                self.match(COLON)
                ref2d2_tok = self.LT(1)
                self.match(REF2D)
                r1, c1 = Utils.cell_to_packed_rowcol(ref2d1_tok.text)
                r2, c2 = Utils.cell_to_packed_rowcol(ref2d2_tok.text)
                ptg = ptgAreaR + _RVAdeltaArea[arg_type]
                self.rpn += struct.pack("<B4H", ptg, r1, r2, c1, c2)
            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):
                pass
                sheet1 = self.sheet()
                sheet2 = sheet1
                la1 = self.LA(1)
                if False:
                    pass
                elif la1 and la1 in [COLON]:
                    pass
                    self.match(COLON)
                    sheet2 = self.sheet()
                elif la1 and la1 in [BANG]:
                    pass
                else:
                    raise antlr.NoViableAltException(self.LT(1),
                                                     self.getFilename())

                self.match(BANG)
                ref3d_ref2d = self.LT(1)
                self.match(REF2D)
                ptg = ptgRef3dR + _RVAdeltaRef[arg_type]
                rpn_ref2d = b""
                r1, c1 = Utils.cell_to_packed_rowcol(ref3d_ref2d.text)
                rpn_ref2d = struct.pack("<3H", 0x0000, r1, c1)
                la1 = self.LA(1)
                if False:
                    pass
                elif la1 and la1 in [COLON]:
                    pass
                    self.match(COLON)
                    ref3d_ref2d2 = self.LT(1)
                    self.match(REF2D)
                    ptg = ptgArea3dR + _RVAdeltaArea[arg_type]
                    r2, c2 = Utils.cell_to_packed_rowcol(ref3d_ref2d2.text)
                    rpn_ref2d = struct.pack("<5H", 0x0000, r1, r2, c1, c2)
                elif la1 and la1 in [
                        EOF, EQ, NE, GT, LT, GE, LE, ADD, SUB, MUL, DIV, POWER,
                        PERCENT, RP, COMMA, SEMICOLON, CONCAT
                ]:
                    pass
                else:
                    raise antlr.NoViableAltException(self.LT(1),
                                                     self.getFilename())

                self.rpn += struct.pack("<B", ptg)
                self.sheet_references.append((sheet1, sheet2, len(self.rpn)))
                self.rpn += rpn_ref2d
            elif (self.LA(1) == NAME) and (_tokenSet_0.member(self.LA(2))):
                name_tok = self.LT(1)
                self.match(NAME)
                raise Exception("[formula] found unexpected NAME token (%r)" %
                                name_tok.txt)
                # #### TODO: handle references to defined names here
            elif (self.LA(1) == NAME) and (self.LA(2) == LP):
                func_tok = self.LT(1)
                self.match(NAME)
                func_toku = func_tok.text.upper()
                if func_toku in all_funcs_by_name:
                    (opcode, min_argc, max_argc, func_type,
                     arg_type_str) = all_funcs_by_name[func_toku]
                    arg_type_list = list(arg_type_str)
                else:
                    raise Exception("[formula] unknown function (%s)" %
                                    func_tok.text)
                # print "**func_tok1 %s %s" % (func_toku, func_type)
                xcall = opcode < 0
                if xcall:
                    # The name of the add-in function is passed as the 1st arg
                    # of the hidden XCALL function
                    self.xcall_references.append(
                        (func_toku, len(self.rpn) + 1))
                    self.rpn += struct.pack(
                        "<BHHH",
                        ptgNameXR,
                        0xadde,  # ##PATCHME## index to REF entry in EXTERNSHEET record
                        0xefbe,  # ##PATCHME## one-based index to EXTERNNAME record
                        0x0000)  # unused
                self.match(LP)
                arg_count = self.expr_list(arg_type_list, min_argc, max_argc)
                self.match(RP)
                if arg_count > max_argc or arg_count < min_argc:
                    raise Exception("%d parameters for function: %s" %
                                    (arg_count, func_tok.text))
                if xcall:
                    func_ptg = ptgFuncVarR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<2BH", func_ptg, arg_count + 1,
                                            255)  # 255 is magic XCALL function
                elif min_argc == max_argc:
                    func_ptg = ptgFuncR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<BH", func_ptg, opcode)
                elif arg_count == 1 and func_tok.text.upper() == "SUM":
                    self.rpn += struct.pack("<BBH", ptgAttr, 0x10,
                                            0)  # tAttrSum
                else:
                    func_ptg = ptgFuncVarR + _RVAdelta[func_type]
                    self.rpn += struct.pack("<2BH", func_ptg, arg_count,
                                            opcode)
            else:
                raise antlr.NoViableAltException(self.LT(1),
                                                 self.getFilename())