marshal-parser 0.1.0

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.
@@ -0,0 +1,880 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lexer"
4
+ require_relative "assertable"
5
+
6
+ module MarshalParser
7
+ class Parser
8
+ include Assertable
9
+
10
+ attr_reader :symbols
11
+
12
+ def initialize(lexer)
13
+ @lexer = lexer
14
+ @index = 0
15
+ @symbols = []
16
+ end
17
+
18
+ def parse
19
+ version_node = build_ast_node
20
+ build_ast_node
21
+ end
22
+
23
+ private
24
+
25
+ def build_ast_node
26
+ token = next_token
27
+
28
+ case token.id
29
+ when Lexer::VERSION
30
+ VersionNode.new(token)
31
+
32
+ when Lexer::ARRAY_PREFIX
33
+ length = next_token
34
+ elements = []
35
+
36
+ length.value.times do
37
+ elements << build_ast_node
38
+ end
39
+
40
+ ArrayNode.new(token, length, elements)
41
+
42
+ when Lexer::STRING_PREFIX
43
+ length = next_token
44
+ content = next_token
45
+
46
+ StringNode.new(token, length, content)
47
+
48
+ when Lexer::OBJECT_WITH_IVARS_PREFIX
49
+ child = build_ast_node
50
+
51
+ count = next_token
52
+ assert_token_type(count, Lexer::INTEGER)
53
+
54
+ ivars = []
55
+
56
+ count.value.times do
57
+ name = build_ast_node
58
+ value = build_ast_node
59
+ ivars << name << value
60
+
61
+ assert_node_type(name, SymbolNode, SymbolLinkNode)
62
+ end
63
+
64
+ ObjectWithIVarsNode.new(token, child, count, ivars)
65
+
66
+ when Lexer::SYMBOL_PREFIX
67
+ length = next_token
68
+ content = next_token
69
+ @symbols << @lexer.source_string[content.index, content.length]
70
+
71
+ SymbolNode.new(token, length, content, @symbols.size - 1)
72
+
73
+ when Lexer::TRUE
74
+ TrueNode.new(token)
75
+
76
+ when Lexer::FALSE
77
+ FalseNode.new(token)
78
+
79
+ when Lexer::NIL
80
+ NilNode.new(token)
81
+
82
+ when Lexer::INTEGER_PREFIX
83
+ value = next_token
84
+ IntegerNode.new(token, value)
85
+
86
+ when Lexer::BIG_INTEGER_PREFIX
87
+ sign = next_token
88
+ length = next_token
89
+ value = next_token
90
+ BigIntegerNode.new(token, sign, length, value)
91
+
92
+ when Lexer::FLOAT_PREFIX
93
+ length = next_token
94
+ value = next_token
95
+ FloatNode.new(token, length, value)
96
+
97
+ when Lexer::SYMBOL_LINK_PREFIX
98
+ index = next_token
99
+
100
+ SymbolLinkNode.new(token, index)
101
+
102
+ when Lexer::HASH_PREFIX
103
+ size = next_token
104
+ assert_token_type size, Lexer::INTEGER
105
+
106
+ key_and_value_nodes = []
107
+
108
+ size.value.times do
109
+ key = build_ast_node
110
+ assert_node_type key, SymbolNode, SymbolLinkNode
111
+
112
+ value = build_ast_node
113
+ key_and_value_nodes << key << value
114
+ end
115
+
116
+ HashNode.new(token, size, key_and_value_nodes)
117
+
118
+ when Lexer::HASH_WITH_DEFAULT_VALUE_PREFIX
119
+ size = next_token
120
+ assert_token_type size, Lexer::INTEGER
121
+
122
+ key_and_value_nodes = []
123
+
124
+ size.value.times do
125
+ key = build_ast_node
126
+ assert_node_type key, SymbolNode, SymbolLinkNode
127
+
128
+ value = build_ast_node
129
+ key_and_value_nodes << key << value
130
+ end
131
+
132
+ default_value_node = build_ast_node
133
+ assert_node_type default_value_node, IntegerNode
134
+
135
+ HashWithDefaultValueNode.new(token, size, key_and_value_nodes, default_value_node)
136
+
137
+ when Lexer::REGEXP_PREFIX
138
+ string_length = next_token
139
+ string = next_token
140
+ options = next_token
141
+
142
+ RegexpNode.new(token, string_length, string, options)
143
+
144
+ when Lexer::CLASS_PREFIX
145
+ length = next_token
146
+ string = next_token
147
+
148
+ ClassNode.new(token, length, string)
149
+
150
+ when Lexer::MODULE_PREFIX
151
+ length = next_token
152
+ string = next_token
153
+
154
+ ModuleNode.new(token, length, string)
155
+
156
+ when Lexer::SUBCLASS_OF_CORE_LIBRARY_CLASS_PREFIX
157
+ class_name_node = build_ast_node
158
+ assert_node_type class_name_node, SymbolNode, SymbolLinkNode
159
+
160
+ object_node = build_ast_node
161
+
162
+ SubclassNode.new(token, class_name_node, object_node)
163
+
164
+ when Lexer::STRUCT_PREFIX
165
+ class_name_node = build_ast_node
166
+ assert_node_type class_name_node, SymbolNode, SymbolLinkNode
167
+
168
+ members_count = next_token
169
+
170
+ member_nodes = []
171
+
172
+ members_count.value.times do
173
+ name = build_ast_node
174
+ value = build_ast_node
175
+
176
+ assert_node_type name, SymbolNode, SymbolLinkNode
177
+
178
+ member_nodes << name << value
179
+ end
180
+
181
+ StructNode.new(token, class_name_node, members_count, member_nodes)
182
+
183
+ when Lexer::OBJECT_PREFIX
184
+ class_name_node = build_ast_node
185
+ assert_node_type class_name_node, SymbolNode, SymbolLinkNode
186
+
187
+ ivars_count = next_token
188
+ assert_token_type(ivars_count, Lexer::INTEGER)
189
+
190
+ ivars_nodes = []
191
+
192
+ ivars_count.value.times do
193
+ name = build_ast_node
194
+ value = build_ast_node
195
+
196
+ ivars_nodes << name << value
197
+ end
198
+
199
+ ObjectNode.new(token, class_name_node, ivars_count, ivars_nodes)
200
+
201
+ when Lexer::OBJECT_LINK_PREFIX
202
+ index = next_token
203
+
204
+ ObjectLinkNode.new(token, index)
205
+
206
+ when Lexer::OBJECT_WITH_DUMP_PREFIX
207
+ class_name_node = build_ast_node
208
+ assert_node_type class_name_node, SymbolNode, SymbolLinkNode
209
+
210
+ length = next_token
211
+ user_dump = next_token
212
+
213
+ ObjectWithDumpMethodNode.new(token, class_name_node, length, user_dump)
214
+
215
+ when Lexer::OBJECT_WITH_MARSHAL_DUMP_PREFIX
216
+ class_name_node = build_ast_node
217
+ assert_node_type class_name_node, SymbolNode, SymbolLinkNode
218
+
219
+ child_node = build_ast_node
220
+
221
+ ObjectWithMarshalDumpMethod.new(token, class_name_node, child_node)
222
+
223
+ when Lexer::OBJECT_EXTENDED_PREFIX
224
+ module_name_node = build_ast_node
225
+ object_node = build_ast_node
226
+
227
+ ObjectExtendedNode.new(token, module_name_node, object_node)
228
+
229
+ else
230
+ raise "Not supported token id #{token.id}"
231
+ end
232
+ end
233
+
234
+ def next_token
235
+ raise "No next token" if @index >= @lexer.tokens.size
236
+
237
+ @index += 1
238
+ @lexer.tokens[@index - 1]
239
+ end
240
+
241
+ def assert_node_type(node, *allowed_classes)
242
+ assert(
243
+ allowed_classes.any? { |node_class| node.instance_of?(node_class) },
244
+ "Node #{node} should be a #{allowed_classes.map(&:name).join(" or ")}"
245
+ )
246
+ end
247
+
248
+ def assert_token_type(token, *token_ids)
249
+ assert(
250
+ token_ids.include?(token.id),
251
+ "Token #{token} should have type #{token_ids.join(" or ")}"
252
+ )
253
+ end
254
+
255
+ module Annotatable
256
+ def annotation
257
+ raise "Not implemented"
258
+ end
259
+ end
260
+
261
+ class Node
262
+ include Assertable
263
+
264
+ def child_entities
265
+ raise "Not implemented"
266
+ end
267
+
268
+ def tokens
269
+ child_entities.grep(Lexer::Token)
270
+ end
271
+
272
+ def children
273
+ child_entities.grep(Node)
274
+ end
275
+
276
+ def decoded_value
277
+ nil
278
+ end
279
+
280
+ def literal_token
281
+ nil
282
+ end
283
+
284
+ def attributes
285
+ {}
286
+ end
287
+
288
+ def always_leaf?
289
+ false
290
+ end
291
+
292
+ private
293
+
294
+ def assert_token_type(token, *token_ids)
295
+ assert(
296
+ token_ids.include?(token.id),
297
+ "Token #{token} should have type #{token_ids.join(" or ")}"
298
+ )
299
+ end
300
+ end
301
+
302
+ class VersionNode < Node
303
+ def initialize(version_token)
304
+ super()
305
+ assert_token_type version_token, Lexer::VERSION
306
+ @version_token = version_token
307
+ end
308
+
309
+ def child_entities
310
+ [@version_token]
311
+ end
312
+ end
313
+
314
+ class ArrayNode < Node
315
+ def initialize(marker_token, length_token, elements_nodes)
316
+ super()
317
+ assert_token_type marker_token, Lexer::ARRAY_PREFIX
318
+ assert_token_type length_token, Lexer::INTEGER
319
+
320
+ @marker_token = marker_token
321
+ @length_token = length_token
322
+ @elements_nodes = elements_nodes
323
+ end
324
+
325
+ def child_entities
326
+ [@marker_token, @length_token] + @elements_nodes
327
+ end
328
+
329
+ def attributes
330
+ {
331
+ @length_token => { name: :length, value: @length_token.value }
332
+ }
333
+ end
334
+ end
335
+
336
+ class StringNode < Node
337
+ def initialize(marker_token, length_token, content_token)
338
+ super()
339
+ assert_token_type marker_token, Lexer::STRING_PREFIX
340
+ assert_token_type length_token, Lexer::INTEGER
341
+ assert_token_type content_token, Lexer::STRING
342
+
343
+ @marker_token = marker_token
344
+ @length_token = length_token
345
+ @content_token = content_token
346
+ end
347
+
348
+ def child_entities
349
+ [@marker_token, @length_token, @content_token]
350
+ end
351
+
352
+ def literal_token
353
+ @content_token
354
+ end
355
+
356
+ def attributes
357
+ {
358
+ @length_token => { name: :length, value: @length_token.value },
359
+ @content_token => { name: :content, value: @content_token }
360
+ }
361
+ end
362
+ end
363
+
364
+ class ObjectWithIVarsNode < Node
365
+ def initialize(marker_token, child, count_token, ivars_nodes)
366
+ super()
367
+ assert_token_type marker_token, Lexer::OBJECT_WITH_IVARS_PREFIX
368
+ # child - any Node
369
+ assert_token_type count_token, Lexer::INTEGER
370
+ # ivars nodes - any nodes
371
+
372
+ @marker_token = marker_token
373
+ @child = child
374
+ @count_token = count_token
375
+ @ivars_nodes = ivars_nodes
376
+ end
377
+
378
+ def child_entities
379
+ [@marker_token, @child, @count_token] + @ivars_nodes
380
+ end
381
+
382
+ def attributes
383
+ {
384
+ @count_token => { name: :ivars_count, value: @count_token.value }
385
+ }
386
+ end
387
+ end
388
+
389
+ class SymbolNode < Node
390
+ include Annotatable
391
+
392
+ def initialize(marker_token, length_token, content_token, link_to_symbol)
393
+ super()
394
+ assert_token_type marker_token, Lexer::SYMBOL_PREFIX
395
+ assert_token_type length_token, Lexer::INTEGER
396
+ assert_token_type content_token, Lexer::SYMBOL
397
+
398
+ @marker_token = marker_token
399
+ @length_token = length_token
400
+ @content_token = content_token
401
+ @link_to_symbol = link_to_symbol # just Integer, index in the Symbols table
402
+ end
403
+
404
+ def child_entities
405
+ [@marker_token, @length_token, @content_token]
406
+ end
407
+
408
+ def annotation
409
+ "symbol ##{@link_to_symbol}"
410
+ end
411
+
412
+ def literal_token
413
+ @content_token
414
+ end
415
+
416
+ def attributes
417
+ {
418
+ @length_token => { name: :length, value: @length_token.value },
419
+ @content_token => { name: :content, value: @content_token }
420
+ }
421
+ end
422
+ end
423
+
424
+ class TrueNode < Node
425
+ def initialize(token)
426
+ super()
427
+ assert_token_type(token, Lexer::TRUE)
428
+ @token = token
429
+ end
430
+
431
+ def child_entities
432
+ [@token]
433
+ end
434
+
435
+ def always_leaf?
436
+ true
437
+ end
438
+ end
439
+
440
+ class FalseNode < Node
441
+ def initialize(token)
442
+ super()
443
+ assert_token_type token, Lexer::FALSE
444
+ @token = token
445
+ end
446
+
447
+ def child_entities
448
+ [@token]
449
+ end
450
+
451
+ def always_leaf?
452
+ true
453
+ end
454
+ end
455
+
456
+ class NilNode < Node
457
+ def initialize(token)
458
+ super()
459
+ assert_token_type token, Lexer::NIL
460
+ @token = token
461
+ end
462
+
463
+ def child_entities
464
+ [@token]
465
+ end
466
+
467
+ def always_leaf?
468
+ true
469
+ end
470
+ end
471
+
472
+ class IntegerNode < Node
473
+ def initialize(prefix, value)
474
+ super()
475
+ assert_token_type prefix, Lexer::INTEGER_PREFIX
476
+ assert_token_type value, Lexer::INTEGER
477
+
478
+ @prefix = prefix
479
+ @value = value
480
+ end
481
+
482
+ def child_entities
483
+ [@prefix, @value]
484
+ end
485
+
486
+ def decoded_value
487
+ @value.value
488
+ end
489
+
490
+ def literal_token
491
+ @value
492
+ end
493
+
494
+ def attributes
495
+ {
496
+ @value => { name: :value, value: @value.value }
497
+ }
498
+ end
499
+ end
500
+
501
+ class BigIntegerNode < Node
502
+ def initialize(prefix, sign, length, value)
503
+ super()
504
+ assert_token_type prefix, Lexer::BIG_INTEGER_PREFIX
505
+ assert_token_type sign, Lexer::PLUS_SIGN, Lexer::MINUS_SIGN
506
+ assert_token_type length, Lexer::INTEGER
507
+ assert_token_type value, Lexer::BIG_INTEGER
508
+
509
+ @prefix = prefix
510
+ @sign = sign
511
+ @length = length
512
+ @value = value
513
+ end
514
+
515
+ def child_entities
516
+ [@prefix, @sign, @length, @value]
517
+ end
518
+
519
+ def decoded_value
520
+ @value.value
521
+ end
522
+
523
+ def literal_token
524
+ @value
525
+ end
526
+
527
+ def attributes
528
+ {
529
+ @value => { name: :value, value: @value.value }
530
+ }
531
+ end
532
+ end
533
+
534
+ class FloatNode < Node
535
+ def initialize(prefix, length, value)
536
+ super()
537
+ assert_token_type prefix, Lexer::FLOAT_PREFIX
538
+ assert_token_type length, Lexer::INTEGER
539
+ assert_token_type value, Lexer::FLOAT
540
+
541
+ @prefix = prefix
542
+ @length = length
543
+ @value = value
544
+ end
545
+
546
+ def child_entities
547
+ [@prefix, @length, @value]
548
+ end
549
+
550
+ def decoded_value
551
+ @value.value
552
+ end
553
+
554
+ def literal_token
555
+ @value
556
+ end
557
+
558
+ def attributes
559
+ {
560
+ @length => { name: :length, value: @length.value },
561
+ @value => { name: :value, value: @value.value }
562
+ }
563
+ end
564
+ end
565
+
566
+ class SymbolLinkNode < Node
567
+ include Annotatable
568
+
569
+ def initialize(marker_token, index_token)
570
+ super()
571
+ assert_token_type marker_token, Lexer::SYMBOL_LINK_PREFIX
572
+ assert_token_type index_token, Lexer::INTEGER
573
+
574
+ @marker_token = marker_token
575
+ @index_token = index_token
576
+ end
577
+
578
+ def child_entities
579
+ [@marker_token, @index_token]
580
+ end
581
+
582
+ def annotation
583
+ "link to symbol ##{@index_token.value}"
584
+ end
585
+
586
+ def decoded_value
587
+ @index_token.value
588
+ end
589
+
590
+ def literal_token
591
+ @index_token
592
+ end
593
+
594
+ def attributes
595
+ {
596
+ @index_token => { name: :index, value: @index_token.value }
597
+ }
598
+ end
599
+ end
600
+
601
+ class HashNode < Node
602
+ def initialize(prefix, size, key_and_value_nodes)
603
+ super()
604
+ assert_token_type prefix, Lexer::HASH_PREFIX
605
+ assert_token_type size, Lexer::INTEGER
606
+
607
+ @prefix = prefix
608
+ @size = size
609
+ @key_and_value_nodes = key_and_value_nodes
610
+ end
611
+
612
+ def child_entities
613
+ [@prefix, @size] + @key_and_value_nodes
614
+ end
615
+
616
+ def attributes
617
+ {
618
+ @size => { name: :size, value: @size.value }
619
+ }
620
+ end
621
+ end
622
+
623
+ class HashWithDefaultValueNode < Node
624
+ def initialize(prefix, size, key_and_value_nodes, default_value_node)
625
+ super()
626
+ assert_token_type prefix, Lexer::HASH_WITH_DEFAULT_VALUE_PREFIX
627
+ assert_token_type size, Lexer::INTEGER
628
+
629
+ @prefix = prefix
630
+ @size = size
631
+ @key_and_value_nodes = key_and_value_nodes
632
+ @default_value_node = default_value_node
633
+ end
634
+
635
+ def child_entities
636
+ [@prefix, @size] + @key_and_value_nodes + [@default_value_node]
637
+ end
638
+
639
+ def attributes
640
+ {
641
+ @size => { name: :size, value: @size.value }
642
+ }
643
+ end
644
+ end
645
+
646
+ class RegexpNode < Node
647
+ def initialize(prefix, string_length, string, options)
648
+ super()
649
+ assert_token_type prefix, Lexer::REGEXP_PREFIX
650
+ assert_token_type string_length, Lexer::INTEGER
651
+ assert_token_type string, Lexer::STRING
652
+ assert_token_type options, Lexer::INTEGER
653
+
654
+ @prefix = prefix
655
+ @string_length = string_length
656
+ @string = string
657
+ @options = options
658
+ end
659
+
660
+ def child_entities
661
+ [@prefix, @string_length, @string, @options]
662
+ end
663
+
664
+ def literal_token
665
+ @string
666
+ end
667
+
668
+ def attributes
669
+ {
670
+ @string_length => { name: :length, value: @string_length.value },
671
+ @string => { name: :source_string, value: @string },
672
+ @options => { name: :options, value: @options.value }
673
+ }
674
+ end
675
+ end
676
+
677
+ class ClassNode < Node
678
+ def initialize(prefix, length, name)
679
+ super()
680
+ assert_token_type prefix, Lexer::CLASS_PREFIX
681
+ assert_token_type length, Lexer::INTEGER
682
+ assert_token_type name, Lexer::STRING
683
+
684
+ @prefix = prefix
685
+ @length = length
686
+ @name = name
687
+ end
688
+
689
+ def child_entities
690
+ [@prefix, @length, @name]
691
+ end
692
+
693
+ def literal_token
694
+ @name
695
+ end
696
+
697
+ def attributes
698
+ {
699
+ @length => { name: :length, value: @length.value },
700
+ @name => { name: :name, value: @name }
701
+ }
702
+ end
703
+ end
704
+
705
+ class ModuleNode < Node
706
+ def initialize(prefix, length, name)
707
+ super()
708
+ assert_token_type prefix, Lexer::MODULE_PREFIX
709
+ assert_token_type length, Lexer::INTEGER
710
+ assert_token_type name, Lexer::STRING
711
+
712
+ @prefix = prefix
713
+ @length = length
714
+ @name = name
715
+ end
716
+
717
+ def child_entities
718
+ [@prefix, @length, @name]
719
+ end
720
+
721
+ def literal_token
722
+ @name
723
+ end
724
+
725
+ def attributes
726
+ {
727
+ @length => { name: :length, value: @length.value },
728
+ @name => { name: :name, value: @name }
729
+ }
730
+ end
731
+ end
732
+
733
+ class SubclassNode < Node
734
+ def initialize(prefix, class_name_node, object_node)
735
+ super()
736
+ assert_token_type prefix, Lexer::SUBCLASS_OF_CORE_LIBRARY_CLASS_PREFIX
737
+
738
+ @prefix = prefix
739
+ @class_name_node = class_name_node
740
+ @object_node = object_node
741
+ end
742
+
743
+ def child_entities
744
+ [@prefix, @class_name_node, @object_node]
745
+ end
746
+ end
747
+
748
+ class StructNode < Node
749
+ def initialize(prefix, class_name_node, members_count, member_nodes)
750
+ super()
751
+ assert_token_type prefix, Lexer::STRUCT_PREFIX
752
+ assert_token_type members_count, Lexer::INTEGER
753
+
754
+ @prefix = prefix
755
+ @class_name_node = class_name_node
756
+ @members_count = members_count
757
+ @member_nodes = member_nodes
758
+ end
759
+
760
+ def child_entities
761
+ [@prefix, @class_name_node, @members_count] + @member_nodes
762
+ end
763
+
764
+ def attributes
765
+ {
766
+ @members_count => { name: :count, value: @members_count.value }
767
+ }
768
+ end
769
+ end
770
+
771
+ class ObjectNode < Node
772
+ def initialize(prefix, class_name_node, ivars_count, ivars_nodes)
773
+ super()
774
+ assert_token_type prefix, Lexer::OBJECT_PREFIX
775
+ assert_token_type ivars_count, Lexer::INTEGER
776
+
777
+ @prefix = prefix
778
+ @class_name_node = class_name_node
779
+ @ivars_count = ivars_count
780
+ @ivars_nodes = ivars_nodes
781
+ end
782
+
783
+ def child_entities
784
+ [@prefix, @class_name_node, @ivars_count] + @ivars_nodes
785
+ end
786
+
787
+ def attributes
788
+ {
789
+ @ivars_count => { name: :ivars_count, value: @ivars_count.value }
790
+ }
791
+ end
792
+ end
793
+
794
+ class ObjectLinkNode < Node
795
+ def initialize(prefix, index)
796
+ super()
797
+ assert_token_type prefix, Lexer::OBJECT_LINK_PREFIX
798
+ assert_token_type index, Lexer::INTEGER
799
+
800
+ @prefix = prefix
801
+ @index = index
802
+ end
803
+
804
+ def child_entities
805
+ [@prefix, @index]
806
+ end
807
+
808
+ def decoded_value
809
+ @index.value
810
+ end
811
+
812
+ def literal_token
813
+ @index
814
+ end
815
+
816
+ def attributes
817
+ {
818
+ @index => { name: :index, value: @index.value }
819
+ }
820
+ end
821
+ end
822
+
823
+ class ObjectWithDumpMethodNode < Node
824
+ def initialize(token, class_name_node, length, user_dump)
825
+ super()
826
+ assert_token_type token, Lexer::OBJECT_WITH_DUMP_PREFIX
827
+ assert_token_type length, Lexer::INTEGER
828
+ assert_token_type user_dump, Lexer::STRING
829
+
830
+ @prefix = token
831
+ @class_name_node = class_name_node
832
+ @length = length
833
+ @user_dump = user_dump
834
+ end
835
+
836
+ def child_entities
837
+ [@prefix, @class_name_node, @length, @user_dump]
838
+ end
839
+
840
+ def literal_token
841
+ @user_dump
842
+ end
843
+
844
+ def attributes
845
+ {
846
+ @length => { name: :length, value: @length.value },
847
+ @user_dump => { name: :dump, value: @user_dump }
848
+ }
849
+ end
850
+ end
851
+
852
+ class ObjectWithMarshalDumpMethod < Node
853
+ def initialize(prefix, class_name_node, child_node)
854
+ super()
855
+ assert_token_type prefix, Lexer::OBJECT_WITH_MARSHAL_DUMP_PREFIX
856
+
857
+ @prefix = prefix
858
+ @class_name_node = class_name_node
859
+ @child_node = child_node
860
+ end
861
+
862
+ def child_entities
863
+ [@prefix, @class_name_node, @child_node]
864
+ end
865
+ end
866
+
867
+ class ObjectExtendedNode < Node
868
+ def initialize(prefix, module_name_node, object_node)
869
+ super()
870
+ @prefix = prefix
871
+ @module_name_node = module_name_node
872
+ @object_node = object_node
873
+ end
874
+
875
+ def child_entities
876
+ [@prefix, @module_name_node, @object_node]
877
+ end
878
+ end
879
+ end
880
+ end