-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjson_parser.py
More file actions
211 lines (186 loc) · 5.11 KB
/
json_parser.py
File metadata and controls
211 lines (186 loc) · 5.11 KB
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import os
current = 0
previous = 0
def json_parser(string:str):
return parse_value(string)
def parse_value(string:str):
global current
global previous
skip_whitespace(string)
value = None
if current == len(string):
return None
match(string[current]):
case '"':
value = parse_string(string)
case 't':
value = parse_true(string)
case 'f':
value = parse_false(string)
case '[':
value = parse_array(string)
case '{':
value = parse_object(string)
case 'n':
value = parse_null(string)
case _:
if string[current] in ['\n', '\t', ' ', '\r']:
skip_whitespace(string)
if string[current].isdigit() or string[current] == '-':
value = parse_number(string)
else:
raise ValueError("Invalid value")
skip_whitespace(string)
return value
def match(string, substring):
global current
global previous
length = len(substring)
if current >= len(string):
return False
if string[current:current+length] == substring:
current += length
previous = current
return True
else:
return False
def peek(string, char):
global current
global previous
if current >= len(string):
return False
if string[current] == char:
return True
else:
return False
def skip_whitespace(string:str):
global current
global previous
length = len(string)
while current < length and string[current] in ['\n', '\t', ' ', '\r']:
current += 1
previous = current
def parse_string(string:str):
global current
global previous
current += 1
previous = current
while string[current] != '"':
current += 1
content = string[previous:current]
match(string, '"')
previous = current
return content
def parse_true(string:str):
global current
global previous
if string[current:current+4] == 'true':
current += 4
previous = current
return True
else:
raise ValueError("Invalid value")
def parse_false(string:str):
global current
global previous
if string[current:current+5] == 'false':
current += 5
previous = current
return False
else:
raise ValueError("Invalid value")
def parse_null(string:str):
global current
global previous
if string[current:current+4] == 'null':
current += 4
previous = current
return None
else:
raise ValueError("Invalid value")
def parse_number(string:str):
global current
global previous
length = len(string)
sign_flag = False
if match(string, '-'):
sign_flag = True
while current < length and (string[current].isdigit() ):
current += 1
if(peek(string, '.')):
current += 1
while current < length and string[current].isdigit():
current += 1
num = float(string[previous:current])
previous = current
if(match(string, 'e') or match(string, 'E')):
if(peek(string, '+') or peek(string, '-')):
current += 1
while current < length and string[current].isdigit():
current += 1
exp = int(string[previous:current])
num = num * (10 ** exp)
previous = current
if sign_flag:
num = -num
return num
def parse_object(string:str):
global current
global previous
current += 1
members = parse_members(string)
skip_whitespace(string)
if not match(string, '}'):
raise ValueError("Unpaired braces")
skip_whitespace(string)
return members
def parse_array(string:str):
global current
global previous
current += 1
elements = parse_elements(string)
skip_whitespace(string)
if not match(string, ']'):
raise ValueError("Unpaired brackets")
skip_whitespace(string)
return elements
def parse_elements(string:str):
global current
global previous
elements = []
skip_whitespace(string)
if peek(string, ']'):
return elements
while True:
elements.append(parse_value(string))
if not match(string, ','):
break
skip_whitespace(string)
return elements
def parse_members(string: str):
global current
global previous
members = {}
skip_whitespace(string)
if peek(string, '}'):
return members
while True:
key = parse_value(string)
if not match(string, ':'):
raise ValueError("Missing colon")
value = parse_value(string)
members[key] = value
if not match(string, ','):
break
skip_whitespace(string)
return members
# print(json_parser('[-1e+9999]'))
if __name__ == "__main__":
file_list = os.listdir('tests')
for file in file_list:
if file.startswith('y'):
with open('tests/'+file, 'r') as f:
example = f.read()
print(example)
current = previous = 0
print(json_parser(example))