home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / re.py < prev    next >
Text File  |  1997-12-08  |  8KB  |  291 lines

  1. #!/usr/bin/env python
  2. # -*- mode: python -*-
  3.  
  4. import sys
  5. import string
  6. from pcre import *
  7.  
  8. #
  9. # First, the public part of the interface:
  10. #
  11.  
  12. # pcre.error and re.error should be the same, since exceptions can be
  13. # raised from either module.
  14.  
  15. # compilation flags
  16.  
  17. I = IGNORECASE
  18. L = LOCALE
  19. M = MULTILINE
  20. S = DOTALL 
  21. X = VERBOSE 
  22.  
  23. #
  24. #
  25. #
  26.  
  27. _cache = {}
  28. _MAXCACHE = 20
  29.  
  30. def _cachecompile(pattern, flags=0):
  31.     key = (pattern, flags)
  32.     try:
  33.     return _cache[key]
  34.     except KeyError:
  35.     pass
  36.     value = compile(pattern, flags)
  37.     if len(_cache) >= _MAXCACHE:
  38.     _cache.clear()
  39.     _cache[key] = value
  40.     return value
  41.  
  42. def match(pattern, string, flags=0):
  43.     return _cachecompile(pattern, flags).match(string)
  44.   
  45. def search(pattern, string, flags=0):
  46.     return _cachecompile(pattern, flags).search(string)
  47.   
  48. def sub(pattern, repl, string, count=0):
  49.     if type(pattern) == type(''):
  50.     pattern = _cachecompile(pattern)
  51.     return pattern.sub(repl, string, count)
  52.  
  53. def subn(pattern, repl, string, count=0):
  54.     if type(pattern) == type(''):
  55.     pattern = _cachecompile(pattern)
  56.     return pattern.subn(repl, string, count)
  57.   
  58. def split(pattern, string, maxsplit=0):
  59.     if type(pattern) == type(''):
  60.     pattern = _cachecompile(pattern)
  61.     return pattern.split(string, maxsplit)
  62.  
  63. def escape(pattern):
  64.     "Escape all non-alphanumeric characters in pattern."
  65.     result = []
  66.     alphanum=string.letters+'_'+string.digits
  67.     for char in pattern:
  68.     if char not in alphanum:
  69.         result.append('\\')
  70.     result.append(char)
  71.     return string.join(result, '')
  72.  
  73. def compile(pattern, flags=0):
  74.     "Compile a regular expression pattern, returning a RegexObject."
  75.     groupindex={}
  76.     code=pcre_compile(pattern, flags, groupindex)
  77.     return RegexObject(pattern, flags, code, groupindex)
  78.     
  79.  
  80. #
  81. #   Class definitions
  82. #
  83.  
  84. class RegexObject:
  85.     def __init__(self, pattern, flags, code, groupindex):
  86.     self.code = code 
  87.     self.flags = flags
  88.     self.pattern = pattern
  89.     self.groupindex = groupindex
  90.  
  91.     def search(self, string, pos=0, endpos=None):
  92.     """Scan through string looking for a match to the pattern, returning
  93.     a MatchObject instance, or None if no match was found."""
  94.  
  95.     if endpos is None or endpos>len(string): 
  96.         endpos=len(string)
  97.     if endpos<pos: endpos=pos
  98.     regs = self.code.match(string, pos, endpos, 0)
  99.     if regs is None:
  100.         return None
  101.     self._num_regs=len(regs)
  102.     
  103.     return MatchObject(self,
  104.                string,
  105.                pos, endpos,
  106.                regs)
  107.     
  108.     def match(self, string, pos=0, endpos=None):
  109.     """Try to apply the pattern at the start of the string, returning
  110.     a MatchObject instance, or None if no match was found."""
  111.  
  112.     if endpos is None or endpos>len(string): 
  113.         endpos=len(string)
  114.     if endpos<pos: endpos=pos
  115.     regs = self.code.match(string, pos, endpos, ANCHORED)
  116.     if regs is None:
  117.         return None
  118.     self._num_regs=len(regs)
  119.     return MatchObject(self,
  120.                string,
  121.                pos, endpos,
  122.                regs)
  123.     
  124.     def sub(self, repl, string, count=0):
  125.     """Return the string obtained by replacing the leftmost
  126.     non-overlapping occurrences of the pattern in string by the
  127.     replacement repl""" 
  128.  
  129.         return self.subn(repl, string, count)[0]
  130.     
  131.     def subn(self, repl, source, count=0): 
  132.     """Return a 2-tuple containing (new_string, number).
  133.     new_string is the string obtained by replacing the leftmost
  134.     non-overlapping occurrences of the pattern in string by the
  135.     replacement repl.  number is the number of substitutions that
  136.     were made."""
  137.  
  138.     if count < 0:
  139.         raise error, "negative substitution count"
  140.     if count == 0:
  141.         import sys
  142.         count = sys.maxint
  143.     if type(repl) == type(''):
  144.         if '\\' in repl:
  145.         repl = lambda m, r=repl: pcre_expand(m, r)
  146.         else:
  147.         repl = lambda m, r=repl: r
  148.     n = 0           # Number of matches
  149.     pos = 0         # Where to start searching
  150.     lastmatch = -1  # End of last match
  151.     results = []    # Substrings making up the result
  152.     end = len(source)
  153.     while n < count and pos <= end:
  154.         m = self.search(source, pos)
  155.         if not m:
  156.         break
  157.         i, j = m.span(0)
  158.         if i == j == lastmatch:
  159.         # Empty match adjacent to previous match
  160.         pos = pos + 1
  161.         results.append(source[lastmatch:pos])
  162.         continue
  163.         if pos < i:
  164.         results.append(source[pos:i])
  165.         results.append(repl(m))
  166.         pos = lastmatch = j
  167.         if i == j:
  168.         # Last match was empty; don't try here again
  169.         pos = pos + 1
  170.         results.append(source[lastmatch:pos])
  171.         n = n + 1
  172.     results.append(source[pos:])
  173.     return (string.join(results, ''), n)
  174.                                         
  175.     def split(self, source, maxsplit=0):
  176.     """Split \var{string} by the occurrences of the pattern,
  177.     returning a list containing the resulting substrings."""
  178.  
  179.     if maxsplit < 0:
  180.         raise error, "negative split count"
  181.     if maxsplit == 0:
  182.         import sys
  183.         maxsplit = sys.maxint
  184.     n = 0
  185.     pos = 0
  186.     lastmatch = 0
  187.     results = []
  188.     end = len(source)
  189.     while n < maxsplit:
  190.         m = self.search(source, pos)
  191.         if not m:
  192.         break
  193.         i, j = m.span(0)
  194.         if i == j:
  195.         # Empty match
  196.         if pos >= end:
  197.             break
  198.         pos = pos+1
  199.         continue
  200.         results.append(source[lastmatch:i])
  201.         g = m.groups()
  202.         if g:
  203.         if type(g)==type( "" ): g = [g]
  204.         results[len(results):] = list(g)
  205.         pos = lastmatch = j
  206.     results.append(source[lastmatch:])
  207.     return results
  208.  
  209.     # The following 3 functions were contributed by Mike Fletcher, and
  210.     # allow pickling and unpickling of RegexObject instances.
  211.     def __getinitargs__(self):
  212.         return (None,None,None,None) # any 4 elements, to work around
  213.                                      # problems with the
  214.                      # pickle/cPickle modules not yet 
  215.                      # ignoring the __init__ function
  216.     def __getstate__(self):
  217.         return self.pattern, self.flags, self.groupindex
  218.     def __setstate__(self, statetuple):
  219.         self.pattern = statetuple[0]
  220.         self.flags = statetuple[1]
  221.         self.groupindex = statetuple[2]
  222.         self.code = apply(pcre_compile, statetuple)
  223.  
  224. class MatchObject:
  225.     def __init__(self, re, string, pos, endpos, regs):
  226.     self.re = re
  227.     self.string = string
  228.     self.pos = pos 
  229.     self.endpos = endpos
  230.     self.regs = regs
  231.     
  232.     def start(self, g = 0):
  233.     "Return the start of the substring matched by group g"
  234.     if type(g) == type(''):
  235.         try:
  236.         g = self.re.groupindex[g]
  237.         except (KeyError, TypeError):
  238.         raise IndexError, ('group "' + g + '" is undefined')
  239.     return self.regs[g][0]
  240.     
  241.     def end(self, g = 0):
  242.     "Return the end of the substring matched by group g"
  243.     if type(g) == type(''):
  244.         try:
  245.         g = self.re.groupindex[g]
  246.         except (KeyError, TypeError):
  247.         raise IndexError, ('group "' + g + '" is undefined')
  248.     return self.regs[g][1]
  249.     
  250.     def span(self, g = 0):
  251.     """Return a tuple containing the start,end of the substring 
  252.     matched by group g"""
  253.     if type(g) == type(''):
  254.         try:
  255.         g = self.re.groupindex[g]
  256.         except (KeyError, TypeError):
  257.         raise IndexError, ('group "' + g + '" is undefined')
  258.     return self.regs[g]
  259.     
  260.     def groups(self):
  261.     "Return a tuple containing all subgroups of the match object"
  262.  
  263.     # If _num_regs==1, we don't want to call self.group with an
  264.     # empty tuple.
  265.     if self.re._num_regs == 1: return ()
  266.     return apply(self.group, tuple(range(1, self.re._num_regs) ) )
  267.  
  268.     def group(self, *groups):
  269.     "Return one or more groups of the match."
  270.     if len(groups) == 0:
  271.         groups = (0,)
  272.     result = []
  273.     for g in groups:
  274.         if type(g) == type(''):
  275.         try:
  276.             g = self.re.groupindex[g]
  277.         except (KeyError, TypeError):
  278.             raise IndexError, ('group "' + g + '" is undefined')
  279.         if len(self.regs)<=g: raise IndexError, ('group "' + str(g) + '" is undefined')
  280.         elif (self.regs[g][0] == -1) or (self.regs[g][1] == -1):
  281.         result.append(None)
  282.         else:
  283.         result.append(self.string[self.regs[g][0]:self.regs[g][1]])
  284.     if len(result) > 1:
  285.         return tuple(result)
  286.     elif len(result) == 1:
  287.         return result[0]
  288.     else:
  289.         return ()
  290.  
  291.