I've been programming as a consultant for years, and I adore my work, which involves a lot of object-oriented analysis and design of software systems using managed languages (ie. software engineering). But I'd like to get a doctorate eventually, and it bothers me that I never really "got" Computer Science theory. In university I only did marginally well in those courses because the way they were taught did not work for me. I learn by observing application of concepts, not rote memorisation.
An example of where I've overcome such a barrier before - I had a horrible first year. The professor (who I now know was barely qualified and an incompetent teacher) started with C++, teaching us procedural programming. Technically I'd learned what an object was, but it wasn't until I saw the application of object-oriented analysis and design (with design patterns and other structures such as linked lists) that I really understood what they were for.
How would I go about learning subjects such as compilers, programming language theory, and analysis of algorithms? What would be a good way to get started on those? For example, I'd like to write a compiler eventually (for fun) but I've no idea where to start. Anyone ever been in this situation? Any suggestions for tutorials, free online lecture videos or reference (Something like w3schools would be wonderful)?
(I'd like to add that browsing Stackoverflow has already taught me loads, but I'd like it to be a bit more formal : )
EDIT: Thanks all for the suggestions. I've marked an answer that works for me personally, but keep the answers coming : )