Lox Analyzer
()Last summer, I started reading Crafting interpreters. This book explains how to write an interpreter for a language named Lox from scratch, along with Java and code examples.
Let's be honest, I didn't read all of it. I've read most of the the first part though, which implements a tree-walk interpreter.
As I was reading, I was writing a Rust implementation of the the interpreter, which can be found here. As I'm still kind of new to Rust, it was not always simple to follow the book instructions. I still learned few things on the way, both about interpreters and about Rust.
At some point I considered doing an online tool that shows the parsing process, but didn't get to do it ... until now!
This project can be found on lox.thoughtful-fiddler.dev, and the github repository is here.
The project
This app lets you input some Lox code and parse it. The parsed view shows the 2 steps necessary for a computer to "read" code:
- The scanning process takes a simple string as an input and returns a list of tokens the language handles. These are your braces, you variable names, your numbers, your language keywords like
for
,while
, ... - The parsing process takes the resulting list of tokens and turns them into an Abstract Syntax Tree (AST). This structure represents the code as a tree that encodes the semantic of the code.
Let's say we have a foo
function being called with the "bar"
string:
foo("bar");
The parsed result for this code shows:
- There are 6 tokens:
foo
,(
,"bar"
,)
,;
andEOF
- The AST says this is a program that has 1 declaration. This declaration is an expression statement, that calls the identifier
foo
with the stringbar
as an argument.
Technology choices
The parser
As a starting point, I wanted to see if I could implement the parser quickly and without much guidance.
To minimize friction caused by the language, I picked Typescript, as it's the one I know best. I wanted to have a try at Bun too, in order to avoid the hassle of setting up a node TS project. And the setup was indeed waaaaaay smoother!
I relied on the language's formal grammar provided in the book.
With all of this, I managed to write most of the parser on a single day, which is much shorter than my first implementation. Obviously, I had to cut some corners to get there, but the final code isn't too messy.
The code for the parser can be found in src/domain
.
The web UI
The web part of the project wasn't planned at first, and I wanted it to remain to be simple.
I've curious to try the BETH stack for a while, but as I wanted to keep the project as simple as possible, I thought I'd leave HTMX out of the equation and see how far I could go with 0 frontend JS.
Here's what the final staxck looks like:
- Bun
- Elysia for the web server
- KitaJS HTML for JSX templating
- Tailwind for styling
- Fly.io to deploy