tsion-rbrainfuck 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|