brainfuck-rb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []