rubasteme 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SicpScheme
4
+
5
+ # primitive procedure for SICP Scheme
6
+
7
+ module Primitives
8
+ def cons(obj1, obj2)
9
+ [obj1, obj2]
10
+ end
11
+
12
+ def pair?(obj)
13
+ obj.instance_of?(Array)
14
+ end
15
+
16
+ def car(lis)
17
+ lis[0]
18
+ end
19
+
20
+ def cdr(lis)
21
+ lis[1..-1]
22
+ end
23
+
24
+ def list(*args)
25
+ args
26
+ end
27
+
28
+ def append(*args)
29
+ if args.empty?
30
+ []
31
+ else
32
+ args[0] + append(*args[1..-1])
33
+ end
34
+ end
35
+
36
+ def write(obj)
37
+ print obj
38
+ end
39
+
40
+ def display(obj)
41
+ write(obj)
42
+ print "\n"
43
+ end
44
+
45
+ def zero?(obj)
46
+ eqv?(obj, 0)
47
+ end
48
+
49
+ def a_calc(op, *args)
50
+ case args.size
51
+ when 0
52
+ 0
53
+ when 1
54
+ args[0]
55
+ else
56
+ a_calc(op, args[0].send(op, args[1]), *args[2..-1])
57
+ end
58
+ end
59
+
60
+ def add(*args)
61
+ a_calc(:+, *args)
62
+ end
63
+
64
+ def subtract(*args)
65
+ a_calc(:-, *args)
66
+ end
67
+
68
+ def mul(*args)
69
+ a_calc(:*, *args)
70
+ end
71
+
72
+ def div(*args)
73
+ a_calc(:/, *args)
74
+ end
75
+
76
+ def mod(*args)
77
+ a_calc(:%, *args)
78
+ end
79
+
80
+ def scm_true
81
+ [:ast_boolean, "#t"]
82
+ end
83
+
84
+ def scm_false
85
+ [:ast_boolean, "#f"]
86
+ end
87
+
88
+ def c_calc(op, *args)
89
+ case args.size
90
+ when 0, 1
91
+ raise ArgumentError, args.to_s
92
+ when 2
93
+ args[0].send(op, args[1]) ? scm_true : scm_false
94
+ else
95
+ args[0].send(op, args[1]) and c_calc(op, *args[1..-1]) ? scm_true : scm_false
96
+ end
97
+ end
98
+
99
+ def lt?(*args)
100
+ c_calc(:<, *args)
101
+ end
102
+
103
+ def le?(*args)
104
+ c_calc(:<=, *args)
105
+ end
106
+
107
+ def gt?(*args)
108
+ c_calc(:>, *args)
109
+ end
110
+
111
+ def ge?(*args)
112
+ c_calc(:>=, *args)
113
+ end
114
+
115
+ def same_value?(*args)
116
+ c_calc(:==, *args)
117
+ end
118
+
119
+ def eqv?(obj1, obj2)
120
+ obj1 == obj2 ? scm_true : scm_false
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SicpScheme
4
+ class Printer
5
+ def initialize
6
+ end
7
+
8
+ def print(scm_obj)
9
+ pp scm_obj
10
+ end
11
+ end
12
+ end
data/exe/rubasteme ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "pp"
4
+ require "rubasteme"
5
+
6
+ def version
7
+ "Rubasteme version: #{Rubasteme::VERSION} (#{Rubasteme::RELEASE})"
8
+ end
9
+
10
+ def usage
11
+ puts <<HELP
12
+ usage:
13
+ rubasteme [option] [FILE]
14
+
15
+ Reads the given files as a sequence of tokens, then print AST nodes.
16
+ If no FILE is specified, then tries to read from the standard input.
17
+
18
+ option:
19
+ -o, --output-file OUTPUT_FILE : specify the output file
20
+ -t, --format-type TYPE : specify the output format
21
+ -d, --debug : specify to run verbosely
22
+ -v, --version : print version
23
+ -h, --help : show this message
24
+
25
+ input format:
26
+ Specify one of the following names:
27
+ ast, array
28
+ HELP
29
+ end
30
+
31
+ def opt_parse(args, opts = {})
32
+ files = []
33
+ while args.size > 0
34
+ arg = args.shift
35
+ case arg
36
+ when "-o", "--output-file"
37
+ opts[:output_file] = args.shift
38
+ when "-t", "--format-type"
39
+ format_type = args.shift
40
+ raise ArgumentError, "not specified as format type" if format_type.nil?
41
+ opts[:format_type] = format_type.intern
42
+ when "-d", "--debug"
43
+ opts[:verbose] = true
44
+ when "-v", "--version"
45
+ puts version
46
+ exit 0
47
+ when "-h", "--help"
48
+ puts usage
49
+ exit 0
50
+ else # must be a filename
51
+ files << arg if arg
52
+ end
53
+ end
54
+ args.concat(files)
55
+ opts
56
+ end
57
+
58
+ opts = opt_parse(ARGV)
59
+ if opts[:verbose]
60
+ puts version
61
+ format = opts[:format_type] || "default (token)"
62
+ puts "Input format: #{format}"
63
+ ofname = opts[:output_file] || "STDOUT"
64
+ puts "Output file: #{ofname}"
65
+ end
66
+
67
+ lines = []
68
+ if ARGV.size > 0
69
+ lines = ARGF.entries.map{|s| s.delete_suffix("\n")}
70
+ else
71
+ lines = STDIN.readlines(chomp: true)
72
+ end
73
+
74
+ tokens = lines.map{|e| Kernel.eval(e)}
75
+ lexer = Rubasteme.lexer(tokens)
76
+ parser = Rubasteme.parser(lexer)
77
+ ast = parser.parse
78
+
79
+ output = ""
80
+ PP.pp(ast.to_a, output)
81
+
82
+ form = opts[:format_type] || :token
83
+ of = STDOUT
84
+ of = File.open(opts[:output_file], "w") if opts[:output_file]
85
+
86
+ of.puts(output)
87
+
88
+ of.close
data/lib/rubasteme.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbscmlex"
4
+
5
+ module Rubasteme
6
+
7
+ def self.lexer(obj)
8
+ Rbscmlex::Lexer.new(obj)
9
+ end
10
+
11
+ require_relative "rubasteme/error"
12
+ require_relative "rubasteme/utils"
13
+ require_relative "rubasteme/ast"
14
+ require_relative "rubasteme/parser"
15
+ require_relative "rubasteme/version"
16
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubasteme
4
+
5
+ def self.write(ast_node, of = STDOUT)
6
+ of.puts ast_node.to_s
7
+ end
8
+
9
+ module AST
10
+
11
+ AST_NODE_TYPE = [ # :nodoc:
12
+ # leaf
13
+ :ast_empty_list,
14
+ :ast_boolean,
15
+ :ast_identifier,
16
+ :ast_character,
17
+ :ast_string,
18
+ :ast_number,
19
+ :ast_dot,
20
+ # branch
21
+ :ast_program,
22
+ :ast_list,
23
+ :ast_quotation,
24
+ :ast_procedure_call,
25
+ :ast_lambda_expression,
26
+ :ast_formals,
27
+ :ast_conditional,
28
+ :ast_assignment,
29
+ :ast_identifier_definition,
30
+ :ast_cond,
31
+ :ast_cond_clause,
32
+ :ast_case,
33
+ :ast_and,
34
+ :ast_or,
35
+ :ast_when,
36
+ :ast_unless,
37
+ :ast_let,
38
+ :ast_let_star,
39
+ :ast_letrec,
40
+ :ast_letrec_star,
41
+ :ast_bindings,
42
+ :ast_bind_spec,
43
+ :ast_begin,
44
+ :ast_do,
45
+ :ast_iteration_bindings,
46
+ :ast_test_and_do_result,
47
+ :ast_iteration_spec,
48
+ # misc.
49
+ :ast_illegal,
50
+ ]
51
+
52
+ def self.instantiate(ast_node_type, literal)
53
+ type_name = Utils.camel_case(ast_node_type.to_s.delete_prefix("ast_"))
54
+ klass = AST.const_get("#{type_name}Node")
55
+
56
+ if klass.nil? or klass == IllegalNode
57
+ IllegalNode.new(ast_node_type, literal)
58
+ else
59
+ klass.new(literal)
60
+ end
61
+ end
62
+
63
+ class Node
64
+ def initialize(_literal = nil)
65
+ end
66
+
67
+ def type
68
+ klass_name = self.class.name.split("::")[-1]
69
+ type_name = Utils.snake_case(klass_name.delete_suffix("Node"))
70
+ "ast_#{type_name}".intern
71
+ end
72
+
73
+ def to_a; []; end
74
+ def to_s; to_a.to_s; end
75
+ end
76
+
77
+ require_relative "ast/leaf_node"
78
+ require_relative "ast/branch_node"
79
+
80
+ class IllegalNode < Node
81
+ def initialize(type, literal)
82
+ super(literal)
83
+ @given_type = type
84
+ @literal = literal
85
+ end
86
+
87
+ def to_a
88
+ [type, @given_type, @literal]
89
+ end
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,514 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubasteme
4
+
5
+ module AST
6
+
7
+ class BranchNode < Node
8
+ def initialize(initial_size = nil)
9
+ super(nil)
10
+ @nodes = initial_size.nil? ? [] : Array.new(initial_size)
11
+ end
12
+
13
+ def size
14
+ @nodes.size
15
+ end
16
+
17
+ def to_a
18
+ [type].concat(@nodes.map(&:to_a))
19
+ end
20
+
21
+ include Enumerable
22
+
23
+ def each(&blk)
24
+ if block_given?
25
+ @nodes.each(&blk)
26
+ self
27
+ else
28
+ @nodes.each
29
+ end
30
+ end
31
+
32
+ def [](index)
33
+ @nodes[index]
34
+ end
35
+
36
+ def []=(index, node)
37
+ @nodes[index] = node
38
+ end
39
+
40
+ def <<(node)
41
+ @nodes << node
42
+ end
43
+ end
44
+
45
+ class ProgramNode < BranchNode
46
+ def initialize(_ = nil)
47
+ super(nil)
48
+ end
49
+ end
50
+
51
+ class VectorNode < BranchNode
52
+ def initialize(_ = nil)
53
+ super(nil)
54
+ end
55
+ end
56
+
57
+ class ListNode < BranchNode
58
+ def initialize(_ = nil)
59
+ super(nil)
60
+ end
61
+ end
62
+
63
+ class QuotationNode < ListNode
64
+ def initialize(_ = nil)
65
+ super(nil)
66
+ end
67
+ end
68
+
69
+ class ProcedureCallNode < ListNode
70
+ def initialize(_ = nil)
71
+ # @nodes = [<operator>, <operand>*]
72
+ super(1)
73
+ end
74
+
75
+ def operator
76
+ @nodes[0]
77
+ end
78
+
79
+ def operator=(node)
80
+ @nodes[0] = node
81
+ end
82
+
83
+ def operands
84
+ @nodes[1..-1]
85
+ end
86
+
87
+ def add_operand(node)
88
+ @nodes << node
89
+ end
90
+ end
91
+
92
+ class LambdaExpressionNode < ListNode
93
+ def initialize(_ = nil)
94
+ # @nodes = [<formals>, <body>, ...]
95
+ super(1)
96
+ end
97
+
98
+ def formals
99
+ @nodes[0]
100
+ end
101
+
102
+ def formals=(node)
103
+ @nodes[0] = node
104
+ end
105
+
106
+ def body
107
+ @nodes[1..-1]
108
+ end
109
+
110
+ def body=(nodes)
111
+ nodes.each_with_index { |node, i|
112
+ @nodes[i + 1] = node
113
+ }
114
+ end
115
+ end
116
+
117
+ class FormalsNode < ListNode
118
+ def initialize(_ = nil)
119
+ # @nodes = [<identifier 1>, <identifier 2>, ... ]
120
+ super(nil)
121
+ end
122
+
123
+ def add_identifier(node)
124
+ @nodes << node
125
+ end
126
+ end
127
+
128
+ class ConditionalNode < ListNode
129
+ def initialize(_ = nil)
130
+ # @nodes = [<test>, <consequent>] or
131
+ # [<test>, <consequent>, <alternate>]
132
+ super(1)
133
+ end
134
+
135
+ def test
136
+ @nodes[0]
137
+ end
138
+
139
+ def test=(node)
140
+ @nodes[0] = node
141
+ end
142
+
143
+ def consequent
144
+ @nodes[1]
145
+ end
146
+
147
+ def consequent=(node)
148
+ @nodes[1] = node
149
+ end
150
+
151
+ def alternate
152
+ @nodes[2]
153
+ end
154
+
155
+ def alternate=(node)
156
+ @nodes[2] = node
157
+ end
158
+
159
+ def alternate?
160
+ !@nodes[2].nil?
161
+ end
162
+ end
163
+
164
+ class AssignmentNode < ListNode
165
+ def initialize(_ = nil)
166
+ # @nodes = [<identifier>, <expression>]
167
+ super(2)
168
+ end
169
+
170
+ def identifier
171
+ @nodes[0]
172
+ end
173
+
174
+ def identifier=(node)
175
+ @nodes[0] = node
176
+ end
177
+
178
+ def expression
179
+ @nodes[1]
180
+ end
181
+
182
+ def expression=(node)
183
+ @nodes[1] = node
184
+ end
185
+ end
186
+
187
+ class IdentifierDefinitionNode < ListNode
188
+ def initialize(_ = nil)
189
+ # @nodes = [<identifier>, <expression>]
190
+ # <expression> might be a lambda expression.
191
+ super(2)
192
+ end
193
+
194
+ def identifier
195
+ @nodes[0]
196
+ end
197
+
198
+ def identifier=(node)
199
+ @nodes[0] = node
200
+ end
201
+
202
+ def expression
203
+ @nodes[1]
204
+ end
205
+
206
+ def expression=(node)
207
+ @nodes[1] = node
208
+ end
209
+
210
+ def def_formals
211
+ lambda? ? expression.formals : nil
212
+ end
213
+
214
+ def body
215
+ lambda? ? expression.body : nil
216
+ end
217
+
218
+ private
219
+
220
+ def lambda?
221
+ expression.type == :ast_lambda_expression
222
+ end
223
+ end
224
+
225
+ class CondNode < ListNode
226
+ def initialize(_ = nil)
227
+ super(nil)
228
+ end
229
+
230
+ def cond_clause
231
+ @nodes[0..-1]
232
+ end
233
+
234
+ def add_clause(node)
235
+ @nodes << node
236
+ end
237
+ end
238
+
239
+ class CondClauseNode < ListNode
240
+ # @nodes = [<test>, <sequence>]
241
+ def initialize(_ = nil)
242
+ super(nil)
243
+ end
244
+
245
+ def test
246
+ @nodes[0]
247
+ end
248
+
249
+ def test=(node)
250
+ @nodes[0] = node
251
+ end
252
+
253
+ def sequence
254
+ @nodes[1..-1]
255
+ end
256
+
257
+ def add_expression(node)
258
+ @nodes << node
259
+ end
260
+ end
261
+
262
+ class AndNode < ListNode
263
+ def initialize(_ = nil)
264
+ # @nodes = [<test>, ...]
265
+ super(nil)
266
+ end
267
+ end
268
+
269
+ class OrNode < ListNode
270
+ def initialize(_ = nil)
271
+ # @nodes = [<test>, ...]
272
+ super(nil)
273
+ end
274
+ end
275
+
276
+ class TestAndSequenceNode < ListNode
277
+ def initialize(_ = nil)
278
+ super(1)
279
+ end
280
+
281
+ def test
282
+ @nodes[0]
283
+ end
284
+
285
+ def test=(node)
286
+ @nodes[0] = node
287
+ end
288
+
289
+ def sequence
290
+ @nodes[1..-1]
291
+ end
292
+
293
+ def add_sequence(node)
294
+ @nodes << node
295
+ end
296
+ end
297
+
298
+ class WhenNode < TestAndSequenceNode
299
+ end
300
+
301
+ class UnlessNode < TestAndSequenceNode
302
+ end
303
+
304
+ class LetNode < ListNode
305
+ def initialize(_ = nil)
306
+ # @nodes = [<bindings>, <body>, ...] or
307
+ # [<identifier>, <bindings>, <body>, ...]
308
+ super(1)
309
+ end
310
+
311
+ def identifier
312
+ named_let? ? @nodes[0] : nil
313
+ end
314
+
315
+ def identifier=(node)
316
+ @nodes.insert(0, node) if node.type == :ast_identifier
317
+ end
318
+
319
+ def bindings
320
+ named_let? ? @nodes[1] : @nodes[0]
321
+ end
322
+
323
+ def bindings=(node)
324
+ if named_let?
325
+ @nodes[1] = node
326
+ else
327
+ @nodes[0] = node
328
+ end
329
+ end
330
+
331
+ def body
332
+ named_let? ? @nodes[2..-1] : @nodes[1..-1]
333
+ end
334
+
335
+ def body=(nodes)
336
+ start_pos = named_let? ? 2 : 1
337
+ nodes.each_with_index { |node, i|
338
+ @nodes[start_pos + i] = node
339
+ }
340
+ end
341
+
342
+ private
343
+
344
+ def named_let?
345
+ @nodes[0].nil? ? false : @nodes[0].type == :ast_identifier
346
+ end
347
+ end
348
+
349
+ class LetBaseNode < ListNode
350
+ def initialize(_ = nil)
351
+ # @nodes = [<bindings>, <body>, ...]
352
+ super(1)
353
+ end
354
+
355
+ def bindings
356
+ @nodes[0]
357
+ end
358
+
359
+ def bindings=(node)
360
+ @nodes[0] = node
361
+ end
362
+
363
+ def body
364
+ @nodes[1..-1]
365
+ end
366
+
367
+ def body=(nodes)
368
+ nodes.each_with_index { |node, i|
369
+ @nodes[1 + i] = node
370
+ }
371
+ end
372
+ end
373
+
374
+ class LetStarNode < LetBaseNode
375
+ end
376
+
377
+ class LetrecNode < LetBaseNode
378
+ end
379
+
380
+ class LetrecStarNode < LetBaseNode
381
+ end
382
+
383
+ class BindingsNode < ListNode
384
+ def initialize(_ = nil)
385
+ # @nodes = [<bind spec 1>, <bind spec 2> , ...]
386
+ super(nil)
387
+ end
388
+
389
+ def add_bind_spec(node)
390
+ @nodes << node
391
+ end
392
+ end
393
+
394
+ class BindSpecNode < ListNode
395
+ def initialize(_ = nil)
396
+ super(2)
397
+ end
398
+
399
+ def identifier
400
+ @nodes[0]
401
+ end
402
+
403
+ def identifier=(node)
404
+ @nodes[0] = node
405
+ end
406
+
407
+ def expression
408
+ @nodes[1]
409
+ end
410
+
411
+ def expression=(node)
412
+ @nodes[1] = node
413
+ end
414
+ end
415
+
416
+ class BeginNode < ListNode
417
+ def initialize(_ = nil)
418
+ super(nil)
419
+ end
420
+ end
421
+
422
+ class DoNode < ListNode
423
+ def initialize(_ = nil)
424
+ # @nodes = [<iteration bindings>, <test and do result>, <command>, ...]
425
+ super(2)
426
+ end
427
+
428
+ def iteration_bindings
429
+ @nodes[0]
430
+ end
431
+
432
+ def iteration_bindings=(node)
433
+ @nodes[0] = node
434
+ end
435
+
436
+ def test_and_do_result
437
+ @nodes[1]
438
+ end
439
+
440
+ def test_and_do_result=(node)
441
+ @nodes[1] = node
442
+ end
443
+
444
+ def commands
445
+ @nodes[2..-1]
446
+ end
447
+
448
+ def add_command(node)
449
+ @nodes << node
450
+ end
451
+ end
452
+
453
+ class IterationBindingsNode < ListNode
454
+ def initialize(_ = nil)
455
+ super(nil)
456
+ end
457
+
458
+ def add_iteration_spec(node)
459
+ @nodes << node
460
+ end
461
+ end
462
+
463
+ class TestAndDoResultNode < ListNode
464
+ def initialize(_ = nil)
465
+ super(1)
466
+ end
467
+
468
+ def test
469
+ @nodes[0]
470
+ end
471
+
472
+ def test=(node)
473
+ @nodes[0] = node
474
+ end
475
+
476
+ def add_expression(node)
477
+ @nodes << node
478
+ end
479
+ end
480
+
481
+ class IterationSpecNode < ListNode
482
+ def initialize(_ = nil)
483
+ # @nodes = [<identifier>, <init>, <step>]
484
+ super(3)
485
+ end
486
+
487
+ def identifier
488
+ @nodes[0]
489
+ end
490
+
491
+ def identifier=(node)
492
+ @nodes[0] = node
493
+ end
494
+
495
+ def init
496
+ @nodes[1]
497
+ end
498
+
499
+ def init=(node)
500
+ @nodes[1] = node
501
+ end
502
+
503
+ def step
504
+ @nodes[2]
505
+ end
506
+
507
+ def step=(node)
508
+ @nodes[2] = node
509
+ end
510
+ end
511
+
512
+ end # end of AST
513
+
514
+ end