This course explores the principles, algorithms, and data structures involved in the design and construction of compilers. Topics include finite-state machines, lexical analysis, context-free grammars, push-down parsers, LR and LALR parsers, other parsing techniques, symbol tables, error recovery, and an introduction to intermediate code generation. Students are provided a skeleton of a functioning compiler in C to which they can add functionality. Several skeletal implementations in C++ as well as a back-end interface to Jasmin are also available. As Jasmin assembles to Java Byte Code, students can develop compilers that target any platform with a Java Virtual Machine, and by the end of the course, students will have developed a compiler for a subset of C.