rubasteme 0.1.1 → 0.1.6

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.
@@ -32,6 +32,10 @@ module Rubasteme
32
32
  def initialize(literal)
33
33
  super
34
34
  end
35
+
36
+ def identifier
37
+ literal
38
+ end
35
39
  end
36
40
 
37
41
  class CharacterNode < LeafNode
@@ -5,7 +5,7 @@ module Rubasteme
5
5
 
6
6
  # :stopdoc:
7
7
  EMSG = {
8
- scheme_sytanx_error: "syntax error: got=%s",
8
+ scheme_syntax_error: "syntax error: %s",
9
9
  unexpected_token_type: "unexpected token type: got=%s, expected=%s",
10
10
  missing_right_parenthesis: "missing right parenthesis",
11
11
  unsupported_feature: "unsupported feature: %s",
@@ -15,8 +15,8 @@ module Rubasteme
15
15
 
16
16
  # Indicates a syntax error as Scheme program.
17
17
  class SchemeSyntaxErrorError < Error
18
- def initialize(literal)
19
- super(EMSG[:scheme_syntax_error] % literal)
18
+ def initialize(msg)
19
+ super(EMSG[:scheme_syntax_error] % msg)
20
20
  end
21
21
  end
22
22
 
@@ -3,607 +3,54 @@
3
3
  module Rubasteme
4
4
 
5
5
  def self.parser
6
- Parser.new
6
+ Parser::Parser.new
7
7
  end
8
8
 
9
- class Parser
9
+ module Parser
10
10
 
11
- def initialize
12
- @lexer = nil
11
+ def self.version
12
+ Rubasteme.send(:make_version, self.name)
13
13
  end
14
14
 
15
- def parse(lexer)
16
- return [] if lexer.nil?
17
- @lexer = lexer
18
- parse_program
19
- end
20
-
21
- def parse_program
22
- ast_program = AST.instantiate(:ast_program, nil)
23
- Kernel.loop {
24
- ast_program << parse_expression
25
- }
26
- ast_program
27
- end
28
-
29
- def parse_expression
30
- if start_delimiter?(@lexer.peek_token)
31
- parse_compound_expression
32
- else
33
- parse_simple_expression
34
- end
35
- end
36
-
37
- def parse_simple_expression
38
- type, literal = *@lexer.next_token
39
- AST.instantiate(ast_simple_type(type), literal)
40
- end
41
-
42
- def parse_identifier
43
- parse_simple_expression
44
- end
45
-
46
- TOKEN_START_DELIMITERS = [ # :nodoc:
47
- :lparen, # list: ( ... )
48
- :vec_lparen, # vector: #( ... )
49
- :bytevec_lparen, # bytevector: #u8( ... )
50
- :quotation, # quotation: '<something>
51
- :backquote, # quasiquote: `<something>
52
- :comma, # used in quasiquote
53
- :comma_at, # used in quasiquote
54
- :comment_lparen, # comment start
55
- ]
56
-
57
- def start_delimiter?(token)
58
- TOKEN_START_DELIMITERS.include?(token.type)
59
- end
60
-
61
- def parse_compound_expression
62
- case @lexer.peek_token.type
63
- when :vec_lparen
64
- parse_vector
65
- when :quotation
66
- parse_quotation
67
- when :lparen
68
- parse_list_expression
69
- else
70
- raise SchemeSyntaxError, @lexer.peek_token.literal
71
- end
72
- end
73
-
74
- def parse_vector
75
- parse_data_to_matched_rparen
76
- end
77
-
78
- def parse_data_to_matched_rparen
79
- token = @lexer.next_token
80
- node = AST.instantiate(ast_compound_type(token.type), nil)
81
- Kernel.loop {
82
- break if @lexer.peek_token.type == :rparen
83
- node << parse_datum
84
- }
85
- skip_rparen
86
-
87
- node
88
- end
89
-
90
- def parse_datum
91
- if start_delimiter?(@lexer.peek_token)
92
- parse_compound_datum
93
- else
94
- parse_simple_datum
95
- end
96
- end
97
-
98
- def parse_simple_datum
99
- parse_simple_expression
100
- end
101
-
102
- def parse_compound_datum
103
- case @lexer.peek_token.type
104
- when :lparen
105
- parse_data_list
106
- when :vec_lparen
107
- parse_vector
108
- else
109
- parse_simple_expression
110
- end
111
- end
112
-
113
- def parse_data_list
114
- parse_data_to_matched_rparen
115
- end
116
-
117
- def parse_quotation
118
- literal = @lexer.next_token.literal
119
- quote_node = AST.instantiate(:ast_quotation, literal)
120
- quote_node << parse_datum
121
- quote_node
122
- end
123
-
124
- DERIVED_IDENTIFIERS = [
125
- "cond", "case", "and", "or", "when", "unless",
126
- "let", "let*", "letrec", "letrec*",
127
- "let-values", "let*-values",
128
- "begin", "do",
129
- "delay", "delay-force",
130
- "parameterize",
131
- "guard",
132
- "case-lambda",
133
- ]
134
-
135
- def parse_list_expression
136
- node = nil
137
- skip_lparen
138
- type, literal = *@lexer.peek_token
139
- case type
140
- when :rparen
141
- # an empty list
142
- node = AST.instantiate(:ast_empty_list, nil)
143
- skip_rparen
144
- when :identifier
145
- case literal
146
- when "lambda"
147
- node = parse_lambda_expression
148
- when "if"
149
- node = parse_conditional
150
- when "set!"
151
- node = parse_assignment
152
- when "let-syntax", "letrec-syntax"
153
- node = parse_macro_block
154
- when "define", "define-syntax", "define-values", "define-record-type"
155
- node = parse_definition
156
- when "include", "include-ci"
157
- node = parse_includer
158
- when *DERIVED_IDENTIFIERS
159
- node = parse_derived_expression
160
- end
161
- end
162
- node || parse_procedure_call
163
- end
164
-
165
- def parse_procedure_call
166
- proc_call_node = AST.instantiate(:ast_procedure_call, nil)
167
- proc_call_node.operator = parse_operator
168
- Kernel.loop {
169
- break if @lexer.peek_token.type == :rparen
170
- proc_call_node.add_operand(parse_operand)
171
- }
172
- skip_rparen
173
- proc_call_node
174
- end
175
-
176
- def parse_operator
177
- parse_expression
178
- end
179
-
180
- def parse_operand
181
- parse_expression
182
- end
183
-
184
- def parse_lambda_expression
185
- @lexer.skip_token # skip :lambda
186
- lambda_node = make_lambda_expression_node(parse_formals, read_body)
187
- skip_rparen
188
- lambda_node
189
- end
190
-
191
- def make_lambda_expression_node(formals, body)
192
- lambda_node = AST.instantiate(:ast_lambda_expression, nil)
193
- lambda_node.formals = formals
194
- lambda_node.body = body
195
- lambda_node
196
- end
197
-
198
- def parse_formals
199
- formals_node = nil
200
- # type 1: <identifier>
201
- # type 2: ( <identifier 1> <identifier 2> ... )
202
- # type 3: ( <identifier 1> <identifier 2> <dot> <identifier n> )
203
- # => not supported yet
204
- if @lexer.peek_token.type == :lparen
205
- formals_node = AST.instantiate(:ast_formals, nil)
206
- skip_lparen
207
- Kernel.loop {
208
- break if @lexer.peek_token.type == :rparen
209
- formals_node.add_identifier(parse_identifier)
210
- }
211
- else # type 1
212
- formals_node = parse_identifier
213
- end
214
- skip_rparen
215
- formals_node
216
- end
217
-
218
- def read_body
219
- body = []
220
- Kernel.loop {
221
- break if @lexer.peek_token.type == :rparen # the end of lambda exp.
222
- body << parse_expression
223
- }
224
- body
225
- end
226
-
227
- def parse_conditional
228
- if_node = AST.instantiate(:ast_conditional, @lexer.next_token.literal)
229
- if_node.test = parse_test
230
- if_node.consequent = parse_consequent
231
- if @lexer.peek_token.type != :rparen
232
- if_node.alternate = parse_alternate
233
- end
234
- skip_rparen
235
- if_node
236
- end
237
-
238
- def parse_test
239
- parse_expression
240
- end
241
-
242
- def parse_consequent
243
- parse_expression
244
- end
245
-
246
- def parse_alternate
247
- parse_expression
248
- end
249
-
250
- def parse_assignment
251
- assignment_node = AST.instantiate(:ast_assignment, @lexer.next_token.literal)
252
- assignment_node.identifier = parse_identifier
253
- assignment_node.expression = parse_expression
254
- skip_rparen
255
- assignment_node
256
- end
257
-
258
- def parse_macro_block
259
- not_implemented_yet("MACRO block")
260
- end
261
-
262
- def parse_definition
263
- case @lexer.peek_token.literal
264
- when "define"
265
- parse_identifier_definition
266
- when "define-syntax"
267
- parse_define_syntax
268
- when "define-values"
269
- parse_define_values
270
- when "define-record-type"
271
- parse_define_record_type
272
- else
273
- raise SchemeSyntaxErrorError, @lexer.peek_token.literal
274
- end
275
- end
276
-
277
- def parse_identifier_definition
278
- # type 1: (define foo 3)
279
- # type 2: (define bar (lambda (x y) (+ x y)))
280
- # type 3: (define (hoge n m) (display n) (display m) (* n m))
281
- define_node = AST.instantiate(:ast_identifier_definition, @lexer.next_token.literal)
282
-
283
- case @lexer.peek_token.type
284
- when :identifier
285
- # type 1 and type 2
286
- define_node.identifier = parse_identifier
287
- define_node.expression = parse_expression
288
- skip_rparen
289
- when :lparen
290
- # type 3:
291
- # make a lambda expression, then handle as type 2
292
- skip_lparen
293
- define_node.identifier = parse_identifier
294
- def_formals_node = AST.instantiate(:ast_formals, nil)
295
- Kernel.loop {
296
- break if @lexer.peek_token.type == :rparen
297
- def_formals_node.add_identifier(parse_identifier)
298
- }
299
- skip_rparen
300
-
301
- lambda_node = make_lambda_expression_node(def_formals_node, read_body)
302
- skip_rparen
303
-
304
- define_node.expression = lambda_node
305
- else
306
- raise SchemeSyntaxErrorError, @lexer.peek_token.literal
307
- end
308
-
309
- define_node
310
- end
311
-
312
- def parse_define_syntax
313
- not_implemented_yet("DEFINE-SYNTAX")
314
- end
315
-
316
- def parse_define_values
317
- not_implemented_yet("DEFINE-VALUES")
318
- end
319
-
320
- def parse_define_record_type
321
- not_implemented_yet("DEFINE-RECORD-TYPE")
322
- end
323
-
324
- def parse_includer
325
- not_implemented_yet("INCLUDE or INCLUDE-CI")
326
- end
327
-
328
- def parse_derived_expression
329
- literal = @lexer.next_token.literal
330
- name = compose_method_name("parse_", literal).intern
331
- if self.respond_to?(name)
332
- m = self.method(name)
333
- m.call
334
- else
335
- not_implemented_yet(literal)
15
+ module Utils
16
+ def ast?(obj)
17
+ obj.kind_of?(AST::Node)
336
18
  end
337
- end
338
-
339
- def parse_cond
340
- cond_node = AST.instantiate(:ast_cond, nil)
341
- Kernel.loop {
342
- break if @lexer.peek_token.type == :rparen
343
- cond_node.add_clause(parse_cond_clause)
344
- }
345
- skip_rparen
346
- cond_node
347
- end
348
-
349
- def parse_cond_clause
350
- skip_lparen
351
- clause_node = AST.instantiate(:ast_cond_clause, nil)
352
- # type 1: ( <test> )
353
- # type 2: ( <test> => <expression> )
354
- # type 3: ( <test> <sequence> )
355
- # type 4: ( else <sequence> )
356
- clause_node.test = parse_test
357
- Kernel.loop {
358
- break if @lexer.peek_token.type == :rparen
359
- clause_node.add_expression(parse_expression)
360
- }
361
- skip_rparen
362
- clause_node
363
- end
364
-
365
- def parse_case
366
- not_implemented_yet("CASE")
367
- end
368
-
369
- def parse_and
370
- parse_logical_test("and")
371
- end
372
-
373
- def parse_or
374
- parse_logical_test("or")
375
- end
376
19
 
377
- def parse_logical_test(type)
378
- ast_type = "ast_#{type}".intern
379
- node = AST.instantiate(ast_type, nil)
380
- Kernel.loop {
381
- break if @lexer.peek_token.type == :rparen
382
- node << parse_test
383
- }
384
- skip_rparen
385
- node
386
- end
387
-
388
- def parse_when
389
- parse_test_and_sequence("when")
390
- end
391
-
392
- def parse_unless
393
- parse_test_and_sequence("unless")
394
- end
395
-
396
- def parse_test_and_sequence(type)
397
- ast_type = "ast_#{type}".intern
398
- node = AST.instantiate(ast_type, nil)
399
- node.test = parse_test
400
- Kernel.loop {
401
- break if @lexer.peek_token.type == :rparen
402
- node << parse_expression
403
- }
404
- skip_rparen
405
- node
406
- end
407
-
408
- def parse_let
409
- let_node = AST.instantiate(:ast_let, nil)
410
- if @lexer.peek_token.type == :identifier
411
- let_node.identifier = parse_identifier
20
+ def ast_type?(obj, type)
21
+ ast?(obj) && obj.type == type
412
22
  end
413
- let_node.bindings = parse_bindings
414
- let_node.body = read_body
415
- skip_rparen
416
- let_node
417
- end
418
-
419
- def parse_bindings
420
- bindings_node = AST.instantiate(:ast_bindings, nil)
421
- skip_lparen
422
- Kernel.loop {
423
- break if @lexer.peek_token.type == :rparen
424
- bindings_node.add_bind_spec(parse_bind_spec)
425
- }
426
- skip_rparen
427
- bindings_node
428
- end
429
-
430
- def parse_bind_spec
431
- spec_node = AST.instantiate(:ast_bind_spec, nil)
432
- skip_lparen
433
- spec_node.identifier = parse_identifier
434
- spec_node.expression = parse_expression
435
- skip_rparen
436
- spec_node
437
- end
438
-
439
- def parse_let_star
440
- parse_let_base("let_star")
441
- end
442
-
443
- def parse_letrec
444
- parse_let_base("letrec")
445
- end
446
-
447
- def parse_letrec_star
448
- parse_let_base("letrec_star")
449
- end
450
23
 
451
- def parse_let_base(type)
452
- ast_type = "ast_#{type}".intern
453
- node = AST.instantiate(ast_type, nil)
454
- node.bindings = parse_bindings
455
- node.body = read_body
456
- skip_rparen
457
- node
458
- end
459
-
460
- def parse_let_values
461
- not_implemented_yet("LET-VALUES")
462
- end
463
-
464
- def parse_let_star_values
465
- not_implemented_yet("LET*-VALUES")
466
- end
467
-
468
- def parse_begin
469
- begin_node = AST.instantiate(:ast_begin, nil)
470
- Kernel.loop {
471
- break if @lexer.peek_token.type == :rparen
472
- begin_node << parse_expression
473
- }
474
- skip_rparen
475
- begin_node
476
- end
477
-
478
- def parse_do
479
- do_node = AST.instantiate(:ast_do, nil)
480
- do_node.iteration_bindings = parse_iteration_bindings
481
- do_node.test_and_do_result = parse_test_and_do_result
482
- Kernel.loop {
483
- break if @lexer.peek_token.type == :rparen
484
- do_node.add_command(parse_expression)
485
- }
486
- skip_rparen
487
- do_node
488
- end
489
-
490
- def parse_iteration_bindings
491
- node = AST.instantiate(:ast_iteration_bindings, nil)
492
- skip_lparen
493
- Kernel.loop {
494
- break if @lexer.peek_token.type == :rparen
495
- node.add_iteration_spec(parse_iteration_spec)
496
- }
497
- skip_rparen
498
- node
499
- end
500
-
501
- def parse_iteration_spec
502
- spec_node = AST.instantiate(:ast_iteration_spec, nil)
503
- skip_lparen
504
- spec_node.identifier = parse_identifier
505
- spec_node.init = parse_init
506
- if @lexer.peek_token.type != :rparen
507
- spec_node.step = parse_step
24
+ def not_implemented_yet(feature)
25
+ raise NotImplementedYetError, feature
508
26
  end
509
- skip_rparen
510
- spec_node
511
- end
512
-
513
- def parse_init
514
- parse_expression
515
- end
516
-
517
- def parse_step
518
- parse_expression
519
- end
520
-
521
- def parse_test_and_do_result
522
- node = AST.instantiate(:ast_test_and_do_result, nil)
523
- skip_lparen
524
- node << parse_test
525
- Kernel.loop {
526
- break if @lexer.peek_token.type == :rparen
527
- node.add_expression(parse_expression)
528
- }
529
- skip_rparen
530
- node
531
- end
532
-
533
- def parse_delay
534
- not_implemented_yet("DELAY")
535
- end
536
-
537
- def parse_delay_force
538
- not_implemented_yet("DELAY-FORCE")
539
- end
540
-
541
- def parse_parameterize
542
- not_implemented_yet("PARAMETERIZE")
543
27
  end
544
28
 
545
- def parse_guard
546
- not_implemented_yet("GUARD")
547
- end
548
-
549
- def parse_case_lambda
550
- not_implemented_yet("CASE-LAMBDA")
551
- end
29
+ require_relative "parser/phase1_parser"
30
+ require_relative "parser/phase2_parser"
552
31
 
553
- private
32
+ class Parser
33
+ include Utils
554
34
 
555
- def skip_lparen
556
- if @lexer.peek_token.type == :lparen
557
- @lexer.skip_token
558
- else
559
- raise UnexpectedTokenTypeError.new(@lexer.peek_token.type, :lparen)
35
+ def self.version
36
+ Rubasteme::Parser.send(:version)
560
37
  end
561
- end
562
38
 
563
- def skip_rparen
564
- if @lexer.peek_token.type == :rparen
565
- @lexer.skip_token
566
- else
567
- raise MissingRightParenthesisError
39
+ def version
40
+ self.class.version
568
41
  end
569
- end
570
42
 
571
- def ast_simple_type(token_type)
572
- case token_type
573
- when :identifier
574
- :ast_identifier
575
- when :boolean, :character, :number, :string
576
- "ast_#{token_type}".intern
577
- when :dot
578
- :ast_dot
579
- else
580
- :ast_identifier
43
+ def initialize
44
+ @p1 = Phase1Parser.new
45
+ @p2 = Phase2Parser.new
581
46
  end
582
- end
583
47
 
584
- def ast_compound_type(token_type)
585
- case token_type
586
- when :vec_lparen
587
- :ast_vector
588
- else
589
- :ast_list
48
+ def parse(lexer)
49
+ return [] if lexer.nil?
50
+ ast_program = AST.instantiate(:ast_program)
51
+ Kernel.loop{ast_program << @p2.parse(@p1.parse(lexer))}
52
+ ast_program
590
53
  end
591
- end
592
-
593
- SCM_CHAR_TO_RB_MAP = {
594
- "*" => "_star",
595
- "-" => "_",
596
- }
597
-
598
- def compose_method_name(prefix, type_name)
599
- converted_name = type_name.gsub(/[*\-]/, SCM_CHAR_TO_RB_MAP)
600
- prefix + converted_name
601
- end
602
-
603
- def not_implemented_yet(feature)
604
- raise NotImplementedYetError, feature
605
- end
606
-
607
- end # end of Parser class
608
-
54
+ end # end of Parser class
55
+ end # end of Parser module
609
56
  end