yarbf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -0
  2. data/bin/yarbf +6 -0
  3. data/lib/yarbf.rb +165 -0
  4. metadata +60 -0
@@ -0,0 +1,4 @@
1
+ ---
2
+ SHA512:
3
+ metadata.gz: 22f7d3768f1b31130f5fa1452d52dc98b0a3236b95c4f1e072c10ec8be3f2f9ec194ec195bdb837bec66e1335336e00e692eedcea4233847f327a33576ffd4e6
4
+ data.tar.gz: cc4df3daa804a1ee6f9e555b04d6f1d550d66b782ae02173652e8990a0114904b1115c30b2e5be2d8a1d1c786ac3506b6271116c08594a805135e8f1ebf3a33e
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yarbf'
4
+
5
+ interpreter = BfInterpreter.new
6
+ interpreter.run(ARGV[0])
@@ -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: []