brainfuck-rb 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61f75a20af1bb4192279cd1c93009d9fa54c91e9
4
+ data.tar.gz: 7d8a008799e664f0da54acee9ae7a4661c28ee1c
5
+ SHA512:
6
+ metadata.gz: b1171d7277b7d96a441f78e2a778c235a03625491a1a8601ccc11705296f484a64b94859dd08ed2c4af3a330b1c3a31b1c2adfe1b925c89519d69961692937a1
7
+ data.tar.gz: 4b7f3805fa508659c7f7132c4d22bf90944ea8564aa6a49c4e666c50448b311cd5bfcbd20e7c221b51d146c9421b736aedbce1368985bef8de3084f8139cfffb
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby -I.
2
+
3
+ require "brainfuck-rb"
4
+
5
+ unless ARGV.length > 0
6
+ puts "USAGE"
7
+ puts "\tbrainfuck FILE_NAME"
8
+ exit
9
+ end
10
+
11
+ Brainfuck.eval(ARGV[0])
@@ -0,0 +1,7 @@
1
+ require "lang/interpreter"
2
+
3
+ module Brainfuck
4
+ def self.eval(file)
5
+ Interpreter.new.eval(File.read(file))
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ require "io/console"
2
+ require "lang/parser"
3
+ require "lang/runtime"
4
+
5
+ module Brainfuck
6
+ class Interpreter
7
+ def initialize
8
+ @parser = Parser.new
9
+ @runtime = Runtime.new
10
+ end
11
+
12
+ def eval(code, show_nodes = false)
13
+ nodes = @parser.parse(code)
14
+ p nodes if show_nodes
15
+ nodes.eval(@runtime)
16
+ end
17
+ end
18
+
19
+ class Nodes
20
+ def eval(runtime)
21
+ nodes.each do |node|
22
+ node.eval(runtime)
23
+ end
24
+ end
25
+ end
26
+
27
+ class ShiftNode
28
+ def eval(runtime)
29
+ runtime.shift(direction)
30
+ end
31
+ end
32
+
33
+ class OperationNode
34
+ def eval(runtime)
35
+ runtime.mutate(type)
36
+ end
37
+ end
38
+
39
+ class LoopNode
40
+ def eval(runtime)
41
+ loop do
42
+ loop_body.eval(runtime)
43
+ break if runtime.value == 0
44
+ end
45
+ end
46
+ end
47
+
48
+ class ReadNode
49
+ def eval(runtime)
50
+ runtime.value = $stdin.getch.ord
51
+ end
52
+ end
53
+
54
+ class PrintNode
55
+ def eval(runtime)
56
+ print runtime.value.chr
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ module Brainfuck
2
+ class Lexer
3
+ class << self
4
+ OPERATORS = ['>', '<', '+', '-', '[', ']', ',', '.']
5
+ def tokenize(code)
6
+ tokens = []
7
+ unless code && code.length > 0
8
+ tokens
9
+ end
10
+ i = 0
11
+ while i < code.length
12
+ case code[i..-1]
13
+ when /\A(\s+)/
14
+ i += $1.length # ignore whitespace
15
+ when /\A(.)/
16
+ if OPERATORS.include? $1
17
+ tokens << [$1, $1]
18
+ end # Comment is anything other than operators, so ignore
19
+ i += 1
20
+ end
21
+ end
22
+ tokens
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ module Brainfuck
2
+ class Nodes < Struct.new(:nodes)
3
+ def <<(node)
4
+ nodes << node
5
+ self
6
+ end
7
+ end
8
+ class ShiftNode < Struct.new(:direction); end
9
+ class OperationNode < Struct.new(:type); end
10
+ class LoopNode < Struct.new(:loop_body); end
11
+ class ReadNode; end
12
+ class PrintNode; end
13
+ end
@@ -0,0 +1,234 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.9
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require "lang/lexer"
10
+ require "lang/nodes"
11
+
12
+ module Brainfuck
13
+
14
+ class Parser < Racc::Parser
15
+
16
+ module_eval(<<'...end grammer.y/module_eval...', 'grammer.y', 46)
17
+ def parse(code, show_tokens = false)
18
+ @tokens = Lexer.tokenize(code)
19
+ p @tokens if show_tokens
20
+ do_parse
21
+ end
22
+
23
+ def next_token
24
+ @tokens.shift
25
+ end
26
+ ...end grammer.y/module_eval...
27
+ ##### State transition tables begin ###
28
+
29
+ racc_action_table = [
30
+ 8, 9, 10, 18, 11, 12, 13, 14, 8, 9,
31
+ 10, 19, 11, 12, 13, 14, 8, 9, 10, 15,
32
+ 11, 12, 13, 14, 8, 9, 10, nil, 11, 12,
33
+ 13, 14 ]
34
+
35
+ racc_action_check = [
36
+ 0, 0, 0, 15, 0, 0, 0, 0, 17, 17,
37
+ 17, 17, 17, 17, 17, 17, 2, 2, 2, 1,
38
+ 2, 2, 2, 2, 10, 10, 10, nil, 10, 10,
39
+ 10, 10 ]
40
+
41
+ racc_action_pointer = [
42
+ -2, 19, 14, nil, nil, nil, nil, nil, nil, nil,
43
+ 22, nil, nil, nil, nil, 3, nil, 6, nil, nil ]
44
+
45
+ racc_action_default = [
46
+ -1, -16, -2, -3, -5, -6, -7, -8, -9, -10,
47
+ -16, -12, -13, -14, -15, -16, -4, -16, 20, -11 ]
48
+
49
+ racc_goto_table = [
50
+ 16, 2, 1, nil, nil, nil, nil, nil, nil, nil,
51
+ nil, 17, nil, nil, nil, 16 ]
52
+
53
+ racc_goto_check = [
54
+ 3, 2, 1, nil, nil, nil, nil, nil, nil, nil,
55
+ nil, 2, nil, nil, nil, 3 ]
56
+
57
+ racc_goto_pointer = [
58
+ nil, 2, 1, -2, nil, nil, nil, nil ]
59
+
60
+ racc_goto_default = [
61
+ nil, nil, nil, 3, 4, 5, 6, 7 ]
62
+
63
+ racc_reduce_table = [
64
+ 0, 0, :racc_error,
65
+ 0, 11, :_reduce_1,
66
+ 1, 11, :_reduce_2,
67
+ 1, 12, :_reduce_3,
68
+ 2, 12, :_reduce_4,
69
+ 1, 13, :_reduce_none,
70
+ 1, 13, :_reduce_none,
71
+ 1, 13, :_reduce_none,
72
+ 1, 13, :_reduce_none,
73
+ 1, 14, :_reduce_9,
74
+ 1, 14, :_reduce_10,
75
+ 3, 15, :_reduce_11,
76
+ 1, 16, :_reduce_12,
77
+ 1, 16, :_reduce_13,
78
+ 1, 17, :_reduce_14,
79
+ 1, 17, :_reduce_15 ]
80
+
81
+ racc_reduce_n = 16
82
+
83
+ racc_shift_n = 20
84
+
85
+ racc_token_table = {
86
+ false => 0,
87
+ :error => 1,
88
+ ">" => 2,
89
+ "<" => 3,
90
+ "[" => 4,
91
+ "]" => 5,
92
+ "," => 6,
93
+ "." => 7,
94
+ "+" => 8,
95
+ "-" => 9 }
96
+
97
+ racc_nt_base = 10
98
+
99
+ racc_use_result_var = true
100
+
101
+ Racc_arg = [
102
+ racc_action_table,
103
+ racc_action_check,
104
+ racc_action_default,
105
+ racc_action_pointer,
106
+ racc_goto_table,
107
+ racc_goto_check,
108
+ racc_goto_default,
109
+ racc_goto_pointer,
110
+ racc_nt_base,
111
+ racc_reduce_table,
112
+ racc_token_table,
113
+ racc_shift_n,
114
+ racc_reduce_n,
115
+ racc_use_result_var ]
116
+
117
+ Racc_token_to_s_table = [
118
+ "$end",
119
+ "error",
120
+ "\">\"",
121
+ "\"<\"",
122
+ "\"[\"",
123
+ "\"]\"",
124
+ "\",\"",
125
+ "\".\"",
126
+ "\"+\"",
127
+ "\"-\"",
128
+ "$start",
129
+ "Program",
130
+ "Expressions",
131
+ "Expression",
132
+ "Shift",
133
+ "Loop",
134
+ "InputOutput",
135
+ "Operation" ]
136
+
137
+ Racc_debug_parser = false
138
+
139
+ ##### State transition tables end #####
140
+
141
+ # reduce 0 omitted
142
+
143
+ module_eval(<<'.,.,', 'grammer.y', 4)
144
+ def _reduce_1(val, _values, result)
145
+ result = Nodes.new([])
146
+ result
147
+ end
148
+ .,.,
149
+
150
+ module_eval(<<'.,.,', 'grammer.y', 5)
151
+ def _reduce_2(val, _values, result)
152
+ result = val[0]
153
+ result
154
+ end
155
+ .,.,
156
+
157
+ module_eval(<<'.,.,', 'grammer.y', 9)
158
+ def _reduce_3(val, _values, result)
159
+ result = Nodes.new(val)
160
+ result
161
+ end
162
+ .,.,
163
+
164
+ module_eval(<<'.,.,', 'grammer.y', 10)
165
+ def _reduce_4(val, _values, result)
166
+ result = val[0] << val[1]
167
+ result
168
+ end
169
+ .,.,
170
+
171
+ # reduce 5 omitted
172
+
173
+ # reduce 6 omitted
174
+
175
+ # reduce 7 omitted
176
+
177
+ # reduce 8 omitted
178
+
179
+ module_eval(<<'.,.,', 'grammer.y', 21)
180
+ def _reduce_9(val, _values, result)
181
+ result = ShiftNode.new(:right)
182
+ result
183
+ end
184
+ .,.,
185
+
186
+ module_eval(<<'.,.,', 'grammer.y', 22)
187
+ def _reduce_10(val, _values, result)
188
+ result = ShiftNode.new(:left)
189
+ result
190
+ end
191
+ .,.,
192
+
193
+ module_eval(<<'.,.,', 'grammer.y', 26)
194
+ def _reduce_11(val, _values, result)
195
+ result = LoopNode.new(val[1])
196
+ result
197
+ end
198
+ .,.,
199
+
200
+ module_eval(<<'.,.,', 'grammer.y', 30)
201
+ def _reduce_12(val, _values, result)
202
+ result = ReadNode.new
203
+ result
204
+ end
205
+ .,.,
206
+
207
+ module_eval(<<'.,.,', 'grammer.y', 31)
208
+ def _reduce_13(val, _values, result)
209
+ result = PrintNode.new
210
+ result
211
+ end
212
+ .,.,
213
+
214
+ module_eval(<<'.,.,', 'grammer.y', 35)
215
+ def _reduce_14(val, _values, result)
216
+ result = OperationNode.new(:incr)
217
+ result
218
+ end
219
+ .,.,
220
+
221
+ module_eval(<<'.,.,', 'grammer.y', 36)
222
+ def _reduce_15(val, _values, result)
223
+ result = OperationNode.new(:decr)
224
+ result
225
+ end
226
+ .,.,
227
+
228
+ def _reduce_none(val, _values, result)
229
+ val[0]
230
+ end
231
+
232
+ end # class Parser
233
+
234
+ end # module Brainfuck
@@ -0,0 +1,40 @@
1
+ module Brainfuck
2
+ class Runtime
3
+ def initialize
4
+ @cells = [0]
5
+ @current_cell = 0
6
+ end
7
+
8
+ def shift(direction)
9
+ case direction
10
+ when :right
11
+ @current_cell += 1
12
+ if @current_cell > @cells.length - 1
13
+ @cells << 0
14
+ end
15
+ when :left
16
+ @current_cell -= 1
17
+ if @current_cell < 0
18
+ @current_cell = 0
19
+ end
20
+ end
21
+ end
22
+
23
+ def mutate(how)
24
+ case how
25
+ when :incr
26
+ @cells[@current_cell] += 1
27
+ when :decr
28
+ @cells[@current_cell] -= 1
29
+ end
30
+ end
31
+
32
+ def value
33
+ @cells[@current_cell]
34
+ end
35
+
36
+ def value=(value)
37
+ @cells[@current_cell] = value
38
+ end
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brainfuck-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Buck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Small and simple Brainfuck interpreter written in Ruby
14
+ email: lordizuriel@gmail.com
15
+ executables:
16
+ - brainfuck
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/brainfuck-rb.rb
21
+ - lib/lang/lexer.rb
22
+ - lib/lang/parser.rb
23
+ - lib/lang/nodes.rb
24
+ - lib/lang/runtime.rb
25
+ - lib/lang/interpreter.rb
26
+ - bin/brainfuck
27
+ homepage: http://github.com/bbuck/brainfuck-rb
28
+ licenses:
29
+ - MIT
30
+ metadata: {}
31
+ post_install_message:
32
+ rdoc_options: []
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
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubyforge_project:
47
+ rubygems_version: 2.0.3
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Brainfuck interpreter written in Ruby
51
+ test_files: []