patternrubyMinor
Brainf**k to Ruby converter -- v2
Viewed 0 times
converterbrainfruby
Problem
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 Brainfk to Ruby converter, and the generated code looks... Well, like Brainfk, 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
Demo
Input:
Output:
```
#!/usr/bin/env ruby
class Mem < Hash
def initialize; super(0); end
def []=(i, val); super(i, val & 2
You know, I think this is the fastest I've ever pushed out an update to anything. This is Version 2 of my Brainfk to Ruby converter, and the generated code looks... Well, like Brainfk, 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 = ARGV
code = IO.read(input_file).tr('^+-<>.,[]', '')
open(output_file, File::CREAT | File::WRONLY) do |output|
output.puts +)|([.,\[\]])/)
.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) }
endDemo
Input:
++++++++[>++++[>++>+++>+++>++>+>->>+[>.>---.+++++++..+++.>>.>+.>++.Output:
```
#!/usr/bin/env ruby
class Mem < Hash
def initialize; super(0); end
def []=(i, val); super(i, val & 2
Solution
You're correct that nesting a
You can remove the capture groups from your
Like this:
Produces:
$ ruby example.rb
Minus signs: 2
Plus signs: 3
Dot!
Comma!
Comma!
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.rb
code = '--+++.,,'
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: 2
Plus signs: 3
Dot!
Comma!
Comma!
Code Snippets
# example.rb
code = '--+++.,,'
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}Context
StackExchange Code Review Q#94520, answer score: 8
Revisions (0)
No revisions yet.