Previous iteration.You know, I think this is the fastest I've ever pushed out an update to anything. This is Version 2 of my Brainf**k to Ruby converter, and the generated code looks... Well, like Brainf**k, converted directly to Ruby, with no attempt at making it more readable.I'm looking for any tips on making things more idiomatic, both in the generator and generated code. The nest if/cases really bug me, but I'm not quite sure how to get rid of them, especially since just two characters are blindly replaced. I'd also like advice on making it run faster.bf_to_ruby.rbinput_file, output_file = ARGVcode = IO.read(input_file).tr('^+-<>.,[]', '')open(output_file, File::CREAT | File::WRONLY) do |output|  output.puts <<-END.gsub(/^[ \t]*\||\s*#@.*$/, '')    |#!/usr/bin/env ruby    |class Mem < Hash #@ `Hash` because it's more memory-efficient and allows negative values.    |  def initialize; super(0); end    |  def []=(i, val); super(i, val & 255); end    |end    |data = Mem.new    |pointer = 0  END  indent_level = 0  code.scan(/(\++)|(\-+)|(<+)|(>+)|([.,\[\]])/)      .map do |string|        if string[0]          next #{'  ' * indent_level}data[pointer] += #{string[0].length}        elsif string[1]          next #{'  ' * indent_level}data[pointer] -= #{string[1].length}        elsif string[2]          next #{'  ' * indent_level}pointer -= #{string[2].length}        elsif string[3]          next #{'  ' * indent_level}pointer += #{string[3].length}        elsif string[4]          case string[4]            when '['              ret = #{'  ' * indent_level}until data[pointer] == 0              indent_level += 1              next ret #Split it so that it's clear that indent is increased *after* the line            when ']'              indent_level -= 1              next #{'  ' * indent_level}end            when ','              next #{'  ' * indent_level}data[pointer] = $stdin.readbyte            when '.'              next #{'  ' * indent_level}putc data[pointer]          end        end      end.each { |line| output.puts(line) }endDemoInput:++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.Output:#!/usr/bin/env rubyclass Mem < Hash  def initialize; super(0); end  def []=(i, val); super(i, val & 255); endenddata = Mem.newpointer = 0data[pointer] += 8until data[pointer] == 0  pointer += 1  data[pointer] += 4  until data[pointer] == 0    pointer += 1    data[pointer] += 2    pointer += 1    data[pointer] += 3    pointer += 1    data[pointer] += 3    pointer += 1    data[pointer] += 1    pointer -= 4    data[pointer] -= 1  end  pointer += 1  data[pointer] += 1  pointer += 1  data[pointer] += 1  pointer += 1  data[pointer] -= 1  pointer += 2  data[pointer] += 1  until data[pointer] == 0    pointer -= 1  end  pointer -= 1  data[pointer] -= 1endpointer += 2putc data[pointer]pointer += 1data[pointer] -= 3putc data[pointer]data[pointer] += 7putc data[pointer]putc data[pointer]data[pointer] += 3putc data[pointer]pointer += 2putc data[pointer]pointer -= 1data[pointer] -= 1putc data[pointer]pointer -= 1putc data[pointer]data[pointer] += 3putc data[pointer]data[pointer] -= 6putc data[pointer]data[pointer] -= 8putc data[pointer]pointer += 2data[pointer] += 1putc data[pointer]pointer += 1data[pointer] += 2putc data[pointer]You'll notice that the generated code is nearly the same as the last version's generated code, but with a lot of duplicate lines merged and indenting.
Brainf**k to Ruby converter -- v2
ruby;converting;brainfuck
You're correct that nesting a case in an elsif ladder is a bit clunky here, but the two things that jump out at me as making the code difficult to comprehend are: 1) we have to know everything that's going on with the Regexp passed to scan() in order to figure out the intent of the if clauses, and 2) the variable string is not a String, but an Array.You can remove the capture groups from your Regexp to just get an Array of Strings back from scan() (instead of an Array of Arrays of Strings), and figure out what exactly was matched by looking at the strings themselves - which means you don't need a nested case anymore, and makes it a little more obvious what scan() is doing without having to actually parse its argument.Like this:# example.rbcode = '--+++.,,'code.scan(/\++|\-+|[.,]/).map { |str|  case str[0]  when '+'    Plus signs: #{str.length}  when '-'    Minus signs: #{str.length}  when '.'    'Dot!'  when ','    'Comma!'  end}.each {|ll| puts ll}Produces:$ ruby example.rb Minus signs: 2Plus signs: 3Dot!Comma!Comma!