Modern Compiler Implementation in ML (I'm not a fan of the C/Java versions)
If you are fluent in a mainstream OO language - Java, C#, Ruby etc
Programming Language Processors in Java: Compilers and Interpreters
( the code is in Java but can be trivially ported into any OO language )
Most compiler programming books use lex/yacc versions for lexing and parsing. Imo, this isn't a good way to learn lexing/parsing, and using recursive descent or combinator parsing approaches is (imho) the right way to begin.
If you want to know how tools like lex and yacc are built, then Holub's "Compiler Construction in C" is very comprehensive and goes into great detail about the required CS theory- (automata DFA, NFA etc).
The book seems to be out of print, but used copies are worth buying (imho)