http://d.hatena.ne.jp/shinichiro_h/20061010#1160420878
の続きです。前回、 sed ってなにか…?という解いに対して、 sed は VM です、という回答を提示しました。 VM つーかマシン語をいじっていてめんどくさいのは、要するにレジスタなりスタック、 sed VM の場合レジスタの管理、これがめんどくさいのです。それならやるべきことは一つです。さぁ太郎君なんでしょう!?
使わなーい
そう! sed VM 向けコンパイラを書けばいいんです!というかぶっちゃけ変数さえあればいいです。メモリの使いかた(決してホールドスペースなどと呼ばないように。初心者が混乱する元です)が sed の難解さの根源なので、他はまぁみんな大人だし自分でできます。 sed の人は sed で変数をうまく扱えるライブラリを作ろうとかそんなこと考えてるみたいですが、本当に必要なのはマクロアセンブラじゃなくてコンパイラじゃないでしょうか…と。
というわけで…なの、ですが、これがヒジョーにめんどくさい。中途半端ですがまぁできた範囲で。続きは宿題です。
http://shinh.skr.jp/tmp/ssed.rb
i@u ~/wrk/bf> ruby ssed.rb hello.ssed > out.sed i@u ~/wrk/bf> echo | sed -f out.sed Hello world! Hello world! Hello Hello world!
echo | がいる理由は…まぁ sed だし。コードは以下みたいなもの。
# 代入 $h = "Hello " $w = "world!" $a = $h $a += $w # それぞれ表示する p $h p $w p $a # world! 以外はマッチするはず $h =~ /Hello/ { p $h } $w =~ /Hello/ { p $w } $a =~ /Hello/ { p $a }
生成されるコードは全部はると長いので、 $a += $w の部分だけを。
# $a += $w g s/[^@]*@\([^@]*\)@[^@]*/\1/ G s/\(.*\)\n\([^@]*\)@[^@]*@[^@]*/\2\1/ G s/\(.*\)\n[^@]*@\([^@]*\)@\([^@]*\)/\1@\2@\3/ h
こんな正規表現人間がイチイチ書けねーとわかっていただけますでしょうか。ちなみに @ を変数のセパレータにしてます。
ちなみにやる気なくなったのは私の脳内にある遠大すぎるロードマップが原因だと思います。
- sed に変数を導入 ← いまここ
- 基本的な演算を全てサポート(これはあと置換だけ作ればオッケ?)
- 同一変数を連続して使用する場合はレジスタをクリアしない
- 数値処理を言語レベルでサポート(正直こういうの飽きたよ)
- sed コンパイラ自体を sed コンパイラで生成する
- オプティマイザ
- brainfuck インタプリタが sed コンパイラによって sed スクリプトとして動くように
- sed.md (GCC のバックエンドに sed を追加)
どうでもいいですけどさっきフト気付いたことがあります。 sed で bf コンパイラ書いてわーい大文字を小文字にする echo ができたぞー と喜んでいたんですが、これで終わりだということが判明しました。
i@u ~/wrk/bf> sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ AHO aho boke boke Ahi ahi
y ってこういう目的で使うんですね!ラクにカウンタ作るためのものだと思ってたよ!