-
Notifications
You must be signed in to change notification settings - Fork 5
/
json.py
93 lines (69 loc) · 2.04 KB
/
json.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
JSON parser implemented with SLY
Implemented by Michael Wayne Goodman. For license information, see
https://github.com/goodmami/python-parsing-benchmarks/
"""
from sly import Lexer, Parser
from bench.helpers import json_unescape
def compile():
class JsonLexer(Lexer):
tokens = { STRING, NUMBER, TRUE, FALSE, NULL }
ignore = ' \t\n\r'
literals = { '{', '}', '[', ']', ':', ',' }
@_(r'-?(0|[1-9][0-9]*)(\.[0-9]+)?([Ee][+-]?[0-9]+)?')
def NUMBER(self, t):
t.value = float(t.value)
return t
@_(r'"([ !#-\[\]-\U0010ffff]+|\\(["\/\\bfnrt]|u[0-9A-Fa-f]{4}))*"')
def STRING(self, t):
t.value = json_unescape(t.value)
return t
@_(r'true')
def TRUE(self, t):
t.value = True
return t
@_(r'false')
def FALSE(self, t):
t.value = False
return t
@_(r'null')
def NULL(self, t):
t.value = None
return t
class JsonParser(Parser):
tokens = JsonLexer.tokens
start = 'value'
@_(r'"{" [ pairs ] "}"')
def value(self, p):
if p.pairs:
return dict(p.pairs)
else:
return {}
@_(r'pair { "," pair }')
def pairs(self, p):
return [p.pair0] + p.pair1
@_(r'STRING ":" value')
def pair(self, p):
return (p.STRING, p.value)
@_(r'"[" [ items ] "]"')
def value(self, p):
if p.items:
return p.items
else:
return []
@_(r'value { "," value }')
def items(self, p):
return [p.value0] + p.value1
@_('STRING',
'NUMBER',
'TRUE',
'FALSE',
'NULL')
def value(self, p):
return p[0]
def error(self, p):
raise ValueError(p)
lexer = JsonLexer()
parser = JsonParser()
return lambda s: parser.parse(lexer.tokenize(s))
parse = compile()