--- /dev/null
+#\r
+# Secret Labs' Regular Expression Engine\r
+#\r
+# re-compatible interface for the sre matching engine\r
+#\r
+# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved.\r
+#\r
+# This version of the SRE library can be redistributed under CNRI's\r
+# Python 1.6 license. For any other use, please contact Secret Labs\r
+# AB (info@pythonware.com).\r
+#\r
+# Portions of this engine have been developed in cooperation with\r
+# CNRI. Hewlett-Packard provided funding for 1.6 integration and\r
+# other compatibility work.\r
+#\r
+\r
+r"""Support for regular expressions (RE).\r
+\r
+This module provides regular expression matching operations similar to\r
+those found in Perl. It supports both 8-bit and Unicode strings; both\r
+the pattern and the strings being processed can contain null bytes and\r
+characters outside the US ASCII range.\r
+\r
+Regular expressions can contain both special and ordinary characters.\r
+Most ordinary characters, like "A", "a", or "0", are the simplest\r
+regular expressions; they simply match themselves. You can\r
+concatenate ordinary characters, so last matches the string 'last'.\r
+\r
+The special characters are:\r
+ "." Matches any character except a newline.\r
+ "^" Matches the start of the string.\r
+ "$" Matches the end of the string or just before the newline at\r
+ the end of the string.\r
+ "*" Matches 0 or more (greedy) repetitions of the preceding RE.\r
+ Greedy means that it will match as many repetitions as possible.\r
+ "+" Matches 1 or more (greedy) repetitions of the preceding RE.\r
+ "?" Matches 0 or 1 (greedy) of the preceding RE.\r
+ *?,+?,?? Non-greedy versions of the previous three special characters.\r
+ {m,n} Matches from m to n repetitions of the preceding RE.\r
+ {m,n}? Non-greedy version of the above.\r
+ "\\" Either escapes special characters or signals a special sequence.\r
+ [] Indicates a set of characters.\r
+ A "^" as the first character indicates a complementing set.\r
+ "|" A|B, creates an RE that will match either A or B.\r
+ (...) Matches the RE inside the parentheses.\r
+ The contents can be retrieved or matched later in the string.\r
+ (?iLmsux) Set the I, L, M, S, U, or X flag for the RE (see below).\r
+ (?:...) Non-grouping version of regular parentheses.\r
+ (?P<name>...) The substring matched by the group is accessible by name.\r
+ (?P=name) Matches the text matched earlier by the group named name.\r
+ (?#...) A comment; ignored.\r
+ (?=...) Matches if ... matches next, but doesn't consume the string.\r
+ (?!...) Matches if ... doesn't match next.\r
+ (?<=...) Matches if preceded by ... (must be fixed length).\r
+ (?<!...) Matches if not preceded by ... (must be fixed length).\r
+ (?(id/name)yes|no) Matches yes pattern if the group with id/name matched,\r
+ the (optional) no pattern otherwise.\r
+\r
+The special sequences consist of "\\" and a character from the list\r
+below. If the ordinary character is not on the list, then the\r
+resulting RE will match the second character.\r
+ \number Matches the contents of the group of the same number.\r
+ \A Matches only at the start of the string.\r
+ \Z Matches only at the end of the string.\r
+ \b Matches the empty string, but only at the start or end of a word.\r
+ \B Matches the empty string, but not at the start or end of a word.\r
+ \d Matches any decimal digit; equivalent to the set [0-9].\r
+ \D Matches any non-digit character; equivalent to the set [^0-9].\r
+ \s Matches any whitespace character; equivalent to [ \t\n\r\f\v].\r
+ \S Matches any non-whitespace character; equiv. to [^ \t\n\r\f\v].\r
+ \w Matches any alphanumeric character; equivalent to [a-zA-Z0-9_].\r
+ With LOCALE, it will match the set [0-9_] plus characters defined\r
+ as letters for the current locale.\r
+ \W Matches the complement of \w.\r
+ \\ Matches a literal backslash.\r
+\r
+This module exports the following functions:\r
+ match Match a regular expression pattern to the beginning of a string.\r
+ search Search a string for the presence of a pattern.\r
+ sub Substitute occurrences of a pattern found in a string.\r
+ subn Same as sub, but also return the number of substitutions made.\r
+ split Split a string by the occurrences of a pattern.\r
+ findall Find all occurrences of a pattern in a string.\r
+ finditer Return an iterator yielding a match object for each match.\r
+ compile Compile a pattern into a RegexObject.\r
+ purge Clear the regular expression cache.\r
+ escape Backslash all non-alphanumerics in a string.\r
+\r
+Some of the functions in this module takes flags as optional parameters:\r
+ I IGNORECASE Perform case-insensitive matching.\r
+ L LOCALE Make \w, \W, \b, \B, dependent on the current locale.\r
+ M MULTILINE "^" matches the beginning of lines (after a newline)\r
+ as well as the string.\r
+ "$" matches the end of lines (before a newline) as well\r
+ as the end of the string.\r
+ S DOTALL "." matches any character at all, including the newline.\r
+ X VERBOSE Ignore whitespace and comments for nicer looking RE's.\r
+ U UNICODE Make \w, \W, \b, \B, dependent on the Unicode locale.\r
+\r
+This module also defines an exception 'error'.\r
+\r
+"""\r
+\r
+import sys\r
+import sre_compile\r
+import sre_parse\r
+try:\r
+ import _locale\r
+except ImportError:\r
+ _locale = None\r
+\r
+# public symbols\r
+__all__ = [ "match", "search", "sub", "subn", "split", "findall",\r
+ "compile", "purge", "template", "escape", "I", "L", "M", "S", "X",\r
+ "U", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",\r
+ "UNICODE", "error" ]\r
+\r
+__version__ = "2.2.1"\r
+\r
+# flags\r
+I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case\r
+L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale\r
+U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale\r
+M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline\r
+S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline\r
+X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments\r
+\r
+# sre extensions (experimental, don't rely on these)\r
+T = TEMPLATE = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking\r
+DEBUG = sre_compile.SRE_FLAG_DEBUG # dump pattern after compilation\r
+\r
+# sre exception\r
+error = sre_compile.error\r
+\r
+# --------------------------------------------------------------------\r
+# public interface\r
+\r
+def match(pattern, string, flags=0):\r
+ """Try to apply the pattern at the start of the string, returning\r
+ a match object, or None if no match was found."""\r
+ return _compile(pattern, flags).match(string)\r
+\r
+def search(pattern, string, flags=0):\r
+ """Scan through string looking for a match to the pattern, returning\r
+ a match object, or None if no match was found."""\r
+ return _compile(pattern, flags).search(string)\r
+\r
+def sub(pattern, repl, string, count=0, flags=0):\r
+ """Return the string obtained by replacing the leftmost\r
+ non-overlapping occurrences of the pattern in string by the\r
+ replacement repl. repl can be either a string or a callable;\r
+ if a string, backslash escapes in it are processed. If it is\r
+ a callable, it's passed the match object and must return\r
+ a replacement string to be used."""\r
+ return _compile(pattern, flags).sub(repl, string, count)\r
+\r
+def subn(pattern, repl, string, count=0, flags=0):\r
+ """Return a 2-tuple containing (new_string, number).\r
+ new_string is the string obtained by replacing the leftmost\r
+ non-overlapping occurrences of the pattern in the source\r
+ string by the replacement repl. number is the number of\r
+ substitutions that were made. repl can be either a string or a\r
+ callable; if a string, backslash escapes in it are processed.\r
+ If it is a callable, it's passed the match object and must\r
+ return a replacement string to be used."""\r
+ return _compile(pattern, flags).subn(repl, string, count)\r
+\r
+def split(pattern, string, maxsplit=0, flags=0):\r
+ """Split the source string by the occurrences of the pattern,\r
+ returning a list containing the resulting substrings."""\r
+ return _compile(pattern, flags).split(string, maxsplit)\r
+\r
+def findall(pattern, string, flags=0):\r
+ """Return a list of all non-overlapping matches in the string.\r
+\r
+ If one or more groups are present in the pattern, return a\r
+ list of groups; this will be a list of tuples if the pattern\r
+ has more than one group.\r
+\r
+ Empty matches are included in the result."""\r
+ return _compile(pattern, flags).findall(string)\r
+\r
+if sys.hexversion >= 0x02020000:\r
+ __all__.append("finditer")\r
+ def finditer(pattern, string, flags=0):\r
+ """Return an iterator over all non-overlapping matches in the\r
+ string. For each match, the iterator returns a match object.\r
+\r
+ Empty matches are included in the result."""\r
+ return _compile(pattern, flags).finditer(string)\r
+\r
+def compile(pattern, flags=0):\r
+ "Compile a regular expression pattern, returning a pattern object."\r
+ return _compile(pattern, flags)\r
+\r
+def purge():\r
+ "Clear the regular expression cache"\r
+ _cache.clear()\r
+ _cache_repl.clear()\r
+\r
+def template(pattern, flags=0):\r
+ "Compile a template pattern, returning a pattern object"\r
+ return _compile(pattern, flags|T)\r
+\r
+_alphanum = frozenset(\r
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")\r
+\r
+def escape(pattern):\r
+ "Escape all non-alphanumeric characters in pattern."\r
+ s = list(pattern)\r
+ alphanum = _alphanum\r
+ for i, c in enumerate(pattern):\r
+ if c not in alphanum:\r
+ if c == "\000":\r
+ s[i] = "\\000"\r
+ else:\r
+ s[i] = "\\" + c\r
+ return pattern[:0].join(s)\r
+\r
+# --------------------------------------------------------------------\r
+# internals\r
+\r
+_cache = {}\r
+_cache_repl = {}\r
+\r
+_pattern_type = type(sre_compile.compile("", 0))\r
+\r
+_MAXCACHE = 100\r
+\r
+def _compile(*key):\r
+ # internal: compile pattern\r
+ pattern, flags = key\r
+ bypass_cache = flags & DEBUG\r
+ if not bypass_cache:\r
+ cachekey = (type(key[0]),) + key\r
+ try:\r
+ p, loc = _cache[cachekey]\r
+ if loc is None or loc == _locale.setlocale(_locale.LC_CTYPE):\r
+ return p\r
+ except KeyError:\r
+ pass\r
+ if isinstance(pattern, _pattern_type):\r
+ if flags:\r
+ raise ValueError('Cannot process flags argument with a compiled pattern')\r
+ return pattern\r
+ if not sre_compile.isstring(pattern):\r
+ raise TypeError, "first argument must be string or compiled pattern"\r
+ try:\r
+ p = sre_compile.compile(pattern, flags)\r
+ except error, v:\r
+ raise error, v # invalid expression\r
+ if not bypass_cache:\r
+ if len(_cache) >= _MAXCACHE:\r
+ _cache.clear()\r
+ if p.flags & LOCALE:\r
+ if not _locale:\r
+ return p\r
+ loc = _locale.setlocale(_locale.LC_CTYPE)\r
+ else:\r
+ loc = None\r
+ _cache[cachekey] = p, loc\r
+ return p\r
+\r
+def _compile_repl(*key):\r
+ # internal: compile replacement pattern\r
+ p = _cache_repl.get(key)\r
+ if p is not None:\r
+ return p\r
+ repl, pattern = key\r
+ try:\r
+ p = sre_parse.parse_template(repl, pattern)\r
+ except error, v:\r
+ raise error, v # invalid expression\r
+ if len(_cache_repl) >= _MAXCACHE:\r
+ _cache_repl.clear()\r
+ _cache_repl[key] = p\r
+ return p\r
+\r
+def _expand(pattern, match, template):\r
+ # internal: match.expand implementation hook\r
+ template = sre_parse.parse_template(template, pattern)\r
+ return sre_parse.expand_template(template, match)\r
+\r
+def _subx(pattern, template):\r
+ # internal: pattern.sub/subn implementation helper\r
+ template = _compile_repl(template, pattern)\r
+ if not template[0] and len(template[1]) == 1:\r
+ # literal replacement\r
+ return template[1][0]\r
+ def filter(match, template=template):\r
+ return sre_parse.expand_template(template, match)\r
+ return filter\r
+\r
+# register myself for pickling\r
+\r
+import copy_reg\r
+\r
+def _pickle(p):\r
+ return _compile, (p.pattern, p.flags)\r
+\r
+copy_reg.pickle(_pattern_type, _pickle, _compile)\r
+\r
+# --------------------------------------------------------------------\r
+# experimental stuff (see python-dev discussions for details)\r
+\r
+class Scanner:\r
+ def __init__(self, lexicon, flags=0):\r
+ from sre_constants import BRANCH, SUBPATTERN\r
+ self.lexicon = lexicon\r
+ # combine phrases into a compound pattern\r
+ p = []\r
+ s = sre_parse.Pattern()\r
+ s.flags = flags\r
+ for phrase, action in lexicon:\r
+ p.append(sre_parse.SubPattern(s, [\r
+ (SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),\r
+ ]))\r
+ s.groups = len(p)+1\r
+ p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])\r
+ self.scanner = sre_compile.compile(p)\r
+ def scan(self, string):\r
+ result = []\r
+ append = result.append\r
+ match = self.scanner.scanner(string).match\r
+ i = 0\r
+ while 1:\r
+ m = match()\r
+ if not m:\r
+ break\r
+ j = m.end()\r
+ if i == j:\r
+ break\r
+ action = self.lexicon[m.lastindex-1][1]\r
+ if hasattr(action, '__call__'):\r
+ self.match = m\r
+ action = action(self, m.group())\r
+ if action is not None:\r
+ append(action)\r
+ i = j\r
+ return result, string[i:]\r