aidial_assistant/json_stream/json_parser.py (55 lines of code) (raw):
from typing_extensions import override
from aidial_assistant.json_stream.chunked_char_stream import (
ChunkedCharStream,
skip_whitespaces,
)
from aidial_assistant.json_stream.exceptions import (
unexpected_end_of_stream_error,
unexpected_symbol_error,
)
from aidial_assistant.json_stream.json_array import JsonArray
from aidial_assistant.json_stream.json_bool import JsonBoolean
from aidial_assistant.json_stream.json_node import JsonNode, NodeParser
from aidial_assistant.json_stream.json_null import JsonNull
from aidial_assistant.json_stream.json_number import JsonNumber
from aidial_assistant.json_stream.json_object import JsonObject
from aidial_assistant.json_stream.json_string import JsonString
def array_node(node: JsonNode) -> JsonArray:
if not isinstance(node, JsonArray):
raise TypeError(
f"Expected json array at position {node.pos}, got {node.type()}"
)
return node
def object_node(node: JsonNode) -> JsonObject:
if not isinstance(node, JsonObject):
raise TypeError(
f"Expected json object at position {node.pos}, got {node.type()}"
)
return node
def string_node(node: JsonNode) -> JsonString:
if not isinstance(node, JsonString):
raise TypeError(
f"Expected json string at position {node.pos}, got {node.type()}"
)
return node
class JsonParser(NodeParser):
@override
async def parse(self, stream: ChunkedCharStream) -> JsonNode:
try:
await skip_whitespaces(stream)
char = await stream.apeek()
if JsonObject.starts_with(char):
return JsonObject.parse(stream, self)
if JsonArray.starts_with(char):
return JsonArray.parse(stream, self)
if JsonString.starts_with(char):
return JsonString.parse(stream)
if JsonNumber.starts_with(char):
return await JsonNumber.parse(stream)
if JsonNull.starts_with(char):
return await JsonNull.parse(stream)
if JsonBoolean.starts_with(char):
return await JsonBoolean.parse(stream)
except StopAsyncIteration:
raise unexpected_end_of_stream_error(stream.char_position)
raise unexpected_symbol_error(char, stream.char_position)