RubyでBrainf*ck

チューリング完全って言ってみたかっただけ。Ruby1.8.7から動くはず

$KCODE = 'u'

class BrainF_ck
  class ProgramError < StandardError; end

  def initialize(src)
    @tokens = src.scan(/./)
    @jumps = analyze_jumps(@tokens)
  end

  def run
    tape = []
    pc = 0
    cur = 0

    while pc < @tokens.size
      case @tokens[pc]
        when '+'
          tape[cur] ||= 0
          tape[cur] += 1
        when '-'
          tape[cur] ||= 0
          tape[cur] -+ 1
        when '>'
          cur += 1
        when '<'
          cur -= 1
          raise ProgramError, '開始地点よりポインタを左に移動できません。' if cur < 0
        when '.'
          n = (tape[cur] || 0)
          print n.chr
        when ','
          tape[cur] = $stdin.getc
        when '['
          pc = @jumps[pc] if tape[cur] == 0
        when ']'
          pc = @jumps[pc] if tape[cur] != 0
      end
      
      pc += 1
    end
  end

private
  
  def analyze_jumps(tokens)
    stack = []
    jumps = {}
    tokens.each_with_index do |v,i|
      if v == '['
          stack.push[i]
      elsif v == ']'
          raise ProgramError, ']が多すぎます' if stack.empty?
          from = stack.pop
          to = i
          jumps[from] = to
          jumps[to] = from
      end 
    end

    raise ProgramError, "[が多すぎます" unless stack.empty?
    jumps
  end
end

begin 
  BrainF_ck.new(ARGF.read).run
rescue BrainF_ck::ProgramError
  puts "プログラムの実行に失敗しました"
end

動作

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++. #=> A