A recursive descent parser drives a train through railroad syntax diagrams.
Each grammar rule is drawn as a classic railroad diagram: terminals are stations, nonterminals are tunnels, alternatives branch on curved switches and repetitions loop back on a lower track that carries the separator. A generic LL(1) recursive descent parser walks those same diagram elements, picking branches with FIRST sets, and records the exact route the train must take. Every rule call opens a new card on the call stack while the train waits in the tunnel above, and every consumed token flies into the parse tree on the right, where arithmetic subtrees show their values as they complete. A syntax error derails the train at the exact token and names what the grammar expected instead.
Try it. Click the canvas and type to edit the input; the train re-runs only the part that changed. Pick a sample below (arithmetic, JSON, deep nesting or a deliberate syntax error), click a tunnel to peek at that rule's diagram, or click anywhere else to replay.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build an animated railroad diagram parser with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Use a small arithmetic grammar: expr is term separated by + or -, term is factor separated by * or /, and factor is a number, a parenthesized expr, or a minus sign followed by a factor.
- Define each rule as a tree of diagram elements: terminal, nonterminal, sequence, choice and loop (an item repeated with a separator).
- Write a layout function that measures each element (its width and how far it reaches above and below the main line), then places it: sequences go left to right, choice branches stack vertically and join with quarter-circle curves, and a loop returns underneath its item with the separator on the lower track. Draw terminals as rounded boxes and nonterminals as rectangles.
- Write a tokenizer and a recursive descent parser with one function per rule, and draw every rule's diagram on the canvas.
Once that works, make it beautiful:
- Make the parser record the path it takes through each diagram (the same points your layout used to draw the track), then animate a small train along that path, pausing at each terminal it consumes.
- When the parser calls a rule, show that rule's diagram as a new card below the current one and let the train continue there; when the rule returns, close the card. This turns the call stack into something you can see.
- Grow a parse tree beside the diagrams as tokens are consumed, and on a syntax error, make the train jump the tracks at the bad token and say what was expected.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a JSON grammar, computing FIRST sets so the parser works from the grammar alone, or evaluating each subtree as it completes.