Created
July 7, 2011 08:45
-
-
Save aisuii/1069116 to your computer and use it in GitHub Desktop.
ruby de brainf*ck
This file contains 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
# coding: utf-8 | |
class Memory | |
def initialize(opts = {}) | |
@memory = Hash.new{|h,k| h[k] = 0 } | |
@pointer = 0 | |
@out = opts[:out] || $stdout | |
@in = opts[:in] || $stdin | |
end | |
def forward | |
@pointer += 1 | |
end | |
def backward | |
@pointer -= 1 | |
end | |
def inc | |
@memory[@pointer] += 1 | |
end | |
def dec | |
@memory[@pointer] -= 1 | |
end | |
def output | |
@out.write dump | |
end | |
def input | |
@memory[@pointer] = @in.read(1) | |
end | |
def raw | |
@memory[@pointer] | |
end | |
def dump | |
null? ? 0.chr : raw.chr | |
end | |
def null? | |
raw.nil? or raw.zero? | |
end | |
end | |
class Bf | |
class BfSyntaxError < StandardError; end | |
OP = { | |
'>' => :forward, | |
'<' => :backward, | |
'+' => :inc, | |
'-' => :dec, | |
'.' => :output, | |
',' => :input, | |
} | |
LOOP = { | |
:open => '[', | |
:close => ']' | |
} | |
def initialize(src, opts = {}) | |
@src = src || '' | |
@out = opts[:out] || $stdout | |
@in = opts[:in] || $stdin | |
@memory = Memory.new(:out => @out, :in => @in) | |
@pointer = 0 | |
@stack = [] | |
@code = @src.chars.to_a | |
raise BfSyntaxError unless syntax_valid? | |
end | |
def run | |
while cmd = read! | |
if op = OP[cmd] | |
@memory.__send__ op | |
elsif loop_open? cmd | |
if @memory.null? | |
proceed_to_close | |
else | |
@stack.push(@pointer - 1) | |
end | |
elsif loop_close? cmd | |
unless @memory.null? | |
@pointer = @stack.pop | |
end | |
end | |
end | |
end | |
private | |
def read! | |
cmd = read | |
@pointer += 1 | |
cmd | |
end | |
def read | |
@code[@pointer] | |
end | |
def proceed_to_close | |
while true | |
break if loop_close?(read!) | |
end | |
end | |
def loop_open?(cmd) | |
LOOP[:open] == cmd | |
end | |
def loop_close?(cmd) | |
LOOP[:close] == cmd | |
end | |
def syntax_valid? | |
stack = [] | |
@code.each do |char| | |
if loop_open?(char) | |
stack.push(true) | |
elsif loop_close?(char) | |
return false unless stack.pop | |
end | |
end | |
stack.empty? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment