
I have the original edition of the book, which is C++ based (building a language that compiles to x86 assembly), but I see on googling that there is a newer edition that is Java-based, I can't comment upon that, but assume the overall theory and mechanics are just as good (but from the overview it seems it is not only Java-language based in implementation, but also targets the Java VM).
1. "Writing Compilers and Interpreters" by Ronald Mak 2. "Building an Optimizing Compiler" by Bob Morgan
Morgan's book is well sought after and out of print. It's one of the few books in the field for which the print edition prices keep climbing.
1. Peter John Brown. 1979. Writing Interactive Compilers and Interpreters.
2. Timothy Budd. 1987. A Little Smalltalk.
3. Ralph E. Griswold. 2000. The Icon Programming Language, 3e.
4. Pat Shaughnessy. 2013. Ruby Under a Microscope: An Illustrated Guide to Ruby Internals.
This is a new one I haven't read yet, but it looks very practical:
5. Clinton L. Jeffery. 2021. Build Your Own Programming Language: A Programmer's Guide to Designing Compilers, Interpreters, and DSLs for Solving Modern Computing Problems.
I don't know anything about this one, but people have told me they prefer the first edition:
6. Ronald Mak. 1991. Writing Compilers and Interpreters: An Applied Approach.
"the art of writing compilers and interpreters has effectively been lost"
I'm curious, how does that happen? Were the techniques used in compilers and interpreters of yore never recorded for posterity in academic papers or technical documentation?
I think I did a pretty good job in answering it, although it was a bit rambling.
The people on the standards committees for these languages are generally also the ones implementing compilers, at least at first. The ones that don't have significant overlap between the two fail. ALGOL-68 comes to mind in the past, FORTRAN-03/08 comes to mind now.
Also, there were fast Lisp compilers back then (as fast as Lisp can get, at least, and keyword "compilers" as I'm not misinterpreting the two), along with decent (eh) Smalltalk compilers: Ruby isn't that unique. An optimizing compiler for Ruby could have used many of the techniques, given that most of the bottlenecks in Ruby are the same as many Lisps. Of course, it won't map perfectly, but much of it would. (I will admit that this paragraph is written with primarily old versions of Ruby in mind, because beyond 2007 or so, when it was basically a Lisp with Smalltalk tendencies under the hood, I haven't really kept up.)
Many techniques absolutely have been lost over time, even in obvious spots, where you'd expect them to be maintained quite well; I have a folder of poorly-OCR'd, poorly-scanned ACM papers of novel, technically-interesting & fast pre-1990 compilers with significantly less downloads than citations. Academic papers aren't really where you'd expect to see "lost" techniques, but publishing is a wasteland, and most non-famous on this subject (and computers in general, partially; ever tried to find more than a handful of papers on Sun's Spring?) written between 1970 and 1990 are practically lost. The industry has the memory of a dormouse, though it might get better now that more and more things are becoming source-available.