gcc - yyparse (declspecs_ts)
では declspecs ができるまで追ってみる。 declspecs_ts は
declspecs_ts: declspecs_nosc_ts_nosa_noea | declspecs_nosc_ts_nosa_ea | declspecs_nosc_ts_sa_noea | declspecs_nosc_ts_sa_ea | declspecs_sc_ts_nosa_noea | declspecs_sc_ts_nosa_ea | declspecs_sc_ts_sa_noea | declspecs_sc_ts_sa_ea ;
とのことで、これらも複雑に似たようなものを呼び出し続ける。 C 言語は型に const だのがべたべたとくっつくのでややこしくなっているのだろう。詳しく見てもあまり本質的では無いだろうから、これらの中で頻繁に呼ばれている tree_cons を読む。 cons は lisp の cons でリストを接続する役割を果たすはず。ここでは新しい node を tree_list 型で作って、
TREE_CHAIN (node) = chain; TREE_PURPOSE (node) = purpose; TREE_VALUE (node) = value;
などとしてメンバに代入している。(例えば TREE_CHAIN(node) は node->chain に化ける)
declspec_ts によって実際にどのように型情報が収められるかどうかを調べる。以下のようなものをコンパイルして tree をダンプさせてみた。
/* declspecs.c */ static volatile const char* volatile const restrict func() {}
ダンプされたものは以下の通り。
start_function = { declspecs = @1 tree_list valu: @2 chan: @3 @2 identifier_node strg: char lngt: 4 @3 tree_list valu: @4 chan: @5 @4 identifier_node strg: const lngt: 5 @5 tree_list valu: @6 chan: @7 @6 identifier_node strg: volatile lngt: 8 @7 tree_list valu: @8 @8 identifier_node strg: static lngt: 6 declarator = @1 indirect_ref type: @2 op 0: @3 @2 tree_list valu: @4 chan: @5 @3 call_expr fn : @6 args: @7 @4 identifier_node strg: restrict lngt: 8 @5 tree_list valu: @8 chan: @9 @6 identifier_node strg: func lngt: 4 @7 tree_list @8 identifier_node strg: const lngt: 5 @9 tree_list valu: @10 @10 identifier_node strg: volatile lngt: 8 attributes = } compstmt = @1 compound_stmt line: 1
すぐに char => const => volatile => static と chain しているのが見て取れる。後置の修飾子は declarator の方に属するようだ。パーサの書きやすさのためだろうか。こちらは indirect_ref (ポインタのことだろう) => restrict => const => volatile と chain している。 declspecs_ts では purpose は使用されないようだ。