Initial commit

This commit is contained in:
2022-06-09 19:34:12 +02:00
parent 74e388dda7
commit 8b265077e4
10 changed files with 587 additions and 1 deletions

73
json_py/parser.py Normal file
View File

@@ -0,0 +1,73 @@
from __future__ import annotations
import typing
import json_py.lexer as lexer
ParserResult = typing.Tuple[typing.Any, lexer.TokenList]
def parse_array(tokens: lexer.TokenList) -> ParserResult:
json_array: typing.List[typing.Any] = []
if tokens[0] == "]":
return json_array, tokens[1:]
expect_comma = False
for i in range(len(tokens)):
t = tokens[i]
if t == "]":
if not expect_comma:
raise ValueError("Expected one more item")
return json_array, tokens[i + 1 :]
elif t == ",":
if not expect_comma:
raise ValueError("Unexpected comma")
expect_comma = False
else:
if expect_comma:
raise ValueError("Expected comma but got item")
json_array.append(t)
expect_comma = True
raise ValueError("List not closed")
def parse_object(tokens: lexer.TokenList) -> ParserResult:
json_object: typing.Any = {}
if tokens[0] == "}":
return json_object, tokens[1:]
is_syntax: typing.Callable[[str], bool] = lambda x: str(x) in ":"
while True:
json_key = tokens[0]
if is_syntax(json_key):
raise Exception(f"Expected value before '{json_key}'")
colon = tokens[1]
if colon != ":":
raise Exception(f"Expected ':' but got '{colon}'")
json_value, tokens = parse(tokens[2:])
json_object[json_key] = json_value
next_token = tokens[0]
if next_token == ",":
tokens = tokens[1:]
elif next_token == "}":
return json_object, tokens[1:]
else:
raise Exception(f"Expected ',' or '{'}'}' but got '{next_token}'")
def parse(tokens: lexer.TokenList) -> typing.Any:
t = tokens[0]
if t == "[":
return parse_array(tokens[1:])
elif t == "{":
return parse_object(tokens[1:])
else:
return t, tokens[1:]