Reading — step 1 of 5
Read
Parsing Arrays
The first container. Its grammar:
array = "[" [ value *( "," value ) ] "]"
Read the ABNF the way the parser will execute it: after [, either the array ends immediately, or there is a value, then zero or more of (comma, value), then ]. The comma is a separator, never a terminator — that single fact generates half of JSON's rejection cases.
parseArray():
expect "["
if peek() == "]": consume(); return []
out = [parseValue()]
while peek() == ",":
consume(",")
out.append(parseValue()) # a value MUST follow every comma
expect "]"
return out
The invariant to internalize: after consuming a comma you are obligated to parse a value. If the next token is ], that is the trailing-comma error — [1, 2,] is invalid JSON, full stop, even though JavaScript and JSON5 allow it. (Copy-pasting a JS literal into a .json file is the classic way to hit this.) Symmetrically, [,1] fails because the first thing after [ must be a value or ], and [1 2] fails at expect time because neither , nor ] follows the first value.
Everything else falls out of recursion:
- Heterogeneous by design.
[1, "two", true, null, [3, 4]]is fine; elements each go throughparseValue, which does not care what its neighbors were. - Nesting costs nothing.
parseArraycallsparseValuewhich may callparseArray— mutual recursion mirrors the grammar exactly. Resist flattening this into a hand-rolled state machine; the recursive shape is the readable, verifiable one (a later lesson deals with adversarial depth). - Whitespace between any two tokens.
[ 1 , 2 ], even split across lines, tokenizes identically to[1,2].
The trap is a loop that treats the comma as optional garnish, e.g. "keep parsing values while there are values, skip commas whenever seen". That accepts [1,] and [1 2] and [,] alike. The grammar-shaped loop above cannot: each comma commits you to one more value.
Your exercise
Parse one array per line and print the Python repr of the resulting list — that formatting is free: repr of [1, "two", True, None] is exactly the expected [1, 'two', True, None], single quotes and capitalized keywords included; do not hand-format. Two grader-caught mistakes: (1) [1, 2,] must print exactly ERR trailing comma — raise ValueError("trailing comma") when ] appears where the post-comma value should be; (2) hidden test [1.5e2, -0.5] must print [150.0, -0.5] — your element parser must apply the scalar rule (./e/E present → float, else int), so reuse the previous lesson's number handling instead of shortcutting with int(). One note: the starter imports the stdlib json module — leave it unused; the output format is repr, and parsing with it defeats the exercise.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…