cambridge 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cambridge.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest' do
5
+ # with Minitest::Unit
6
+ watch(%r|^test/(.*)\/?test_(.*)\.rb|)
7
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { "test" }
8
+ watch(%r|^test/helper\.rb|) { "test" }
9
+ end
10
+
11
+ guard 'ragel', :output => 'bin' do
12
+ watch(%r{^lib/cambridge/scan/(.+)\.rl$})
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Bryce Kerley
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Cambridge
2
+
3
+ A dumb stack-based language compiler. Don't use this! Ever!!!
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cambridge'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cambridge
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << 'lib' << 'test'
9
+ test.pattern = 'test/test_*.rb'
10
+ test.verbose = true
11
+ end
12
+
13
+ task :default => :test
14
+
15
+ task :test => :scanner
16
+
17
+ desc 'Generate the Ragel scanner'
18
+ task :scanner => 'lib/cambridge/parser/scan.rb'
19
+
20
+ file 'lib/cambridge/parser/scan.rb' => ['lib/cambridge/parser/scan.rl'] do |t|
21
+ sh "ragel -R -F1 -o #{t.name} #{t.prerequisites.first}"
22
+ end
23
+
24
+ directory 'doc'
25
+
26
+ namespace :scanner do
27
+ desc 'Generate a PDF graph of the Ragel scanner'
28
+ task :pdf => 'doc/scan.pdf'
29
+ file 'doc/scan.pdf' => ['doc/scan.dot', 'doc'] do |t|
30
+ sh "dot -Tpdf -o #{t.name} #{t.prerequisites.first}"
31
+ end
32
+
33
+ file 'doc/scan.dot' => ['lib/cambridge/parser/scan.rl', 'doc'] do |t|
34
+ sh "ragel -Vp -o #{t.name} #{t.prerequisites.first}"
35
+ end
36
+ end
data/cambridge.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/cambridge/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Bryce Kerley"]
6
+ gem.email = ["bkerley@brycekerley.net"]
7
+ gem.description = %q{A stack-based language to demo}
8
+ gem.summary = %q{A stack-based language to demo}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "cambridge"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Cambridge::VERSION
17
+ gem.required_ruby_version = '~> 1.9.3'
18
+
19
+ gem.add_development_dependency 'minitest', '~> 3.0.0'
20
+ gem.add_development_dependency 'guard-minitest'
21
+ gem.add_development_dependency 'guard-ragel'
22
+ gem.add_development_dependency 'shoulda-context', '~> 1.0.0'
23
+ gem.add_development_dependency 'mocha', '~> 0.11.4'
24
+ gem.add_development_dependency 'bundler', '~> 1.1.3'
25
+ gem.add_development_dependency 'rake', '~> 0.9.2'
26
+ end
data/lib/cambridge.rb ADDED
@@ -0,0 +1,19 @@
1
+ %w{version tokenizer tokens scanner environment}.each do |f|
2
+ require_relative File.join('cambridge', f)
3
+ end
4
+
5
+ module Cambridge
6
+ def self.run_file(filename)
7
+ contents = File.read filename
8
+ run_string contents
9
+ end
10
+
11
+ def self.run_string(string)
12
+ Environment.new.eval compile_string(string)
13
+ end
14
+
15
+ def self.compile_string(string)
16
+ tokenizer = Cambridge::Tokenizer.new string
17
+ tokenizer.to_ruby
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module Cambridge
2
+ class Environment
3
+ def initialize
4
+ @stack = []
5
+ end
6
+
7
+ def eval(ruby)
8
+ instance_eval ruby
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,315 @@
1
+
2
+ # line 1 "lib/cambridge/parser/scan.rl"
3
+
4
+ # line 29 "lib/cambridge/parser/scan.rl"
5
+
6
+
7
+ module Cambridge
8
+ module Parser
9
+ class Scan
10
+ def initialize
11
+ @tokens = []
12
+ @num_stack = []
13
+ end
14
+
15
+ def parse(line)
16
+ data = line.codepoints.to_a
17
+ stack = []
18
+ p = 0
19
+ ts = 0
20
+ te = 0
21
+ act = 0
22
+ eof = data.length
23
+
24
+ # line 25 "lib/cambridge/parser/scan.rb"
25
+ class << self
26
+ attr_accessor :_scanner_trans_keys
27
+ private :_scanner_trans_keys, :_scanner_trans_keys=
28
+ end
29
+ self._scanner_trans_keys = [
30
+ 0, 0, 34, 122, 34, 34,
31
+ 9, 122, 9, 122, 9,
32
+ 34, 9, 57, 9, 122,
33
+ 9, 57, 9, 122, 0
34
+ ]
35
+
36
+ class << self
37
+ attr_accessor :_scanner_key_spans
38
+ private :_scanner_key_spans, :_scanner_key_spans=
39
+ end
40
+ self._scanner_key_spans = [
41
+ 0, 89, 1, 114, 114, 26, 49, 114,
42
+ 49, 114
43
+ ]
44
+
45
+ class << self
46
+ attr_accessor :_scanner_index_offsets
47
+ private :_scanner_index_offsets, :_scanner_index_offsets=
48
+ end
49
+ self._scanner_index_offsets = [
50
+ 0, 0, 90, 92, 207, 322, 349, 399,
51
+ 514, 564
52
+ ]
53
+
54
+ class << self
55
+ attr_accessor :_scanner_indicies
56
+ private :_scanner_indicies, :_scanner_indicies=
57
+ end
58
+ self._scanner_indicies = [
59
+ 0, 1, 1, 1, 1, 1, 1, 1,
60
+ 1, 1, 1, 1, 1, 1, 2, 2,
61
+ 2, 2, 2, 2, 2, 2, 2, 2,
62
+ 1, 1, 1, 1, 1, 1, 1, 3,
63
+ 3, 3, 3, 3, 3, 3, 3, 3,
64
+ 3, 3, 3, 3, 3, 3, 3, 3,
65
+ 3, 3, 3, 3, 3, 3, 3, 3,
66
+ 3, 1, 1, 1, 1, 1, 1, 3,
67
+ 3, 3, 3, 3, 3, 3, 3, 3,
68
+ 3, 3, 3, 3, 3, 3, 3, 3,
69
+ 3, 3, 3, 3, 3, 3, 3, 3,
70
+ 3, 1, 5, 4, 6, 6, 6, 6,
71
+ 6, 4, 4, 4, 4, 4, 4, 4,
72
+ 4, 4, 4, 4, 4, 4, 4, 4,
73
+ 4, 4, 4, 6, 4, 7, 4, 4,
74
+ 4, 4, 4, 4, 4, 4, 4, 4,
75
+ 4, 4, 4, 8, 8, 8, 8, 8,
76
+ 8, 8, 8, 8, 8, 4, 4, 4,
77
+ 4, 4, 4, 4, 9, 9, 9, 9,
78
+ 9, 9, 9, 9, 9, 9, 9, 9,
79
+ 9, 9, 9, 9, 9, 9, 9, 9,
80
+ 9, 9, 9, 9, 9, 9, 4, 4,
81
+ 4, 4, 4, 4, 9, 9, 9, 9,
82
+ 9, 9, 9, 9, 9, 9, 9, 9,
83
+ 9, 9, 9, 9, 9, 9, 9, 9,
84
+ 9, 9, 9, 9, 9, 9, 4, 10,
85
+ 10, 10, 10, 10, 1, 1, 1, 1,
86
+ 1, 1, 1, 1, 1, 1, 1, 1,
87
+ 1, 1, 1, 1, 1, 1, 10, 1,
88
+ 0, 1, 1, 1, 1, 1, 1, 1,
89
+ 1, 1, 1, 1, 1, 1, 2, 2,
90
+ 2, 2, 2, 2, 2, 2, 2, 2,
91
+ 1, 1, 1, 1, 1, 1, 1, 3,
92
+ 3, 3, 3, 3, 3, 3, 3, 3,
93
+ 3, 3, 3, 3, 3, 3, 3, 3,
94
+ 3, 3, 3, 3, 3, 3, 3, 3,
95
+ 3, 1, 1, 1, 1, 1, 1, 3,
96
+ 3, 3, 3, 3, 3, 3, 3, 3,
97
+ 3, 3, 3, 3, 3, 3, 3, 3,
98
+ 3, 3, 3, 3, 3, 3, 3, 3,
99
+ 3, 1, 11, 11, 11, 11, 11, 4,
100
+ 4, 4, 4, 4, 4, 4, 4, 4,
101
+ 4, 4, 4, 4, 4, 4, 4, 4,
102
+ 4, 11, 4, 5, 4, 12, 12, 12,
103
+ 12, 12, 4, 4, 4, 4, 4, 4,
104
+ 4, 4, 4, 4, 4, 4, 4, 4,
105
+ 4, 4, 4, 4, 12, 4, 5, 4,
106
+ 4, 4, 4, 4, 4, 4, 4, 4,
107
+ 4, 4, 4, 4, 13, 13, 13, 13,
108
+ 13, 13, 13, 13, 13, 13, 4, 14,
109
+ 14, 14, 14, 14, 4, 4, 4, 4,
110
+ 4, 4, 4, 4, 4, 4, 4, 4,
111
+ 4, 4, 4, 4, 4, 4, 14, 4,
112
+ 5, 4, 4, 4, 4, 4, 4, 4,
113
+ 4, 4, 4, 4, 4, 4, 15, 15,
114
+ 15, 15, 15, 15, 15, 15, 15, 15,
115
+ 4, 4, 4, 4, 4, 4, 4, 15,
116
+ 15, 15, 15, 15, 15, 15, 15, 15,
117
+ 15, 15, 15, 15, 15, 15, 15, 15,
118
+ 15, 15, 15, 15, 15, 15, 15, 15,
119
+ 15, 4, 4, 4, 4, 4, 4, 15,
120
+ 15, 15, 15, 15, 15, 15, 15, 15,
121
+ 15, 15, 15, 15, 15, 15, 15, 15,
122
+ 15, 15, 15, 15, 15, 15, 15, 15,
123
+ 15, 4, 16, 16, 16, 16, 16, 1,
124
+ 1, 1, 1, 1, 1, 1, 1, 1,
125
+ 1, 1, 1, 1, 1, 1, 1, 1,
126
+ 1, 16, 1, 1, 1, 1, 1, 1,
127
+ 1, 1, 1, 1, 1, 1, 1, 1,
128
+ 1, 17, 17, 17, 17, 17, 17, 17,
129
+ 17, 17, 17, 1, 18, 18, 18, 18,
130
+ 18, 1, 1, 1, 1, 1, 1, 1,
131
+ 1, 1, 1, 1, 1, 1, 1, 1,
132
+ 1, 1, 1, 18, 1, 1, 1, 1,
133
+ 1, 1, 1, 1, 1, 1, 1, 1,
134
+ 1, 1, 1, 19, 19, 19, 19, 19,
135
+ 19, 19, 19, 19, 19, 1, 1, 1,
136
+ 1, 1, 1, 1, 19, 19, 19, 19,
137
+ 19, 19, 19, 19, 19, 19, 19, 19,
138
+ 19, 19, 19, 19, 19, 19, 19, 19,
139
+ 19, 19, 19, 19, 19, 19, 1, 1,
140
+ 1, 1, 1, 1, 19, 19, 19, 19,
141
+ 19, 19, 19, 19, 19, 19, 19, 19,
142
+ 19, 19, 19, 19, 19, 19, 19, 19,
143
+ 19, 19, 19, 19, 19, 19, 1, 0
144
+ ]
145
+
146
+ class << self
147
+ attr_accessor :_scanner_trans_targs
148
+ private :_scanner_trans_targs, :_scanner_trans_targs=
149
+ end
150
+ self._scanner_trans_targs = [
151
+ 2, 0, 8, 9, 2, 5, 3, 5,
152
+ 6, 7, 4, 3, 3, 6, 3, 7,
153
+ 4, 8, 4, 9
154
+ ]
155
+
156
+ class << self
157
+ attr_accessor :_scanner_trans_actions
158
+ private :_scanner_trans_actions, :_scanner_trans_actions=
159
+ end
160
+ self._scanner_trans_actions = [
161
+ 1, 0, 2, 3, 0, 0, 0, 1,
162
+ 2, 3, 0, 4, 5, 0, 6, 0,
163
+ 5, 0, 6, 0
164
+ ]
165
+
166
+ class << self
167
+ attr_accessor :_scanner_eof_actions
168
+ private :_scanner_eof_actions, :_scanner_eof_actions=
169
+ end
170
+ self._scanner_eof_actions = [
171
+ 0, 0, 0, 0, 0, 4, 5, 6,
172
+ 5, 6
173
+ ]
174
+
175
+ class << self
176
+ attr_accessor :scanner_start
177
+ end
178
+ self.scanner_start = 1;
179
+ class << self
180
+ attr_accessor :scanner_first_final
181
+ end
182
+ self.scanner_first_final = 5;
183
+ class << self
184
+ attr_accessor :scanner_error
185
+ end
186
+ self.scanner_error = 0;
187
+
188
+ class << self
189
+ attr_accessor :scanner_en_main
190
+ end
191
+ self.scanner_en_main = 1;
192
+
193
+
194
+ # line 48 "lib/cambridge/parser/scan.rl"
195
+
196
+ # line 197 "lib/cambridge/parser/scan.rb"
197
+ begin
198
+ p ||= 0
199
+ pe ||= data.length
200
+ cs = scanner_start
201
+ end
202
+
203
+ # line 49 "lib/cambridge/parser/scan.rl"
204
+
205
+ # line 206 "lib/cambridge/parser/scan.rb"
206
+ begin
207
+ testEof = false
208
+ _slen, _trans, _keys, _inds, _acts, _nacts = nil
209
+ _goto_level = 0
210
+ _resume = 10
211
+ _eof_trans = 15
212
+ _again = 20
213
+ _test_eof = 30
214
+ _out = 40
215
+ while true
216
+ if _goto_level <= 0
217
+ if p == pe
218
+ _goto_level = _test_eof
219
+ next
220
+ end
221
+ if cs == 0
222
+ _goto_level = _out
223
+ next
224
+ end
225
+ end
226
+ if _goto_level <= _resume
227
+ _keys = cs << 1
228
+ _inds = _scanner_index_offsets[cs]
229
+ _slen = _scanner_key_spans[cs]
230
+ _trans = if ( _slen > 0 &&
231
+ _scanner_trans_keys[_keys] <= data[p].ord &&
232
+ data[p].ord <= _scanner_trans_keys[_keys + 1]
233
+ ) then
234
+ _scanner_indicies[ _inds + data[p].ord - _scanner_trans_keys[_keys] ]
235
+ else
236
+ _scanner_indicies[ _inds + _slen ]
237
+ end
238
+ cs = _scanner_trans_targs[_trans]
239
+ if _scanner_trans_actions[_trans] != 0
240
+ case _scanner_trans_actions[_trans]
241
+ when 1 then
242
+ # line 4 "lib/cambridge/parser/scan.rl"
243
+ begin
244
+ @mark_str = p end
245
+ when 4 then
246
+ # line 5 "lib/cambridge/parser/scan.rl"
247
+ begin
248
+ @tokens << Tokens::String.new(data[@mark_str..p-1]) end
249
+ when 3 then
250
+ # line 7 "lib/cambridge/parser/scan.rl"
251
+ begin
252
+ @mark_cmd = p end
253
+ when 6 then
254
+ # line 8 "lib/cambridge/parser/scan.rl"
255
+ begin
256
+ @tokens << Tokens::Command.new(data[@mark_cmd..p-1]) end
257
+ when 2 then
258
+ # line 10 "lib/cambridge/parser/scan.rl"
259
+ begin
260
+ @mark_num = p end
261
+ when 5 then
262
+ # line 11 "lib/cambridge/parser/scan.rl"
263
+ begin
264
+ @tokens << Tokens::Number.new(data[@mark_num..p-1]) end
265
+ # line 266 "lib/cambridge/parser/scan.rb"
266
+ end
267
+ end
268
+ end
269
+ if _goto_level <= _again
270
+ if cs == 0
271
+ _goto_level = _out
272
+ next
273
+ end
274
+ p += 1
275
+ if p != pe
276
+ _goto_level = _resume
277
+ next
278
+ end
279
+ end
280
+ if _goto_level <= _test_eof
281
+ if p == eof
282
+ case _scanner_eof_actions[cs]
283
+ when 4 then
284
+ # line 5 "lib/cambridge/parser/scan.rl"
285
+ begin
286
+ @tokens << Tokens::String.new(data[@mark_str..p-1]) end
287
+ when 6 then
288
+ # line 8 "lib/cambridge/parser/scan.rl"
289
+ begin
290
+ @tokens << Tokens::Command.new(data[@mark_cmd..p-1]) end
291
+ when 5 then
292
+ # line 11 "lib/cambridge/parser/scan.rl"
293
+ begin
294
+ @tokens << Tokens::Number.new(data[@mark_num..p-1]) end
295
+ # line 296 "lib/cambridge/parser/scan.rb"
296
+ end
297
+ end
298
+
299
+ end
300
+ if _goto_level <= _out
301
+ break
302
+ end
303
+ end
304
+ end
305
+
306
+ # line 50 "lib/cambridge/parser/scan.rl"
307
+ return @tokens
308
+ end
309
+
310
+ def atos(a)
311
+ a.map(&:chr).join
312
+ end
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,58 @@
1
+ %%{
2
+ machine scanner;
3
+
4
+ action _string { @mark_str = p }
5
+ action string { @tokens << Tokens::String.new(data[@mark_str..p-1]) }
6
+
7
+ action _command { @mark_cmd = p }
8
+ action command { @tokens << Tokens::Command.new(data[@mark_cmd..p-1]) }
9
+
10
+ action _number { @mark_num = p }
11
+ action number { @tokens << Tokens::Number.new(data[@mark_num..p-1]) }
12
+
13
+
14
+ SingleCharacter = any;
15
+
16
+ StringComponent = SingleCharacter;
17
+
18
+ String = ('"' any* '"') >_string %string;
19
+
20
+ Number = (digit+) >_number %number;
21
+
22
+ Command = (alpha alnum*) >_command %command;
23
+
24
+ Token = String | Number | Command;
25
+
26
+ Program = Token (space+ Token)*;
27
+
28
+ main := Program;
29
+ }%%
30
+
31
+ module Cambridge
32
+ module Parser
33
+ class Scan
34
+ def initialize
35
+ @tokens = []
36
+ @num_stack = []
37
+ end
38
+
39
+ def parse(line)
40
+ data = line.codepoints.to_a
41
+ stack = []
42
+ p = 0
43
+ ts = 0
44
+ te = 0
45
+ act = 0
46
+ eof = data.length
47
+ %% write data;
48
+ %% write init;
49
+ %% write exec;
50
+ return @tokens
51
+ end
52
+
53
+ def atos(a)
54
+ a.map(&:chr).join
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ require_relative File.join('parser', 'scan')
2
+ module Cambridge
3
+ class Scanner
4
+ def initialize
5
+ @parser = Parser::Scan.new
6
+ end
7
+
8
+ def parse(line)
9
+ @line = line
10
+ @parser.parse @line
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module Cambridge
2
+ class Tokenizer
3
+ def initialize(source)
4
+ @source = source
5
+ end
6
+
7
+ def to_ruby
8
+ tokens.map(&:to_ruby).join("\n")
9
+ end
10
+
11
+ def tokens
12
+ @tokens ||= scanner.parse @source
13
+ end
14
+
15
+ def scanner
16
+ @scanner ||= Scanner.new
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Cambridge
2
+ module Tokens
3
+ class Base
4
+ def de_codepoint(array_of_codepoints)
5
+ return array_of_codepoints if array_of_codepoints.is_a? String
6
+ array_of_codepoints.map(&:chr).join
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ %w{string number command}.each do |f|
13
+ require_relative File.join('tokens', f)
14
+ end
@@ -0,0 +1,24 @@
1
+ module Cambridge
2
+ module Tokens
3
+ class Command < Base
4
+ def initialize(name)
5
+ @name = de_codepoint name
6
+ end
7
+
8
+ def to_ruby
9
+ case @name
10
+ when 'dump'
11
+ "puts @stack.inspect"
12
+ when 'prints'
13
+ "puts @stack.pop"
14
+ when 'printi'
15
+ "puts @stack.pop.to_s"
16
+ when 'add'
17
+ "@stack.push(@stack.pop + @stack.pop)"
18
+ when 'mult'
19
+ "@stack.push(@stack.pop * @stack.pop)"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Cambridge
2
+ module Tokens
3
+ class Number < Base
4
+ def initialize(string)
5
+ @number = de_codepoint(string).to_i
6
+ end
7
+
8
+ def to_ruby
9
+ "@stack.push #{@number.to_s}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ module Cambridge
2
+ module Tokens
3
+ class String < Base
4
+ def initialize(string)
5
+ @string = unquote de_codepoint string
6
+ end
7
+
8
+ def to_ruby
9
+ "@stack.push #{@string.inspect}"
10
+ end
11
+
12
+ private
13
+ def unquote(string)
14
+ string.gsub(/^"/, '').gsub(/"$/, '')
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Cambridge
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1 @@
1
+ "Hello World" prints
@@ -0,0 +1 @@
1
+ 5 6 add 4 mult printi
data/test/helper.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'shoulda-context'
2
+ require 'mocha'
3
+ require 'minitest/autorun'
4
+
5
+ require_relative File.join('..', 'lib', 'cambridge')
6
+
7
+ class CambridgeCase < MiniTest::Unit::TestCase
8
+ include Shoulda::Context::Assertions
9
+ include Shoulda::Context::InstanceMethods
10
+ extend Shoulda::Context::ClassMethods
11
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'helper'
2
+
3
+ class TestCambridge < CambridgeCase
4
+ context 'Hello World' do
5
+ setup do
6
+ @filename = File.join(File.dirname(__FILE__), 'fixtures', 'hello.cambridge')
7
+ end
8
+
9
+ should 'print to stdout' do
10
+ $stdout.expects(:puts).with('Hello World')
11
+
12
+ Cambridge.run_file @filename
13
+ end
14
+ end
15
+
16
+ context 'Math demo' do
17
+ setup do
18
+ @filename = File.join(File.dirname(__FILE__), 'fixtures', 'math.cambridge')
19
+ end
20
+
21
+ should 'print to stdout' do
22
+ $stdout.expects(:puts).with('44')
23
+
24
+ Cambridge.run_file @filename
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require_relative 'helper'
2
+
3
+ class TestScanner < CambridgeCase
4
+ include Cambridge::Tokens
5
+
6
+ def self.should_parse(line, *sequence)
7
+ context "the line #{line.inspect}" do
8
+ setup do
9
+ @parsed = nil
10
+ @error = nil
11
+ begin
12
+ @parsed = @scanner.parse line
13
+ rescue => e
14
+ @error = e
15
+ end
16
+ end
17
+ should "parse without error" do
18
+ assert_nil @error, @error.inspect
19
+ refute_nil @parsed
20
+ end
21
+ should "parse into #{sequence.inspect}" do
22
+ assert_equal sequence.length, @parsed.length
23
+ @parsed.zip sequence do |result, klass|
24
+ assert_kind_of klass, result
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ context 'a scanner' do
31
+ setup do
32
+ @scanner = Cambridge::Scanner.new
33
+ end
34
+
35
+ should_parse '"hello"', Cambridge::Tokens::String
36
+ should_parse 'prints', Command
37
+ should_parse '"hello world"', Cambridge::Tokens::String
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cambridge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bryce Kerley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard-minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-ragel
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: shoulda-context
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: mocha
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.11.4
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.11.4
94
+ - !ruby/object:Gem::Dependency
95
+ name: bundler
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 1.1.3
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.1.3
110
+ - !ruby/object:Gem::Dependency
111
+ name: rake
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 0.9.2
126
+ description: A stack-based language to demo
127
+ email:
128
+ - bkerley@brycekerley.net
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - Gemfile
135
+ - Guardfile
136
+ - LICENSE
137
+ - README.md
138
+ - Rakefile
139
+ - cambridge.gemspec
140
+ - lib/cambridge.rb
141
+ - lib/cambridge/environment.rb
142
+ - lib/cambridge/parser/scan.rb
143
+ - lib/cambridge/parser/scan.rl
144
+ - lib/cambridge/scanner.rb
145
+ - lib/cambridge/tokenizer.rb
146
+ - lib/cambridge/tokens.rb
147
+ - lib/cambridge/tokens/command.rb
148
+ - lib/cambridge/tokens/number.rb
149
+ - lib/cambridge/tokens/string.rb
150
+ - lib/cambridge/version.rb
151
+ - test/fixtures/hello.cambridge
152
+ - test/fixtures/math.cambridge
153
+ - test/helper.rb
154
+ - test/test_cambridge.rb
155
+ - test/test_scanner.rb
156
+ homepage: ''
157
+ licenses: []
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ~>
166
+ - !ruby/object:Gem::Version
167
+ version: 1.9.3
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 1.8.23
177
+ signing_key:
178
+ specification_version: 3
179
+ summary: A stack-based language to demo
180
+ test_files:
181
+ - test/fixtures/hello.cambridge
182
+ - test/fixtures/math.cambridge
183
+ - test/helper.rb
184
+ - test/test_cambridge.rb
185
+ - test/test_scanner.rb