A compiler is often made up of several components, one of which is a parser.
A common set of components in a compiler is:
- Lexer – break the program up into words.
- Parser – check that the syntax of the sentences are correct.
- Semantic Analysis – check that the sentences make sense.
- Optimizer – edit the sentences for brevity.
- Code generator – output something with equivalent semantic meaning using another vocabulary.
To add a little bit:
As mentioned elsewhere, small C is a recursive decent compiler that generated code as it parsed. Basically syntactical analysis, semantic analysis, and code generation in one pass. As I recall, it also lexed in the parser.
A long time ago, I wrote a C compiler (actually several: the Introl-C family for microcontrollers) that used recursive descent and did syntax and semantic checking during the parse and produced a tree representation of the program from which code was generated.
Today, I’m working on a compiler that does source -> tokens -> AST -> IR -> code, pretty much as I described above.