Skip to content

Instantly share code, notes, and snippets.

@fabiommendes
Created August 6, 2021 19:01
Show Gist options
  • Save fabiommendes/17696368f79f8f5d2fe3f275f6bb8de9 to your computer and use it in GitHub Desktop.
Save fabiommendes/17696368f79f8f5d2fe3f275f6bb8de9 to your computer and use it in GitHub Desktop.
src = ""
pos = 0
def loads(text: str) -> object:
"""
Carrega um documento JSON e retorna o valor Python correspondente.
"""
global src, pos
src = text
pos = 0
ws()
value = read_value()
ws()
rest = src[pos:]
if rest == '' or rest.isspace():
return value
else:
raise SyntaxError(f'espera EOF, obteve {rest!r}')
def read_value():
global pos
if src.startswith("true", pos):
pos += 4
return True
elif src.startswith("false", pos):
pos += 5
return False
elif src.startswith("null", pos):
pos += 4
return None
elif src[pos].isdigit():
return read_number()
elif src[pos] == '"':
return read_string()
elif src[pos] == "[":
return read_array()
elif src[pos] == "{":
return read_object()
elif src[pos] == '-':
pos += 1
n = read_number()
return -n
else:
raise SyntaxError(f"unexpected {src[pos:]!r}")
def read_number():
global pos
pos_end = pos
while pos_end < len(src) and src[pos_end].isdigit():
pos_end += 1
n = int(src[pos:pos_end])
pos = pos_end
return n
def read_string():
global pos
pos_end = src.find('"', pos + 1)
st = src[pos + 1 : pos_end]
pos = pos_end + 1
return st
def read_array():
global pos
pos += 1
ws()
if src[pos] == "]":
pos += 1
return []
elements = [read_value()]
ws()
while True:
if src[pos] == "]":
pos += 1
return elements
read(",")
ws()
elements.append(read_value())
ws()
def read_object():
global pos
pos += 1
if src[pos] == "}":
pos += 1
return {}
elements = [read_pair()]
while True:
if src[pos] == "}":
pos += 1
return dict(elements)
read(",")
elements.append(read_pair())
def read_pair():
key = read_string()
read(":")
value = read_value()
return (key, value)
def read(st):
global pos
if not src.startswith(st, pos):
raise SyntaxError(f"espera {st!r}")
pos += len(st)
def ws():
global pos
try:
while src[pos] in " \n\r\t":
pos += 1
except IndexError:
return
# Exemplos
print(loads("true"))
print(loads("false"))
print(loads("null"))
print(loads("42"))
print(loads("-42"))
print(loads('"Hello World"'))
print(loads("[true,false,null,[1,2,3,[]]]"))
print(loads('{"answer":[1,2,[]]}'))
# Exercícios
# 1. Implemente suporte para números negativos.
# >>> print(loads("-42"))
# 2. Implemente suporte para números com parte decimal. Lembre-se que a parte
# decimal deve ser opcional.
# >>> print(loads("3.14"))
# >>> print(loads("-10.01"))
# 3. O leitor de JSON deve aceitar espaços em branco entre elementos. Crie uma
# função ws() que pule espaços em branco (" ", "\n", "\r", "\t") e
# modifique o código para chamar esta função nos locais apropriados.
# >>> print(loads(" 42 "))
# >>> print(loads(" [ 1 , 2 , 3 ] "))
# >>> print(loads(' { "key" : "value" } '))
print(loads(" 42 "))
print(loads(" [ 1 , 2 , 3 ] "))
# print(loads(' { "key" : "value" } '))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment