syck 1.0.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.
Files changed (54) hide show
  1. data/.autotest.erb +8 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +6 -0
  4. data/Manifest.txt +52 -0
  5. data/README.rdoc +51 -0
  6. data/Rakefile +32 -0
  7. data/ext/syck/bytecode.c +1165 -0
  8. data/ext/syck/emitter.c +1247 -0
  9. data/ext/syck/extconf.h +3 -0
  10. data/ext/syck/extconf.rb +5 -0
  11. data/ext/syck/gram.c +1894 -0
  12. data/ext/syck/gram.h +79 -0
  13. data/ext/syck/handler.c +173 -0
  14. data/ext/syck/implicit.c +2990 -0
  15. data/ext/syck/node.c +407 -0
  16. data/ext/syck/rubyext.c +2328 -0
  17. data/ext/syck/syck.c +524 -0
  18. data/ext/syck/syck.h +453 -0
  19. data/ext/syck/token.c +2724 -0
  20. data/ext/syck/yaml2byte.c +259 -0
  21. data/ext/syck/yamlbyte.h +171 -0
  22. data/lib/syck.bundle +0 -0
  23. data/lib/syck.rb +447 -0
  24. data/lib/syck/baseemitter.rb +242 -0
  25. data/lib/syck/basenode.rb +222 -0
  26. data/lib/syck/constants.rb +45 -0
  27. data/lib/syck/encoding.rb +35 -0
  28. data/lib/syck/error.rb +34 -0
  29. data/lib/syck/loader.rb +14 -0
  30. data/lib/syck/rubytypes.rb +450 -0
  31. data/lib/syck/stream.rb +41 -0
  32. data/lib/syck/stringio.rb +85 -0
  33. data/lib/syck/syck.rb +16 -0
  34. data/lib/syck/tag.rb +95 -0
  35. data/lib/syck/types.rb +192 -0
  36. data/lib/syck/yamlnode.rb +54 -0
  37. data/lib/syck/ypath.rb +54 -0
  38. data/lib/yaml/syck.rb +14 -0
  39. data/test/helper.rb +2 -0
  40. data/test/test_array.rb +13 -0
  41. data/test/test_boolean.rb +36 -0
  42. data/test/test_class.rb +11 -0
  43. data/test/test_exception.rb +45 -0
  44. data/test/test_hash.rb +24 -0
  45. data/test/test_null.rb +19 -0
  46. data/test/test_omap.rb +55 -0
  47. data/test/test_set.rb +30 -0
  48. data/test/test_string.rb +44 -0
  49. data/test/test_struct.rb +32 -0
  50. data/test/test_symbol.rb +21 -0
  51. data/test/test_time.rb +23 -0
  52. data/test/test_yaml.rb +1403 -0
  53. data/test/test_yaml_properties.rb +63 -0
  54. metadata +187 -0
