I recommend: just read and reread, commenting it as you go, until it all makes sense.
It's written in a very limited dialect of C --- most notably, it doesn't use structs --- because it compiles itself. The expression parser in particular would be clearer with structs rather than array offsets. But once you realize that's why it's so gnarly in places, it's straightforward to mentally translate.
It's a very simple design: a simple lexer with a "pull" API (next()) feeds a precedence-climbing expression parser that spits out bytecode for a simple stack machine.