-
Notifications
You must be signed in to change notification settings - Fork 5
/
json.py
71 lines (53 loc) · 1.85 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
from lark import Lark, Transformer, v_args
from bench.helpers import json_unescape
def compile():
# NOTE: the ; after value is to detect the end of the input
json_grammar = r"""
?start: _WS? value _WS? ";"
?value: object
| array
| string
| NUMBER -> number
| "true" -> true
| "false" -> false
| "null" -> null
array : _BRACK1 [value (_COMMA value)*] _BRACK2
object : _CURLY1 [pair (_COMMA pair)*] _CURLY2
pair : string _COLON value
_COLON: /\s*:\s*/
_COMMA: /\s*,\s*/
_CURLY1: /\s*{\s*/
_CURLY2: /\s*}\s*/
_BRACK1: /\s*\[\s*/
_BRACK2: /\s*\]\s*/
string : STRING
STRING: "\"" INNER* "\""
INNER: /[ !#-\[\]-\U0010ffff]*/
| /\\(?:["\/\\bfnrt]|u[0-9A-Fa-f]{4})/
NUMBER : INTEGER FRACTION? EXPONENT?
INTEGER: ["-"] ("0" | "1".."9" INT?)
FRACTION: "." INT
EXPONENT: ("e"|"E") ["+"|"-"] INT
_WS: /\s+/
%import common.INT
"""
class TreeToJson(Transformer):
@v_args(inline=True)
def string(self, s):
return json_unescape(s)
array = list
pair = tuple
object = dict
number = v_args(inline=True)(float)
null = lambda self, _: None
true = lambda self, _: True
false = lambda self, _: False
json_parser = Lark(json_grammar,
parser='lalr',
lexer='basic',
propagate_positions=False,
maybe_placeholders=False,
transformer=TreeToJson())
# trailing ; is currently necessary to detect end of input
return lambda s: json_parser.parse(s + ';')
parse = compile()