我决定查看一个标准的Haskell模块Data.List的源代码,并发现了一些有趣的东西。显然,代码首先是由C预处理器处理的,就像一堆#ifdef
建议的那样,然后才由Haskell编译器编译。然而,正如documentation中指出的那样,C预处理器对不同于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预处理器做什么呢?它是如何被“愚弄”的呢?
发布于 2017-02-12 06:02:47
如果你简单地这样说:
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/C++ //
注释行,这个问题是相似的:你不能不在下一行继续注释:不是你想要的。
https://stackoverflow.com/questions/42181630
复制相似问题