Changeset 956


Ignore:
Timestamp:
Jun 20, 2012 10:57:40 PM (11 years ago)
Author:
jemian
Message:

refs #8, basics of the parser are established

Location:
specdomain/src/specdomain/test
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • specdomain/src/specdomain/test/parser.py

    r954 r956  
    1919
    2020
     21string_start                = r'^'
     22string_end                  = r'$'
     23match_all                   = r'.*'
     24non_greedy_filler           = match_all + r'?'
     25non_greedy_whitespace       = r'\w*?'
     26double_quote_string_match   = r'("' + non_greedy_filler + r'")'
     27word_match                  = r'((?:[a-z_]\w*))'
     28cdef_match                  = r'(cdef)'
     29extended_comment_marker     = r'\"{3}'
     30extended_comment_match      = r'(' + extended_comment_marker + r')'
     31
     32spec_macro_sig_re = re.compile(
     33                               r'''^ ([a-zA-Z_]\w*)         # macro name
     34                               ''', re.VERBOSE)
     35
     36spec_func_sig_re = re.compile(word_match + r'\('
     37                      + r'(' + match_all + r')'
     38                      + r'\)',
     39                      re.IGNORECASE|re.DOTALL)
     40
     41spec_cdef_name_sig_re = re.compile(double_quote_string_match,
     42                                   re.IGNORECASE|re.DOTALL)
     43
     44
     45spec_extended_comment_flag_sig_re = re.compile(extended_comment_marker,
     46                                               re.IGNORECASE|re.DOTALL)
     47spec_extended_comment_start_sig_re = re.compile(string_start
     48                                                + non_greedy_whitespace
     49                                                + extended_comment_match,
     50                                                re.IGNORECASE|re.VERBOSE)
     51spec_extended_comment_end_sig_re = re.compile(non_greedy_whitespace
     52                                                + extended_comment_match
     53                                                + non_greedy_whitespace
     54                                                + r'#' + non_greedy_filler
     55                                                + r'$',
     56                                                re.IGNORECASE|re.VERBOSE)
     57spec_extended_comment_block_sig_re = re.compile(string_start
     58                                                + non_greedy_whitespace
     59                                                + extended_comment_marker
     60                                                + r'(' + non_greedy_filler + r')'
     61                                                + extended_comment_marker
     62                                                + non_greedy_filler
     63                                                + string_end,
     64                                                re.IGNORECASE|re.DOTALL|re.MULTILINE)
     65
     66
    2167class SpecMacrofileParser:
    2268    '''
     
    2571    '''
    2672
     73    states = (
     74        'command level',
     75        'extended comment',
     76        'def macro',
     77        'rdef macro',
     78        'cdef macro'
     79             
     80    )
     81
    2782    def __init__(self, macrofile):
    2883        '''
    2984        Constructor
    3085        '''
    31         self.filename = macrofile
    32         if not os.path.exists(macrofile):
    33             raise Exception, "file not found: " + str(macrofile)
     86        self.buf = None
     87        self.findings = []
     88        self.filename = None
     89        self.read(macrofile)
     90        self.parse_macro_file()
     91   
     92    def read(self, filename):
     93        """
     94        load the SPEC macro source code file into an internal buffer
     95       
     96        :param str filename: name (with optional path) of SPEC macro file
     97            (The path is relative to the ``.rst`` document.)
     98        """
     99        if not os.path.exists(filename):
     100            raise RuntimeError, "file not found: " + filename
     101        self.filename = filename
     102        self.buf = open(filename, 'r').read()
     103   
     104    def parse_macro_file(self):
     105        """
     106        parse the internal buffer
     107        """
     108        line_number = 0
     109        state = 'command level'
     110        state_stack = []
     111        for line in self.buf.split('\n'):
     112            if state not in self.states:
     113                raise RuntimeError, "unexpected parser state: " + state
     114            line_number += 1
     115            if state == 'command level':
     116                # test if one-line extended comment
     117                m = self._match(spec_extended_comment_block_sig_re, line)
     118                if m is not None:
     119                    del m['start'], m['end'], m['line']
     120                    m['objtype'] = 'extended comment'
     121                    m['start_line'] = line_number
     122                    m['end_line'] = line_number
     123                    self.findings.append(m)
     124                    continue
     125               
     126                # test if start of multiline extended comment
     127                m = self._match(spec_extended_comment_start_sig_re, line)
     128                if m is not None:
     129                    text = m['line'][m['end']:]
     130                    del m['start'], m['end'], m['line']
     131                    m['objtype'] = 'extended comment'
     132                    m['start_line'] = line_number
     133                    ec = dict(m)    # container for extended comment data
     134                    ec['text'] = [text]
     135                    state_stack.append(state)
     136                    state = 'extended comment'
     137                    continue
     138
     139            elif state == 'extended comment':
     140                # test if end of multiline extended comment
     141                if line_number > 250:
     142                    pass
     143                m = self._match(spec_extended_comment_end_sig_re, line)
     144                if m is not None:
     145                    text = m['line'][:m['start']]
     146                    ec['text'].append(text)
     147                    ec['text'] = '\n'.join(ec['text'])
     148                    ec['end_line'] = line_number
     149                    self.findings.append(ec)
     150                    state = state_stack.pop()
     151                    del ec
     152                else:
     153                    # multiline extended comment continues
     154                    ec['text'].append(line)
     155                continue
     156   
     157    def _match(self, regexp, line):
     158        m = regexp.search(line)
     159        if m is None:
     160            return None
     161        d = {
     162            'start': m.start(1),
     163            'end':   m.end(1),
     164            'text':  m.group(1),
     165            'line':  line,
     166        }
     167        return d
     168
     169    def __str__(self):
     170        s = []
     171        for r in self.findings:
     172            s.append( '' )
     173            t = '%s %s %d %d %s' % ('*'*20, r['objtype'], r['start_line'], r['end_line'], '*'*20)
     174            s.append( t )
     175            s.append( r['text'] )
     176        return '\n'.join(s)
    34177
    35178
    36179if __name__ == '__main__':
    37     p = SpecMacrofileParser('test-battery.mac')
    38     p = SpecMacrofileParser('cdef-examples.mac')
    39     pass
     180    print SpecMacrofileParser('test-battery.mac')
     181    print SpecMacrofileParser('cdef-examples.mac')
  • specdomain/src/specdomain/test/test-battery.mac

    r943 r956  
    248248"""
    249249
     250#==============================================================================
     251
     252"""    # This is the start of an extended comment
     253
     254this is located within an extended comment
     255
     256"""    # this is a normal comment after the extended comment
     257
     258
     259a = 42.0    #  """ this is not an extended comment"""
     260#==============================================================================
     261
     262
    250263"""End of $Id$"""
Note: See TracChangeset for help on using the changeset viewer.