My graduate work on SuperC made made me way too familiar with the C preprocessor’s ins and outs, more than I ever could have imagined (or wanted). SuperC’s novel preprocessing and parsing algorithms let you parse a program without having to run the preprocessor first. Solving this challenge exposed me to interesting quirks of the preprocessor and strange usage patterns that appear in the wild. I’d like to share these and bring attention to this underrated aspect of compilers, hopefully providing insight for future language development and software tools.
Lurking between the lexer and parser, it can be hard to distinguish the preprocessor from the C language itself. For instance
#include is not part of the C language, but a preprocessing feature that basically just copies in a given file before compilation. This and the rest of the preprocessor constructs, macros (
#define) and conditional compilation (
#ifdef), are completely distinct from the C language, sharing only its lexical specification. This makes for a powerful tool that is used to augment the diminutive C language, even enabling what resemble generics, iterators, modules, and more. Continue reading “Notes on the C Preprocessor: Introduction”