At some point ANTLR [3] looked promising, but these days I'd probably write a lexer and recursive descent parser by hand, then generate LLVM IR [4].
[1] https://github.com/westes/flex
[2] https://www.gnu.org/software/bison/
* for a subset of the full C89 spec
I decided to write my own lexer/parser/compiler it's pretty straightforward.
Sources I use(d) to program this, e.g look at resulting assembly from other compilers or look at how the AST is generated for other languages.
https://en.wikipedia.org/wiki/Recursive_descent_parser
https://en.cppreference.com/w/c/language/operator_precedence
I didn't start writing C yesterday, and most of the things are just stuff I've learned over the years and seeing how other languages work and then just use what I know to try to program in a logical manner.
Also I've written a implementation of a scripting language (compiler and VM) before in similar fashion.