libjit, GNU lightning,
Lexing & parsing are not the main work of a compiler or an interpreter. They are the simple parts. A compiler is mostly transforming (very often in several passes) some internal representations (in particular Abstract Syntax Trees, but not only them) of the source code that it is compiling. An interpreter is often transforming some internal representations, then traversing others (e.g. some bytecode, or some normalized AST). Play with GCC's
-fdump-tree-all option, and perhaps with MELT (a Lisp-like DSL to inspect and/or transform GCC internal representations). The semantics of your programming language matters more than syntax.
An important part is memory management. Do you want a garbage collector (it is a core part of your semantics)? What about typing (static or dynamic) & type inference? Do you handle tail-calls? Do you want homoiconicity? metaprogramming? Do you want closures (they most often need a GC)? Consider Boehm's conservative GC, and/or read the GC handbook.
Bootstrapping compilers is important. See also this and the references I gave there. Read also this & that answers explaining technical & practical details (and should heal your headache about "Haskell written in Haskell", "Ocaml written in Ocaml", "MELT written in MELT", "CAIA written in CAIA", "GCC or Clang/LLVM written in C++").
Also, if you know none of them, play with Ocaml, or Common Lisp, or Haskell, or Scheme (see also SICP). Read Scott's book on Programming Language Pragmatics and Queinnec's book on Lisp In Small Pieces and Pitrat's book Artificial Beings, the conscience of a conscious machine (and blog here).
Be sure to make your language implementation some free software (on http://github.com/ you'll find many other language implementations - e.g. compilers or interpreters).