Remember, a compiler is itself a program. it parses a text file, enforces some grammer, and converts it to some other kind of file. You can write a compiler FOR any language IN any language. The trick here is how you get started.
A simple, contrived, (and probably not very good) example would be a made-up language that does arithmetic, call the language EasyMath.
EasyMath is a language that supports addition, subtraction and multiplication.
on your first pass, you write a complier using Java, for example. All this compiler handles is addition and inverting a bit
pattern. you now have a compiler that can handle any EasyMath program, as long as it ONLY has addition or bit inversion in it.
ok, so now what? well, subtraction can be defined in terms of addition. you negate the number and add. How do you negate a number? invert the bits and add 1. AHA!!! my first compiler can handle that. Multiplication can also be defined in terms of addition. my first compiler can handle that.
so, now i write a compiler, in EasyMath, that converts multiplication and subtraction into addition problems. i run THAT through my first compiler, and create a NEW compiler.
i now have a compiler, written in EasyMath, that can compile any EasyMath program.
does that make more sense?