JavaScript1.6でBrainf**kもどきを実装
2008/09/10追記
gistに置いた
9713’s gists · GitHub
動機
1000speakersとかで言語の処理系を実装した人をたくさん目にしたが、
自分はまだ一つも実装していない。
これでプログラマを名乗ってていいのか?
言い訳とか
やっつけ仕事のためにArray.prototype.indexOfが使いたかったのでJavaScript1.6。
とりあえずHelloWorldだけでも動かしたかったので、
,での入力、ネストした[]でのループは未実装。
実装
メモリセル
function Cell(memory){ this._memory = memory || []; if(!this._memory.length){ this._memory.push(this); } }; Cell.prototype._memory; Cell.prototype._num = 0; Cell.prototype.incr = function(){ if(this._num < 255){ this._num++; } return this; }; Cell.prototype.decr = function(){ if(this._num > 0){ this._num--; } return this; }; Cell.prototype.ptrIncr = function(){ var mem = this._memory; var idx = mem.indexOf(this); if(idx < 0){ throw new Error(); }else if(idx < mem.length - 1){ return mem[idx + 1]; }else{ var cell = new Cell(mem); mem.push(cell); return cell; } }; Cell.prototype.ptrDecr = function(){ var mem = this._memory; var idx = this._memory.indexOf(this); if(idx < 0){ throw new Error(); }else if(idx == 0){ var cell = new Cell(mem); mem.unshift(cell); return cell; }else{ return mem[idx - 1]; } }; Cell.prototype.put = function(){ console.log(String.fromCharCode(this._num)); } Cell.prototype.getNum = function(){ return this._num; }
値と自分が属するメモリへの参照を持ってるクラス。
ポインタのインクリメント・デクリメント=配列の後・前への移動に
Array.prototype.indexOfを利用した。
前後それぞれの端まで行ってしまったら新しいCellインスタンスをくっつけていく。
なので、メモリが許す限り無限に続くメモリセルの連なりになってるはず。
ソースを読んで処理する側
function fuck(source){ var idx = 0; var curr = new Cell(); while(idx < source.length){ switch(source.charAt(idx)){ case '>': curr = curr.ptrIncr(); idx++; break; case '<': curr = curr.ptrDecr(); idx++; break; case '+': curr.incr(); idx++; break; case '-': curr.decr(); idx++; break; case ',': idx++; break; case '.': curr.put(); idx++; break; case '[': if(curr.getNum() == 0){ var end = source.indexOf(']',idx); if(end < 0){ throw new Error(); } idx = end; }else{ idx++; } break; case ']': if(curr.getNum() != 0){ var start = source.lastIndexOf('[',idx); if(start < 0){ throw new Error(); } idx = start; }else{ idx++; } break; default: throw new Error(); } } }
ちょーやっつけ。
文字列上を右に行ったり左に行ったりしてるだけ。
ブラケットの片割れを探すのをString.prototype.indexOfと
String.prototype.lastIndexOfでやってるのでネストしてると駄目。
HelloWorld
fuck('+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.');
上の関数を呼んでやるだけ。