Fix up Rubinius specific library specs.
[rbx.git] / lib / rbyaml / composer.rb
blob7052b47e1b0247079ee99a0278c4299481f58632
1 require 'rbyaml/error'
2 require 'rbyaml/events'
3 require 'rbyaml/nodes'
5 module RbYAML
6   class ComposerError < YAMLError
7   end
9   class Composer
10     def initialize(parser,resolver)
11       @parser = parser
12       @resolver = resolver
13       @anchors = {}
14     end
16     def check_node
17       !@parser.peek_event.__is_stream_end
18     end
20     def get_node
21       compose_document if check_node
22     end
24     def each_node
25       yield compose_document while check_node
26     end
28     def compose_document
29       # Drop the STREAM-START event.
30       @parser.get_event if @parser.peek_event.__is_stream_start
31       # Drop the DOCUMENT-START event.
32       @parser.get_event
33       # Compose the root node.
34       node = compose_node(nil,nil)
35       # Drop the DOCUMENT-END event.
36       @parser.get_event
37       @anchors = {}
38       node
39     end
41     def compose_node(parent,index)
42       if @parser.peek_event.__is_alias
43         event = @parser.get_event
44         anchor = event.anchor
45         raise ComposerError.new(nil, "found undefined alias #{anchor}") if !@anchors.include?(anchor)
46         return @anchors[anchor]
47       end
48       event = @parser.peek_event
49       anchor = event.anchor
50       if !anchor.nil?
51         if @anchors.include?(anchor)
52           raise ComposerError.new("found duplicate anchor #{anchor}; first occurence","second occurence")
53         end
54       end
55       @resolver.descend_resolver(parent,index)
56       if @parser.peek_event.__is_scalar
57         node = compose_scalar_node(anchor)
58       elsif @parser.peek_event.__is_sequence_start
59         node = compose_sequence_node(anchor)
60       elsif @parser.peek_event.__is_mapping_start
61         node = compose_mapping_node(anchor)
62       end
63       @resolver.ascend_resolver
64       node
65     end
67     def compose_scalar_node(anchor)
68       event = @parser.get_event
69       tag = event.tag
70       tag = @resolver.resolve(ScalarNode,event.value,event.implicit) if tag.nil? || tag == "!"
71       node = ScalarNode.new(tag, event.value,event.style)
72       @anchors[anchor] = node if !anchor.nil?
73       node
74     end
76     def compose_sequence_node(anchor)
77       start_event = @parser.get_event
78       tag = start_event.tag
79       tag = @resolver.resolve(SequenceNode,nil,start_event.implicit) if tag.nil? || tag == "!"
80       node = SequenceNode.new(tag,[],start_event.flow_style)
81       @anchors[anchor] = node if !anchor.nil?
82       index = 0
83       while !@parser.peek_event.__is_sequence_end
84         node.value << compose_node(node,index)
85         index += 1
86       end
87       @parser.get_event
88       node
89     end
91     def compose_mapping_node(anchor)
92       start_event = @parser.get_event
93       tag = start_event.tag
94       tag = @resolver.resolve(MappingNode,nil,start_event.implicit) if tag.nil? || tag == "!"
95       node = MappingNode.new(tag, {},start_event.flow_style)
96       @anchors[anchor] = node if !anchor.nil?
97       while !@parser.peek_event.__is_mapping_end
98         key_event = @parser.peek_event
99         item_key = compose_node(node,nil)
100         if node.value.include?(item_key)
101           raise ComposerError.new("while composing a mapping","found duplicate key")
102         end
103         item_value = compose_node(node,item_key)
104         node.value[item_key] = item_value
105       end
106       @parser.get_event
107       node
108     end
109   end