Как линия с двумя обратными слэшами преувеличивает C препроцессор?

Я решил взглянуть на источник стандартного модуля Haskell Data.List нашел что-то интересное. Код, очевидно, сначала обрабатывается препроцессором C, как набор #ifdef, и только после этого компилируется компилятором Haskell. Однако препроцессор C не очень дружелюбен к исходному коду, отличному от самого C, как указано в документации :

Препроцессор C предназначен для использования только с исходными кодами C, С++ и Objective-C. Раньше он злоупотреблялся как обычный текстовый процессор. Он будет подавлять входные данные, которые не подчиняются C лексическим правилам. Например, апострофы будут интерпретироваться как начало символьных констант и вызвать ошибки. Кроме того, вы не можете полагаться на это, сохраняя характеристики ввода, которые не имеют существенного значения для языков C-семейства. Если Makefile предварительно обработан, все жесткие вкладки будут удалены, и Makefile не будет работать.

Но почему-то код Haskell все еще сохраняется при предварительной обработке C? Вероятно, этот фрагмент дает ключ:

#ifdef __GLASGOW_HASKELL__
import GHC.Num
import GHC.Real
import GHC.List
import GHC.Base
#endif

infix 5 \\ -- comment to fool cpp

-- -----------------------------------------------------------------------------
-- List functions

Как работает этот comment to fool cpp? Похоже на интересный хак, но я не мог ничего сделать по этой теме. В Haskell эта строка объявляет инфиксный оператор \\ с приоритетом 5, и весь текст после -- игнорируется. Но что он делает с препроцессором C и каким образом это действительно "обмануто"?

Ответы

Ответ 1

Если вы просто нажмете это:

infix 5 \\

препроцессор C выдает следующее сообщение, когда строка находится в конце файла:

infix 5 \foo.c:8:10: warning: backslash-newline at end of file

И если это не в конце файла (спасибо @commenter), он просто "съедает" одну обратную косую черту (чтобы связать ее со следующей строкой новой строки), а выход неверен на стороне Haskell:

infix 5 \

НО, если после этого вы добавите комментарий типа Haskell, Haskell проигнорирует его (очевидно!), и это не проблема для препроцессора C, так как \ не находится в конце строки:

infix 5 \\ -- comment

cpp выдает точный текст, и Haskell может анализировать интересную часть, зачищая комментарий ``.

(обратите внимание, что он никогда не действителен C, но препроцессор не против)

Примечание: проблема аналогична, если вы хотите закончить строку комментария C/С++ // с помощью \: вы не можете без нее продолжить комментарий на следующей строке: не то, что вы хотите.