4

我想部分解析 C 声明和/或函数定义的列表。

也就是说,我想将它拆分为子字符串,每个子字符串都包含一个声明或函数定义。

然后每个声明(单独)将被传递给另一个模块(它确实包含一个完整的 C 解析器,但我不能直接调用。)

显然,我可以通过在我的程序中包含另一个完整的 C 解析器来做到这一点,但我希望避免这种情况。

到目前为止,我遇到的棘手案例涉及是否'}'终止声明/定义的问题。例如在

int main(int ac, char **av) {return 0;}

... the'}'是一个终止符,而在

typedef struct foo {int bar;} *pfoo;

它不是。也可能有这样的病态代码:

struct {int bar;} *getFooPtr(...) { /* code... */ }

笔记

  • 请假设 C 代码在我的函数看到之前已经完全预处理。(实际上它没有,但我们有一个解决方法。)
  • 我的解析器可能会用LPeg在 Lua 中实现
4

3 回答 3

1

要在您的答案中扩展状态机以处理函数定义,请添加以下步骤:

  1. 将 fun/var 状态设置为“未知”
  2. 检查当前位置的字符
  3. 如果是;,我们已经找到了声明的结尾,并且它不是函数定义(尽管可能是函数声明)。
  4. 如果是"or ',跳转到匹配的引号,必要时跳过转义序列。
  5. 如果是(, [or {,则跳转到匹配的), ]or }(如有必要,递归跳过嵌套的括号和字符串)
  6. 如果 fun/var state 是 'function' 而我们只是跳过了{.. },我们已经找到了声明的结尾,它是一个函数定义
  7. 如果 fun/var 状态为 'unknown' 而我们只是跳过了(.. ),则将 fun/var 状态设置为 'function'。
  8. 如果当前 char 是=or ,,则将 fun/var 状态设置为 'not-function'。
  9. 前进到下一个输入字符,然后返回 2。

当然,这只适用于预处理后的代码——如果你有宏可以做各种尚未扩展的奇怪事情,那么所有的赌注都没有了。

于 2012-11-26T21:20:14.773 回答
1

据我所知,以下解决方案仅适用于声明(也就是说,函数定义必须保留在本节之外,或者在它们之后添加分号可能是一种解决方法:)

  1. 检查当前位置的字符
  2. 如果是;,我们已经找到了声明的结尾。
  3. 如果是"or ',跳转到匹配的引号,必要时跳过转义序列。
  4. 如果是(, [or {,则跳转到匹配的), ]or }(如有必要,递归跳过嵌套的括号和字符串)
  5. 否则,前进到下一个输入字符并转到步骤 1。

如果这证明不令人满意,我将切换到clang解析器。

于 2012-11-26T21:06:17.043 回答
0

您最好的选择是提取与声明相关的 C 语法部分,并为此构建解析器或它的缩写版本。类似地,你想要函数体的语法,以类似的方式缩写,所以你可以跳过它们。

这可能会为声明生成一个相对可靠的解析器。

不幸的是,您不太可能掌握可靠的 C 语法。ANSI 标准中的那个不是编译器实际使用的那个。每个供应商都在他们的编译器中添加了好东西和复杂性(例如,MS C 的 declspecs 等)。

预处理器运行的假设很有趣。您将在哪里获得预处理器配置?(例如,编译器命令行定义、包含路径、编译指示设置等)?这比看起来更难,因为每个开发环境都定义了不同的方法来设置预处理器条件。

如果您愿意接受偶尔出现的错误,那么任何启发式都是有效的候选者,以它在重要客户代码上出错的频率为模。这也意味着您可以处理未处理的代码,完全避免预处理器问题。

于 2012-11-26T22:00:09.147 回答