1 """JSON token scanner 2 """ 3 import re 4 def _import_c_make_scanner(): 5 try: 6 from simplejson._speedups import make_scanner 7 return make_scanner 8 except ImportError: 9 return None 10 c_make_scanner = _import_c_make_scanner() 11 12 __all__ = ['make_scanner'] 13 14 NUMBER_RE = re.compile( 15 r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?', 16 (re.VERBOSE | re.MULTILINE | re.DOTALL)) 17 18 def py_make_scanner(context): 19 parse_object = context.parse_object 20 parse_array = context.parse_array 21 parse_string = context.parse_string 22 match_number = NUMBER_RE.match 23 encoding = context.encoding 24 strict = context.strict 25 parse_float = context.parse_float 26 parse_int = context.parse_int 27 parse_constant = context.parse_constant 28 object_hook = context.object_hook 29 object_pairs_hook = context.object_pairs_hook 30 memo = context.memo 31 32 def _scan_once(string, idx): 33 try: 34 nextchar = string[idx] 35 except IndexError: 36 raise StopIteration 37 38 if nextchar == '"': 39 return parse_string(string, idx + 1, encoding, strict) 40 elif nextchar == '{': 41 return parse_object((string, idx + 1), encoding, strict, 42 _scan_once, object_hook, object_pairs_hook, memo) 43 elif nextchar == '[': 44 return parse_array((string, idx + 1), _scan_once) 45 elif nextchar == 'n' and string[idx:idx + 4] == 'null': 46 return None, idx + 4 47 elif nextchar == 't' and string[idx:idx + 4] == 'true': 48 return True, idx + 4 49 elif nextchar == 'f' and string[idx:idx + 5] == 'false': 50 return False, idx + 5 51 52 m = match_number(string, idx) 53 if m is not None: 54 integer, frac, exp = m.groups() 55 if frac or exp: 56 res = parse_float(integer + (frac or '') + (exp or '')) 57 else: 58 res = parse_int(integer) 59 return res, m.end() 60 elif nextchar == 'N' and string[idx:idx + 3] == 'NaN': 61 return parse_constant('NaN'), idx + 3 62 elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity': 63 return parse_constant('Infinity'), idx + 8 64 elif nextchar == '-' and string[idx:idx + 9] == '-Infinity': 65 return parse_constant('-Infinity'), idx + 9 66 else: 67 raise StopIteration 68 69 def scan_once(string, idx): 70 try: 71 return _scan_once(string, idx) 72 finally: 73 memo.clear() 74 75 return scan_once 76 77 make_scanner = c_make_scanner or py_make_scanner 78