如何在C / C ++源代码中揭示typedef?

时间:2013-02-11 10:30:49

标签: c++ c parsing typedef abstract-syntax-tree

我想用我的原始解析器解析C / C ++代码以获得ast树。

但它不支持macro和typedef。

可以借助gcc选项在任何C / C ++项目中揭示宏定义。 之后,我自己的解析器能够处理C / C ++ - 代码,但仅限于以下情况,如果其中没有typedef。

所以,我想以某种方式摆脱typedef。但我不知道,我该怎么做。

我想替换重新定义的类型名称,例如:

typedef char CHAR;
typedef int& INT;
INT a;
CHAR b;

原件:

int &a;
char b;

结果,我想获得相同的源,但是使用原始类型,没有typedef。

我想,这对编译器来说非常简单,但不适合学生的项目。 :)

据我所知,g ++的DECL_ORIGINAL_TYPE(TYPE_NAME(t))指向具有原始对象类型的树节点。 但我真的不想深入研究g ++来源,以便根据我的要求采用它。

那么,推出typedef最简单的方法是什么?

非常感谢任何帮助。

编辑:

GCCXML的解决方案非常好,但我仍然不明白,如何获得 来自它的XML表示的C / C ++代码。你能解释一下,我该怎么做才能转换XML:

(an example from http://www.gccxml.org/HTML/example1out.html)

<?xml version="1.0"?>
<GCC_XML>
  <Namespace id="_1" name="::" members="_2 _3 _4 "/>
  <Function id="_2" name="main" returns="_5" context="_1" location="f0:8"/>
  <Function id="_3" name="a_function" returns="_5" context="_1" location="f0:4">
    <Argument name="f" type="_6"/>
    <Argument name="e" type="_4"/>
  </Function>
  <Struct id="_4" name="EmptyClass" context="_1" location="f0:1" members="_7 _8 " bases=""/>
  <FundamentalType id="_5" name="int"/>
  <FundamentalType id="_6" name="float"/>
  <Constructor id="_7" name="EmptyClass" context="_4" location="f0:1">
    <Argument name="_ctor_arg" type="_9"/>
  </Constructor>
  <Constructor id="_8" name="EmptyClass" context="_4" location="f0:1"/>
  <ReferenceType id="_9" type="_4c"/>
  <File id="f0" name="example1.cxx"/>
</GCC_XML>

回到C / C ++:

(an example from http://www.gccxml.org/HTML/example1in.html)

struct EmptyClass {};

int a_function(float f, EmptyClass e)
{
}

int main(void)
{
  return 0;
}

你能解释一下吗?

4 个答案:

答案 0 :(得分:3)

因为类型是一个很复杂的论点,我建议使用GCCXML。它是一个从具体源生成抽象语法树的前端。我用它来生成Prolog / OpenGL接口。如果你想充分利用它,你需要一个好的XML阅读器(SWI-Prolog,它真的很擅长)。

修改

以下微文件x.c

typedef struct A {
  int X, Y;
} T;

T v[100];

处理
gccxml -fxml=x.xml x.c

在x.xml(以及许多其他语句)中生成以下xml语句

...
<Variable id="_3" name="v" type="_141" context="_1" location="f0:5" file="f0" line="5"/>
...
<Struct id="_139" name="A" context="_1" mangled="1A" demangled="A" location="f0:1" file="f0" line="1" artificial="1" size="64" align="32" members="_160 _161 _162 _163 _164 _165 " bases=""/>
<Typedef id="_140" name="T" type="_139" context="_1" location="f0:3" file="f0" line="3"/>
<ArrayType id="_141" min="0" max="99u" type="_140" size="6400" align="32"/>
...
<Field id="_160" name="X" type="_147" offset="0" context="_139" access="public" location="f0:2" file="f0" line="2"/>
<Field id="_161" name="Y" type="_147" offset="32" context="_139" access="public" location="f0:2" file="f0" line="2"/>
<Destructor id="_162" name="A" artificial="1" throw="" context="_139" access="public" mangled="_ZN1AD1Ev *INTERNAL* " demangled="A::~A()" location="f0:1" file="f0" line="1" endline="1" inline="1">
</Destructor>

您可以看到在type =“...”符号链后面,您可以重建分配给typedef的类型。

答案 1 :(得分:0)

对于解析宏,你可以使用gcc预处理器cpp,它打印到stdout预处理代码。 不幸的是,你的typedef不是宏,所以你需要自己处理它们。

答案 2 :(得分:0)

在我看来,你正在翻译阶段。与注释替换相比,Typedef替换似乎很容易。您的程序是否将以下内容视为注释?如果没有,那么我建议在尝试3&amp; 4之前回到翻译阶段1和2。

// this is a basic comment
/* this is another basic comment */

// this is a slightly\
   less basic comment
/* this is a slightly
 * less basic comment */

/??/
*??/
c??/
o??/
m??/
m??/
e??/
n??/
t??/
*??/
/

答案 3 :(得分:-1)

解析C ++非常困难,需要递归下降解析器。我建议您使用@CapelliC提出的GCCXML,或者作为更好的维护替代方案,使用libclang。甚至存在Python绑定,这使得它的使用变得更加简单。