こんにちは、高木です。
以前、PHPでC言語の列挙体を自動生成しました。そのときは列挙定数の文字列化までやりましたが、今回は文字列化は割愛して、列挙体の生成だけを行うことにします。
これまでも関数や構造体を生成するコードを、C++対応するために拡張してきました。今回も同じ要領で拡張していきます。
まずは拡張した列挙体を定義する配列から見ていきます。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php $direction_type = [ 'name' => 'direction_t', 'typedef' => false, 'class' => true, 'underlying_type' => 'int', 'type' => [ 'upward' => '↑', 'rightward' => '→', 'downward' => '↓', 'leftward' => '←', 'none' => [ -1, '無効値' ], ], ]; ?> |
大体は構造体のときの配列と同じなんですが、キー’template’はありません。また、キー’class’をtrueにするとスコープを持つ列挙型を生成することができます。キー’underlying_type’を指定すると基底型を指定することができます。
列挙定数にはコメントを付けられるように変更しました。以前はキーが整数かどうかで列挙定数の値を指定できるかどうかを決めていたのですが、今回はキーは必ず文字列にして、値が配列かどうかで判断するように変更しました。
それでは、この配列を受け取って列挙型を生成するPHPのコードを見ていきましょう。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?php function make_enumeration(array $info): string { $r = 'enum '; // スコープ付きにする。 if (array_key_exists('class', $info)) $r .= 'class '; // typedefを付けるかどうか if ($info['typedef']) $r = "typedef $r "; else $r .= "{$info['name']} "; // 基底型の指定 if (array_key_exists('underlying_type', $info)) $r .= ": {$info['underlying_type']} "; $r .= '{' . PHP_EOL; // 列挙定数の生成 foreach ($info['type'] as $key => $value) { if (is_array($value)) $r .= " $key = {$value[0]}, // {$value[1]}" . PHP_EOL; else $r .= " $key // $value" . PHP_EOL; } $r .= '}'; // typedef名 if ($info['typedef']) $r .= " {$info['name']}"; $r .= ';' . PHP_EOL; return $r; } ?> |
例によってエラー処理は省略しています。キー’typedef’とキー’class’は排他的でなければなりませんが、そのチェックもやっていません。
このmake_enumeration関数に先ほどの$direction_typeを渡すと次のような列挙体が生成されます。
0 1 2 3 4 5 6 7 8 |
enum class direction_t : int { upward // ↑ rightward // → downward // ↓ leftward // ← none = -1, // 無効値 }; |
まだまだ改善の余地はありそうですが、これで列挙体の生成に関してもC++対応することができました。