Package pygccxml :: Package declarations :: Module pattern_parser

# Source Code for Module pygccxml.declarations.pattern_parser

      1  # Copyright 2004-2008 Roman Yakovenko.
      2  # Distributed under the Boost Software License, Version 1.0. (See
      3  # accompanying file LICENSE_1_0.txt or copy at
      4  # http://www.boost.org/LICENSE_1_0.txt)
      5
      6  """implementation details"""
      7
      8  import types
      9
     10 -class parser_t( object ):
     11      """implementation details"""
     12 -    def __init__( self
     13                    , pattern_char_begin
     14                    , pattern_char_end
     15                    , pattern_char_separator ):
     16          self.__begin = pattern_char_begin
     17          self.__end = pattern_char_end
     18          self.__separator = pattern_char_separator
     19          #right now parser does not take into account next qualifiers, but it will
     20          self.__text_qualifier = '"'
     21          self.__char_qualifier = "'"
     22          self.__escape = '\\'
     23
     24 -    def has_pattern( self, decl_string ):
     25          """implementation details"""
     26          last_part = decl_string.split( '::' )[-1]
     27          return -1 != decl_string.find( self.__begin ) and -1 != last_part.find( self.__end )
     28
     29 -    def name( self, decl_string ):
     30          """implementation details"""
     31          assert isinstance( decl_string, types.StringTypes )
     32          if not self.has_pattern( decl_string ):
     33              return decl_string
     34          args_begin = decl_string.find( self.__begin )
     35          return decl_string[0: args_begin].strip()
     36
     37 -    def __find_args_separator( self, decl_string, start_pos ):
     38          """implementation details"""
     39          bracket_depth = 0
     40          for index, ch in enumerate( decl_string[start_pos:] ):
     41              if ch not in ( self.__begin, self.__end, self.__separator ):
     42                  continue #I am interested only in < and >
     43              elif self.__separator == ch:
     44                  if not bracket_depth:
     45                      return index + start_pos
     46              elif self.__begin == ch:
     47                  bracket_depth += 1
     48              elif not bracket_depth:
     49                  return index + start_pos
     50              else:
     51                  bracket_depth -= 1
     52          return -1
     53
     54 -    def args( self, decl_string ):
     55          """implementation details"""
     56          args_begin = decl_string.find( self.__begin )
     57          args_end = decl_string.rfind( self.__end )
     58          if -1 in ( args_begin, args_end ) or args_begin == args_end:
     59              raise RuntimeError( "%s doesn't valid template instantiation string" % decl_string )
     60
     61          args_only = decl_string[args_begin + 1: args_end ]
     62          args = []
     63          previous_found, found = 0, 0
     64          while True:
     65              found = self.__find_args_separator( args_only, previous_found)
     66              if -1 == found:
     67                  args.append( args_only[ previous_found : ] )
     68                  break
     69              #elif decl_string[ found ] == self.__end:
     70              #    print args
     71              #    raise RuntimeError( "unmatched '%s' token has been found." % self.__end )
     72              else:
     73                  args.append( args_only[ previous_found : found ] )
     74              previous_found = found + 1 #skip found sep
     75          return [ arg.strip() for arg in args ]
     76
     77      NOT_FOUND = ( -1, -1 )
     78      """implementation details"""
     79
     80 -    def find_args(self, text, start=None ):
     81          """implementation details"""
     82          if start==None:
     83              start = 0
     84          first_occurance = text.find( self.__begin, start )
     85          if first_occurance == -1:
     86              return self.NOT_FOUND
     87          previous_found, found = first_occurance + 1, 0
     88          while True:
     89              found = self.__find_args_separator( text, previous_found)
     90              if -1 == found:
     91                  return self.NOT_FOUND
     92              elif text[ found ] == self.__end:
     93                  return ( first_occurance, found )
     94              else:
     95                  previous_found = found + 1 #skip found sep
     96
     97 -    def split( self, decl_string ):
     98          """implementation details"""
     99          assert self.has_pattern( decl_string )
    100          return self.name( decl_string ), self.args( decl_string )
    101
    102 -    def split_recursive( self, decl_string ):
    103          """implementation details"""
    104          assert self.has_pattern( decl_string )
    105          answer = []
    106          to_go = [ decl_string ]
    107          while to_go:
    108              name, args = self.split( to_go.pop() )
    109              answer.append( ( name, args ) )
    110              for arg in args:
    111                  if self.has_pattern( arg ):
    112                      to_go.append( arg )
    113          return answer
    114
    115 -    def join( self, name, args, arg_separator=None ):
    116          """implementation details"""
    117          if None is arg_separator:
    118              arg_separator = ', '
    119          args = filter( None, args)
    120          args_str = ''
    121          if not args:
    122              args_str = ' '
    123          elif 1 == len( args ):
    124              args_str = ' ' + args[0] + ' '
    125          else:
    126              args_str = ' ' + arg_separator.join( args ) + ' '
    127
    128          return ''.join( [ name, self.__begin, args_str, self.__end ] )
    129
    130 -    def normalize( self, decl_string, arg_separator=None ):
    131          """implementation details"""
    132          if not self.has_pattern( decl_string ):
    133              return decl_string
    134          name, args = self.split( decl_string )
    135          for i, arg in enumerate( args ):
    136              args[i] = self.normalize( arg )
    137          return self.join( name, args, arg_separator )
    138