https://ru.wikipedia.org/wiki/Препроцессор
https://en.wikipedia.org/wiki/C_preprocessor

Preprocessing is defined by the first four (of eight) phases of translation specified in the C Standard.
- Trigraph replacement: The preprocessor replaces trigraph sequences with the characters they represent.
- Line splicing: Physical source lines that are continued with escaped newline sequences are spliced to form logical lines.
- Tokenization: The preprocessor breaks the result into preprocessing tokens and whitespace. It replaces comments with whitespace.
- Macro expansion and directive handling: Preprocessing directive lines, including file inclusion and conditional compilation, are executed. The preprocessor simultaneously expands macros and, in the 1999 version of the C standard,[clarification needed] handles _Pragma operators.

не вижу тут, как обрабатываются комментарии и куда деваются #pragma - директивы (как они управляют компилятором?).
мне препроцессор был бы удобен для того, чтобы избавится от комментариев и директив типа include перед тем как начать основную компиляцию.

Комментарии с одной стороны нельзя вырезать в препроцессоре (потому что комментарии должны сформировать в XML-документацию, а для формирования этой документации нужны данные из компилятора). А с другой стороны, вроде бы компилятор в комментариях не каждый раз разбирается (документацию-то необязательно делать).

Возникают две мысли:
- а не сделать ли обработку комментариев отдельным (третьим) синтаксисом (нет. как он данные об основной компиляции получит, отдельный такой?)
- не объединить ли препроцессор и компилятор в один синтаксис (этому мешают макроподстановки. В C# их убрали и всё у них хорошо. Однако budden против: "Язык без препроцессора мне не нравится".)

Если препроцессор не нужен, то как обрабатывать подключение разных (других) файлов, если сканер сканит только один файл ?
Парсер препроцессора обработает директиву включения и на выход вместо ней зачитает подключаемый файл (а в остальном выдаст исходный).

Зачем выдавать текст, если можно выдавать лексические токены?
Но почему-то интерфейса для соединения в цепочку двух парсеров никто не придумывает (то есть один парсер должен выглядеть для другого как сканер)
В простых случаях директиву препроцессора распознавать на уровне сканера.

А можно не лексические токены выдавать, а узлы AST между собой склеивать.