Compilers
Expression Parser Explorer
Type an expression and watch the tokens, the recursive-descent call stack and the AST.
Free 10-chapter course · C++20 · x86-64 · NASM · Docker
Build a compiler in C++ for Si, a small programming language targeting Linux x86-64. The series takes you from language design and tokenisation through parsing, type checking, intermediate representation, assembly generation, and optimisation.
The project connects a C++ compiler, a small assembly runtime, and a command-line toolchain. Together, they translate Si programs such as this one into executable code.
The example calls a function, multiplies two integers, and prints 42. Supporting it requires the compiler to recognise the source text, check its meaning, generate
instructions, and link the program with the runtime.
fn multiply(a: int, b: int): int {
return a * b;
}
fn main(): int {
let answer: int = multiply(6, 7);
out(answer);
return 0;
} Design a language, then lex, parse, check and compile it to native Linux x86-64 programs.
Each chapter extends the same project, with explanations, implementation code, and tests. Follow the chapters in order to build the complete compiler, or jump to the stage you want to understand.
Learn how a compiler transforms source code into machine code through lexing, parsing, semantic analysis, IR, optimisation and x86-64 code generation.
Design a small statically typed C-style programming language from scratch, including its syntax, types and grammar, then build its compiler in C++ with CMake and Docker.
Build a lexer in C++ that converts source code into tokens, recognises keywords and operators, applies maximum munch, and reports useful errors.
Build a recursive descent parser in C++ that converts lexer tokens into an AST, handles operator precedence, reports syntax errors, and runs CTest tests.
Learn semantic analysis in a compiler by building symbol tables, nested scopes and static type checking in C++, with diagnostics and CTest tests.
Build an intermediate representation in C++. Lower a checked AST into three-address-style instructions with temporaries, variables, basic blocks, branches, loops and function calls.
Build a compiler backend in C++ that translates checked IR into x86-64 NASM assembly with stack frames, arithmetic operations and native Linux executables.
Add System V AMD64 function calls to a C++ compiler with x86-64 argument registers, stack alignment, return values, a NASM runtime and ELF64 linking.
Implement compiler control flow in x86-64 assembly by lowering IR comparisons, conditional branches, if/else statements and while loops.
Build an IR optimiser in C++ with constant folding, branch simplification, unreachable-code removal and dead code elimination while preserving behaviour.
The series page, From Source to Machine Code , has the same chapters with a topic index.
Want the background first? The Compilers learning path puts this project in order with the chapters and explorers that lead up to it.
The versions the series' code was last tested with.
Each chapter's code is on its own branch, so what you check out matches what you read.
Drive the hardest part of the project yourself before, or after, you implement it.
Compilers
Type an expression and watch the tokens, the recursive-descent call stack and the AST.
Si, a small statically typed, C-style language designed in chapter 2 for this series. It has typed variables, arithmetic, functions, conditions, loops and output: enough to write real programs while keeping every stage of the compiler small enough to understand and test.
No. Assembly concepts are introduced when the project reaches code generation. If you want a head start, the x86-64 Assembly Hello World guide walks through assembling and linking a first NASM program.
NASM assembly for Linux x86-64. NASM and the system linker turn that output, together with a small assembly runtime, into a native executable you can run.
Yes. The series uses a Docker image based on Ubuntu 24.04 as its development environment, so the compiler, NASM and the linker run inside Linux regardless of the host system.
In the Si compiler repository on GitHub. Every implementation chapter links to its own branch, so the code you check out matches the listings in the chapter you are reading.
Written by the engineers behind BIOS Confessions. 10 of 10 chapters are published, and all of them are free.
Begin with Chapter 1