Skip to content

Instantly share code, notes, and snippets.

@DuoSRX
Created July 6, 2011 20:51
Show Gist options
  • Save DuoSRX/1068293 to your computer and use it in GitHub Desktop.
Save DuoSRX/1068293 to your computer and use it in GitHub Desktop.
# Befunge-93 interpreter (http://en.wikipedia.org/wiki/Befunge)
class BefungeParser
attr_accessor :stack, :program, :px, :py, :direction, :debug_mode
Binary_ops = ['*', '+', '-', '/', '%']
def initialize(code)
@stack = []
@program = []
@px = 0
@py = 0
@direction = :right
@debug_mode = false
parse_code(code)
end
def parse_code(code)
code.each_line do |line|
@program << line.split(//).map do |op|
#convert ops to Integer if needed
op = op.to_i if op =~ /\d/
op
end
end
end
def run
string_mode = false
while get_op && get_op != '@' do
op = get_op
if debug_mode then
puts stack.inspect
puts "#{op} - #{px} - #{py} - #{direction}"
end
if string_mode then
if op == '"' then
string_mode = false
else
@stack << op
end
elsif
#TODO: move this huge block to his own funcion
case op
when Integer then @stack << op
when '#' then move_pointer
when '"' then string_mode = true
when ',' then $stdout.putc stack.pop
when '~' then @stack << $stdin.getc
when '>' then @direction = :right
when '<' then @direction = :left
when 'v' then @direction = :down
when '^' then @direction = :up
when '?' then @direction = [:right, :left, :up, :down][rand(4)-1]
when ':' then @stack << stack.last
when '!' then @stack << (stack.pop == 0 ? 1 : 0)
when '$' then @stack.pop
when 'g' then @stack << program[stack.pop][stack.pop]
when 'p' then @program[stack.pop][stack.pop] = stack.pop
when '`' then @stack << (stack.pop < stack.pop) ? 1 : 0
when '\\' then @stack += [stack.pop, stack.pop]
when *Binary_ops then @stack << stack.pop.send(op, stack.pop)
#TODO: dry this up
when '_'
val = stack.pop || 0
@direction = val == 0 ? :right : :left
when '|'
val = stack.pop || 0
@direction = val == 0 ? :down : :up
end
end
move_pointer
end
end
def move_pointer
case direction
when :right then @px += 1
when :left then @px -= 1
when :down then @py += 1
when :up then @py -= 1
end
end
def get_op
program[py][px]
end
end
code = ARGF.read
parser = BefungeParser.new(code)
parser.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment