Introduction to Compiler Design is a textbook is intended for an introductory course on compiler design, suitable for use in an undergraduate programme in computer science or related fields.
The book presents techniques for making realistic, though non-optimising compilers for simple programming languages using methods that are close to those used in "real" compilers, albeit slightly simplified in places for presentation purposes. All phases required for translating a high-level language to machine language is covered, including lexing, parsing, intermediate-code generation, machine-code generation and register allocation. Interpretation is covered briefly.
The book aims to be neutral with respect to implementation languages, so algorithms are presented in pseudo-code rather than in any specific programming language, and suggestions for implementation in several different language flavours are in many cases given. The techniques are illustrated with examples and exercises.
The author has taught compiler design at the University of Copenhagen for over a decade, and the book is based on material used in the undergraduate compiler design course there.
Additional material for use with this book is available below. More material will be added later.
Introduction to Compiler Design is published by Springer Verlag, and is now in its second edition.
Read more at Springer Verlag's page.
Material for the first edition can be found here.
Cosmin Oancea from DIKU, who uses the book in a course, has made his slides available. They do not follow the book exactly, and there are some assignment-specific material, but they may be a good starting point for making your own.
There is an overweight of solutions to exercises from Chapters 1--2. This might be remedied later.
Only significant misprints are reported, misspellings and such are left for the reader to figure out.
= Nullable(R) \/ (false /\ Nullable(T) /\ false) = Nullable(R)
parseR, two occurences of
tNode('R'should be replaced by
let go s = table[top(stack),n] ; push(n,stack) ; push(s,stack)
push(n,stack) ; push(s,stack) where table[top(stack),n] = go s
as the stack has to be read before pushing n.
Alternatively, just wrap the two pushes in parentheses, so it is clear that the where-clause covers both.