寿司言語を作ってみた
マジメな記事 を書いていて休日ながら疲れてしまったので、ちょっとプログラムでも書こうと思いました。
なんかRuby gemが作りたかったので、作ってみました。
3時間ほどで完成しました。
すし言語
すしとRubyはともに日本を代表する文化であり、相性が良いに違いありません。
文法
文法 | 意味 |
---|---|
し | pointer_increment |
すし | pointer_decrement |
すすし | pointer_value_increment |
すすすし | pointer_value_decrement |
すすすすし | output |
すすすすすし | input |
すすすすすすし | jump_forward |
すすすすすすすし | jump_backward |
いわゆるBrainfu*k派生言語です。
インストール
gemにしましたが、面倒だったので rake release
はしていません。
specific_installを使って下さい。
$ gem install specific_install $ gem specific_install -l https://github.com/s2terminal/sushi_lang.git
Hello World
しすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすしすすすすしすすしすすしすすしすすしすすしすすしすすしすすすすしすすすすしすすしすすしすすしすすすすしすすすすすすしすすすしすすすすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすししすすすしすすすすすすすしすしすすすすしすすしすすしすすしすすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすすしすすすすすすしすすすしすすすすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすしすすすすしすすすすすすしすすすしすすすすすすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすし
$ cat sample/sample_script.sushi しすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすしすすすすしすすしすすしすすしすすしすすしすすしすすしすすすすしすすすすしすすしすすしすすしすすすすしすすすすすすしすすすしすすすすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすししすすすしすすすすすすすしすしすすすすしすすしすすしすすしすすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすしすすすすしすすすすすすしすすすしすすすすすすすししすすしすすしすすしすすしすすしすすしすすしすすしすすすすすすしすしすすしすすしすすしすすししすすすしすすすすすすすしすしすすしすすすすしすすすすすすしすすすしすすすすすすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすしすすすすし $ sushi_lang sample/sample_script.sushi Hello World!
実装
メインの sushi_lang/sushi_lang.rb はこんな感じ
class Sushi NETA = [ :pointer_increment, # > :pointer_decrement, # < :pointer_value_increment, # + :pointer_value_decrement, # - :output, # . :input, # , :jump_forward, # [ :jump_backward # ] ] def initialize(filename) # Compiler @source = filename @object_code = [] @jump = {} # Turing Machine @tape = [] @pointer = 0 @line = 0 end def compile File.open(@source) do |file| su_count = 0 line = 0 jump_stack = [] file.each_char{|char| case char when "す" su_count += 1 when "し" code = NETA[su_count] # jump if code == :jump_forward jump_stack.push(line) elsif code == :jump_backward left_curly_brace = jump_stack.pop @jump[line] = left_curly_brace @jump[left_curly_brace] = line end @object_code.push(code) su_count = 0 line += 1 end } end end def execute until @object_code[@line].nil? self.send(@object_code[@line]) @line += 1 end end private # ++p; def pointer_increment @pointer += 1 end # --p; def pointer_decrement @pointer -= 1 end # ++*p; def pointer_value_increment @tape[@pointer] ||= 0 @tape[@pointer] += 1 end # --*p; def pointer_value_decrement @tape[@pointer] ||= 0 @tape[@pointer] -= 1 end # putchar(*p); def output print @tape[@pointer].chr end # *p = getchar(); def input @tape[@pointer] ||= 0 @tape[@pointer] = STDIN.getc end # while (*p) { def jump_forward @line = @jump[@line] if @tape[@pointer] == 0 end # } def jump_backward @line = @jump[@line] if @tape[@pointer] != 0 end end
sendを使って全部プライベートメソッド化している所とかちょっと格好つけてみました。