Writing a JSON Parser From Scratch: Lexer, Recursive Descent, and the Cases You Forget

I’ve been reading JSON for years without ever writing the code that parses it. That’s a strange gap: it’s a format we touch most days, and the one whose internals I’d thought about least. So I sat down one evening and wrote one from scratch in Python, no json.loads, no regex shortcuts, just the spec and a blank file. The structure is the textbook one: a lexer that turns characters into tokens, and a recursive-descent parser that turns tokens into a tree. What I want to write about is less the structure itself (that part is well-trodden) and more the places where the spec is sharper than it looks, and where a reasonable-seeming shortcut quietly produces a parser that accepts invalid input. ...

May 10, 2026 · Giulia

C: Variables, Symbolic Constants, and the Preprocessor

This is part one of two. Part two covers the C memory model and stack frames. -Wall If I use the -Wall flag, the compiler emits warnings. Simple rule: always use it. 0 means more than zero The value 0 is equivalent to false in C boolean expressions. It also shows up in shell short-circuit evaluation. In an expression like ./a.out && ls, ls only executes if ./a.out returns 0. That’s because 0 is the success exit code, and && short-circuits on failure. So ./a.out returning 0 makes ls run. The 0 in the exit code sense is “success / true” from the shell’s perspective, opposite of the C boolean convention, which trips people up. ...

March 22, 2026 · Giulia

What Actually Happens When You Compile a C Program

Most developers treat compilation as a black box: you put source code in, you get a binary out. But there are actually three distinct stages happening, each with its own job and its own output. Understanding them has made me significantly better at debugging linker errors, understanding dependencies, and reasoning about what ends up in a binary. Let’s walk through what happens when you run gcc hello.c -o hello. Stage 1: The Preprocessor Before the compiler sees a single line of your code, the preprocessor runs. Its job is mechanical: it handles all the # directives. ...

March 8, 2026 · Giulia