Created
July 6, 2011 20:51
-
-
Save DuoSRX/1068293 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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