This course does not build one compiler in six pieces. It builds six compilers, each one the previous one with a new language feature threaded through all six phases. By December you will have written the front end six times, and that repetition is the point: the second time you add a construct you will already know which files it touches.
Lecture notes
The theory for each topic, anchored in Compilers: Principles, Techniques and Tools — with diagrams, worked examples and self-check questions. Start here.
Topic 1 — The Structure of a Compiler, and the Theory of Lexical Analysis
Why a compiler is built as a sequence of phases, what each one is responsible for, and the automata theory that makes the first phase a solved problem.
Topic 2 — Grammars, Parsing, Translation — and a Compiler End to End
Context-free grammars and the two families of parser; how attributes turn a parse into a translation; and what happens between a syntax tree and a running program.
Topic 3 — Storage, Scope, and the Run-Time Environment
Where a name lives at run time — in the data area, in a stack frame, or behind a pointer — and the calling conventions that make functions and recursion possible at all.
Topic 4 — Control Flow, Flow Graphs, and What Optimization Actually Is
Lowering structured statements to jumps; basic blocks and the flow graph; and the data-flow framework that makes optimization something you can reason about rather than guess at.
Topic 5 — Decisions, Ambiguity, and Generating Code for Two Machines
The dangling else and how LR parsers resolve it; short-circuit code and backpatching; three ways to compile a switch; and what retargeting a compiler actually costs.
Topic 6 — Measuring, Documenting, and Knowing the Limits of What You Built
No new syntax. What separates a project from a piece of engineering: honest measurement, an accurate account of the limits, and knowing what a production compiler does that yours does not.
Reference
The toolchain →
Tutorials for the four tools this course runs on: make, Git and GitHub, flex, and bison. Start here in week 1.
Grammar reference →
The language as it grows across the six topics, in BNF, with the precedence table and the differences from C.
Schedule
Each topic page collects that topic's class activities, starter code and assignment description.
| Topic | Weeks | Dates | In class | Project | Due | |
|---|---|---|---|---|---|---|
| Topic 1 | Compiler Design Phases | Week 1 | Sep 8 – Sep 13, 2026 | activities | Project 1 | Sep 13, 2026 |
| Topic 2 | Compiler for a Starter Language | Weeks 2–5 | Sep 14 – Oct 11, 2026 | activities | Project 2 | Oct 11, 2026 |
| Topic 3 | Compiling Complex Variables and Functions | Weeks 6–8 | Oct 12 – Nov 1, 2026 | activities | Project 3 | Nov 1, 2026 |
| Topic 4 | Compiling Loops | Weeks 9–11 | Nov 2 – Nov 22, 2026 | activities | Project 4 | Nov 22, 2026 |
| Topic 5 | Compiling Control Flow — Decisions | Weeks 12–14 | Nov 23 – Dec 13, 2026 | activities | Project 5 | Dec 13, 2026 |
| Topic 6 | Compiler Design and Implementation | Week 15 | Dec 14 – Dec 20, 2026 | activities | Project 6 | Dec 20, 2026 |
How the code is organized
student/topic-N/— the compiler you start from for that topic. It is the PREVIOUS milestone, complete and working, with this topic's work removed and replaced by numbered TODOs. Build it before you change anything: it compiles and runs as handed to you.student/topic-N/compiler/tests/— the programs your compiler has to pass, each stating its expected output in a header comment. They are cumulative: Topic 5 must still pass the Topic 3 tests.- The grammar reference — the language as it grows across the six topics, in BNF.
Every folder builds with make and self-tests with make test. You need flex, bison, gcc, and SPIM or QtSPIM to run the generated MIPS.