-
Notifications
You must be signed in to change notification settings - Fork 25
/
json.py
69 lines (51 loc) · 1.75 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
#!/usr/bin/env python
from codetalker.pgm import Grammar, Translator
from codetalker.pgm.special import star, plus, _or, commas
from codetalker.pgm.tokens import STRING, NUMBER, EOF, NEWLINE, WHITE, ReToken, re, CharToken, StringToken
'''Man this looks sweet. It really should be
this easy to write a json parser.'''
# special tokens
class SYMBOL(CharToken):
chars = '{},[]:'
num = 6
class TFN(StringToken):
strings = ['true', 'false', 'null']
# rules (value is the start rule)
def value(rule):
rule | dict_ | list_ | STRING | TFN | NUMBER
rule.pass_single = True
def dict_(rule):
rule | ('{', [commas((STRING, ':', value))], '}')
rule.astAttrs = {'keys': [STRING], 'values': [value]}
dict_.astName = 'Dict'
def list_(rule):
rule | ('[', [commas(value)], ']')
rule.astAttrs = {'values': [value]}
list_.astName = 'List'
grammar = Grammar(start=value,
tokens=[SYMBOL],
ignore=[WHITE, NEWLINE],
ast_tokens=[STRING, TFN, NUMBER])
# translator stuff
JSON = Translator(grammar)
ast = grammar.ast_classes
@JSON.translates(ast.Dict)
def t_dict(node):
return dict((JSON.translate(key), JSON.translate(value))\
for (key, value) in zip(node.keys, node.values))
@JSON.translates(ast.List)
def t_list(node):
return list(JSON.translate(value) for value in node.values)
@JSON.translates(STRING)
def t_string(node):
return node.value[1:-1].decode('string_escape')
@JSON.translates(NUMBER)
def t_number(node):
if '.' in node.value or 'e' in node.value.lower():
return float(node.value)
return int(node.value)
@JSON.translates(TFN)
def t_tfn(node):
return {'true':True, 'false':False, 'null':None}[node.value]
loads = JSON.from_string
# vim: et sw=4 sts=4