From 71fa97c60d0299689255dd49031464c719f8b545 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 18 Jul 1997 04:26:03 +0000 Subject: Jeffrey's latest -- reorder my chages somewhat, removed some of his own cruft. Added \g<...> references in replacement text. --- Lib/re.py | 166 +++++++++++++++++++++++++++----------------------------------- 1 file changed, 71 insertions(+), 95 deletions(-) diff --git a/Lib/re.py b/Lib/re.py index abc31c8..3594e36 100644 --- a/Lib/re.py +++ b/Lib/re.py @@ -77,14 +77,37 @@ def split(pattern, string, maxsplit=0): # # +def _expand(m, repl): + results = [] + index = 0 + size = len(repl) + while index < size: + found = string.find(repl, '\\', index) + if found < 0: + results.append(repl[index:]) + break + if found > index: + results.append(repl[index:found]) + escape_type, value, index = expand_escape(repl, found+1, REPLACEMENT) + if escape_type == CHAR: + results.append(value) + elif escape_type == MEMORY_REFERENCE: + r = m.group(value) + if r is None: + raise error, ('group "' + str(value) + '" did not contribute ' + 'to the match') + results.append(m.group(value)) + else: + raise error, "bad escape in replacement" + return string.join(results, '') + class RegexObject: - def __init__(self, pattern, flags, code, num_regs, groupindex, callouts): + def __init__(self, pattern, flags, code, num_regs, groupindex): self.code = code self.num_regs = num_regs self.flags = flags self.pattern = pattern self.groupindex = groupindex - self.callouts = callouts self.fastmap = build_fastmap(code) if code[0].name == 'bol': @@ -132,44 +155,52 @@ class RegexObject: regs) def sub(self, repl, string, count=0): - return self.subn(repl, string, count)[0] + return self.subn(repl, string, count)[0] def subn(self, repl, source, count=0): - if count < 0: raise error, "negative substibution count" - if count == 0: import sys; count = sys.maxint + if count < 0: + raise ValueError, "negative substibution count" + if count == 0: + import sys + count = sys.maxint if type(repl) == type(''): if '\\' in repl: repl = lambda m, r=repl: _expand(m, r) else: repl = lambda m, r=repl: r - n = 0 # Number of matches - pos = 0 # Where to start searching - lastmatch = -1 # End of last match - results = [] # Substrings making up the result + n = 0 # Number of matches + pos = 0 # Where to start searching + lastmatch = -1 # End of last match + results = [] # Substrings making up the result end = len(source) while n < count and pos <= end: m = self.search(source, pos) - if not m: break + if not m: + break i, j = m.span(0) if i == j == lastmatch: # Empty match adjacent to previous match - pos = pos+1 + pos = pos + 1 results.append(source[lastmatch:pos]) continue - if pos < i: results.append(source[pos:i]) + if pos < i: + results.append(source[pos:i]) results.append(repl(m)) pos = lastmatch = j if i == j: # Last match was empty; don't try here again - pos = pos+1 + pos = pos + 1 results.append(source[lastmatch:pos]) - n = n+1 + n = n + 1 results.append(source[pos:]) return (string.join(results, ''), n) - + def split(self, source, maxsplit=0): - if maxsplit < 0: raise error, "negative split count" - if maxsplit == 0: import sys; maxsplit = sys.maxint + if maxsplit < 0: + raise error, "negative split count" + if maxsplit == 0: + import sys + maxsplit = sys.maxint n = 0 pos = 0 lastmatch = 0 @@ -177,11 +208,13 @@ class RegexObject: end = len(source) while n < maxsplit: m = self.search(source, pos) - if not m: break + if not m: + break i, j = m.span(0) if i == j: # Empty match - if pos >= end: break + if pos >= end: + break pos = pos+1 continue results.append(source[lastmatch:i]) @@ -192,26 +225,6 @@ class RegexObject: results.append(source[lastmatch:]) return results -def _expand(m, repl): - results = [] - index = 0 - size = len(repl) - while index < size: - found = string.find(repl, '\\', index) - if found < 0: - results.append(repl[index:]) - break - if found > index: - results.append(repl[index:found]) - escape_type, value, index = expand_escape(repl, found+1, REPLACEMENT) - if escape_type == CHAR: - results.append(value) - elif escape_type == MEMORY_REFERENCE: - results.append(m.group(value)) - else: - raise error, "bad escape in replacement" - return string.join(results, '') - class MatchObject: def __init__(self, re, string, pos, regs): self.re = re @@ -280,16 +293,6 @@ class Instruction: def __repr__(self): return '%-15s' % (self.name) -class FunctionCallout(Instruction): - name = 'function' - def __init__(self, function): - self.function = function - Instruction.__init__(self, chr(22), 2 + len(self.function)) - def assemble(self, position, labels): - return self.opcode + chr(len(self.function)) + self.function - def __repr__(self): - return '%-15s %-10s' % (self.name, self.function) - class End(Instruction): name = 'end' def __init__(self): @@ -608,11 +611,6 @@ def build_fastmap_aux(code, pos, visited, fastmap): find_label(code, instruction.label), visited, fastmap) - elif instruction.name == 'function': - for char in map(chr, range(256)): - fastmap.add(char) - fastmap.can_be_null = 1 - return def build_fastmap(code, pos=0): visited = [0] * len(code) @@ -825,10 +823,25 @@ def expand_escape(pattern, index, context=NORMAL): value = string.atoi(pattern[index]) return MEMORY_REFERENCE, value, index + 1 - while (end < len(pattern)) and (pattern[end] in string.digits): - end = end + 1 - value = pattern[index:end] + elif pattern[index] == 'g': + if context != REPLACEMENT: + return CHAR, 'g', index + 1 + index = index + 1 + if index >= len(pattern): + raise error, 'unfinished symbolic reference' + if pattern[index] != '<': + raise error, 'missing < in symbolic reference' + + index = index + 1 + end = string.find(pattern, '>', index) + if end == -1: + raise error, 'unfinished symbolic reference' + value = pattern[index:end] + if not valid_identifier(value): + raise error, 'illegal symbolic reference' + return MEMORY_REFERENCE, value, end + 1 + else: return CHAR, pattern[index], index + 1 @@ -837,7 +850,6 @@ def compile(pattern, flags=0): label = 0 register = 1 groupindex = {} - callouts = [] lastop = '' # look for embedded pattern modifiers at the beginning of the pattern @@ -989,21 +1001,6 @@ def compile(pattern, flags=0): index = end + 1 lastop = '(?P=)' - elif pattern[index] == '!': - # function callout - if index >= len(pattern): - raise error, 'no function callout name' - start = index + 1 - end = string.find(pattern, ')', start) - if end == -1: - raise error, 'no ) to end function callout name' - name = pattern[start:end] - if name not in callouts: - raise error, ('function callout name not listed ' - 'in callouts dict') - stack.append([FunctionCallout(name)]) - lastop = '(?P!)' - else: raise error, ('unknown Python extension: ' + \ pattern[index]) @@ -1490,25 +1487,4 @@ def compile(pattern, flags=0): code.append(Label(label)) label = label + 1 code.append(End()) - return RegexObject(pattern, flags, code, register, groupindex, callouts) - -if __name__ == '__main__': - print compile('a(b)*') - print compile('a{3}') - print compile('(a){2}') - print compile('a{2,4}') - print compile('a|b') - print compile('a(b|c)') - print compile('a*') - print compile('a+') - print compile('a|b|c') - print compile('a(b|c)*') - print compile('\\n') - print compile('a(?# huh huh)b') - print compile('[a-c\\w]') - print compile('[[]') - print compile('[]]') - print compile('(a)') - print compile('\Q*\e') - print compile('a{0,}') - + return RegexObject(pattern, flags, code, register, groupindex) -- cgit v0.12