RbYAML 0.0.1

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.
Files changed (66) hide show
  1. data/LICENSE +19 -0
  2. data/README +31 -0
  3. data/lib/rbyaml.rb +378 -0
  4. data/lib/rbyaml/composer.rb +189 -0
  5. data/lib/rbyaml/constructor.rb +374 -0
  6. data/lib/rbyaml/detector.rb +44 -0
  7. data/lib/rbyaml/dumper.rb +40 -0
  8. data/lib/rbyaml/emitter.rb +1116 -0
  9. data/lib/rbyaml/error.rb +81 -0
  10. data/lib/rbyaml/events.rb +92 -0
  11. data/lib/rbyaml/loader.rb +49 -0
  12. data/lib/rbyaml/nodes.rb +69 -0
  13. data/lib/rbyaml/parser.rb +488 -0
  14. data/lib/rbyaml/reader.rb +127 -0
  15. data/lib/rbyaml/representer.rb +183 -0
  16. data/lib/rbyaml/scanner.rb +1258 -0
  17. data/lib/rbyaml/serializer.rb +120 -0
  18. data/lib/rbyaml/test.rb +56 -0
  19. data/lib/rbyaml/tokens.rb +163 -0
  20. data/lib/rbyaml/yaml.rb +143 -0
  21. data/test/test_rbyaml.rb +18 -0
  22. data/test/yaml/gems.yml +130951 -0
  23. data/test/yaml/gems2.yml +113 -0
  24. data/test/yaml/test1.yml +3 -0
  25. data/test/yaml/test10.yml +8 -0
  26. data/test/yaml/test12.yml +8 -0
  27. data/test/yaml/test13.yml +4 -0
  28. data/test/yaml/test14.yml +4 -0
  29. data/test/yaml/test15.yml +8 -0
  30. data/test/yaml/test16.yml +7 -0
  31. data/test/yaml/test18.yml +6 -0
  32. data/test/yaml/test19.yml +5 -0
  33. data/test/yaml/test2.yml +3 -0
  34. data/test/yaml/test20.yml +6 -0
  35. data/test/yaml/test21.yml +4 -0
  36. data/test/yaml/test22.yml +4 -0
  37. data/test/yaml/test23.yml +13 -0
  38. data/test/yaml/test24.yml +14 -0
  39. data/test/yaml/test25.yml +7 -0
  40. data/test/yaml/test26.yml +7 -0
  41. data/test/yaml/test27.yml +29 -0
  42. data/test/yaml/test28.yml +26 -0
  43. data/test/yaml/test29.yml +13 -0
  44. data/test/yaml/test3.yml +8 -0
  45. data/test/yaml/test30.yml +7 -0
  46. data/test/yaml/test31.yml +2 -0
  47. data/test/yaml/test32.yml +13 -0
  48. data/test/yaml/test33.yml +2 -0
  49. data/test/yaml/test34.yml +8 -0
  50. data/test/yaml/test35.yml +4 -0
  51. data/test/yaml/test36.yml +8 -0
  52. data/test/yaml/test37.yml +2 -0
  53. data/test/yaml/test38.yml +8 -0
  54. data/test/yaml/test39.yml +2 -0
  55. data/test/yaml/test4.yml +8 -0
  56. data/test/yaml/test40.yml +3 -0
  57. data/test/yaml/test41.yml +5 -0
  58. data/test/yaml/test42.yml +12 -0
  59. data/test/yaml/test43.yml +15 -0
  60. data/test/yaml/test44.yml +23 -0
  61. data/test/yaml/test5.yml +3 -0
  62. data/test/yaml/test6.yml +5 -0
  63. data/test/yaml/test7.yml +10 -0
  64. data/test/yaml/test8.yml +10 -0
  65. data/test/yaml/test9.yml +8 -0
  66. metadata +111 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2006 Ola Bini
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,31 @@
1
+ = RbYAML - A pure Ruby YAML 1.1 loader and dumper
2
+
3
+ Project Contact: Ola Bini <ola@ologix.com>
4
+
5
+ The code is based mostly on the Python code written by Kirill Simonov <xi@resolvent.net> for PyYAML3000.
6
+
7
+ RbYAML is a project originating in the JRuby project (http://jruby.sourceforge.net), to create a pure Ruby
8
+ YAML parser for use in JRuby and SYCK cannot be used in this case.
9
+ Since the effort of writing a new one from scratch seemed like a major undertaking it seemed easier to
10
+ port an existing one.
11
+
12
+ The current functionality is more or less 1.1-compliant. What's missing is the Unicode-support. The idea
13
+ is to have the interface resemble SYCK as much as possible, but this is still work in progress, since some
14
+ of the major architectural choices are quite different.
15
+
16
+ == Use
17
+
18
+ Just require 'rbyaml' and use it as you would use YAML, but in module RbYAML instead:
19
+
20
+ require 'rbyaml'
21
+
22
+ RbYAML.load("--- \n- A\n- b\n- c\n") ----> ["A","b","c"]
23
+ "foo".to_yaml ----> "foo\n"
24
+
25
+ == More information
26
+
27
+ Visit http://rbyaml.ologix.com for more information and updated versions
28
+
29
+ == License
30
+
31
+ RbYAML is distributed with a MIT license, which can be found in the file LICENSE.
@@ -0,0 +1,378 @@
1
+
2
+ require 'rbyaml/yaml'
3
+
4
+ module RbYAML
5
+ def self.dump(obj, io = nil)
6
+ _dump(obj,io)
7
+ end
8
+
9
+ def self.load( io )
10
+ _load(io)
11
+ end
12
+
13
+ def self.load_file( filepath )
14
+ File.open( filepath ) do |f|
15
+ load( f )
16
+ end
17
+ end
18
+
19
+ # this operation does not make sense in RbYAML (right now)
20
+ def self.parse( io )
21
+ # yp = @@parser.new( :Model => :Generic ).load( io )
22
+ end
23
+
24
+ # this operation does not make sense in RbYAML (right now)
25
+ def self.parse_file( filepath )
26
+ # File.open( filepath ) do |f|
27
+ # parse( f )
28
+ # end
29
+ end
30
+
31
+ def self.each_document( io, &block )
32
+ _load_all(io,&block)
33
+ end
34
+
35
+ def self.load_documents( io, &doc_proc )
36
+ each_document( io, &doc_proc )
37
+ end
38
+
39
+ # this operation does not make sense in RbYAML (right now)
40
+ def self.each_node( io, &doc_proc )
41
+ # yp = @@parser.new( :Model => :Generic ).load_documents( io, &doc_proc )
42
+ end
43
+
44
+ # this operation does not make sense in RbYAML (right now)
45
+ def self.parse_documents( io, &doc_proc )
46
+ # YAML.each_node( io, &doc_proc )
47
+ end
48
+
49
+ def self.load_stream( io )
50
+ d = nil
51
+ load_documents(io) { |doc|
52
+ d = Stream.new( nil ) if not d
53
+ d.add( doc )
54
+ }
55
+ d
56
+ end
57
+
58
+ def self.dump_stream( *objs )
59
+ d = RbYAML::Stream.new
60
+ objs.each do |doc|
61
+ d.add( doc )
62
+ end
63
+ d.emit
64
+ end
65
+
66
+ # this operation does not make sense in RbYAML (right now)
67
+ def self.add_domain_type( domain, type_re, &transfer_proc )
68
+ # @@loader.add_domain_type( domain, type_re, &transfer_proc )
69
+ end
70
+
71
+ # this operation does not make sense in RbYAML (right now)
72
+ def self.add_builtin_type( type_re, &transfer_proc )
73
+ # @@loader.add_builtin_type( type_re, &transfer_proc )
74
+ end
75
+
76
+ # this operation does not make sense in RbYAML (right now)
77
+ def self.add_ruby_type( type_tag, &transfer_proc )
78
+ # @@loader.add_ruby_type( type, &transfer_proc )
79
+ end
80
+
81
+ # this operation does not make sense in RbYAML (right now)
82
+ def self.add_private_type( type_re, &transfer_proc )
83
+ # @@loader.add_private_type( type_re, &transfer_proc )
84
+ end
85
+
86
+ def self.detect_implicit( val )
87
+ SimpleDetector.detect(val)
88
+ end
89
+
90
+ # this operation does not make sense in RbYAML (right now)
91
+ def self.transfer( type_id, obj )
92
+ # @@loader.transfer( type_id, obj )
93
+ end
94
+
95
+ # this operation does not make sense in RbYAML (right now)
96
+ def self.try_implicit( obj )
97
+ # YAML.transfer( YAML.detect_implicit( obj ), obj )
98
+ end
99
+
100
+ def self.read_type_class( type, obj_class )
101
+ scheme, domain, type, tclass = type.split( ':', 4 )
102
+ tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass
103
+ return [ type, obj_class ]
104
+ end
105
+
106
+ def self.object_maker( obj_class, val )
107
+ if Hash === val
108
+ o = obj_class.allocate
109
+ val.each_pair { |k,v|
110
+ o.instance_variable_set("@#{k}", v)
111
+ }
112
+ o
113
+ else
114
+ raise YAMLError, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
115
+ end
116
+ end
117
+
118
+ # this operation does not make sense in RbYAML (right now)
119
+ def self.quick_emit( oid, opts = {}, &e )
120
+ end
121
+
122
+ # A dictionary of taguris which map to
123
+ # Ruby classes.
124
+ @@tagged_classes = {}
125
+
126
+ #
127
+ # Associates a taguri _tag_ with a Ruby class _cls_. The taguri is used to give types
128
+ # to classes when loading YAML. Taguris are of the form:
129
+ #
130
+ # tag:authorityName,date:specific
131
+ #
132
+ # The +authorityName+ is a domain name or email address. The +date+ is the date the type
133
+ # was issued in YYYY or YYYY-MM or YYYY-MM-DD format. The +specific+ is a name for
134
+ # the type being added.
135
+ #
136
+ # For example, built-in YAML types have 'yaml.org' as the +authorityName+ and '2002' as the
137
+ # +date+. The +specific+ is simply the name of the type:
138
+ #
139
+ # tag:yaml.org,2002:int
140
+ # tag:yaml.org,2002:float
141
+ # tag:yaml.org,2002:timestamp
142
+ #
143
+ # The domain must be owned by you on the +date+ declared. If you don't own any domains on the
144
+ # date you declare the type, you can simply use an e-mail address.
145
+ #
146
+ # tag:why@ruby-lang.org,2004:notes/personal
147
+ #
148
+ def self.tag_class( tag, cls )
149
+ if @@tagged_classes.has_key? tag
150
+ warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
151
+ end
152
+ @@tagged_classes[tag] = cls
153
+ end
154
+
155
+ # Returns the complete dictionary of taguris, paired with classes. The key for
156
+ # the dictionary is the full taguri. The value for each key is the class constant
157
+ # associated to that taguri.
158
+ #
159
+ # YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer
160
+ #
161
+ def self.tagged_classes
162
+ @@tagged_classes
163
+ end
164
+
165
+ #
166
+ # RbYAML::Stream -- for emitting many documents
167
+ #
168
+ class Stream
169
+ include Enumerable
170
+
171
+ attr_accessor :documents, :options
172
+ def initialize(opts = {})
173
+ @options = opts
174
+ @documents = []
175
+ end
176
+
177
+ def [](i)
178
+ @documents[ i ]
179
+ end
180
+
181
+ def add(doc)
182
+ @documents << doc
183
+ end
184
+
185
+ def edit(doc_num,doc)
186
+ @documents[ doc_num ] = doc
187
+ end
188
+
189
+ def each(&block)
190
+ @documents.each(&block)
191
+ end
192
+
193
+ def emit
194
+ # TODO: implement
195
+
196
+ opts = @options.dup
197
+ opts[:UseHeader] = true if @documents.length > 1
198
+ ct = 0
199
+ out = Emitter.new( opts )
200
+ @documents.each { |v|
201
+ if ct > 0
202
+ out << "\n--- "
203
+ end
204
+ v.to_yaml( :Emitter => out )
205
+ ct += 1
206
+ }
207
+ out.end_object
208
+ end
209
+ end
210
+ end
211
+
212
+ if !Object.method_defined?(:to_yaml)
213
+ class Module # :nodoc: all
214
+ def yaml_as( tag, sc = true )
215
+ class_eval <<-"end;", __FILE__, __LINE__+1
216
+ attr_writer :taguri
217
+ def taguri
218
+ return @taguri if defined?(@taguri) and @taguri
219
+ tag = #{ tag.dump }
220
+ if self.class.yaml_tag_subclasses? and self.class != RbYAML::tagged_classes[tag]
221
+ tag = "\#{ tag }:\#{ self.class.yaml_tag_class_name }"
222
+ end
223
+ tag
224
+ end
225
+ def self.yaml_tag_subclasses?; #{ sc ? 'true' : 'false' }; end
226
+ end;
227
+ RbYAML::tag_class tag, self
228
+ end
229
+ # Transforms the subclass name into a name suitable for display
230
+ # in a subclassed tag.
231
+ def yaml_tag_class_name
232
+ self.name
233
+ end
234
+ # Transforms the subclass name found in the tag into a Ruby
235
+ # constant name.
236
+ def yaml_tag_read_class( name )
237
+ name
238
+ end
239
+ end
240
+
241
+ require 'date'
242
+
243
+ class Class
244
+ def to_yaml( opts = {} )
245
+ raise RbYAML::TypeError, "can't dump anonymous class %s" % self.class
246
+ end
247
+ end
248
+
249
+ class Object
250
+ yaml_as "tag:ruby.yaml.org,2002:object"
251
+ def is_complex_yaml?; true; end
252
+ def to_yaml_style; end
253
+ def to_yaml_properties; instance_variables.sort; end
254
+ def to_yaml( opts = {} )
255
+ RbYAML::_dump_ruby_object(self)
256
+ end
257
+ end
258
+
259
+ class Hash
260
+ yaml_as "tag:ruby.yaml.org,2002:hash"
261
+ yaml_as "tag:yaml.org,2002:map"
262
+ def is_complex_yaml?; true; end
263
+ def yaml_initialize( tag, val )
264
+ if Array === val
265
+ update Hash.[]( *val ) # Convert the map to a sequence
266
+ elsif Hash === val
267
+ update val
268
+ else
269
+ raise RbYAML::TypeError, "Invalid map explicitly tagged #{ tag }: " + val.inspect
270
+ end
271
+ end
272
+ end
273
+
274
+ class Array
275
+ yaml_as "tag:ruby.yaml.org,2002:array"
276
+ yaml_as "tag:yaml.org,2002:seq"
277
+ def is_complex_yaml?; true; end
278
+ def yaml_initialize( tag, val ); concat( val.to_a ); end
279
+ end
280
+
281
+ class Exception
282
+ yaml_as "tag:ruby.yaml.org,2002:exception"
283
+ def Exception.yaml_new( klass, tag, val )
284
+ o = RbYAML.object_maker( klass, { 'mesg' => val.delete( 'message' ) } )
285
+ val.each_pair do |k,v|
286
+ o.instance_variable_set("@#{k}", v)
287
+ end
288
+ o
289
+ end
290
+ end
291
+
292
+ class String
293
+ yaml_as "tag:ruby.yaml.org,2002:string"
294
+ yaml_as "tag:yaml.org,2002:binary"
295
+ yaml_as "tag:yaml.org,2002:str"
296
+ def is_complex_yaml?
297
+ to_yaml_style or not to_yaml_properties.empty? or self =~ /\n.+/
298
+ end
299
+ def is_binary_data?
300
+ ( self.count( "^ -~", "^\r\n" ) / self.size > 0.3 || self.count( "\x00" ) > 0 ) unless empty?
301
+ end
302
+ def String.yaml_new( klass, tag, val )
303
+ val = val.unpack("m")[0] if tag == "tag:yaml.org,2002:binary"
304
+ val = { 'str' => val } if String === val
305
+ if Hash === val
306
+ s = klass.allocate
307
+ # Thank you, NaHi
308
+ String.instance_method(:initialize).
309
+ bind(s).
310
+ call( val.delete( 'str' ) )
311
+ val.each { |k,v| s.instance_variable_set( k, v ) }
312
+ s
313
+ else
314
+ raise RbYAML::TypeError, "Invalid String: " + val.inspect
315
+ end
316
+ end
317
+ end
318
+
319
+ class Symbol
320
+ yaml_as "tag:ruby.yaml.org,2002:symbol"
321
+ yaml_as "tag:ruby.yaml.org,2002:sym"
322
+ def is_complex_yaml?; false; end
323
+ def Symbol.yaml_new( klass, tag, val )
324
+ if String === val
325
+ val.intern
326
+ else
327
+ raise RbYAML::TypeError, "Invalid Symbol: " + val.inspect
328
+ end
329
+ end
330
+ end
331
+
332
+ class Time
333
+ yaml_as "tag:ruby.yaml.org,2002:time"
334
+ yaml_as "tag:yaml.org,2002:timestamp"
335
+ def is_complex_yaml?; false; end
336
+ def Time.yaml_new( klass, tag, val )
337
+ if Hash === val
338
+ t = val.delete( 'at' )
339
+ val.each { |k,v| t.instance_variable_set( k, v ) }
340
+ t
341
+ else
342
+ raise RbYAML::TypeError, "Invalid Time: " + val.inspect
343
+ end
344
+ end
345
+ end
346
+
347
+ class Date
348
+ yaml_as "tag:yaml.org,2002:timestamp#ymd"
349
+ def is_complex_yaml?; false; end
350
+ end
351
+
352
+ class Numeric
353
+ def is_complex_yaml?; false; end
354
+ end
355
+
356
+ class Fixnum
357
+ yaml_as "tag:yaml.org,2002:int"
358
+ end
359
+
360
+ class Float
361
+ yaml_as "tag:yaml.org,2002:float"
362
+ end
363
+
364
+ class TrueClass
365
+ yaml_as "tag:yaml.org,2002:bool#yes"
366
+ def is_complex_yaml?; false; end
367
+ end
368
+
369
+ class FalseClass
370
+ yaml_as "tag:yaml.org,2002:bool#no"
371
+ def is_complex_yaml?; false; end
372
+ end
373
+
374
+ class NilClass
375
+ yaml_as "tag:yaml.org,2002:null"
376
+ def is_complex_yaml?; false; end
377
+ end
378
+ end
@@ -0,0 +1,189 @@
1
+ require 'rbyaml/error'
2
+ require 'rbyaml/events'
3
+ require 'rbyaml/nodes'
4
+
5
+ module RbYAML
6
+ class ComposerError < MarkedYAMLError
7
+ end
8
+
9
+ module BaseComposer
10
+ @@yaml_resolvers = {}
11
+
12
+ def initialize_composer
13
+ @all_anchors = {}
14
+ @complete_anchors = {}
15
+ @resolver_tags = []
16
+ @resolver_paths = []
17
+ end
18
+
19
+ def check_node
20
+ !check_event(StreamEndEvent)
21
+ end
22
+
23
+ def get_node
24
+ compose_document if check_node
25
+ end
26
+
27
+ def each_node
28
+ yield compose_document while check_node
29
+ end
30
+
31
+ def compose_document
32
+ # Drop the STREAM-START event.
33
+ get_event if check_event(StreamStartEvent)
34
+ get_event
35
+ # Compose the root node.
36
+ node = compose_node([])
37
+ # Drop the DOCUMENT-END event.
38
+ get_event
39
+ @all_anchors = {}
40
+ @complete_anchors = {}
41
+ @resolver_tags = []
42
+ @resolver_paths = []
43
+ node
44
+ end
45
+
46
+ def increase_resolver_depth(path)
47
+ depth = path.length
48
+ tag = []
49
+ paths = []
50
+ if depth == 0
51
+ for resolver_path in @@yaml_resolvers.keys
52
+ if resolver_path
53
+ paths += resolver_path
54
+ else
55
+ tag = @@yaml_resolvers[resolver_path]
56
+ end
57
+ end
58
+ else
59
+ base, index = path[-1]
60
+ if ScalarNode === index && index.tag == DEFAULT_SCALAR_TAG
61
+ index = index.value
62
+ elsif Node === index
63
+ index = nil
64
+ end
65
+ if @resolver_paths[-1]
66
+ for resolver_path in @resolver_paths[-1]
67
+ resolver_index = resolver_path[depth-1]
68
+ if resolver_index.nil? || resolver_index == index
69
+ if resolver_index.length > depth
70
+ paths += resolver_path
71
+ else
72
+ tag = @@yaml_resolvers[resolver_path]
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ @resolver_tags += tag
80
+ @resolver_paths += paths
81
+ end
82
+
83
+ def decrease_resolver_depth
84
+ @resolver_tags.pop
85
+ @resolver_paths.pop
86
+ end
87
+
88
+ def compose_node(path)
89
+ if check_event(AliasEvent)
90
+ event = get_event
91
+ anchor = event.anchor
92
+ raise ComposerError.new(nil, nil, "found undefined alias #{anchor}", event.start_mark) if !@all_anchors.include?(anchor)
93
+ if !@complete_anchors.include?(anchor)
94
+ collection_event = @all_anchors[anchor]
95
+ raise ComposerError.new("while composing a collection",collection_event.start_mark,"found recursive anchor #{anchor}",event.start_mark)
96
+ end
97
+ return @complete_anchors[anchor]
98
+ end
99
+ increase_resolver_depth(path)
100
+ event = peek_event
101
+ anchor = event.anchor
102
+ if !anchor.nil?
103
+ if @all_anchors.include?(anchor)
104
+ raise ComposerError.new("found duplicate anchor #{anchor}; first occurence", @all_anchors[anchor].start_mark,"second occurence", event.start_mark)
105
+ end
106
+ @all_anchors[anchor] = event
107
+ end
108
+ if check_event(ScalarEvent)
109
+ node = compose_scalar_node(path)
110
+ elsif check_event(SequenceStartEvent)
111
+ node = compose_sequence_node(path)
112
+ elsif check_event(MappingStartEvent)
113
+ node = compose_mapping_node(path)
114
+ end
115
+
116
+ if !anchor.nil?
117
+ @complete_anchors[anchor] = node
118
+ end
119
+ decrease_resolver_depth
120
+ node
121
+ end
122
+
123
+ def compose_scalar_node(path)
124
+ event = get_event
125
+ tag = resolve_scalar(path, event.tag, event.implicit, event.value)
126
+ ScalarNode.new(tag, event.value,event.start_mark, event.end_mark, style=event.style)
127
+ end
128
+
129
+ def compose_sequence_node(path)
130
+ start_event = get_event
131
+ tag = resolve_sequence(path, start_event.tag)
132
+ node = SequenceNode.new(tag, [],start_event.start_mark, nil,flow_style=start_event.flow_style)
133
+ index = 0
134
+ while !check_event(SequenceEndEvent)
135
+ node.value << compose_node(path+[[node, index]])
136
+ index += 1
137
+ end
138
+
139
+ end_event = get_event
140
+ node.end_mark = end_event.end_mark
141
+ node
142
+ end
143
+
144
+ def compose_mapping_node(path)
145
+ start_event = get_event
146
+ tag = resolve_mapping(path, start_event.tag)
147
+ node = MappingNode.new(tag, {},start_event.start_mark, nil,flow_style=start_event.flow_style)
148
+ while !check_event(MappingEndEvent)
149
+ key_event = peek_event
150
+ item_key = compose_node(path+[[node, nil]])
151
+ item_value = compose_node(path+[[node, item_key]])
152
+ if node.value.include?(item_key)
153
+ raise ComposerError.new("while composing a mapping", start_event.start_mark,"found duplicate key", key_event.start_mark)
154
+ end
155
+ node.value[item_key] = item_value
156
+ end
157
+ end_event = get_event
158
+ node.end_mark = end_event.end_mark
159
+ node
160
+ end
161
+
162
+ def resolve_scalar(path, tag, implicit, value)
163
+ tag = detect(value) if implicit
164
+ tag = resolver_tags[-1] if (tag.nil? || tag == []) && @resolver_tags[-1]
165
+ tag = DEFAULT_SCALAR_TAG if tag.nil? || tag == [] || tag == "!"
166
+ tag
167
+ end
168
+
169
+ def resolve_sequence(path, tag)
170
+ tag = resolver_tags[-1] if tag.nil? && @resolver_tags[-1]
171
+ tag = DEFAULT_SEQUENCE_TAG if tag.nil? || tag == "!"
172
+ tag
173
+ end
174
+
175
+ def resolve_mapping(path, tag)
176
+ tag = resolver_tags[-1] if tag.nil? && @resolver_tags[-1]
177
+ tag = DEFAULT_MAPPING_TAG if tag.nil? || tag == "!"
178
+ tag
179
+ end
180
+
181
+ def self.add_resolver(tag, path)
182
+ @@yaml_resolvers[path] = tag
183
+ end
184
+ end
185
+
186
+ module Composer
187
+ include BaseComposer
188
+ end
189
+ end