Зачем нужен отдельный синтаксис для препроцессора?
Зачем нужен отдельный синтаксис для препроцессора
Затем, что препроцессор -- это отдельная программа с отдельным языком? Внутри препроцессируемого файла может быть что угодно, не обязательно код на С или С++. Так, например, linux препроцессирует скрипты линковщика перед тем как использовать их. И исходники написанные на ассемблере, хотя у ассемблера есть собственные макросы, директивы для включения файлов и условной компиляции.
Не зачем, а почему. Так получилось. В те времена, когда C созадавался, технологии были не настолько развиты. Первый компилятор даже, по-моему, и код-то оптимизировать особо не мог. Предложенная вами compile-time директива слишком сложна. Даже в C++ что-то подобное завезли только совсем недавно.

Когда понадобилось на этапе компиляции что-то менять - единственное дастаточно простое и хорошо работающее решение было использовать вот такой тупой препроцессор - без разбора всего синтаксиса Си, а используя максимально простой синтаксис.

Еще одна причина - это кросс-платформенный код. Ну вот вызов какой-то функции winapi просто не скомпилируется под linux, потому что ее там тупо нет. Значит надо сказать компилятору вот тот кусок вообще игнорировать. Если это делается на том же этапе, что и сама компиляция, да и с тем же синтакисом, то возникает проблема - в синтаксисе-то ошибка под linux. Как-то разбираться, что эта ошибка не критичская и весь кусок кода можно тупо выкинуть - это компилятору сложно, да и опасно это. Поэтому нужен именно какой-то предварительный этап, который не может использовать тот же самый синтаксис.