tsion-rbrainfuck 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rbrainfuck +28 -0
- data/lib/brainfuck.rb +88 -0
- metadata +55 -0
data/bin/rbrainfuck
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'optparse'
|
4
|
+
require 'brainfuck'
|
5
|
+
|
6
|
+
stdout = STDOUT
|
7
|
+
stdin = STDIN
|
8
|
+
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: #{$0} [options] script"
|
11
|
+
|
12
|
+
opts.on("-d", "--[no-]debug", "Run in debug mode") do |d|
|
13
|
+
Brainfuck.debug = d
|
14
|
+
end
|
15
|
+
opts.on("-o", "--output=FILE", "Specify a file for stdout") do |file|
|
16
|
+
stdout = File.new(file, 'w')
|
17
|
+
end
|
18
|
+
opts.on("-i", "--input=FILE", "Specify a file for stdin") do |file|
|
19
|
+
stdin = File.new(file, 'r')
|
20
|
+
end
|
21
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
22
|
+
puts opts
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end.parse!
|
26
|
+
|
27
|
+
b = Brainfuck.new(ARGV[0], stdout, stdin)
|
28
|
+
b.run
|
data/lib/brainfuck.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Ruby Brainfuck interpreter
|
3
|
+
# (C) Scott Olson <scott@scott-olson.org>
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
class Brainfuck
|
7
|
+
attr_accessor :script, :stdin, :stdout
|
8
|
+
|
9
|
+
# script is the brainfuck program
|
10
|
+
# stdin and stdout are the input and output, respectively
|
11
|
+
# they can be String, IO, or something else that accepts putc/getc
|
12
|
+
def initialize(script=nil, stdout=nil, stdin=nil)
|
13
|
+
@script = script || ''
|
14
|
+
@stdout = stdout || ''
|
15
|
+
@stdin = stdin || ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
ptr = 0
|
20
|
+
stack = [0]
|
21
|
+
script = @script.split('')
|
22
|
+
script_ptr = 0
|
23
|
+
|
24
|
+
while script_ptr < script.length
|
25
|
+
debug("%0#{script.length.to_s.length}i: (#{ptr}=#{stack[ptr]}) #{script[script_ptr]}" % script_ptr)
|
26
|
+
case script[script_ptr]
|
27
|
+
when '>'
|
28
|
+
ptr += 1
|
29
|
+
stack[ptr] ||= 0 # set the cell to 0 if it is nil
|
30
|
+
|
31
|
+
when '<'
|
32
|
+
ptr -= 1
|
33
|
+
stack[ptr] ||= 0 # set the cell to 0 if it is nil
|
34
|
+
|
35
|
+
when '+'
|
36
|
+
stack[ptr] += 1
|
37
|
+
|
38
|
+
when '-'
|
39
|
+
stack[ptr] -= 1
|
40
|
+
|
41
|
+
when '.'
|
42
|
+
debug(" outputting #{stack[ptr].chr.inspect}")
|
43
|
+
case @stdout
|
44
|
+
when String
|
45
|
+
@stdout << stack[ptr]
|
46
|
+
else
|
47
|
+
@stdout.putc stack[ptr]
|
48
|
+
end
|
49
|
+
|
50
|
+
when ','
|
51
|
+
case @stdin
|
52
|
+
when String
|
53
|
+
if /^1\.8/ === RUBY_VERION
|
54
|
+
stack[ptr] = @stdin.first[0] # grab first char as int
|
55
|
+
@stdin[0] = '' # remove the char from the string
|
56
|
+
else
|
57
|
+
stack[ptr] = @stdin.first.ord # grab first char as int
|
58
|
+
@stdin[0] = '' # remove the char from the string
|
59
|
+
end
|
60
|
+
else
|
61
|
+
stack[ptr] = @stdin.getc
|
62
|
+
end
|
63
|
+
|
64
|
+
when '['
|
65
|
+
came_from = script_ptr # never forget where you came from
|
66
|
+
# this code jumps to the next ']' if our current byte is 0
|
67
|
+
script_ptr += script[script_ptr..-1].index(']') if stack[ptr] == 0
|
68
|
+
|
69
|
+
when ']'
|
70
|
+
raise "unmatched ] encountered" unless defined? :came_from
|
71
|
+
script_ptr = came_from - 1 # go back to the start of the loop
|
72
|
+
|
73
|
+
end
|
74
|
+
script_ptr += 1
|
75
|
+
debug("\n")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@@debug = false # default
|
80
|
+
def self.debug=(val)
|
81
|
+
@@debug = val
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def debug(str)
|
86
|
+
$stderr.print str if @@debug
|
87
|
+
end
|
88
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tsion-rbrainfuck
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Scott Olson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-01 00:00:00 -08:00
|
13
|
+
default_executable: rbrainfuck
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A brainfuck interpreter in Ruby
|
17
|
+
email: scott@scott-olson.org
|
18
|
+
executables:
|
19
|
+
- rbrainfuck
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- bin/rbrainfuck
|
26
|
+
- lib/brainfuck.rb
|
27
|
+
has_rdoc: true
|
28
|
+
homepage: http://github.com/tsion/rbrainfuck
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options:
|
31
|
+
- --inline-source
|
32
|
+
- --charset=UTF-8
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: "0"
|
40
|
+
version:
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
requirements: []
|
48
|
+
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.2.0
|
51
|
+
signing_key:
|
52
|
+
specification_version: 2
|
53
|
+
summary: A brainfuck interpreter in Ruby
|
54
|
+
test_files: []
|
55
|
+
|