1

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

但它不支持宏和 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

4 回答 4

3

由于类型是一个很大的复杂参数,我建议使用GCCXML。它是一个从具体源生成抽象语法树的前端。我用它来生成接口 Prolog/OpenGL。如果你想好好利用它,你需要一个好的 XML 阅读器(SWI-Prolog 非常擅长这个)。

编辑

以下微文件 xc

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 的类型。

于 2013-02-11T10:37:19.153 回答
0

为了解析宏,您可以使用 gcc 预处理器 cpp,它将预处理代码打印到标准输出。不幸的是你 typedef 不是宏,所以你需要自己处理它们。

于 2013-02-11T13:31:40.910 回答
0

在我看来,您在翻译阶段是在抢先一步。与注释替换相比,Typedef 替换似乎很容易。您的程序是否将以下内容识别为注释?如果没有,那么我建议在尝试 3 和 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??/
*??/
/
于 2013-02-11T14:47:20.727 回答
-1

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

于 2013-02-11T13:32:22.003 回答