blob: 1b56352451de95c8c432efd7f50a5a07dc0beac9 [file] [log] [blame]
Guido van Rossum7627c0d2000-03-31 14:58:54 +00001#
2# Secret Labs' Regular Expression Engine
Guido van Rossum7627c0d2000-03-31 14:58:54 +00003#
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +00004# convert re-style regular expression to sre pattern
Guido van Rossum7627c0d2000-03-31 14:58:54 +00005#
6# Copyright (c) 1998-2000 by Secret Labs AB. All rights reserved.
7#
Guido van Rossum7627c0d2000-03-31 14:58:54 +00008# Portions of this engine have been developed in cooperation with
Fredrik Lundh22d25462000-07-01 17:50:59 +00009# CNRI. Hewlett-Packard provided funding for 2.0 integration and
Guido van Rossum7627c0d2000-03-31 14:58:54 +000010# other compatibility work.
11#
12
Guido van Rossum7627c0d2000-03-31 14:58:54 +000013import string, sys
14
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000015import _sre
16
Guido van Rossum7627c0d2000-03-31 14:58:54 +000017from sre_constants import *
18
Fredrik Lundh3562f112000-07-02 12:00:07 +000019MAXREPEAT = 65535
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000020
Fredrik Lundh3562f112000-07-02 12:00:07 +000021# FIXME: the following might change in 2.0 final. but for now, this
22# seems to be the best way to be compatible with 1.5.2
Fredrik Lundh4ccea942000-06-30 18:39:20 +000023CHARMASK = 0xff
Fredrik Lundh0640e112000-06-30 13:55:15 +000024
Guido van Rossum7627c0d2000-03-31 14:58:54 +000025SPECIAL_CHARS = ".\\[{()*+?^$|"
26REPEAT_CHARS = "*+?{"
27
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +000028DIGITS = tuple("012345689")
Guido van Rossumb81e70e2000-04-10 17:10:48 +000029
Fredrik Lundh75f2d672000-06-29 11:34:28 +000030OCTDIGITS = tuple("01234567")
31HEXDIGITS = tuple("0123456789abcdefABCDEF")
Guido van Rossum7627c0d2000-03-31 14:58:54 +000032
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +000033WHITESPACE = tuple(" \t\n\r\v\f")
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000034
Guido van Rossum7627c0d2000-03-31 14:58:54 +000035ESCAPES = {
Fredrik Lundh0640e112000-06-30 13:55:15 +000036 r"\a": (LITERAL, 7),
37 r"\b": (LITERAL, 8),
38 r"\f": (LITERAL, 12),
39 r"\n": (LITERAL, 10),
40 r"\r": (LITERAL, 13),
41 r"\t": (LITERAL, 9),
42 r"\v": (LITERAL, 11),
43 r"\\": (LITERAL, ord("\\"))
Guido van Rossum7627c0d2000-03-31 14:58:54 +000044}
45
46CATEGORIES = {
Fredrik Lundh01016fe2000-06-30 00:27:46 +000047 r"\A": (AT, AT_BEGINNING), # start of string
48 r"\b": (AT, AT_BOUNDARY),
49 r"\B": (AT, AT_NON_BOUNDARY),
50 r"\d": (IN, [(CATEGORY, CATEGORY_DIGIT)]),
51 r"\D": (IN, [(CATEGORY, CATEGORY_NOT_DIGIT)]),
52 r"\s": (IN, [(CATEGORY, CATEGORY_SPACE)]),
53 r"\S": (IN, [(CATEGORY, CATEGORY_NOT_SPACE)]),
54 r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]),
55 r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]),
56 r"\Z": (AT, AT_END), # end of string
Guido van Rossum7627c0d2000-03-31 14:58:54 +000057}
58
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000059FLAGS = {
Fredrik Lundh436c3d582000-06-29 08:58:44 +000060 # standard flags
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000061 "i": SRE_FLAG_IGNORECASE,
62 "L": SRE_FLAG_LOCALE,
63 "m": SRE_FLAG_MULTILINE,
64 "s": SRE_FLAG_DOTALL,
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000065 "x": SRE_FLAG_VERBOSE,
Fredrik Lundh436c3d582000-06-29 08:58:44 +000066 # extensions
67 "t": SRE_FLAG_TEMPLATE,
68 "u": SRE_FLAG_UNICODE,
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +000069}
70
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +000071class Pattern:
72 # master pattern object. keeps track of global attributes
Guido van Rossum7627c0d2000-03-31 14:58:54 +000073 def __init__(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +000074 self.flags = 0
75 self.groups = 1
76 self.groupdict = {}
Guido van Rossum7627c0d2000-03-31 14:58:54 +000077 def getgroup(self, name=None):
Fredrik Lundh90a07912000-06-30 07:50:59 +000078 gid = self.groups
79 self.groups = gid + 1
80 if name:
81 self.groupdict[name] = gid
82 return gid
Guido van Rossum7627c0d2000-03-31 14:58:54 +000083
84class SubPattern:
85 # a subpattern, in intermediate form
86 def __init__(self, pattern, data=None):
Fredrik Lundh90a07912000-06-30 07:50:59 +000087 self.pattern = pattern
88 if not data:
89 data = []
90 self.data = data
91 self.width = None
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +000092 def dump(self, level=0):
93 nl = 1
94 for op, av in self.data:
95 print level*" " + op,; nl = 0
96 if op == "in":
97 # member sublanguage
98 print; nl = 1
99 for op, a in av:
100 print (level+1)*" " + op, a
101 elif op == "branch":
102 print; nl = 1
103 i = 0
104 for a in av[1]:
105 if i > 0:
106 print level*" " + "or"
107 a.dump(level+1); nl = 1
108 i = i + 1
109 elif type(av) in (type(()), type([])):
110 for a in av:
111 if isinstance(a, SubPattern):
112 if not nl: print
113 a.dump(level+1); nl = 1
114 else:
115 print a, ; nl = 0
116 else:
117 print av, ; nl = 0
118 if not nl: print
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000119 def __repr__(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000120 return repr(self.data)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000121 def __len__(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000122 return len(self.data)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000123 def __delitem__(self, index):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000124 del self.data[index]
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000125 def __getitem__(self, index):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000126 return self.data[index]
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000127 def __setitem__(self, index, code):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000128 self.data[index] = code
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000129 def __getslice__(self, start, stop):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000130 return SubPattern(self.pattern, self.data[start:stop])
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000131 def insert(self, index, code):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000132 self.data.insert(index, code)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000133 def append(self, code):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000134 self.data.append(code)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000135 def getwidth(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000136 # determine the width (min, max) for this subpattern
137 if self.width:
138 return self.width
139 lo = hi = 0L
140 for op, av in self.data:
141 if op is BRANCH:
142 l = sys.maxint
143 h = 0
144 for av in av[1]:
145 i, j = av.getwidth()
146 l = min(l, i)
147 h = min(h, j)
148 lo = lo + i
149 hi = hi + j
150 elif op is CALL:
151 i, j = av.getwidth()
152 lo = lo + i
153 hi = hi + j
154 elif op is SUBPATTERN:
155 i, j = av[1].getwidth()
156 lo = lo + i
157 hi = hi + j
158 elif op in (MIN_REPEAT, MAX_REPEAT):
159 i, j = av[2].getwidth()
160 lo = lo + long(i) * av[0]
161 hi = hi + long(j) * av[1]
162 elif op in (ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY):
163 lo = lo + 1
164 hi = hi + 1
165 elif op == SUCCESS:
166 break
167 self.width = int(min(lo, sys.maxint)), int(min(hi, sys.maxint))
168 return self.width
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000169
170class Tokenizer:
171 def __init__(self, string):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000172 self.string = string
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000173 self.index = 0
174 self.__next()
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000175 def __next(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000176 if self.index >= len(self.string):
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000177 self.next = None
178 return
Fredrik Lundh90a07912000-06-30 07:50:59 +0000179 char = self.string[self.index]
180 if char[0] == "\\":
181 try:
182 c = self.string[self.index + 1]
183 except IndexError:
184 raise error, "bogus escape"
185 char = char + c
186 self.index = self.index + len(char)
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000187 self.next = char
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000188 def match(self, char):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000189 if char == self.next:
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000190 self.__next()
Fredrik Lundh90a07912000-06-30 07:50:59 +0000191 return 1
192 return 0
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000193 def get(self):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000194 this = self.next
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000195 self.__next()
Fredrik Lundh90a07912000-06-30 07:50:59 +0000196 return this
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000197 def tell(self):
198 return self.index, self.next
199 def seek(self, index):
200 self.index, self.next = index
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000201
Fredrik Lundh4781b072000-06-29 12:38:45 +0000202def isident(char):
203 return "a" <= char <= "z" or "A" <= char <= "Z" or char == "_"
204
205def isdigit(char):
206 return "0" <= char <= "9"
207
208def isname(name):
209 # check that group name is a valid string
Fredrik Lundh4781b072000-06-29 12:38:45 +0000210 if not isident(name[0]):
Fredrik Lundh90a07912000-06-30 07:50:59 +0000211 return 0
Fredrik Lundh4781b072000-06-29 12:38:45 +0000212 for char in name:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000213 if not isident(char) and not isdigit(char):
214 return 0
Fredrik Lundh4781b072000-06-29 12:38:45 +0000215 return 1
216
Fredrik Lundh01016fe2000-06-30 00:27:46 +0000217def _group(escape, groups):
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000218 # check if the escape string represents a valid group
219 try:
Fredrik Lundhb71624e2000-06-30 09:13:06 +0000220 gid = int(escape[1:])
221 if gid and gid < groups:
222 return gid
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000223 except ValueError:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000224 pass
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000225 return None # not a valid group
226
227def _class_escape(source, escape):
228 # handle escape code inside character class
229 code = ESCAPES.get(escape)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000230 if code:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000231 return code
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000232 code = CATEGORIES.get(escape)
233 if code:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000234 return code
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000235 try:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000236 if escape[1:2] == "x":
237 while source.next in HEXDIGITS:
238 escape = escape + source.get()
239 escape = escape[2:]
Fredrik Lundh0640e112000-06-30 13:55:15 +0000240 return LITERAL, int(escape[-4:], 16) & CHARMASK
Fredrik Lundh90a07912000-06-30 07:50:59 +0000241 elif str(escape[1:2]) in OCTDIGITS:
242 while source.next in OCTDIGITS:
243 escape = escape + source.get()
244 escape = escape[1:]
Fredrik Lundh0640e112000-06-30 13:55:15 +0000245 return LITERAL, int(escape[-6:], 8) & CHARMASK
Fredrik Lundh90a07912000-06-30 07:50:59 +0000246 if len(escape) == 2:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000247 return LITERAL, ord(escape[1])
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000248 except ValueError:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000249 pass
Fredrik Lundh436c3d582000-06-29 08:58:44 +0000250 raise error, "bogus escape: %s" % repr(escape)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000251
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000252def _escape(source, escape, state):
253 # handle escape code in expression
254 code = CATEGORIES.get(escape)
255 if code:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000256 return code
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000257 code = ESCAPES.get(escape)
258 if code:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000259 return code
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000260 try:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000261 if escape[1:2] == "x":
262 while source.next in HEXDIGITS:
263 escape = escape + source.get()
264 escape = escape[2:]
Fredrik Lundh0640e112000-06-30 13:55:15 +0000265 return LITERAL, int(escape[-4:], 16) & CHARMASK
Fredrik Lundh90a07912000-06-30 07:50:59 +0000266 elif escape[1:2] in DIGITS:
267 while 1:
268 group = _group(escape, state.groups)
269 if group:
270 if (not source.next or
271 not _group(escape + source.next, state.groups)):
Fredrik Lundh72b82ba2000-07-03 21:31:48 +0000272 return GROUPREF, group
Fredrik Lundh90a07912000-06-30 07:50:59 +0000273 escape = escape + source.get()
274 elif source.next in OCTDIGITS:
275 escape = escape + source.get()
276 else:
277 break
278 escape = escape[1:]
Fredrik Lundh0640e112000-06-30 13:55:15 +0000279 return LITERAL, int(escape[-6:], 8) & CHARMASK
Fredrik Lundh90a07912000-06-30 07:50:59 +0000280 if len(escape) == 2:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000281 return LITERAL, ord(escape[1])
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000282 except ValueError:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000283 pass
Fredrik Lundh436c3d582000-06-29 08:58:44 +0000284 raise error, "bogus escape: %s" % repr(escape)
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000285
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000286def _parse_sub(source, state, nested=1):
287 # parse an alternation: a|b|c
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000288
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000289 items = []
290 while 1:
291 items.append(_parse(source, state))
292 if source.match("|"):
293 continue
294 if not nested:
295 break
296 if not source.next or source.match(")"):
297 break
298 else:
299 raise error, "pattern not properly closed"
300
301 if len(items) == 1:
302 return items[0]
303
304 subpattern = SubPattern(state)
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000305
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000306 # check if all items share a common prefix
307 while 1:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000308 prefix = None
309 for item in items:
310 if not item:
311 break
312 if prefix is None:
313 prefix = item[0]
314 elif item[0] != prefix:
315 break
316 else:
317 # all subitems start with a common "prefix".
318 # move it out of the branch
319 for item in items:
320 del item[0]
321 subpattern.append(prefix)
322 continue # check next one
323 break
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000324
325 # check if the branch can be replaced by a character set
326 for item in items:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000327 if len(item) != 1 or item[0][0] != LITERAL:
328 break
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000329 else:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000330 # we can store this as a character set instead of a
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000331 # branch (the compiler may optimize this even more)
Fredrik Lundh90a07912000-06-30 07:50:59 +0000332 set = []
333 for item in items:
334 set.append(item[0])
335 subpattern.append((IN, set))
336 return subpattern
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000337
338 subpattern.append((BRANCH, (None, items)))
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000339 return subpattern
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000340
Fredrik Lundh55a4f4a2000-06-30 22:37:31 +0000341def _parse(source, state):
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000342 # parse a simple pattern
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000343
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000344 subpattern = SubPattern(state)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000345
346 while 1:
347
Fredrik Lundh90a07912000-06-30 07:50:59 +0000348 if source.next in ("|", ")"):
349 break # end of subpattern
350 this = source.get()
351 if this is None:
352 break # end of pattern
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000353
Fredrik Lundh90a07912000-06-30 07:50:59 +0000354 if state.flags & SRE_FLAG_VERBOSE:
355 # skip whitespace and comments
356 if this in WHITESPACE:
357 continue
358 if this == "#":
359 while 1:
360 this = source.get()
361 if this in (None, "\n"):
362 break
363 continue
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000364
Fredrik Lundh90a07912000-06-30 07:50:59 +0000365 if this and this[0] not in SPECIAL_CHARS:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000366 subpattern.append((LITERAL, ord(this)))
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000367
Fredrik Lundh90a07912000-06-30 07:50:59 +0000368 elif this == "[":
369 # character set
370 set = []
371## if source.match(":"):
372## pass # handle character classes
373 if source.match("^"):
374 set.append((NEGATE, None))
375 # check remaining characters
376 start = set[:]
377 while 1:
378 this = source.get()
379 if this == "]" and set != start:
380 break
381 elif this and this[0] == "\\":
382 code1 = _class_escape(source, this)
383 elif this:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000384 code1 = LITERAL, ord(this)
Fredrik Lundh90a07912000-06-30 07:50:59 +0000385 else:
386 raise error, "unexpected end of regular expression"
387 if source.match("-"):
388 # potential range
389 this = source.get()
390 if this == "]":
391 set.append(code1)
Fredrik Lundh0640e112000-06-30 13:55:15 +0000392 set.append((LITERAL, ord("-")))
Fredrik Lundh90a07912000-06-30 07:50:59 +0000393 break
394 else:
395 if this[0] == "\\":
396 code2 = _class_escape(source, this)
397 else:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000398 code2 = LITERAL, ord(this)
Fredrik Lundh90a07912000-06-30 07:50:59 +0000399 if code1[0] != LITERAL or code2[0] != LITERAL:
400 raise error, "illegal range"
Fredrik Lundh90a07912000-06-30 07:50:59 +0000401 set.append((RANGE, (code1[1], code2[1])))
402 else:
403 if code1[0] is IN:
404 code1 = code1[1][0]
405 set.append(code1)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000406
Fredrik Lundh90a07912000-06-30 07:50:59 +0000407 # FIXME: <fl> move set optimization to compiler!
408 if len(set)==1 and set[0][0] is LITERAL:
409 subpattern.append(set[0]) # optimization
410 elif len(set)==2 and set[0][0] is NEGATE and set[1][0] is LITERAL:
411 subpattern.append((NOT_LITERAL, set[1][1])) # optimization
412 else:
413 # FIXME: <fl> add charmap optimization
414 subpattern.append((IN, set))
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000415
Fredrik Lundh90a07912000-06-30 07:50:59 +0000416 elif this and this[0] in REPEAT_CHARS:
417 # repeat previous item
418 if this == "?":
419 min, max = 0, 1
420 elif this == "*":
421 min, max = 0, MAXREPEAT
422 elif this == "+":
423 min, max = 1, MAXREPEAT
424 elif this == "{":
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000425 here = source.tell()
Fredrik Lundh90a07912000-06-30 07:50:59 +0000426 min, max = 0, MAXREPEAT
427 lo = hi = ""
428 while source.next in DIGITS:
429 lo = lo + source.get()
430 if source.match(","):
431 while source.next in DIGITS:
432 hi = hi + source.get()
433 else:
434 hi = lo
435 if not source.match("}"):
Fredrik Lundhc13222c2000-07-01 23:49:14 +0000436 subpattern.append((LITERAL, ord(this)))
437 source.seek(here)
438 continue
Fredrik Lundh90a07912000-06-30 07:50:59 +0000439 if lo:
440 min = int(lo)
441 if hi:
442 max = int(hi)
443 # FIXME: <fl> check that hi >= lo!
444 else:
445 raise error, "not supported"
446 # figure out which item to repeat
447 if subpattern:
448 item = subpattern[-1:]
449 else:
450 raise error, "nothing to repeat"
451 if source.match("?"):
452 subpattern[-1] = (MIN_REPEAT, (min, max, item))
453 else:
454 subpattern[-1] = (MAX_REPEAT, (min, max, item))
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000455
Fredrik Lundh90a07912000-06-30 07:50:59 +0000456 elif this == ".":
457 subpattern.append((ANY, None))
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000458
Fredrik Lundh90a07912000-06-30 07:50:59 +0000459 elif this == "(":
460 group = 1
461 name = None
462 if source.match("?"):
463 group = 0
464 # options
465 if source.match("P"):
466 # python extensions
467 if source.match("<"):
468 # named group: skip forward to end of name
469 name = ""
470 while 1:
471 char = source.get()
472 if char is None:
473 raise error, "unterminated name"
474 if char == ">":
475 break
476 name = name + char
477 group = 1
478 if not isname(name):
479 raise error, "illegal character in group name"
480 elif source.match("="):
481 # named backreference
Fredrik Lundhb71624e2000-06-30 09:13:06 +0000482 name = ""
483 while 1:
484 char = source.get()
485 if char is None:
486 raise error, "unterminated name"
487 if char == ")":
488 break
489 name = name + char
490 if not isname(name):
491 raise error, "illegal character in group name"
492 gid = state.groupdict.get(name)
493 if gid is None:
494 raise error, "unknown group name"
Fredrik Lundh72b82ba2000-07-03 21:31:48 +0000495 subpattern.append((GROUPREF, gid))
Fredrik Lundh7cafe4d2000-07-02 17:33:27 +0000496 continue
Fredrik Lundh90a07912000-06-30 07:50:59 +0000497 else:
498 char = source.get()
499 if char is None:
500 raise error, "unexpected end of pattern"
501 raise error, "unknown specifier: ?P%s" % char
502 elif source.match(":"):
503 # non-capturing group
504 group = 2
505 elif source.match("#"):
506 # comment
507 while 1:
508 if source.next is None or source.next == ")":
509 break
510 source.get()
Fredrik Lundh6f013982000-07-03 18:44:21 +0000511 elif source.next in ("=", "!", "<"):
Fredrik Lundh43b3b492000-06-30 10:41:31 +0000512 # lookahead assertions
513 char = source.get()
Fredrik Lundh6f013982000-07-03 18:44:21 +0000514 dir = 1
515 if char == "<":
516 if source.next not in ("=", "!"):
517 raise error, "syntax error"
518 dir = -1 # lookbehind
519 char = source.get()
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000520 p = _parse_sub(source, state)
521 if char == "=":
522 subpattern.append((ASSERT, (dir, p)))
523 else:
524 subpattern.append((ASSERT_NOT, (dir, p)))
525 continue
Fredrik Lundh90a07912000-06-30 07:50:59 +0000526 else:
527 # flags
528 while FLAGS.has_key(source.next):
529 state.flags = state.flags | FLAGS[source.get()]
530 if group:
531 # parse group contents
Fredrik Lundh90a07912000-06-30 07:50:59 +0000532 if group == 2:
533 # anonymous group
534 group = None
535 else:
536 group = state.getgroup(name)
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000537 p = _parse_sub(source, state)
538 subpattern.append((SUBPATTERN, (group, p)))
539 if group is not None:
540 p.append((INDEX, group))
Fredrik Lundh90a07912000-06-30 07:50:59 +0000541 else:
542 while 1:
543 char = source.get()
544 if char is None or char == ")":
545 break
546 raise error, "unknown extension"
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000547
Fredrik Lundh90a07912000-06-30 07:50:59 +0000548 elif this == "^":
549 subpattern.append((AT, AT_BEGINNING))
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000550
Fredrik Lundh90a07912000-06-30 07:50:59 +0000551 elif this == "$":
552 subpattern.append((AT, AT_END))
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000553
Fredrik Lundh90a07912000-06-30 07:50:59 +0000554 elif this and this[0] == "\\":
555 code = _escape(source, this, state)
556 subpattern.append(code)
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000557
Fredrik Lundh90a07912000-06-30 07:50:59 +0000558 else:
559 raise error, "parser error"
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000560
561 return subpattern
562
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000563def parse(str, flags=0):
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000564 # parse 're' pattern into list of (opcode, argument) tuples
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000565
566 source = Tokenizer(str)
567
568 pattern = Pattern()
569 pattern.flags = flags
570
571 p = _parse_sub(source, pattern, 0)
572
573 tail = source.get()
574 if tail == ")":
575 raise error, "unbalanced parenthesis"
576 elif tail:
577 raise error, "bogus characters at end of regular expression"
578
579 # p.dump()
580
Guido van Rossum7627c0d2000-03-31 14:58:54 +0000581 return p
582
Fredrik Lundh436c3d582000-06-29 08:58:44 +0000583def parse_template(source, pattern):
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000584 # parse 're' replacement string into list of literals and
585 # group references
586 s = Tokenizer(source)
587 p = []
588 a = p.append
589 while 1:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000590 this = s.get()
591 if this is None:
592 break # end of replacement string
593 if this and this[0] == "\\":
594 # group
595 if this == "\\g":
596 name = ""
597 if s.match("<"):
598 while 1:
599 char = s.get()
600 if char is None:
601 raise error, "unterminated group name"
602 if char == ">":
603 break
604 name = name + char
605 if not name:
606 raise error, "bad group name"
607 try:
608 index = int(name)
609 except ValueError:
610 if not isname(name):
611 raise error, "illegal character in group name"
612 try:
613 index = pattern.groupindex[name]
614 except KeyError:
615 raise IndexError, "unknown group name"
616 a((MARK, index))
617 elif len(this) > 1 and this[1] in DIGITS:
618 code = None
619 while 1:
620 group = _group(this, pattern.groups+1)
621 if group:
622 if (not s.next or
623 not _group(this + s.next, pattern.groups+1)):
624 code = MARK, int(group)
625 break
626 elif s.next in OCTDIGITS:
627 this = this + s.get()
628 else:
629 break
630 if not code:
631 this = this[1:]
Fredrik Lundh0640e112000-06-30 13:55:15 +0000632 code = LITERAL, int(this[-6:], 8) & CHARMASK
Fredrik Lundh90a07912000-06-30 07:50:59 +0000633 a(code)
634 else:
635 try:
636 a(ESCAPES[this])
637 except KeyError:
638 for c in this:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000639 a((LITERAL, ord(c)))
Fredrik Lundh90a07912000-06-30 07:50:59 +0000640 else:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000641 a((LITERAL, ord(this)))
Andrew M. Kuchling815d5b92000-06-09 14:08:07 +0000642 return p
643
Fredrik Lundh436c3d582000-06-29 08:58:44 +0000644def expand_template(template, match):
645 # FIXME: <fl> this is sooooo slow. drop in the slicelist
646 # code instead
647 p = []
648 a = p.append
Fredrik Lundh0640e112000-06-30 13:55:15 +0000649 sep = match.string[:0]
650 if type(sep) is type(""):
Fredrik Lundh4ccea942000-06-30 18:39:20 +0000651 char = chr
Fredrik Lundh0640e112000-06-30 13:55:15 +0000652 else:
Fredrik Lundh4ccea942000-06-30 18:39:20 +0000653 char = unichr
Fredrik Lundh436c3d582000-06-29 08:58:44 +0000654 for c, s in template:
Fredrik Lundh90a07912000-06-30 07:50:59 +0000655 if c is LITERAL:
Fredrik Lundh0640e112000-06-30 13:55:15 +0000656 a(char(s))
Fredrik Lundh90a07912000-06-30 07:50:59 +0000657 elif c is MARK:
658 s = match.group(s)
659 if s is None:
660 raise error, "empty group"
661 a(s)
Fredrik Lundh8a3ebf82000-07-23 21:46:17 +0000662 return string.join(p, sep)