rubic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa663739b7fa978469e0da9249943c65d9ffa786
4
+ data.tar.gz: c6f7a585aaefff3c18608022c100a2433e69f9e7
5
+ SHA512:
6
+ metadata.gz: 77ee9b97ca0f112b8e6157791373cde32f6d7c1940aafe558269ee26e8ffd33b80e491259c1591b69ffb84248670cae5c490438bef0ccea1ec551f74bd99cd7b
7
+ data.tar.gz: 610b6efcb0e4b59214fb88b54a7c49850902a1942085fbea7e8b2945e109d06faa4efe316829615be4bb5f164a0c1e9c5157308f815f7cb1dda8ff601bb37265
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vendor/
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rubic.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 notozeki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # Rubic - A tiny Scheme interpreter
2
+
3
+ **Rubic** is a very simple Scheme interpreter written in Ruby.
4
+
5
+ NOTE: This is my hobby project. You may find it is good for nothing in practical uses :wink:
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'rubic'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rubic
22
+
23
+ ## Usage
24
+
25
+ ```ruby
26
+ rubic = Rubic::Interpreter.new
27
+ rubic.evaluate("...write your Scheme code here...")
28
+ ```
29
+
30
+ ## Development
31
+
32
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
33
+
34
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it ( https://github.com/notozeki/rubic/fork )
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ namespace :racc do
9
+ desc 'Compile syntax file'
10
+ task :compile do
11
+ src = 'lib/rubic/parser.y'
12
+ dst = 'lib/rubic/parser.rb'
13
+ sh "bundle exec racc -o #{dst} #{src}"
14
+ end
15
+ end
16
+
17
+ task :test => 'racc:compile'
18
+ task :default => 'racc:compile'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rubic"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+ module Rubic
2
+ class RubicRuntimeError < StandardError; end
3
+
4
+ class Environment
5
+ def initialize(outer=nil)
6
+ @outer = outer
7
+ @table = {}
8
+ end
9
+
10
+ def defvar(name, value)
11
+ @table[name] = value
12
+ end
13
+
14
+ def refvar(name)
15
+ if @table.key? name
16
+ @table[name]
17
+ elsif @outer
18
+ @outer.refvar(name)
19
+ else
20
+ raise RubicRuntimeError, "undefined variable `#{name}'"
21
+ end
22
+ end
23
+
24
+ def bind(params, args)
25
+ if params.size != args.size
26
+ raise RubicRuntimeError, "wrong number of arguments (#{args.size} for #{params.size})"
27
+ end
28
+
29
+ params.each.with_index do |name, i|
30
+ @table[name] = args[i]
31
+ end
32
+ end
33
+
34
+ alias []= defvar
35
+ alias [] refvar
36
+ end
37
+ end
@@ -0,0 +1,89 @@
1
+ require 'rubic/parser'
2
+ require 'rubic/environment'
3
+
4
+ module Rubic
5
+ class Interpreter
6
+ DEFAULT_GLOBAL_VARS = {
7
+ '+' => -> (*args) { args.reduce(:+) },
8
+ '-' => -> (*args) { args.size == 1 ? -args.first : args.reduce(:-) },
9
+ '*' => -> (*args) { args.reduce(:*) },
10
+ '/' => -> (*args) { args.reduce(:/) },
11
+ '<' => -> (a, b) { a < b },
12
+ '>' => -> (a, b) { a > b },
13
+ '=' => -> (a, b) { a == b },
14
+ 'not' => -> (a) { !a },
15
+ }
16
+
17
+ def initialize
18
+ @parser = Parser.new
19
+ @global = Environment.new
20
+ DEFAULT_GLOBAL_VARS.each {|k, v| @global[k] = v }
21
+ end
22
+
23
+ def evaluate(str)
24
+ list = @parser.parse(str)
25
+ execute(list, @global)
26
+ end
27
+
28
+ private
29
+
30
+ def execute(list_or_atom, env)
31
+ # Atom
32
+ case list_or_atom
33
+ when Float, Integer
34
+ atom = list_or_atom
35
+ when String
36
+ atom = env[list_or_atom]
37
+ else
38
+ # fallthrough
39
+ end
40
+ return atom if atom
41
+
42
+ list = list_or_atom
43
+ # Special Forms
44
+ case list.first
45
+ when :define
46
+ _, name, expr = list
47
+ env[name] = execute(expr, env)
48
+ return
49
+ when :define_proc
50
+ _, (name, *params), *body = list
51
+ env[name] = -> (*args) do
52
+ local = Environment.new(env)
53
+ local.bind(params, args)
54
+ body.map {|expr| execute(expr, local) }.last
55
+ end
56
+ return
57
+ when :cond
58
+ _, *clauses = list
59
+ clauses.each do |pred, expr|
60
+ if pred == :else || execute(pred, env)
61
+ return execute(expr, env)
62
+ end
63
+ end
64
+ return
65
+ when :if
66
+ _, pred, cons, alt = list
67
+ return execute(pred, env) ? execute(cons, env) : execute(alt, env)
68
+ when :and
69
+ _, *exprs = list
70
+ exprs.each do |expr|
71
+ return false unless execute(expr, env)
72
+ end
73
+ return true
74
+ when :or
75
+ _, *exprs = list
76
+ exprs.each do |expr|
77
+ return true if execute(expr, env)
78
+ end
79
+ return false
80
+ else
81
+ # fallthrough
82
+ end
83
+
84
+ # Anything else
85
+ op, *args = list.map {|e| execute(e, env) }
86
+ op.call(*args)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,328 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.12
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'strscan'
10
+
11
+ module Rubic
12
+ class UnknownCharacterError < StandardError; end
13
+
14
+ class Parser < Racc::Parser
15
+
16
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 92)
17
+ EOT = [false, nil] # end of token
18
+ SYM_CHARS = Regexp.escape("+-*/<>=?")
19
+
20
+ def parse(str)
21
+ @s = StringScanner.new(str)
22
+ do_parse
23
+ end
24
+
25
+ def next_token
26
+ @s.skip(/\s+/)
27
+ return EOT if @s.eos?
28
+
29
+ case
30
+ when @s.scan(/[0-9]+(\.[0-9]+)?/)
31
+ [:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
32
+ when @s.scan(/[\(\)]/o)
33
+ [@s[0], nil]
34
+ when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
35
+ case @s[0] # keyword check
36
+ when 'define'
37
+ [:KW_DEFINE, nil]
38
+ when 'cond'
39
+ [:KW_COND, nil]
40
+ when 'else'
41
+ [:KW_ELSE, nil]
42
+ when 'if'
43
+ [:KW_IF, nil]
44
+ when 'and'
45
+ [:KW_AND, nil]
46
+ when 'or'
47
+ [:KW_OR, nil]
48
+ else
49
+ [:IDENT, @s[0]]
50
+ end
51
+ else
52
+ raise UnknownCharacterError, "unknown character #{@s.getch}"
53
+ end
54
+ end
55
+
56
+ ...end parser.y/module_eval...
57
+ ##### State transition tables begin ###
58
+
59
+ racc_action_table = [
60
+ 2, 10, 25, 11, 3, 4, 13, 14, 2, 15,
61
+ 2, 16, 3, 4, 3, 4, 36, 2, 25, 2,
62
+ 33, 3, 4, 3, 4, 2, 43, 2, 44, 3,
63
+ 4, 3, 4, 2, 38, 2, 45, 3, 4, 3,
64
+ 4, 2, 46, 47, 22, 3, 4, 2, 21, 27,
65
+ 9, 3, 4, 2, 32, 29, nil, 3, 4, 2,
66
+ nil, 30, 2, 3, 4, 2, 3, 4, 2, 3,
67
+ 4, nil, 3, 4, 2, nil, 49, nil, 3, 4 ]
68
+
69
+ racc_action_check = [
70
+ 2, 2, 14, 2, 2, 2, 2, 2, 25, 2,
71
+ 35, 9, 25, 25, 35, 35, 25, 37, 23, 10,
72
+ 23, 37, 37, 10, 10, 11, 39, 12, 39, 11,
73
+ 11, 12, 12, 36, 31, 0, 40, 36, 36, 0,
74
+ 0, 15, 41, 42, 13, 15, 15, 17, 13, 17,
75
+ 1, 17, 17, 19, 22, 19, nil, 19, 19, 20,
76
+ nil, 20, 21, 20, 20, 43, 21, 21, 26, 43,
77
+ 43, nil, 26, 26, 48, nil, 48, nil, 48, 48 ]
78
+
79
+ racc_action_pointer = [
80
+ 33, 50, -2, nil, nil, nil, nil, nil, nil, 11,
81
+ 17, 23, 25, 42, 0, 39, nil, 45, nil, 51,
82
+ 57, 60, 48, 16, nil, 6, 66, nil, nil, nil,
83
+ nil, 30, nil, nil, nil, 8, 31, 15, nil, 22,
84
+ 32, 38, 39, 63, nil, nil, nil, nil, 72, nil ]
85
+
86
+ racc_action_default = [
87
+ -22, -22, -22, -4, -5, -6, -7, -8, -9, -22,
88
+ -22, -22, -22, -22, -22, -22, 50, -22, -10, -22,
89
+ -22, -22, -22, -22, -17, -22, -22, -1, -11, -2,
90
+ -3, -22, -14, -16, -18, -22, -22, -22, -12, -22,
91
+ -22, -22, -22, -22, -15, -19, -20, -21, -22, -13 ]
92
+
93
+ racc_goto_table = [
94
+ 1, 24, 12, 23, 39, 17, 19, 20, nil, nil,
95
+ 34, nil, nil, nil, nil, 26, nil, 28, nil, 28,
96
+ 28, 31, nil, nil, nil, 35, 37, nil, nil, nil,
97
+ nil, nil, nil, nil, nil, 40, 41, 42, 48, nil,
98
+ nil, nil, nil, nil, nil, nil, nil, nil, 28 ]
99
+
100
+ racc_goto_check = [
101
+ 1, 9, 1, 8, 7, 2, 2, 2, nil, nil,
102
+ 9, nil, nil, nil, nil, 1, nil, 1, nil, 1,
103
+ 1, 1, nil, nil, nil, 1, 1, nil, nil, nil,
104
+ nil, nil, nil, nil, nil, 1, 1, 1, 2, nil,
105
+ nil, nil, nil, nil, nil, nil, nil, nil, 1 ]
106
+
107
+ racc_goto_pointer = [
108
+ nil, 0, -5, nil, nil, nil, nil, -28, -11, -13 ]
109
+
110
+ racc_goto_default = [
111
+ nil, 18, nil, 5, 6, 7, 8, nil, nil, nil ]
112
+
113
+ racc_reduce_table = [
114
+ 0, 0, :racc_error,
115
+ 4, 13, :_reduce_1,
116
+ 4, 13, :_reduce_2,
117
+ 4, 13, :_reduce_3,
118
+ 1, 13, :_reduce_none,
119
+ 1, 13, :_reduce_none,
120
+ 1, 13, :_reduce_none,
121
+ 1, 13, :_reduce_none,
122
+ 1, 13, :_reduce_none,
123
+ 1, 13, :_reduce_none,
124
+ 1, 14, :_reduce_10,
125
+ 2, 14, :_reduce_11,
126
+ 5, 15, :_reduce_12,
127
+ 8, 16, :_reduce_13,
128
+ 0, 19, :_reduce_14,
129
+ 2, 19, :_reduce_15,
130
+ 4, 17, :_reduce_16,
131
+ 1, 20, :_reduce_17,
132
+ 2, 20, :_reduce_18,
133
+ 4, 21, :_reduce_19,
134
+ 4, 21, :_reduce_20,
135
+ 6, 18, :_reduce_21 ]
136
+
137
+ racc_reduce_n = 22
138
+
139
+ racc_shift_n = 50
140
+
141
+ racc_token_table = {
142
+ false => 0,
143
+ :error => 1,
144
+ "(" => 2,
145
+ :KW_AND => 3,
146
+ ")" => 4,
147
+ :KW_OR => 5,
148
+ :IDENT => 6,
149
+ :NUMBER => 7,
150
+ :KW_DEFINE => 8,
151
+ :KW_COND => 9,
152
+ :KW_ELSE => 10,
153
+ :KW_IF => 11 }
154
+
155
+ racc_nt_base = 12
156
+
157
+ racc_use_result_var = false
158
+
159
+ Racc_arg = [
160
+ racc_action_table,
161
+ racc_action_check,
162
+ racc_action_default,
163
+ racc_action_pointer,
164
+ racc_goto_table,
165
+ racc_goto_check,
166
+ racc_goto_default,
167
+ racc_goto_pointer,
168
+ racc_nt_base,
169
+ racc_reduce_table,
170
+ racc_token_table,
171
+ racc_shift_n,
172
+ racc_reduce_n,
173
+ racc_use_result_var ]
174
+
175
+ Racc_token_to_s_table = [
176
+ "$end",
177
+ "error",
178
+ "\"(\"",
179
+ "KW_AND",
180
+ "\")\"",
181
+ "KW_OR",
182
+ "IDENT",
183
+ "NUMBER",
184
+ "KW_DEFINE",
185
+ "KW_COND",
186
+ "KW_ELSE",
187
+ "KW_IF",
188
+ "$start",
189
+ "expr",
190
+ "seq",
191
+ "define",
192
+ "define_proc",
193
+ "cond",
194
+ "if",
195
+ "params",
196
+ "clauses",
197
+ "clause" ]
198
+
199
+ Racc_debug_parser = false
200
+
201
+ ##### State transition tables end #####
202
+
203
+ # reduce 0 omitted
204
+
205
+ module_eval(<<'.,.,', 'parser.y', 6)
206
+ def _reduce_1(val, _values)
207
+ [:and, *val[2]]
208
+
209
+ end
210
+ .,.,
211
+
212
+ module_eval(<<'.,.,', 'parser.y', 10)
213
+ def _reduce_2(val, _values)
214
+ [:or, *val[2]]
215
+
216
+ end
217
+ .,.,
218
+
219
+ module_eval(<<'.,.,', 'parser.y', 14)
220
+ def _reduce_3(val, _values)
221
+ [val[1], *val[2]]
222
+
223
+ end
224
+ .,.,
225
+
226
+ # reduce 4 omitted
227
+
228
+ # reduce 5 omitted
229
+
230
+ # reduce 6 omitted
231
+
232
+ # reduce 7 omitted
233
+
234
+ # reduce 8 omitted
235
+
236
+ # reduce 9 omitted
237
+
238
+ module_eval(<<'.,.,', 'parser.y', 25)
239
+ def _reduce_10(val, _values)
240
+ [val[0]]
241
+
242
+ end
243
+ .,.,
244
+
245
+ module_eval(<<'.,.,', 'parser.y', 29)
246
+ def _reduce_11(val, _values)
247
+ val[0].push(val[1])
248
+
249
+ end
250
+ .,.,
251
+
252
+ module_eval(<<'.,.,', 'parser.y', 35)
253
+ def _reduce_12(val, _values)
254
+ [:define, val[2], val[3]]
255
+
256
+ end
257
+ .,.,
258
+
259
+ module_eval(<<'.,.,', 'parser.y', 41)
260
+ def _reduce_13(val, _values)
261
+ [:define_proc, [val[3], *val[4]], *val[6]]
262
+
263
+ end
264
+ .,.,
265
+
266
+ module_eval(<<'.,.,', 'parser.y', 46)
267
+ def _reduce_14(val, _values)
268
+ []
269
+
270
+ end
271
+ .,.,
272
+
273
+ module_eval(<<'.,.,', 'parser.y', 50)
274
+ def _reduce_15(val, _values)
275
+ val[0].push(val[1])
276
+
277
+ end
278
+ .,.,
279
+
280
+ module_eval(<<'.,.,', 'parser.y', 56)
281
+ def _reduce_16(val, _values)
282
+ [:cond, *val[2]]
283
+
284
+ end
285
+ .,.,
286
+
287
+ module_eval(<<'.,.,', 'parser.y', 61)
288
+ def _reduce_17(val, _values)
289
+ [val[0]]
290
+
291
+ end
292
+ .,.,
293
+
294
+ module_eval(<<'.,.,', 'parser.y', 65)
295
+ def _reduce_18(val, _values)
296
+ val[0].push(val[1])
297
+
298
+ end
299
+ .,.,
300
+
301
+ module_eval(<<'.,.,', 'parser.y', 70)
302
+ def _reduce_19(val, _values)
303
+ [val[1], val[2]]
304
+
305
+ end
306
+ .,.,
307
+
308
+ module_eval(<<'.,.,', 'parser.y', 74)
309
+ def _reduce_20(val, _values)
310
+ [:else, val[2]]
311
+
312
+ end
313
+ .,.,
314
+
315
+ module_eval(<<'.,.,', 'parser.y', 80)
316
+ def _reduce_21(val, _values)
317
+ [:if, val[2], val[3], val[4]]
318
+
319
+ end
320
+ .,.,
321
+
322
+ def _reduce_none(val, _values)
323
+ val[0]
324
+ end
325
+
326
+ end # class Parser
327
+
328
+ end # of module Rubic
@@ -0,0 +1,132 @@
1
+ class Parser
2
+ options no_result_var
3
+
4
+ rule
5
+ expr : '(' KW_AND seq ')'
6
+ {
7
+ [:and, *val[2]]
8
+ }
9
+ | '(' KW_OR seq ')'
10
+ {
11
+ [:or, *val[2]]
12
+ }
13
+ | '(' expr seq ')'
14
+ {
15
+ [val[1], *val[2]]
16
+ }
17
+ | IDENT
18
+ | NUMBER
19
+ | define
20
+ | define_proc
21
+ | cond
22
+ | if
23
+
24
+ seq : expr
25
+ {
26
+ [val[0]]
27
+ }
28
+ | seq expr
29
+ {
30
+ val[0].push(val[1])
31
+ }
32
+
33
+ /* Define statement */
34
+ define : '(' KW_DEFINE IDENT expr ')'
35
+ {
36
+ [:define, val[2], val[3]]
37
+ }
38
+
39
+ /* Procedure definition */
40
+ define_proc : '(' KW_DEFINE '(' IDENT params ')' seq ')'
41
+ {
42
+ [:define_proc, [val[3], *val[4]], *val[6]]
43
+ }
44
+
45
+ params : /* empty */
46
+ {
47
+ []
48
+ }
49
+ | params IDENT
50
+ {
51
+ val[0].push(val[1])
52
+ }
53
+
54
+ /* Condition statement */
55
+ cond : '(' KW_COND clauses ')'
56
+ {
57
+ [:cond, *val[2]]
58
+ }
59
+
60
+ clauses : clause
61
+ {
62
+ [val[0]]
63
+ }
64
+ | clauses clause
65
+ {
66
+ val[0].push(val[1])
67
+ }
68
+
69
+ clause : '(' expr expr ')'
70
+ {
71
+ [val[1], val[2]]
72
+ }
73
+ | '(' KW_ELSE expr ')'
74
+ {
75
+ [:else, val[2]]
76
+ }
77
+
78
+ /* If statement */
79
+ if : '(' KW_IF expr expr expr ')'
80
+ {
81
+ [:if, val[2], val[3], val[4]]
82
+ }
83
+ end
84
+
85
+ ---- header
86
+ require 'strscan'
87
+
88
+ module Rubic
89
+ class UnknownCharacterError < StandardError; end
90
+
91
+ ---- inner
92
+ EOT = [false, nil] # end of token
93
+ SYM_CHARS = Regexp.escape("+-*/<>=?")
94
+
95
+ def parse(str)
96
+ @s = StringScanner.new(str)
97
+ do_parse
98
+ end
99
+
100
+ def next_token
101
+ @s.skip(/\s+/)
102
+ return EOT if @s.eos?
103
+
104
+ case
105
+ when @s.scan(/[0-9]+(\.[0-9]+)?/)
106
+ [:NUMBER, @s[0].include?('.') ? @s[0].to_f : @s[0].to_i]
107
+ when @s.scan(/[\(\)]/o)
108
+ [@s[0], nil]
109
+ when @s.scan(/[A-Za-z_#{SYM_CHARS}][A-Za-z0-9_#{SYM_CHARS}]*/o)
110
+ case @s[0] # keyword check
111
+ when 'define'
112
+ [:KW_DEFINE, nil]
113
+ when 'cond'
114
+ [:KW_COND, nil]
115
+ when 'else'
116
+ [:KW_ELSE, nil]
117
+ when 'if'
118
+ [:KW_IF, nil]
119
+ when 'and'
120
+ [:KW_AND, nil]
121
+ when 'or'
122
+ [:KW_OR, nil]
123
+ else
124
+ [:IDENT, @s[0]]
125
+ end
126
+ else
127
+ raise UnknownCharacterError, "unknown character #{@s.getch}"
128
+ end
129
+ end
130
+
131
+ ---- footer
132
+ end # of module Rubic
@@ -0,0 +1,3 @@
1
+ module Rubic
2
+ VERSION = "0.1.0"
3
+ end
data/lib/rubic.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Rubic
2
+ end
3
+
4
+ require 'rubic/version'
5
+ require 'rubic/interpreter'
data/rubic.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rubic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rubic"
8
+ spec.version = Rubic::VERSION
9
+ spec.authors = ["notozeki"]
10
+ spec.email = ["notozeki@gmail.com"]
11
+
12
+ spec.summary = %q{A tiny Scheme interpreter}
13
+ spec.description = %q{Rubic is a very simple Scheme interpreter written in Ruby.}
14
+ spec.homepage = "https://github.com/notozeki/rubic"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.9"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "minitest", "~> 5.5"
23
+
24
+ spec.add_dependency "racc", "~> 1.4"
25
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - notozeki
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: racc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ description: Rubic is a very simple Scheme interpreter written in Ruby.
70
+ email:
71
+ - notozeki@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/console
83
+ - bin/setup
84
+ - lib/rubic.rb
85
+ - lib/rubic/environment.rb
86
+ - lib/rubic/interpreter.rb
87
+ - lib/rubic/parser.rb
88
+ - lib/rubic/parser.y
89
+ - lib/rubic/version.rb
90
+ - rubic.gemspec
91
+ homepage: https://github.com/notozeki/rubic
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.4.5
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: A tiny Scheme interpreter
115
+ test_files: []