psych 3.1.0 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -0
  3. data/LICENSE +21 -0
  4. data/README.md +2 -5
  5. data/Rakefile +8 -15
  6. data/ext/psych/depend +2 -0
  7. data/ext/psych/extconf.rb +6 -2
  8. data/ext/psych/psych.c +6 -3
  9. data/ext/psych/psych_parser.c +20 -33
  10. data/ext/psych/psych_yaml_tree.c +0 -12
  11. data/ext/psych/yaml/api.c +22 -22
  12. data/ext/psych/yaml/config.h +76 -6
  13. data/ext/psych/yaml/dumper.c +1 -1
  14. data/ext/psych/yaml/emitter.c +44 -10
  15. data/ext/psych/yaml/loader.c +206 -106
  16. data/ext/psych/yaml/parser.c +6 -1
  17. data/ext/psych/yaml/scanner.c +45 -25
  18. data/ext/psych/yaml/yaml.h +43 -29
  19. data/ext/psych/yaml/yaml_private.h +4 -4
  20. data/lib/psych/class_loader.rb +10 -8
  21. data/lib/psych/core_ext.rb +1 -1
  22. data/lib/psych/exception.rb +2 -2
  23. data/lib/psych/handler.rb +1 -1
  24. data/lib/psych/handlers/document_stream.rb +1 -1
  25. data/lib/psych/handlers/recorder.rb +1 -1
  26. data/lib/psych/json/stream.rb +2 -2
  27. data/lib/psych/json/tree_builder.rb +1 -1
  28. data/lib/psych/nodes/node.rb +4 -4
  29. data/lib/psych/nodes/scalar.rb +1 -1
  30. data/lib/psych/nodes.rb +7 -7
  31. data/lib/psych/scalar_scanner.rb +25 -39
  32. data/lib/psych/syntax_error.rb +1 -1
  33. data/lib/psych/tree_builder.rb +1 -1
  34. data/lib/psych/versions.rb +3 -3
  35. data/lib/psych/visitors/json_tree.rb +1 -1
  36. data/lib/psych/visitors/to_ruby.rb +53 -20
  37. data/lib/psych/visitors/visitor.rb +17 -3
  38. data/lib/psych/visitors/yaml_tree.rb +83 -47
  39. data/lib/psych/visitors.rb +6 -6
  40. data/lib/psych.rb +222 -122
  41. data/psych.gemspec +10 -16
  42. metadata +12 -43
  43. data/.travis.yml +0 -22
  44. data/CHANGELOG.rdoc +0 -583
@@ -9,21 +9,19 @@ module Psych
9
9
  TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
10
10
 
11
11
  # Taken from http://yaml.org/type/float.html