@@ -0,0 +1,45 @@
1
+ #
2
+ # Constants used throughout the library
3
+ #
4
+ module Syck
5
+
6
+ #
7
+ # Constants
8
+ #
9
+ VERSION = '1.0.0'
10
+ SUPPORTED_YAML_VERSIONS = ['1.0']
11
+
12
+ #
13
+ # Parser tokens
14
+ #
15
+ WORD_CHAR = 'A-Za-z0-9'
16
+ PRINTABLE_CHAR = '-_A-Za-z0-9!?/()$\'". '
17
+ NOT_PLAIN_CHAR = '\x7f\x0-\x1f\x80-\x9f'
18
+ ESCAPE_CHAR = '[\\x00-\\x09\\x0b-\\x1f]'
19
+ INDICATOR_CHAR = '*&!|\\\\^@%{}[]='
20
+ SPACE_INDICATORS = '-#:,?'
21
+ RESTRICTED_INDICATORS = '#:,}]'
22
+ DNS_COMP_RE = "\\w(?:[-\\w]*\\w)?"
23
+ DNS_NAME_RE = "(?:(?:#{DNS_COMP_RE}\\.)+#{DNS_COMP_RE}|#{DNS_COMP_RE})"
24
+ ESCAPES = %w{\x00 \x01 \x02 \x03 \x04 \x05 \x06 \a
25
+ \x08 \t \n \v \f \r \x0e \x0f
26
+ \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17
27
+ \x18 \x19 \x1a \e \x1c \x1d \x1e \x1f
28
+ }
29
+ UNESCAPES = {
30
+ 'a' => "\x07", 'b' => "\x08", 't' => "\x09",
31
+ 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c",
32
+ 'r' => "\x0d", 'e' => "\x1b", '\\' => '\\',
33
+ }
34
+
35
+ #
36
+ # Default settings
37
+ #
38
+ DEFAULTS = {
39
+ :Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.0',
40
+ :SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false,
41
+ :WidthType => 'absolute', :BestWidth => 80,
42
+ :UseBlock => false, :UseFold => false, :Encoding => :None
43
+ }
44
+
45
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # Handle Unicode-to-Internal conversion
3
+ #
4
+
5
+ module Syck
6
+
7
+ #
8
+ # Escape the string, condensing common escapes
9
+ #
10
+ def self.escape( value, skip = "" )
11
+ warn "#{caller[0]}: YAML.escape is deprecated" if $VERBOSE
12
+ value.gsub( /\\/, "\\\\\\" ).
13
+ gsub( /"/, "\\\"" ).
14
+ gsub( /([\x00-\x1f])/ ) do
15
+ skip[$&] || ESCAPES[ $&.unpack("C")[0] ]
16
+ end
17
+ end
18
+
19
+ #
20
+ # Unescape the condenses escapes
21
+ #
22
+ def self.unescape( value )
23
+ warn "#{caller[0]}: YAML.unescape is deprecated" if $VERBOSE
24
+ value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) {
25
+ if $3
26
+ ["#$3".hex ].pack('U*')
27
+ elsif $2
28
+ [$2].pack( "H2" )
29
+ else
30
+ UNESCAPES[$1]
31
+ end
32
+ }
33
+ end
34
+
35
+ end
@@ -0,0 +1,34 @@
1
+ #
2
+ # Error messages and exception class
3
+ #
4
+
5
+ module Syck
6
+
7
+ #
8
+ # Error messages
9
+ #
10
+
11
+ ERROR_NO_HEADER_NODE = "With UseHeader=false, the node Array or Hash must have elements"
12
+ ERROR_NEED_HEADER = "With UseHeader=false, the node must be an Array or Hash"
13
+ ERROR_BAD_EXPLICIT = "Unsupported explicit transfer: '%s'"
14
+ ERROR_MANY_EXPLICIT = "More than one explicit transfer"
15
+ ERROR_MANY_IMPLICIT = "More than one implicit request"
16
+ ERROR_NO_ANCHOR = "No anchor for alias '%s'"
17
+ ERROR_BAD_ANCHOR = "Invalid anchor: %s"
18
+ ERROR_MANY_ANCHOR = "More than one anchor"
19
+ ERROR_ANCHOR_ALIAS = "Can't define both an anchor and an alias"
20
+ ERROR_BAD_ALIAS = "Invalid alias: %s"
21
+ ERROR_MANY_ALIAS = "More than one alias"
22
+ ERROR_ZERO_INDENT = "Can't use zero as an indentation width"
23
+ ERROR_UNSUPPORTED_VERSION = "This release of YAML.rb does not support YAML version %s"
24
+ ERROR_UNSUPPORTED_ENCODING = "Attempt to use unsupported encoding: %s"
25
+
26
+ #
27
+ # YAML Error classes
28
+ #
29
+
30
+ class Error < StandardError; end
31
+ class ParseError < Error; end
32
+ class TypeError < StandardError; end
33
+
34
+ end
@@ -0,0 +1,14 @@
1
+ #
2
+ # YAML::Loader class
3
+ # .. type handling ..
4
+ #
5
+ module Syck
6
+ class Loader
7
+ TRANSFER_DOMAINS = {
8
+ 'yaml.org,2002' => {},
9
+ 'ruby.yaml.org,2002' => {}
10
+ }
11
+ PRIVATE_TYPES = {}
12
+ IMPLICIT_TYPES = [ 'null', 'bool', 'time', 'int', 'float' ]
13
+ end
14
+ end
@@ -0,0 +1,450 @@
1
+ # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
2
+ require 'date'
3
+
4
+ class Class
5
+ def to_yaml( opts = {} )
6
+ raise TypeError, "can't dump anonymous class %s" % self.class
7
+ end
8
+ end
9
+
10
+ class Object
11
+ yaml_as "tag:ruby.yaml.org,2002:object"
12
+ def to_yaml_style; end
13
+ undef to_yaml_properties rescue nil
14
+ def to_yaml_properties; instance_variables.sort; end
15
+ def to_yaml( opts = {} )
16
+ Syck::quick_emit( self, opts ) do |out|
17
+ out.map( taguri, to_yaml_style ) do |map|
18
+ to_yaml_properties.each do |m|
19
+ map.add( m[1..-1], instance_variable_get( m ) )
20
+ end
21
+ end
22
+ end
23
+ end
24
+ alias :syck_to_yaml :to_yaml
25
+ end
26
+
27
+ class Hash
28
+ yaml_as "tag:ruby.yaml.org,2002:hash"
29
+ yaml_as "tag:yaml.org,2002:map"
30
+ def yaml_initialize( tag, val )
31
+ if Array === val
32
+ update Hash.[]( *val ) # Convert the map to a sequence
33
+ elsif Hash === val
34
+ update val
35
+ else
36
+ raise Syck::TypeError, "Invalid map explicitly tagged #{ tag }: " + val.inspect
37
+ end
38
+ end
39
+ def to_yaml( opts = {} )
40
+ Syck::quick_emit( self, opts ) do |out|
41
+ out.map( taguri, to_yaml_style ) do |map|
42
+ each do |k, v|
43
+ map.add( k, v )
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ class Struct
51
+ yaml_as "tag:ruby.yaml.org,2002:struct"
52
+ def self.yaml_tag_class_name; self.name.gsub( "Struct::", "" ); end
53
+ def self.yaml_tag_read_class( name ); "Struct::#{ name }"; end
54
+ def self.yaml_new( klass, tag, val )
55
+ if Hash === val
56
+ struct_type = nil
57
+
58
+ #
59
+ # Use existing Struct if it exists
60
+ #
61
+ props = {}
62
+ val.delete_if { |k,v| props[k] = v if k =~ /^@/ }
63
+ begin
64
+ struct_type = Syck.read_type_class( tag, Struct ).last
65
+ rescue NameError
66
+ end
67
+ if not struct_type
68
+ struct_def = [ tag.split( ':', 4 ).last ]
69
+ struct_type = Struct.new( *struct_def.concat( val.keys.collect { |k| k.intern } ) )
70
+ end
71
+
72
+ #
73
+ # Set the Struct properties
74
+ #
75
+ st = Syck::object_maker( struct_type, {} )
76
+ st.members.each do |m|
77
+ st.send( "#{m}=", val[m.to_s] )
78
+ end
79
+ props.each do |k,v|
80
+ st.instance_variable_set(k, v)
81
+ end
82
+ st
83
+ else
84
+ raise Syck::TypeError, "Invalid Ruby Struct: " + val.inspect
85
+ end
86
+ end
87
+ def to_yaml( opts = {} )
88
+ Syck::quick_emit( self, opts ) do |out|
89
+ #
90
+ # Basic struct is passed as a YAML map
91
+ #
92
+ out.map( taguri, to_yaml_style ) do |map|
93
+ self.members.each do |m|
94
+ map.add( m.to_s, self[m.to_s] )
95
+ end
96
+ self.to_yaml_properties.each do |m|
97
+ map.add( m, instance_variable_get( m ) )
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class Array
105
+ yaml_as "tag:ruby.yaml.org,2002:array"
106
+ yaml_as "tag:yaml.org,2002:seq"
107
+ def yaml_initialize( tag, val ); concat( val.to_a ); end
108
+ def to_yaml( opts = {} )
109
+ Syck::quick_emit( self, opts ) do |out|
110
+ out.seq( taguri, to_yaml_style ) do |seq|
111
+ each do |x|
112
+ seq.add( x )
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ class Exception
120
+ yaml_as "tag:ruby.yaml.org,2002:exception"
121
+ def Exception.yaml_new( klass, tag, val )
122
+ o = klass.allocate
123
+ Exception.instance_method(:initialize).bind(o).call(val.delete('message'))
124
+ val.each_pair do |k,v|
125
+ o.instance_variable_set("@#{k}", v)
126
+ end
127
+ o
128
+ end
129
+ def to_yaml( opts = {} )
130
+ Syck::quick_emit( self, opts ) do |out|
131
+ out.map( taguri, to_yaml_style ) do |map|
132
+ map.add( 'message', message )
133
+ to_yaml_properties.each do |m|
134
+ map.add( m[1..-1], instance_variable_get( m ) )
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ class String
142
+ yaml_as "tag:ruby.yaml.org,2002:string"
143
+ yaml_as "tag:yaml.org,2002:binary"
144
+ yaml_as "tag:yaml.org,2002:str"
145
+ def is_complex_yaml?
146
+ to_yaml_style or not to_yaml_properties.empty? or self =~ /\n.+/
147
+ end
148
+ def is_binary_data?
149
+ self.count("\x00-\x7F", "^ -~\t\r\n").fdiv(self.size) > 0.3 || self.index("\x00") unless self.empty?
150
+ end
151
+ def String.yaml_new( klass, tag, val )
152
+ val = val.unpack("m")[0] if tag == "tag:yaml.org,2002:binary"
153
+ val = { 'str' => val } if String === val
154
+ if Hash === val
155
+ s = klass.allocate
156
+ # Thank you, NaHi
157
+ String.instance_method(:initialize).
158
+ bind(s).
159
+ call( val.delete( 'str' ) )
160
+ val.each { |k,v| s.instance_variable_set( k, v ) }
161
+ s
162
+ else
163
+ raise Syck::TypeError, "Invalid String: " + val.inspect
164
+ end
165
+ end
166
+ def to_yaml( opts = {} )
167
+ Syck::quick_emit( is_complex_yaml? ? self : nil, opts ) do |out|
168
+ if is_binary_data?
169
+ out.scalar( "tag:yaml.org,2002:binary", [self].pack("m"), :literal )
170
+ elsif to_yaml_properties.empty?
171
+ out.scalar( taguri, self, self =~ /^:/ ? :quote2 : to_yaml_style )
172
+ else
173
+ out.map( taguri, to_yaml_style ) do |map|
174
+ map.add( 'str', "#{self}" )
175
+ to_yaml_properties.each do |m|
176
+ map.add( m, instance_variable_get( m ) )
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ class Symbol
185
+ yaml_as "tag:ruby.yaml.org,2002:symbol"
186
+ yaml_as "tag:ruby.yaml.org,2002:sym"
187
+ def Symbol.yaml_new( klass, tag, val )
188
+ if String === val
189
+ val = Syck::load( val ) if val =~ /\A(["']).*\1\z/
190
+ val.intern
191
+ else
192
+ raise Syck::TypeError, "Invalid Symbol: " + val.inspect
193
+ end
194
+ end
195
+ def to_yaml( opts = {} )
196
+ Syck::quick_emit( nil, opts ) do |out|
197
+ out.scalar( "tag:yaml.org,2002:str", self.inspect, :plain )
198
+ end
199
+ end
200
+ end
201
+
202
+ class Range
203
+ yaml_as "tag:ruby.yaml.org,2002:range"
204
+ def Range.yaml_new( klass, tag, val )
205
+ inr = %r'(\w+|[+-]?\d+(?:\.\d+)?(?:e[+-]\d+)?|"(?:[^\\"]|\\.)*")'
206
+ opts = {}
207
+ if String === val and val =~ /^#{inr}(\.{2,3})#{inr}$/o
208
+ r1, rdots, r2 = $1, $2, $3
209
+ opts = {
210
+ 'begin' => Syck.load( "--- #{r1}" ),
211
+ 'end' => Syck.load( "--- #{r2}" ),
212
+ 'excl' => rdots.length == 3
213
+ }
214
+ val = {}
215
+ elsif Hash === val
216
+ opts['begin'] = val.delete('begin')
217
+ opts['end'] = val.delete('end')
218
+ opts['excl'] = val.delete('excl')
219
+ end
220
+ if Hash === opts
221
+ r = Syck::object_maker( klass, {} )
222
+ # Thank you, NaHi
223
+ Range.instance_method(:initialize).
224
+ bind(r).
225
+ call( opts['begin'], opts['end'], opts['excl'] )
226
+ val.each { |k,v| r.instance_variable_set( k, v ) }
227
+ r
228
+ else
229
+ raise Syck::TypeError, "Invalid Range: " + val.inspect
230
+ end
231
+ end
232
+ def to_yaml( opts = {} )
233
+ Syck::quick_emit( self, opts ) do |out|
234
+ # if self.begin.is_complex_yaml? or self.begin.respond_to? :to_str or
235
+ # self.end.is_complex_yaml? or self.end.respond_to? :to_str or
236
+ # not to_yaml_properties.empty?
237
+ out.map( taguri, to_yaml_style ) do |map|
238
+ map.add( 'begin', self.begin )
239
+ map.add( 'end', self.end )
240
+ map.add( 'excl', self.exclude_end? )
241
+ to_yaml_properties.each do |m|
242
+ map.add( m, instance_variable_get( m ) )
243
+ end
244
+ end
245
+ # else
246
+ # out.scalar( taguri ) do |sc|
247
+ # sc.embed( self.begin )
248
+ # sc.concat( self.exclude_end? ? "..." : ".." )
249
+ # sc.embed( self.end )
250
+ # end
251
+ # end
252
+ end
253
+ end
254
+ end
255
+
256
+ class Regexp
257
+ yaml_as "tag:ruby.yaml.org,2002:regexp"
258
+ def Regexp.yaml_new( klass, tag, val )
259
+ if String === val and val =~ /^\/(.*)\/([mixn]*)$/
260
+ val = { 'regexp' => $1, 'mods' => $2 }
261
+ end
262
+ if Hash === val
263
+ mods = nil
264
+ unless val['mods'].to_s.empty?
265
+ mods = 0x00
266
+ mods |= Regexp::EXTENDED if val['mods'].include?( 'x' )
267
+ mods |= Regexp::IGNORECASE if val['mods'].include?( 'i' )
268
+ mods |= Regexp::MULTILINE if val['mods'].include?( 'm' )
269
+ mods |= Regexp::NOENCODING if val['mods'].include?( 'n' )
270
+ end
271
+ val.delete( 'mods' )
272
+ r = Syck::object_maker( klass, {} )
273
+ Regexp.instance_method(:initialize).
274
+ bind(r).
275
+ call( val.delete( 'regexp' ), mods )
276
+ val.each { |k,v| r.instance_variable_set( k, v ) }
277
+ r
278
+ else
279
+ raise Syck::TypeError, "Invalid Regular expression: " + val.inspect
280
+ end
281
+ end
282
+ def to_yaml( opts = {} )
283
+ Syck::quick_emit( nil, opts ) do |out|
284
+ if to_yaml_properties.empty?
285
+ out.scalar( taguri, self.inspect, :plain )
286
+ else
287
+ out.map( taguri, to_yaml_style ) do |map|
288
+ src = self.inspect
289
+ if src =~ /\A\/(.*)\/([a-z]*)\Z/
290
+ map.add( 'regexp', $1 )
291
+ map.add( 'mods', $2 )
292
+ else
293
+ raise Syck::TypeError, "Invalid Regular expression: " + src
294
+ end
295
+ to_yaml_properties.each do |m|
296
+ map.add( m, instance_variable_get( m ) )
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end
303
+
304
+ class Time
305
+ yaml_as "tag:ruby.yaml.org,2002:time"
306
+ yaml_as "tag:yaml.org,2002:timestamp"
307
+ def Time.yaml_new( klass, tag, val )
308
+ if Hash === val
309
+ t = val.delete( 'at' )
310
+ val.each { |k,v| t.instance_variable_set( k, v ) }
311
+ t
312
+ else
313
+ raise Syck::TypeError, "Invalid Time: " + val.inspect
314
+ end
315
+ end
316
+ def to_yaml( opts = {} )
317
+ Syck::quick_emit( self, opts ) do |out|
318
+ tz = "Z"
319
+ # from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
320
+ unless self.utc?
321
+ utc_same_instant = self.dup.utc
322
+ utc_same_writing = Time.utc(year,month,day,hour,min,sec,usec)
323
+ difference_to_utc = utc_same_writing - utc_same_instant
324
+ if (difference_to_utc < 0)
325
+ difference_sign = '-'
326
+ absolute_difference = -difference_to_utc
327
+ else
328
+ difference_sign = '+'
329
+ absolute_difference = difference_to_utc
330
+ end
331
+ difference_minutes = (absolute_difference/60).round
332
+ tz = "%s%02d:%02d" % [ difference_sign, difference_minutes / 60, difference_minutes % 60]
333
+ end
334
+ standard = self.strftime( "%Y-%m-%d %H:%M:%S" )
335
+ standard += ".%06d" % [usec] if usec.nonzero?
336
+ standard += " %s" % [tz]
337
+ if to_yaml_properties.empty?
338
+ out.scalar( taguri, standard, :plain )
339
+ else
340
+ out.map( taguri, to_yaml_style ) do |map|
341
+ map.add( 'at', standard )
342
+ to_yaml_properties.each do |m|
343
+ map.add( m, instance_variable_get( m ) )
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ class Date
352
+ yaml_as "tag:yaml.org,2002:timestamp#ymd"
353
+ def to_yaml( opts = {} )
354
+ Syck::quick_emit( self, opts ) do |out|
355
+ out.scalar( "tag:yaml.org,2002:timestamp", self.to_s, :plain )
356
+ end
357
+ end
358
+ end
359
+
360
+ class Integer
361
+ yaml_as "tag:yaml.org,2002:int"
362
+ def to_yaml( opts = {} )
363
+ Syck::quick_emit( nil, opts ) do |out|
364
+ out.scalar( "tag:yaml.org,2002:int", self.to_s, :plain )
365
+ end
366
+ end
367
+ end
368
+
369
+ class Float
370
+ yaml_as "tag:yaml.org,2002:float"
371
+ def to_yaml( opts = {} )
372
+ Syck::quick_emit( nil, opts ) do |out|
373
+ str = self.to_s
374
+ if str == "Infinity"
375
+ str = ".Inf"
376
+ elsif str == "-Infinity"
377
+ str = "-.Inf"
378
+ elsif str == "NaN"
379
+ str = ".NaN"
380
+ end
381
+ out.scalar( "tag:yaml.org,2002:float", str, :plain )
382
+ end
383
+ end
384
+ end
385
+
386
+ class Rational
387
+ yaml_as "tag:ruby.yaml.org,2002:object:Rational"
388
+ def Rational.yaml_new( klass, tag, val )
389
+ if val.is_a? String
390
+ Rational( val )
391
+ else
392
+ Rational( val['numerator'], val['denominator'] )
393
+ end
394
+ end
395
+ def to_yaml( opts = {} )
396
+ Syck::quick_emit( self, opts ) do |out|
397
+ out.map( taguri, nil ) do |map|
398
+ map.add( 'denominator', denominator )
399
+ map.add( 'numerator', numerator )
400
+ end
401
+ end
402
+ end
403
+ end
404
+
405
+ class Complex
406
+ yaml_as "tag:ruby.yaml.org,2002:object:Complex"
407
+ def Complex.yaml_new( klass, tag, val )
408
+ if val.is_a? String
409
+ Complex( val )
410
+ else
411
+ Complex( val['real'], val['image'] )
412
+ end
413
+ end
414
+ def to_yaml( opts = {} )
415
+ Syck::quick_emit( self, opts ) do |out|
416
+ out.map( taguri, nil ) do |map|
417
+ map.add( 'image', imaginary )
418
+ map.add( 'real', real )
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ class TrueClass
425
+ yaml_as "tag:yaml.org,2002:bool#yes"
426
+ def to_yaml( opts = {} )
427
+ Syck::quick_emit( nil, opts ) do |out|
428
+ out.scalar( taguri, "true", :plain )
429
+ end
430
+ end
431
+ end
432
+
433
+ class FalseClass
434
+ yaml_as "tag:yaml.org,2002:bool#no"
435
+ def to_yaml( opts = {} )
436
+ Syck::quick_emit( nil, opts ) do |out|
437
+ out.scalar( taguri, "false", :plain )
438
+ end
439
+ end
440
+ end
441
+
442
+ class NilClass
443
+ yaml_as "tag:yaml.org,2002:null"
444
+ def to_yaml( opts = {} )
445
+ Syck::quick_emit( nil, opts ) do |out|
446
+ out.scalar( taguri, "", :plain )
447
+ end
448
+ end
449
+ end
450
+