解析C文件而不预处理它

时间:2012-05-19 21:36:18

标签: c parsing

我想对C文件进行简单分析(例如,如果你以foo为参数调用INT_TYPE宏,然后将响应转换为int*),我不想预处理文件,我只是想解析它(例如,我会有正确的行号)。

也就是说,我想从

获得
#include <a.h>

#define FOO(f)

int f() {FOO(1);}

这样的令牌列表
<include_directive value="a.h"/>
<macro name="FOO"><param name="f"/><result/></macro>
<function name="f">
    <return>int</return>
    <body>
        <macro_call name="FOO"><param>1</param></macro_call>
    </body>
</function>

无需设置包含路径等

有没有预先存在的解析器呢?我知道的所有解析器都假设C是经过预处理的。我想访问宏和实际包含说明。

3 个答案:

答案 0 :(得分:1)

我们的C Front End可以解析包含preprocesser元素的代码,可以在合理范围内执行此操作,并且仍构建可用的AST。 (是的,解析树具有精确的文件/行/列号信息)。

有许多限制,允许它处理大多数代码。在少数情况下,它无法处理,通常是对源文件进行小的,简单的更改,从而提供等效的代码来解决问题。

这是一套粗略的规则和限制:

  • #includes和#defines可以出现在声明或语句可以发生的任何地方,但不能出现在语句的中间。这些很少会引起问题。
  • 宏调用可以在表达式中发生函数调用时发生,或者可以不使用分号代替语句。跨越非格式良好的块的宏调用处理不好(任何人都感到惊讶?)。后者偶尔发生但很少发生,需要手动修改。 OP的“j(v,oid)*”示例存在问题,但在代码中这种情况很少见。
  • #if ... #endif必须是wrapped around major language concepts (nonterminals)(常量,表达式,语句,声明,函数)或此类实体的序列,或围绕某些非格式化但常见的惯用语,例如< strong> if(exp){。条件的每个臂必须包含与其他臂相同类型的句法结构。 #if缠绕随机文本作为坏评论是有问题的,但通过做出真正的评论很容易在源中修复。如果不满足这些条件,您需要修改原始源代码,通常是移动#if #elsif #else #end几个令牌。

根据我们的经验,人们可以在几个小时内修改50,000行的代码库来解决这些问题。虽然这看起来很烦人(而且确实如此),但替代方案是根本无法解析源代码,这比烦人的要糟糕得多。

您还需要的不仅仅是解析器。请参阅Life After Parsing,了解成功获取解析树后会发生什么。我们在构建符号表方面做了一些额外的工作,其中声明是使用嵌入它们的预处理器上下文记录的,从而使类型检查能够包含预处理器条件。

答案 1 :(得分:0)

您可以查看此ANTLR grammar。但是,您必须为预处理程序令牌添加规则。

答案 2 :(得分:-1)

您可以通过编写自己的解析并忽略宏扩展来处理您的具体示例。

因为FOO(1)本身可以解释为函数调用。

但是,当考虑更多案例时,解析器要困难得多。您可以参考PDF Link查找更多信息。