Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
实现C#include指令的内部处理_C_Parsing_Compiler Construction_Language Implementation - Fatal编程技术网

实现C#include指令的内部处理

实现C#include指令的内部处理,c,parsing,compiler-construction,language-implementation,C,Parsing,Compiler Construction,Language Implementation,我需要以尽可能干净的方式来实现C编译器的#include指令的功能 我只知道如何实现处理的外部部分:获取行开头的“#”字符以运行仅限预处理器的循环,并且我还知道如何收集“include”字符串以及或之间的字符串 我不知道的是实现内部处理以运行#include指令实际效果的最佳方法:扩展库头文件的完整路径(使用),但不扩展使用的头文件的完整路径。“(假设它们位于当前目录中可能更干净、更灵活,因为这样还可以正确地包含具有完整路径的源文件) 我认为我需要执行的任务是: 作为命令行参数传递给编译器的主

我需要以尽可能干净的方式来实现C编译器的
#include
指令的功能

我只知道如何实现处理的外部部分:获取行开头的
“#”
字符以运行仅限预处理器的循环,并且我还知道如何收集
“include”
字符串以及
之间的字符串

我不知道的是实现内部处理以运行#include指令实际效果的最佳方法:扩展库头文件的完整路径(使用
),但不扩展使用
的头文件的完整路径。“
(假设它们位于当前目录中可能更干净、更灵活,因为这样还可以正确地包含具有完整路径的源文件)

我认为我需要执行的任务是:

  • 作为命令行参数传递给编译器的主C文件应该像
    #include“mainfile.C”
    指令一样进行处理,以统一的方式开始编译

  • 展开包含引号的文件的路径(
    ,单引号是否至少对某些编译器有效?)

  • 将文件放在文件列表中,同时指出我们在哪一行和哪一个文件中找到了
    #include
    指令

  • 在预处理阶段,查看它是否是一个
    #include
    指令,并尝试无条件打开指定的文件,以尝试从一开始就正确获取所有文件。如果文件不存在,请不要在预处理阶段发出错误信号,只有在我们将它们标记为可用时,才确定是否应该包含它们在尝试翻译实际的C代码时,由于
    #ifdef
    #elif
    而导致ot

  • 在完成处理代码中的所有
    #includes
    后,立即处理剩余的预处理器代码,并包含完整的潜在文件集

我认为使用一堆文件是有用的,但只有在完成预处理阶段之后,并且我们已经翻译了整个代码并添加了文件(将文件索引推到源文件堆栈上的
#include
,并在源文件末尾弹出文件索引)


我认为处理代码最简单的方法是检查
#include
所指的所有文件,列出它们的列表,然后稍后只标记为可用,我将实际包含并完全处理的文件,那些满足
#ifdef
#elif
条件的文件,但为此我需要查看包含的文件整个源文件集中都有文件。

您通常在读取所有预处理器指令时对其进行处理。因此,当您看到一个
#include
时,您可以获得文件名,搜索include路径,打开文件并开始处理,无需延迟。一旦到达所包含文件的末尾,您就可以继续执行pro正在处理原始文件


类似地,对于
#if
,您读取条件并确定其为真或假。如果为假,则开始跳过输入,忽略它,直到找到匹配的
#else
#endif
。因此,如果其中有
#include
,您只需跳过它。

似乎需要删除预处理器代码要正确地知道我们是否已经执行了定义内容或包含文件之类的任务,以避免再次执行这些任务,因此确实需要对其进行解析,因为我们按照找到预处理器指令的顺序找到预处理器指令


实际的C代码可能可以按任意顺序进行分析,方法是进行多次传递,主要是传递到全局声明的内容,以便在声明之前能够使用这些内容,但需要对预处理器进行处理,以便能够有选择地定义和包含这些内容。

您在第一次和第二次访问中遇到了一个有趣的讽刺t语句.include的定义不明确:)请注意,不同的编译器对“”中的路径名的处理方式不同,尽管GNU编译器集合的流行已迫使进行了一些协调。通常,通过搜索一系列备选路径来定位
“q-char-sequence”或
包含的文件名,通常包括执行
#include
的文件位于前面,以防有多个符合条件的路径(例如,/usr/include/foo.h和/usr/include/sys/foo.h plus-Ipath,当存在路径/foo.h时,它们会找到路径/bar.h)。但是……您也可以使用
#定义标题“foo.h”之类的技术
后接
#include HEADER
,因此您可以使用pp令牌构造技术在某种程度上动态地构建路径名。这意味着通常您必须在遇到路径名时解释路径名并展开pp-tokens。这会使预处理器必须为每个源文件单独运行,而不是为单个pas运行吗s表示完整的代码?最多,它会强制编译器只识别以前声明过的内容。如果没有,则在代码序列中声明之前使用这些内容将被视为未声明。解析每个源文件的预处理器指令,而不是单个pr中的整个源代码eprocessor运行会增加编译器代码的复杂性,因为解析循环需要调用预处理器并安排它找到的内容,而不是从一开始就将其修复。如果在使用之前或之后声明了某个内容,则只运行一次预处理器本质上会丢失该内容,除非我们将整个代码的偏移量用于know是第一次申报的地方。