yarbf 0.0.1
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.
- checksums.yaml +4 -0
- data/bin/yarbf +6 -0
- data/lib/yarbf.rb +165 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
metadata.gz: 22f7d3768f1b31130f5fa1452d52dc98b0a3236b95c4f1e072c10ec8be3f2f9ec194ec195bdb837bec66e1335336e00e692eedcea4233847f327a33576ffd4e6
|
4
|
+
data.tar.gz: cc4df3daa804a1ee6f9e555b04d6f1d550d66b782ae02173652e8990a0114904b1115c30b2e5be2d8a1d1c786ac3506b6271116c08594a805135e8f1ebf3a33e
|
data/bin/yarbf
ADDED
data/lib/yarbf.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
|
3
|
+
class BfInterpreter
|
4
|
+
# private constants
|
5
|
+
KEY_DEBUG = 'debug'
|
6
|
+
KEY_WRAP = 'wrap_around'
|
7
|
+
KEY_CELL = 'cell_size'
|
8
|
+
private_constant :KEY_DEBUG, :KEY_WRAP, :KEY_CELL
|
9
|
+
|
10
|
+
def initialize(debug = false, wrap_around = true, cell_size = 8)
|
11
|
+
@option = Hash.new
|
12
|
+
@option[KEY_DEBUG] = debug
|
13
|
+
@option[KEY_WRAP] = wrap_around
|
14
|
+
@option[KEY_CELL] = cell_size
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug?
|
18
|
+
@option[KEY_DEBUG]
|
19
|
+
end
|
20
|
+
|
21
|
+
def debug=(debug)
|
22
|
+
@option[KEY_DEBUG] = debug
|
23
|
+
end
|
24
|
+
|
25
|
+
def wrap_around?
|
26
|
+
@option[KEY_WRAP]
|
27
|
+
end
|
28
|
+
|
29
|
+
def wrap_around=(wrap_around)
|
30
|
+
@option[KEY_WRAP] = wrap_around
|
31
|
+
end
|
32
|
+
|
33
|
+
def cell_size?
|
34
|
+
@option[KEY_CELL]
|
35
|
+
end
|
36
|
+
|
37
|
+
def cell_size=(cell_size)
|
38
|
+
@option[KEY_CELL] = cell_size
|
39
|
+
end
|
40
|
+
|
41
|
+
def run(src)
|
42
|
+
units = []
|
43
|
+
|
44
|
+
# construct units
|
45
|
+
File.open(src) do |file|
|
46
|
+
units = construct_program_units(file)
|
47
|
+
end
|
48
|
+
|
49
|
+
# match brackets
|
50
|
+
match_brackets(units)
|
51
|
+
|
52
|
+
# do interpret
|
53
|
+
tape = Array.new
|
54
|
+
position = 0
|
55
|
+
unit = units[0]
|
56
|
+
while unit != nil
|
57
|
+
tape[position] = BfCell.new(position) if tape[position] == nil
|
58
|
+
|
59
|
+
STDERR.printf('%s', unit.instruction) if debug?
|
60
|
+
|
61
|
+
case unit.instruction
|
62
|
+
when '+' then tape[position].increase(1, wrap_around?)
|
63
|
+
when '-' then tape[position].decrease(1, wrap_around?)
|
64
|
+
when '<' then
|
65
|
+
position -= 1
|
66
|
+
fail 'Cell position out of bound!' if position < 0
|
67
|
+
when '>' then position += 1
|
68
|
+
when ',' then
|
69
|
+
tape[position].value = STDIN.getch.ord
|
70
|
+
when '.' then STDOUT.putc tape[position].value
|
71
|
+
when '[' then
|
72
|
+
if tape[position].value == 0
|
73
|
+
unit = unit.match
|
74
|
+
next
|
75
|
+
end
|
76
|
+
when ']' then
|
77
|
+
if tape[position].value != 0
|
78
|
+
unit = unit.match
|
79
|
+
next
|
80
|
+
end
|
81
|
+
else fail "Illegal instruction '#{unit.instruction}'!"
|
82
|
+
end
|
83
|
+
|
84
|
+
unit = unit.next
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def construct_program_units(file)
|
89
|
+
units = Array.new
|
90
|
+
position = 0
|
91
|
+
|
92
|
+
file.each_byte do |c|
|
93
|
+
case c.chr
|
94
|
+
when '+', '-', '<', '>', '[', ']', '.', ',' then
|
95
|
+
unit = BfProgramUnit.new(c.chr)
|
96
|
+
units[position - 1].next = unit if position > 0
|
97
|
+
units[position] = unit
|
98
|
+
position += 1
|
99
|
+
else
|
100
|
+
# other characters are considered as comments, do nothing
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
units
|
105
|
+
end
|
106
|
+
|
107
|
+
def match_brackets(units)
|
108
|
+
units.each_index do |i|
|
109
|
+
if units[i].instruction == '['
|
110
|
+
level = 0
|
111
|
+
units[i + 1 .. units.length - 1].each_index do |j|
|
112
|
+
j += i + 1
|
113
|
+
if units[j].instruction == '['
|
114
|
+
level += 1
|
115
|
+
elsif units[j].instruction == ']'
|
116
|
+
if level > 0
|
117
|
+
level -= 1
|
118
|
+
else
|
119
|
+
units[i].match = units[j]
|
120
|
+
units[j].match = units[i]
|
121
|
+
break
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
fail 'Unmatched brackets!' if level > 0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private :construct_program_units, :match_brackets
|
131
|
+
|
132
|
+
class BfCell
|
133
|
+
attr_accessor :position, :value
|
134
|
+
|
135
|
+
def initialize(position, value = 0)
|
136
|
+
@position = position
|
137
|
+
@value = value
|
138
|
+
end
|
139
|
+
|
140
|
+
def increase(increment = 1, wrap_around = true)
|
141
|
+
if !wrap_around && (@value + increment < 0 || @value + increment > 255)
|
142
|
+
fail 'Overflow or underflow happened while forbidden!'
|
143
|
+
else
|
144
|
+
@value = (@value + increment) % 256
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def decrease(decrement = 1, wrap_around = true)
|
149
|
+
self.increase(-decrement, wrap_around)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class BfProgramUnit
|
154
|
+
attr_reader :instruction
|
155
|
+
|
156
|
+
attr_accessor :match
|
157
|
+
attr_accessor :next
|
158
|
+
|
159
|
+
def initialize(instruction)
|
160
|
+
@instruction = instruction
|
161
|
+
@match = nil
|
162
|
+
@next = nil
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yarbf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chaos Shen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: io-console
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
27
|
+
description: yarbf, is a simple Brainfuck interpreter in Ruby.
|
28
|
+
email: chaosdefinition@hotmail.com
|
29
|
+
executables:
|
30
|
+
- yarbf
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- bin/yarbf
|
35
|
+
- lib/yarbf.rb
|
36
|
+
homepage: http://github.com/chaosdefinition/yarbf
|
37
|
+
licenses:
|
38
|
+
- MIT
|
39
|
+
metadata: {}
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.4.5.1
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Yet another Brainfuck interpreter in Ruby
|
60
|
+
test_files: []
|