唐突にコンパイラを作ることにした。 記述言語は Ruby でコンパイル対象言語はC♭ (C フラットと読め。C のサブセット)。 ターゲットマシンは ix86/Linux のはずだけど、 とりあえずはメインマシンが AMD64 なので AMD64 で行ってみた。
~/c/cflat % cat test/hello.cb aamine@serenade int main(int argc, char **argv) { printf("Hello, World!\n"); return 0; } ~/c/cflat % ruby -I./lib bin/cbc test/hello.cb aamine@serenade ~/c/cflat % ./hello aamine@serenade Hello, World! ~/c/cflat % file hello aamine@serenade hello: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.0, dynamically linked (uses shared libs), not stripped
Hello, World! (だけ) はコンパイルできるようになった。 次は式のコンパイルを真面目にやろうかな。 レジスタアロケーションは大変なので後回しにして、 とりあえずはスタック使いまくりでやってみよう。
(03:42)
まだ Racc の動的パーサ生成について考え中。
うーむ。やっぱりシンボルの連接には Java の某パーサジェネレータみたいにメソッド呼び出しを使うのがいいかもなあ。
g.defvar = g.type . IDENT . option(g.initval) . char(';') {....}
見ためはちょっとスッキリしたかなあ。 それに instance_eval しなくて済む。 しかし option とか many がちょっと浮く感じがしないでもない。 「g.」をどこに入れたらいいのかわかりにくい気もする。うーん。むずい。
いっそのこと文字列で書くというのはどうかねえ。
g.defvar = _("type IDENT [initval] ';'") {....}
スッキリしてはいるのだが。いるのだが……。 何か大切なものを失っているような気がする。 それにこれって埋め込みアクションが書きにくいし。
いやそんなことない。 連接の演算子を導入すればいいんだ。 それならこう書ける。
g.scope = _ { push_scope } + _('defvar* stmts') { pop_scope; .... }
見ためがイマイチだけど、 どうせ埋め込みアクションなんて滅多に使わないんだからいいか。
結論としては、まだ決心つかず。 なんかいい方法ないっすかね。
(03:56)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
文字列にするのがアリなら、Rubyの文法に手を入れてしまうという禁じ手も・・・。
いやー、それはさすがに禁じ手すぎるでしょう。
そもそも自分で文法を作る気なら元の Racc で
よかったわけですし。