12
- FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
13
- |[-+]?\.(inf|Inf|INF)(?# infinity)
14
- |\.(nan|NaN|NAN)(?# not a number))$/x
12
+ # Base 60, [-+]inf and NaN are handled separately
13
+ FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
15
14
 
16
15
  # Taken from http://yaml.org/type/int.html
17
- INTEGER = /^(?:[-+]?0b[0-1_]+ (?# base 2)
18
- |[-+]?0[0-7_]+ (?# base 8)
19
- |[-+]?(?:0|[1-9][0-9_]*) (?# base 10)
20
- |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
16
+ INTEGER = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
17
+ |[-+]?0[0-7_,]+ (?# base 8)
18
+ |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
19
+ |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
21
20
 
22
21
  attr_reader :class_loader
23
22
 
24
23
  # Create a new scanner
25
24
  def initialize class_loader
26
- @string_cache = {}
27
25
  @symbol_cache = {}
28
26
  @class_loader = class_loader
29
27
  end
@@ -31,81 +29,70 @@ module Psych
31
29
  # Tokenize +string+ returning the Ruby object
32
30
  def tokenize string
33
31
  return nil if string.empty?
34
- return string if @string_cache.key?(string)
35
32
  return @symbol_cache[string] if @symbol_cache.key?(string)
36
33
 
37
- case string
38
34
  # Check for a String type, being careful not to get caught by hash keys, hex values, and
39
35
  # special floats (e.g., -.inf).
40
- when /^[^\d\.:-]?[A-Za-z_\s!@#\$%\^&\*\(\)\{\}\<\>\|\/\\~;=]+/, /\n/
41
- if string.length > 5
42
- @string_cache[string] = true
43
- return string
44
- end
36
+ if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
37
+ return string if string.length > 5
45
38
 
46
- case string
47
- when /^[^ytonf~]/i
48
- @string_cache[string] = true
39
+ if string.match?(/^[^ytonf~]/i)
49
40
  string
50
- when '~', /^null$/i
41
+ elsif string == '~' || string.match?(/^null$/i)
51
42
  nil
52
- when /^(yes|true|on)$/i
43
+ elsif string.match?(/^(yes|true|on)$/i)
53
44
  true
54
- when /^(no|false|off)$/i
45
+ elsif string.match?(/^(no|false|off)$/i)
55
46
  false
56
47
  else
57
- @string_cache[string] = true
58
48
  string
59
49
  end
60
- when TIME
50
+ elsif string.match?(TIME)
61
51
  begin
62
52
  parse_time string
63
53
  rescue ArgumentError
64
54
  string
65
55
  end
66
- when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
56
+ elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
67
57
  require 'date'
68
58
  begin
69
59
  class_loader.date.strptime(string, '%Y-%m-%d')
70
60
  rescue ArgumentError
71
61
  string
72
62
  end
73
- when /^\.inf$/i
63
+ elsif string.match?(/^\+?\.inf$/i)
74
64
  Float::INFINITY
75
- when /^-\.inf$/i
65
+ elsif string.match?(/^-\.inf$/i)
76
66
  -Float::INFINITY
77
- when /^\.nan$/i
67
+ elsif string.match?(/^\.nan$/i)
78
68
  Float::NAN
79
- when /^:./
69
+ elsif string.match?(/^:./)
80
70
  if string =~ /^:(["'])(.*)\1/
81
71
  @symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
82
72
  else
83
73
  @symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
84
74
  end
85
- when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/
75
+ elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/)
86
76
  i = 0
87
77
  string.split(':').each_with_index do |n,e|
88
78
  i += (n.to_i * 60 ** (e - 2).abs)
89
79
  end
90
80
  i
91
- when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/
81
+ elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/)
92
82
  i = 0
93
83
  string.split(':').each_with_index do |n,e|
94
84
  i += (n.to_f * 60 ** (e - 2).abs)
95
85
  end
96
86
  i
97
- when FLOAT
98
- if string =~ /\A[-+]?\.\Z/
99
- @string_cache[string] = true
87
+ elsif string.match?(FLOAT)
88
+ if string.match?(/\A[-+]?\.\Z/)
100
89
  string
101
90
  else
102
91
  Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
103
92
  end
93
+ elsif string.match?(INTEGER)
94
+ parse_int string
104
95
  else
105
- int = parse_int string.gsub(/[,_]/, '')
106
- return int if int
107
-
108
- @string_cache[string] = true
109
96
  string
110
97
  end
111
98
  end
@@ -113,8 +100,7 @@ module Psych
113
100
  ###
114
101
  # Parse and return an int from +string+
115
102
  def parse_int string
116
- return unless INTEGER === string
117
- Integer(string)
103
+ Integer(string.gsub(/[,_]/, ''))
118
104
  end
119
105
 
120
106
  ###
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/exception'
2
+ require_relative 'exception'
3
3
 
4
4
  module Psych
5
5
  class SyntaxError < Psych::Exception
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/handler'
2
+ require_relative 'handler'
3
3
 
4
4
  module Psych
5
5
  ###
@@ -1,10 +1,10 @@
1
-
2
1
  # frozen_string_literal: true
2
+
3
3
  module Psych
4
4
  # The version of Psych you are using
5
- VERSION = '3.1.0' unless defined?(::Psych::VERSION)
5
+ VERSION = '4.0.3'
6
6
 
7
7
  if RUBY_ENGINE == 'jruby'
8
- DEFAULT_SNAKEYAML_VERSION = '1.23'.freeze
8
+ DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze
9
9
  end
10
10
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/json/ruby_events'
2
+ require_relative '../json/ruby_events'
3
3
 
4
4
  module Psych
5
5
  module Visitors
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/scalar_scanner'
3
- require 'psych/class_loader'
4
- require 'psych/exception'
2
+ require_relative '../scalar_scanner'
3
+ require_relative '../class_loader'
4
+ require_relative '../exception'
5
5
 
6
6
  unless defined?(Regexp::NOENCODING)
7
7
  Regexp::NOENCODING = 32
@@ -12,39 +12,44 @@ module Psych
12
12
  ###
13
13
  # This class walks a YAML AST, converting each node to Ruby
14
14
  class ToRuby < Psych::Visitors::Visitor
15
- def self.create
15
+ def self.create(symbolize_names: false, freeze: false)
16
16
  class_loader = ClassLoader.new
17
17
  scanner = ScalarScanner.new class_loader
18
- new(scanner, class_loader)
18
+ new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
19
19
  end
20
20
 
21
21
  attr_reader :class_loader
22
22
 
23
- def initialize ss, class_loader
23
+ def initialize ss, class_loader, symbolize_names: false, freeze: false
24
24
  super()
25
25
  @st = {}
26
26
  @ss = ss
27
+ @load_tags = Psych.load_tags
27
28
  @domain_types = Psych.domain_types
28
29
  @class_loader = class_loader
30
+ @symbolize_names = symbolize_names
31
+ @freeze = freeze
29
32
  end
30
33
 
31
34
  def accept target
32
35
  result = super
33
- return result if @domain_types.empty? || !target.tag
34
36
 
35
- key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
36
- key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
37
+ unless @domain_types.empty? || !target.tag
38
+ key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
39
+ key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
37
40
 
38
- if @domain_types.key? key
39
- value, block = @domain_types[key]
40
- return block.call value, result
41
+ if @domain_types.key? key
42
+ value, block = @domain_types[key]
43
+ result = block.call value, result
44
+ end
41
45
  end
42
46
 
47
+ result = deduplicate(result).freeze if @freeze
43
48
  result
44
49
  end
45
50
 
46
51
  def deserialize o
47
- if klass = resolve_class(Psych.load_tags[o.tag])
52
+ if klass = resolve_class(@load_tags[o.tag])
48
53
  instance = klass.allocate
49
54
 
50
55
  if instance.respond_to?(:init_with)
@@ -124,7 +129,7 @@ module Psych
124
129
  end
125
130
 
126
131
  def visit_Psych_Nodes_Sequence o
127
- if klass = resolve_class(Psych.load_tags[o.tag])
132
+ if klass = resolve_class(@load_tags[o.tag])
128
133
  instance = klass.allocate
129
134
 
130
135
  if instance.respond_to?(:init_with)
@@ -156,8 +161,8 @@ module Psych
156
161
  end
157
162
 
158
163
  def visit_Psych_Nodes_Mapping o
159
- if Psych.load_tags[o.tag]
160
- return revive(resolve_class(Psych.load_tags[o.tag]), o)
164
+ if @load_tags[o.tag]
165
+ return revive(resolve_class(@load_tags[o.tag]), o)
161
166
  end
162
167
  return revive_hash(register(o, {}), o) unless o.tag
163
168
 
@@ -252,6 +257,8 @@ module Psych
252
257
 
253
258
  e = build_exception((resolve_class($1) || class_loader.exception),
254
259
  h.delete('message'))
260
+
261
+ e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
255
262
  init_with(e, h, o)
256
263
 
257
264
  when '!set', 'tag:yaml.org,2002:set'
@@ -320,6 +327,7 @@ module Psych
320
327
  end
321
328
 
322
329
  private
330
+
323
331
  def register node, object
324
332
  @st[node.anchor] = object if node.anchor
325
333
  object
@@ -331,13 +339,12 @@ module Psych
331
339
  list
332
340
  end
333
341
 
334
- SHOVEL = '<<'
335
- def revive_hash hash, o
342
+ def revive_hash hash, o, tagged= false
336
343
  o.children.each_slice(2) { |k,v|
337
344
  key = accept(k)
338
345
  val = accept(v)
339
346
 
340
- if key == SHOVEL && k.tag != "tag:yaml.org,2002:str"
347
+ if key == '<<' && k.tag != "tag:yaml.org,2002:str"
341
348
  case v
342
349
  when Nodes::Alias, Nodes::Mapping
343
350
  begin
@@ -359,6 +366,12 @@ module Psych
359
366
  hash[key] = val
360
367
  end
361
368
  else
369
+ if !tagged && @symbolize_names && key.is_a?(String)
370
+ key = key.to_sym
371
+ elsif !@freeze
372
+ key = deduplicate(key)
373
+ end
374
+
362
375
  hash[key] = val
363
376
  end
364
377
 
@@ -366,12 +379,32 @@ module Psych
366
379
  hash
367
380
  end
368
381
 
382
+ if RUBY_VERSION < '2.7'
383
+ def deduplicate key
384
+ if key.is_a?(String)
385
+ # It is important to untaint the string, otherwise it won't
386
+ # be deduplicated into an fstring, but simply frozen.
387
+ -(key.untaint)
388
+ else
389
+ key
390
+ end
391
+ end
392
+ else
393
+ def deduplicate key
394
+ if key.is_a?(String)
395
+ -key
396
+ else
397
+ key
398
+ end
399
+ end
400
+ end
401
+
369
402
  def merge_key hash, key, val
370
403
  end
371
404
 
372
405
  def revive klass, node
373
406
  s = register(node, klass.allocate)
374
- init_with(s, revive_hash({}, node), node)
407
+ init_with(s, revive_hash({}, node, true), node)
375
408
  end
376
409
 
377
410
  def init_with o, h, node
@@ -8,12 +8,26 @@ module Psych
8
8
 
9
9
  private
10
10
 
11
- DISPATCH = Hash.new do |hash, klass|
12
- hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
11
+ # @api private
12
+ def self.dispatch_cache
13
+ Hash.new do |hash, klass|
14
+ hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
15
+ end.compare_by_identity
16
+ end
17
+
18
+ if defined?(Ractor)
19
+ def dispatch
20
+ @dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache)
21
+ end
22
+ else
23
+ DISPATCH = dispatch_cache
24
+ def dispatch
25
+ DISPATCH
26
+ end
13
27
  end
14
28
 
15
29
  def visit target
16
- send DISPATCH[target.class], target
30
+ send dispatch[target.class], target
17
31
  end
18
32
  end
19
33
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/tree_builder'
3
- require 'psych/scalar_scanner'
4
- require 'psych/class_loader'
2
+ require_relative '../tree_builder'
3
+ require_relative '../scalar_scanner'
4
+ require_relative '../class_loader'
5
5
 
6
6
  module Psych
7
7
  module Visitors
@@ -80,7 +80,7 @@ module Psych
80
80
  raise(TypeError, "Can't dump #{target.class}") unless method
81
81
 
82
82
  h[klass] = method
83
- end
83
+ end.compare_by_identity
84
84
  end
85
85
 
86
86
  def start encoding = Nodes::Stream::UTF8
@@ -181,41 +181,11 @@ module Psych
181
181
  end
182
182
 
183
183
  def visit_Exception o
184
- tag = ['!ruby/exception', o.class.name].join ':'
185
-
186
- @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
187
-
188
- {
189
- 'message' => private_iv_get(o, 'mesg'),
190
- 'backtrace' => private_iv_get(o, 'backtrace'),
191
- }.each do |k,v|
192
- next unless v
193
- @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
194
- accept v
195
- end
196
-
197
- dump_ivars o
198
-
199
- @emitter.end_mapping
184
+ dump_exception o, o.message.to_s
200
185
  end
201
186
 
202
187
  def visit_NameError o
203
- tag = ['!ruby/exception', o.class.name].join ':'
204
-
205
- @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
206
-
207
- {
208
- 'message' => o.message.to_s,
209
- 'backtrace' => private_iv_get(o, 'backtrace'),
210
- }.each do |k,v|
211
- next unless v
212
- @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
213
- accept v
214
- end
215
-
216
- dump_ivars o
217
-
218
- @emitter.end_mapping
188
+ dump_exception o, o.message.to_s
219
189
  end
220
190
 
221
191
  def visit_Regexp o
@@ -302,6 +272,8 @@ module Psych
302
272
  tag = 'tag:yaml.org,2002:str'
303
273
  plain = false
304
274
  quote = false
275
+ elsif o == 'y' || o == 'n'
276
+ style = Nodes::Scalar::DOUBLE_QUOTED
305
277
  elsif @line_width && o.length > @line_width
306
278
  style = Nodes::Scalar::FOLDED
307
279
  elsif o =~ /^[^[:word:]][^"]*$/
@@ -458,15 +430,6 @@ module Psych
458
430
  node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
459
431
  register(o, node)
460
432
 
461
- # Dump the elements
462
- accept 'elements'
463
- @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
464
- o.each do |k,v|
465
- accept k
466
- accept v
467
- end
468
- @emitter.end_mapping
469
-
470
433
  # Dump the ivars
471
434
  accept 'ivars'
472
435
  @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
@@ -476,6 +439,15 @@ module Psych
476
439
  end
477
440
  @emitter.end_mapping
478
441
 
442
+ # Dump the elements
443
+ accept 'elements'
444
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
445
+ o.each do |k,v|
446
+ accept k
447
+ accept v
448
+ end
449
+ @emitter.end_mapping
450
+
479
451
  @emitter.end_mapping
480
452
  else
481
453
  tag = "!ruby/hash:#{o.class}"
@@ -492,6 +464,24 @@ module Psych
492
464
  def dump_list o
493
465
  end
494
466
 
467
+ def dump_exception o, msg
468
+ tag = ['!ruby/exception', o.class.name].join ':'
469
+
470
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
471
+
472
+ if msg
473
+ @emitter.scalar 'message', nil, nil, true, false, Nodes::Scalar::ANY
474
+ accept msg
475
+ end
476
+
477
+ @emitter.scalar 'backtrace', nil, nil, true, false, Nodes::Scalar::ANY
478
+ accept o.backtrace
479
+
480
+ dump_ivars o
481
+
482
+ @emitter.end_mapping
483
+ end
484
+
495
485
  def format_time time
496
486
  if time.utc?
497
487
  time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
@@ -521,9 +511,9 @@ module Psych
521
511
  def emit_coder c, o
522
512
  case c.type
523
513
  when :scalar
524
- @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY
514
+ @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style
525
515
  when :seq
526
- @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK
516
+ @emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
527
517
  c.seq.each do |thing|
528
518
  accept thing
529
519
  end
@@ -547,5 +537,51 @@ module Psych
547
537
  end
548
538
  end
549
539
  end
540
+
541
+ class RestrictedYAMLTree < YAMLTree
542
+ DEFAULT_PERMITTED_CLASSES = {
543
+ TrueClass => true,
544
+ FalseClass => true,
545
+ NilClass => true,
546
+ Integer => true,
547
+ Float => true,
548
+ String => true,
549
+ Array => true,
550
+ Hash => true,
551
+ }.compare_by_identity.freeze
552
+
553
+ def initialize emitter, ss, options
554
+ super
555
+ @permitted_classes = DEFAULT_PERMITTED_CLASSES.dup
556
+ Array(options[:permitted_classes]).each do |klass|
557
+ @permitted_classes[klass] = true
558
+ end
559
+ @permitted_symbols = {}.compare_by_identity
560
+ Array(options[:permitted_symbols]).each do |symbol|
561
+ @permitted_symbols[symbol] = true
562
+ end
563
+ @aliases = options.fetch(:aliases, false)
564
+ end
565
+
566
+ def accept target
567
+ if !@aliases && @st.key?(target)
568
+ raise BadAlias, "Tried to dump an aliased object"
569
+ end
570
+
571
+ unless @permitted_classes[target.class]
572
+ raise DisallowedClass.new('dump', target.class.name || target.class.inspect)
573
+ end
574
+
575
+ super
576
+ end
577
+
578
+ def visit_Symbol sym
579
+ unless @permitted_symbols[sym]
580
+ raise DisallowedClass.new('dump', "Symbol(#{sym.inspect})")
581
+ end
582
+
583
+ super
584
+ end
585
+ end
550
586
  end
551
587
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'psych/visitors/visitor'
3
- require 'psych/visitors/to_ruby'
4
- require 'psych/visitors/emitter'
5
- require 'psych/visitors/yaml_tree'
6
- require 'psych/visitors/json_tree'
7
- require 'psych/visitors/depth_first'
2
+ require_relative 'visitors/visitor'
3
+ require_relative 'visitors/to_ruby'
4
+ require_relative 'visitors/emitter'
5
+ require_relative 'visitors/yaml_tree'
6
+ require_relative 'visitors/json_tree'
7
+ require_relative 'visitors/depth_first'