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 を使用できます。これは、前処理されたコードを stdout に出力します。残念ながら、typedef はマクロではないため、自分で処理する必要があります。

于 2013-02-11T13:31:40.910 に答える
0

あなたは翻訳段階で銃を飛ばしているように思えます。typedef 置換は、コメント置換に比べて簡単に思えます。あなたのプログラムは以下をコメントとして認識しますか? そうでない場合は、翻訳フェーズ 1 と 2 に戻ってから 3 と 4 に進むことをお勧めします。

// 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 に答える