3

我基本上需要用 Python 编写一个 C 预处理器,我已经四处搜索,因为我需要完全自定义我的代码并对正在发生的事情有一个完美的理解,所以我最好自己编写。

这就是我所在的位置:我首先解析一些头文件 (.h) 以找到 #define 关键字并使用所有已建立的指令(它们的值都有一个)建立一个字典。然后我需要根据之前找到的指令解析源文件 (.c)。我目前用来检查代码是否需要处理的机制如下:我取所有定义的名称及其值并执行一个exec("define_name = define_value")(未指定时使用值'1')。然后解决一个条件,例如#if defined DEFINE_1 || defined DEFINE_2 && (DEFINE_3 == 10) ....我删除 C 预处理器关键字以使它们生成 Python 风格的DEFINE_1 or defined DEFINE_2 and (DEFINE_3 == 10).

我最后eval(...)在那个字符串上使用来找出结果。

问题是我想知道是否有必要使用 exec / eval 并且很多人不愿意使用它们,有没有更好的解决方案?

4

1 回答 1

4

当然exec()不需要也不应该使用。我什至不确定你期望它做什么,因为它会调用一个 shell 来设置一个只存在于子 shell 中的变量。

通常,您应该避免eval()陈述,因为这很少是正确的做法。

所以,你可以做什么?

1)首先,因为可以在一个语句覆盖前一个语句的地方编写程序,所以您不能预处理 .h 文件(甚至假设#define您要查找的 's 仅在 .h 文件中第一名)并让它工作。考虑一下:

#define foo 1
#if foo == 1
this line is true!
#endif
#define foo 0

如果您预处理所有内容,您会将“foo”设置为 1,然后设置为 0,然后稍后评估 #if。你不能那样做...

2) 更常见的做法是编写一个解析器,它逐行处理并一次处理每一行的内容。这样,您甚至可以编写一个递归函数来处理#include语句,这样您就可以只从 .c 文件开始,让它拉入它正在使用的正确标题,而不是要求以其他方式指定它们。

最后,你应该得到类似的东西(在一个名为“read_file”的函数中):

# ... file opening not shown ...

for line in file:
    includematch = re.match("#include\\s+\\"(.*)\\"", line)
    if match:
        # deal with an include statement by calling a function to process it
        read_file(includematch.group(1), definedict)

    definematch = re.match("#define\\s+(\\w+)\\s+(.*)")
    if definematch:
        # deal with define statements by saving it in a dict
        definedict[match.group(1)] = definedict[match.group(2)]

    #....

显然,如果我向您展示了整个解决方案(上面的代码几乎不是漂亮的代码,但为了展示目的它很简洁),我会为您解决您的问题(家庭作业?)。但上述方法是构建整个事物的更好方法,而不是您前进的路径。

于 2013-06-05T13:09:31.607 回答