summaryrefslogtreecommitdiffstats
path: root/Lib/json/scanner.py
diff options
context:
space:
mode:
authorBrett Cannon <bcannon@gmail.com>2008-05-05 20:21:38 (GMT)
committerBrett Cannon <bcannon@gmail.com>2008-05-05 20:21:38 (GMT)
commit4b964f9c904744b7d7d88054e54a2e4ca8aeb395 (patch)
treec24ba51492fc3fc714c54f2e671f21172d063908 /Lib/json/scanner.py
parent5f2e0e5ccb988cdf65137034b33ee57198cc23b9 (diff)
downloadcpython-4b964f9c904744b7d7d88054e54a2e4ca8aeb395.zip
cpython-4b964f9c904744b7d7d88054e54a2e4ca8aeb395.tar.gz
cpython-4b964f9c904744b7d7d88054e54a2e4ca8aeb395.tar.bz2
Add the 'json' package. Code taken from simplejson 1.9 and contributed by Bob
Ippolito. Closes issue #2750.
Diffstat (limited to 'Lib/json/scanner.py')
-rw-r--r--Lib/json/scanner.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/Lib/json/scanner.py b/Lib/json/scanner.py
new file mode 100644
index 0000000..4b065ab
--- /dev/null
+++ b/Lib/json/scanner.py
@@ -0,0 +1,69 @@
+"""Iterator based sre token scanner
+
+"""
+
+import re
+import sre_parse
+import sre_compile
+import sre_constants
+
+from re import VERBOSE, MULTILINE, DOTALL
+from sre_constants import BRANCH, SUBPATTERN
+
+__all__ = ['Scanner', 'pattern']
+
+FLAGS = (VERBOSE | MULTILINE | DOTALL)
+
+class Scanner(object):
+ def __init__(self, lexicon, flags=FLAGS):
+ self.actions = [None]
+ # Combine phrases into a compound pattern
+ s = sre_parse.Pattern()
+ s.flags = flags
+ p = []
+ for idx, token in enumerate(lexicon):
+ phrase = token.pattern
+ try:
+ subpattern = sre_parse.SubPattern(s,
+ [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])
+ except sre_constants.error:
+ raise
+ p.append(subpattern)
+ self.actions.append(token)
+
+ s.groups = len(p) + 1 # NOTE(guido): Added to make SRE validation work
+ p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
+ self.scanner = sre_compile.compile(p)
+
+ def iterscan(self, string, idx=0, context=None):
+ """Yield match, end_idx for each match
+
+ """
+ match = self.scanner.scanner(string, idx).match
+ actions = self.actions
+ lastend = idx
+ end = len(string)
+ while True:
+ m = match()
+ if m is None:
+ break
+ matchbegin, matchend = m.span()
+ if lastend == matchend:
+ break
+ action = actions[m.lastindex]
+ if action is not None:
+ rval, next_pos = action(m, context)
+ if next_pos is not None and next_pos != matchend:
+ # "fast forward" the scanner
+ matchend = next_pos
+ match = self.scanner.scanner(string, matchend).match
+ yield rval, matchend
+ lastend = matchend
+
+
+def pattern(pattern, flags=FLAGS):
+ def decorator(fn):
+ fn.pattern = pattern
+ fn.regex = re.compile(pattern, flags)
+ return fn
+ return decorator