Rruuubbyyyy作った
ennnndをFeature Requestしたら思いの外反響が大きいというか、特に外国人にはクソミソに言われまくりで、その中の一人は Rruuubbyyyy とか言ってた。で、意味はわかんないけどたぶん作って欲しいんだなと思ったので、とりあえずその Rruuubbyyyy を作ってみた。
サンプルコード
moooodddulee Foo cclllasss Bar dddeeefff xyzzy iiffff tttrrueee ttheeen p :hheeellooo endd eeend ennndd eeendd Foo::Bar.new.xyzzy
mooooddduleeとかcclllasssとかがmoduleとかclassになる。要するにキーワード内で連続する文字が無視される。ennnndと書いてもend1つ分にしか見なされないことに注意。
実行結果
$ ./ruby rrruby.rb :hheeellooo
ん、動いた。
実装
つまり、前回学んだことをさっそく使ってみたと。
--- ../ruby-1.9.2-p290/parse.y 2011-07-03 21:24:13.000000000 +0900 +++ parse.y 2011-07-23 23:46:52.000000000 +0900 @@ -7755,6 +7755,50 @@ /* See if it is a reserved word. */ kw = rb_reserved_word(tok(), toklen()); + if (!kw) { + int i; + char *tmpbuf = ALLOC_N(char, toklen()); + int tmplen; + char prev = tokenbuf[0]; + + tmpbuf[0] = prev; + tmplen = 1; + for (i = 1; i < toklen(); i++) { + char cur = tokenbuf[i]; + if (prev != cur) { + tmpbuf[tmplen++] = cur; + } + prev = cur; + } + if (tmplen < toklen()) { + tmpbuf[tmplen] = '\0'; + kw = rb_reserved_word(tmpbuf, tmplen); + if (kw) { + tokidx = tmplen; + for (i = 0; i < tokidx; i++) { + tokenbuf[i] = tmpbuf[i]; + } + tokfix(); + } + else if (tmplen == 4 && strncmp(tmpbuf, "clas", 4) == 0) { + strcpy(tokenbuf, "class"); + tokidx = 5; + kw = rb_reserved_word(tok(), toklen()); + } + else if (tmplen == 4 && strncmp(tmpbuf, "unles", 5) == 0) { + strcpy(tokenbuf, "unless"); + tokidx = 6; + kw = rb_reserved_word(tok(), toklen()); + } + else if (tmplen == 3 && strncmp(tmpbuf, "end", 3) == 0) { + xfree(tmpbuf); + lex_state = EXPR_END; + return keyword_end; + } + } + xfree(tmpbuf); + } + if (kw) { enum lex_state_e state = lex_state; lex_state = kw->state;
また一歩、野望に近づいた。
なかだ師匠(左)と遠藤師匠(右)に感謝。
おまけ
class Object def method_missing(name, *args, &block) new_name = name.gsub /(.)\1+/, '\1' raise NoMethodErrror.new(name) if name == new_name send new_name, *args, &block end end
こういうのをprelude.rbに追加しておけばメソッド名も同じように引き伸ばせるはず。試してないけど。