Ignore:
Timestamp:
Jul 11, 2012 12:58:32 PM (10 years ago)
Author:
jemian
Message:

refs #8, now handle multi-line cdef

File:
1 edited

Legend:

Unmodified
Added
Removed
  • specdomain/trunk/src/specdomain/sphinxcontrib/specmacrofileparser.py

    r1001 r1002  
    109109
    110110    def parse_macro_file(self):
     111        ext_com = self.find_extended_comments()
     112        desc_com = self.find_descriptive_comments()
     113        def_macro = self.find_def_macro()
     114        cdef_macro = self.find_cdef_macro()
     115        vars = self.find_variables()
     116       
     117        for linenumber in range(len(self.line_positions)):
     118            # TODO: decide the parent for each item, expect all def are at global scope
     119            # TODO: decide which macros and variables should not be documented
     120            # walk through the line numbers in the file
     121            #  if a def_macro starts, note its name and set the parent field
     122            #     of all comments, variables, var_desc, rdef, and cdef within
     123            #     its start_line and end_line range
     124            #  How to handle descriptive comments?
     125            pass
     126       
    111127        self.findings = []
    112         self.findings.extend(self.find_extended_comments())
    113         self.findings.extend(self.find_def_macro())
    114         vd = self.find_variable_descriptions()
    115         if len(vd) > 0:
    116             self.findings.extend(vd)
    117         self.findings.extend(self.find_variables())
    118         # TODO: decide the parent for each item, expect all def are at global scope
    119         # TODO: decide which macros and variables should not be documented
     128        for item in (ext_com, desc_com, def_macro, cdef_macro, vars,):
     129            if len(item)>0:
     130                self.findings.extend(item)
    120131       
    121132    extended_comment_block_sig_re = re.compile(
     
    135146        items = []
    136147        for mo in self.extended_comment_block_sig_re.finditer(self.buf):
    137             start = self.find_line_pos(mo.start(1))
    138             end = self.find_line_pos(mo.end(1))
     148            start = self.find_pos_in_line_number(mo.start(1))
     149            end = self.find_pos_in_line_number(mo.end(1))
    139150            text = mo.group(1)
    140151            items.append({
     
    157168                            re.IGNORECASE|re.DOTALL|re.MULTILINE)
    158169
    159     def find_variable_descriptions(self):
    160         """
    161         parse the internal buffer for variable descriptions that look like::
    162        
    163             #: two-theta, the scattering angle
    164             global tth
     170    def find_descriptive_comments(self):
     171        """
     172        Descriptive comments are used to document items that cannot contain
     173        extended comments (triple-quoted strings) such as variable declarations
     174        or *rdef* or *cdef* macro declarations.  They appear either in-line
     175        with the declaration or on the preceding line.
     176       
     177        Descriptive comment example that documents *tth*, a global variable declaration::
     178           
     179            global tth    #: two-theta, the scattering angle
     180       
     181        Descriptive comment example that documents *ccdset_shutter*, a *rdef* declaration::
     182       
     183            #: clear the ccd shutter handler
     184            rdef ccdset_shutter ''
    165185        """
    166186        items = []
    167187        for mo in self.variable_description_re.finditer(self.buf):
    168             start = self.find_line_pos(mo.start(1))
    169             end = self.find_line_pos(mo.end(1))
     188            start = self.find_pos_in_line_number(mo.start(1))
     189            end = self.find_pos_in_line_number(mo.end(1))
    170190            items.append({
    171191                            'start_line': start,
     
    201221        items = []
    202222        for mo in self.lgc_variable_sig_re.finditer(self.buf):
    203             start = self.find_line_pos(mo.start(1))
    204             end = self.find_line_pos(mo.end(1))
     223            start = self.find_pos_in_line_number(mo.start(1))
     224            end = self.find_pos_in_line_number(mo.end(1))
    205225            objtype = mo.group(1)
    206226            content = mo.group(2)
     
    251271        for mo in self.spec_macro_declaration_match_re.finditer(self.buf):
    252272            objtype = mo.group(1)
    253             start = self.find_line_pos(mo.start(1))
    254             end = self.find_line_pos(mo.end(4))
     273            start = self.find_pos_in_line_number(mo.start(1))
     274            end = self.find_pos_in_line_number(mo.end(4))
    255275            args = mo.group(3)
    256276            if len(args)>2:
     
    259279                    objtype = 'function ' + objtype
    260280                    args = m.group(1)
     281            # TODO: What if args is multi-line?  flatten.  What if really long?
    261282            items.append({
    262283                            'start_line': start,
     
    271292        return items
    272293
    273     def find_line_pos(self, pos):
     294    def find_cdef_macro(self):
     295        """
     296        parse the internal buffer for def and rdef macro declarations
     297        """
     298       
     299        # note:  It is not possible to find properly all variations
     300        # of the argument list in a cdef declaration using a regular expression,
     301        # especially across multiple lines.
     302       
     303        items = []
     304        for mo in re.finditer('cdef\(', self.buf):
     305            # look at each potential cdef declaration
     306            objtype = 'cdef'
     307            s = mo.start()
     308            start = self.find_pos_in_line_number(s)
     309            p = mo.end()
     310            nesting = 1                     # number of nested parentheses
     311            sign = {'(': 1, ')': -1}        # increment or decrement
     312            while nesting > 0 and p < len(self.buf):
     313                if self.buf[p] in sign.keys():
     314                    nesting += sign[self.buf[p]]
     315                p += 1
     316            e = p
     317            text = self.buf[s+5:e-1]    # carve it out, and remove cdef( ... ) wrapping
     318            end = self.find_pos_in_line_number(e)
     319            p = text.find(',')
     320            name = text[:p].strip('"')
     321            if len(name) == 0:
     322                name = '<empty name>'
     323            args = text[p+1:]
     324            # TODO: parse "args" for content
     325            # TODO: What if args is multi-line?  convert \n to ;
     326            #   args = ';'.join(args.splitlines())  # WRONG: This converts string content, as well
     327            # TODO: What if args is really long?
     328            items.append({
     329                            'start_line': start,
     330                            'end_line':   end,
     331                            'objtype':    objtype,
     332                            'name':       name,
     333                            'args':       args,
     334#                            'body':       mo.group(4),
     335#                            'comment':    mo.group(5),
     336                            'parent':     None,
     337                          })
     338        return items
     339
     340    def find_pos_in_line_number(self, pos):
    274341        """
    275342        find the line number that includes *pos*
     
    281348        linenumber = None
    282349        for linenumber, start, end in self.line_positions:
    283             if pos >= start and pos < end:
     350            if start <= pos < end:
    284351                break
    285352        return linenumber
     353   
     354    #------------------------ reporting section below ----------------------------------
    286355
    287356    def ReST(self):
     
    321390                s.append( '' )
    322391                # TODO: make this next be part of the signature display (in specdomain)
    323                 s.append( '.. rubric:: %s macro declaration' % r['objtype']  )
     392                #s.append( '.. rubric:: %s macro declaration' % r['objtype']  )
    324393                s.append( '' )
    325394                s.append( '.. spec:%s:: %s' % ( r['objtype'], r['name'],) )
     
    334403                                              r['end_line']) )
    335404                s.append( '' )
    336                 s.append( '.. rubric:: %s macro function declaration' % r['objtype']  )
     405                #s.append( '.. rubric:: %s macro function declaration' % r['objtype']  )
    337406                s.append( '' )
    338407                s.append( '.. spec:%s:: %s(%s)' % ( r['objtype'], r['name'], r['args']) )
Note: See TracChangeset for help on using the changeset viewer.