Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env ruby
- require 'optparse'
- options = Hash.new(false)
- option_parser = OptionParser.new do |opts|
- opts.banner = "Usage: bf.rb [options] <bf_file_or_string>"
- opts.on '-t', '--[no-]timing', 'Track compilation and execution time' do |v|
- options[:timing] = v
- end
- opts.on '-e', '--echo', 'Echo input file' do |v|
- options[:echo] = v
- end
- opts.on '-c', '--compiled', 'Echo generated Ruby code' do |v|
- options[:compiled] = v
- end
- opts.on '-o', '--optimize', 'Use experimental optimizations' do |v|
- options[:optimize] = v
- puts "Warning: The option --optimize is not yet supported\n"
- end
- opts.on '-d', '--debug', 'Enable debug mode' do |v|
- options[:debug] = v
- end
- opts.on '-i', '--input=INPUT', 'Use given input string instead of STDIN' do |v|
- options[:input] = v.each_byte
- end
- opts.on '--count', 'Count executed instructions' do |v|
- options[:count] = v
- end
- if ARGV.empty?
- abort(opts.help)
- end
- end.parse!
- begin
- ic = 0 if options[:count]
- t0 = Time.now if options[:timing]
- input = File.exists?(ARGV[0]) ? File.open(ARGV[0], 'r').read : ARGV[0]
- puts input if options[:echo]
- code = 'm=Hash.new(p=0);'+input.gsub(
- /./,
- '>' => 'p+=1;' + (options[:count] ? 'ic+=1;' : ''),
- '<' => 'p-=1;' + (options[:count] ? 'ic+=1;' : ''),
- '+' => 'm[p]+=1;' + (options[:count] ? 'ic+=1;' : ''),
- '-' => 'm[p]-=1;' + (options[:count] ? 'ic+=1;' : ''),
- '[' => '(' + (options[:count] ? 'ic+=1;' : ''),
- ']' => ')while((m[p]&=255)!=0);' + (options[:count] ? 'ic+=1;' : ''),
- '.' => 'putc(m[p]&=255);' + (options[:count] ? 'ic+=1;' : ''),
- ',' => options[:input] ? 'begin m[p]=options[:input].next rescue m[p]=0 end;' : 'm[p]=STDIN.getbyte.ord if !STDIN.eof;' + (options[:count] ? 'ic+=1;' : ''),
- '#' => options[:debug] ? 'print "m="+0.upto(m.keys.max).map{|i|m[i]%256}.to_s+"; p=#{p};\n";' : '',
- )
- puts code if options[:compiled]
- t1 = Time.now if options[:timing]
- print "\n"
- print "output:\n"
- eval code
- print "\n"
- t2 = Time.now if options[:timing]
- if options[:timing]
- puts "Time used:"
- puts "Compilation: " + ((t1-t0)*1000).to_s + "ms"
- puts "Execution: " + ((t2-t1)*1000).to_s + "ms"
- end
- puts "#{ic} instructions" if options[:count]
- rescue SyntaxError => e
- abort("Syntax Error - Are there unbalanced brackets?")
- rescue Interrupt => e
- abort("Interrupted")
- end
Add Comment
Please, Sign In to add comment