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