зеркало из https://github.com/github/ruby.git
* ext/psych/lib/psych/emitter.rb: removing unused file.
* ext/psych/lib/psych/json/tree_builder.rb: moving tree builder to an event based external class. * ext/psych/lib/psych/tree_builder.rb: adding an end_stream event. * ext/psych/lib/psych/visitors/json_tree.rb: using event based AST builder. * ext/psych/lib/psych/visitors/yaml_tree.rb: using event based AST builder. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
d62a9f00b8
Коммит
2f39988511
|
@ -3,6 +3,7 @@ require 'psych/nodes'
|
|||
require 'psych/visitors'
|
||||
require 'psych/handler'
|
||||
require 'psych/tree_builder'
|
||||
require 'psych/json/tree_builder'
|
||||
require 'psych/parser'
|
||||
require 'psych/omap'
|
||||
require 'psych/set'
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
module Psych
|
||||
class Emitter < Psych::Handler
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module Psych
|
||||
module JSON
|
||||
###
|
||||
# Psych::JSON::TreeBuilder is an event based AST builder. Events are sent
|
||||
# to an instance of Psych::JSON::TreeBuilder and a JSON AST is constructed.
|
||||
class TreeBuilder < Psych::TreeBuilder
|
||||
def start_document version, tag_directives, implicit
|
||||
super(version, tag_directives, true)
|
||||
end
|
||||
|
||||
def end_document implicit_end
|
||||
super(true)
|
||||
end
|
||||
|
||||
def start_mapping anchor, tag, implicit, style
|
||||
super(anchor, tag, implicit, Nodes::Mapping::FLOW)
|
||||
end
|
||||
|
||||
def start_sequence anchor, tag, implicit, style
|
||||
super(anchor, tag, implicit, Nodes::Sequence::FLOW)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,15 +14,14 @@ module Psych
|
|||
# See Psych::Handler for documentation on the event methods used in this
|
||||
# class.
|
||||
class TreeBuilder < Psych::Handler
|
||||
# Returns the root node for the built tree
|
||||
attr_reader :root
|
||||
|
||||
# Create a new TreeBuilder instance
|
||||
def initialize
|
||||
@stack = []
|
||||
@last = nil
|
||||
end
|
||||
|
||||
# Returns the root node for the built tree
|
||||
def root
|
||||
@stack.first
|
||||
@root = nil
|
||||
end
|
||||
|
||||
%w{
|
||||
|
@ -48,7 +47,7 @@ module Psych
|
|||
#
|
||||
# See Psych::Handler#start_document
|
||||
def start_document version, tag_directives, implicit
|
||||
n = Nodes::Document.new(version, tag_directives, implicit)
|
||||
n = Nodes::Document.new version, tag_directives, implicit
|
||||
@last.children << n
|
||||
push n
|
||||
end
|
||||
|
@ -64,7 +63,12 @@ module Psych
|
|||
end
|
||||
|
||||
def start_stream encoding
|
||||
push Nodes::Stream.new(encoding)
|
||||
@root = Nodes::Stream.new(encoding)
|
||||
push @root
|
||||
end
|
||||
|
||||
def end_stream
|
||||
pop
|
||||
end
|
||||
|
||||
def scalar value, anchor, tag, plain, quoted, style
|
||||
|
@ -82,8 +86,9 @@ module Psych
|
|||
end
|
||||
|
||||
def pop
|
||||
@stack.pop
|
||||
x = @stack.pop
|
||||
@last = @stack.last
|
||||
x
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
module Psych
|
||||
module Visitors
|
||||
class JSONTree < YAMLTree
|
||||
def initialize options = {}, emitter = Psych::JSON::TreeBuilder.new
|
||||
super
|
||||
end
|
||||
|
||||
def visit_NilClass o
|
||||
scalar = create_scalar(
|
||||
'null', nil, nil, true, false, Nodes::Scalar::PLAIN)
|
||||
append scalar
|
||||
@emitter.scalar 'null', nil, nil, true, false, Nodes::Scalar::PLAIN
|
||||
end
|
||||
|
||||
def visit_Integer o
|
||||
append create_scalar(o.to_s, nil, nil, true, false, Nodes::Scalar::PLAIN)
|
||||
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::PLAIN
|
||||
end
|
||||
|
||||
def visit_Float o
|
||||
|
@ -17,31 +19,11 @@ module Psych
|
|||
end
|
||||
|
||||
def visit_String o
|
||||
append create_scalar o.to_s
|
||||
@emitter.scalar o.to_s, nil, nil, false, true, Nodes::Scalar::ANY
|
||||
end
|
||||
alias :visit_Symbol :visit_String
|
||||
|
||||
private
|
||||
def create_document
|
||||
doc = super
|
||||
doc.implicit = true
|
||||
doc.implicit_end = true
|
||||
doc
|
||||
end
|
||||
|
||||
def create_mapping
|
||||
map = super
|
||||
map.style = Nodes::Mapping::FLOW
|
||||
map
|
||||
end
|
||||
|
||||
def create_scalar value, anchor = nil, tag = nil, plain = false, quoted = true, style = Nodes::Scalar::ANY
|
||||
super
|
||||
end
|
||||
|
||||
def create_sequence anchor = nil, tag = nil, implicit = true, style = Nodes::Sequence::FLOW
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
module Psych
|
||||
module Visitors
|
||||
###
|
||||
# YAMLTree builds a YAML ast given a ruby object. For example:
|
||||
#
|
||||
# builder = Psych::Visitors::YAMLTree.new
|
||||
# builder << { :foo => 'bar' }
|
||||
# builder.tree # => #<Psych::Nodes::Stream .. }
|
||||
#
|
||||
class YAMLTree < Psych::Visitors::Visitor
|
||||
attr_reader :tree
|
||||
|
||||
def initialize options = {}
|
||||
def initialize options = {}, emitter = Psych::TreeBuilder.new
|
||||
super()
|
||||
@tree = Nodes::Stream.new
|
||||
@stack = []
|
||||
@st = {}
|
||||
@ss = ScalarScanner.new
|
||||
@emitter = emitter
|
||||
@st = {}
|
||||
@ss = ScalarScanner.new
|
||||
|
||||
@emitter.start_stream Psych::Nodes::Stream::UTF8
|
||||
|
||||
@dispatch_cache = Hash.new do |h,klass|
|
||||
method = "visit_#{(klass.name || '').split('::').join('_')}"
|
||||
|
@ -21,18 +27,21 @@ module Psych
|
|||
end
|
||||
end
|
||||
|
||||
def tree
|
||||
@emitter.end_stream
|
||||
end
|
||||
|
||||
def << object
|
||||
doc = create_document
|
||||
@stack << doc
|
||||
@tree.children << doc
|
||||
@emitter.start_document [], [], false
|
||||
accept object
|
||||
@emitter.end_document true
|
||||
end
|
||||
|
||||
def accept target
|
||||
# return any aliases we find
|
||||
if node = @st[target.object_id]
|
||||
node.anchor = target.object_id.to_s
|
||||
return append Nodes::Alias.new target.object_id.to_s
|
||||
return @emitter.alias target.object_id.to_s
|
||||
end
|
||||
|
||||
if target.respond_to?(:to_yaml)
|
||||
|
@ -56,12 +65,11 @@ module Psych
|
|||
end
|
||||
|
||||
def visit_Psych_Omap o
|
||||
seq = create_sequence(nil, '!omap', false)
|
||||
seq = @emitter.start_sequence(nil, '!omap', false, Nodes::Sequence::BLOCK)
|
||||
register(o, seq)
|
||||
|
||||
@stack.push append seq
|
||||
o.each { |k,v| visit_Hash k => v }
|
||||
@stack.pop
|
||||
@emitter.end_sequence
|
||||
end
|
||||
|
||||
def visit_Object o
|
||||
|
@ -71,54 +79,48 @@ module Psych
|
|||
tag = ['!ruby/object', klass].compact.join(':')
|
||||
end
|
||||
|
||||
map = append create_mapping(nil, tag, false)
|
||||
map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
|
||||
register(o, map)
|
||||
|
||||
@stack.push map
|
||||
dump_ivars(o, map)
|
||||
@stack.pop
|
||||
dump_ivars o
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Struct o
|
||||
tag = ['!ruby/struct', o.class.name].compact.join(':')
|
||||
|
||||
map = register(o, create_mapping(nil, tag, false))
|
||||
|
||||
@stack.push append map
|
||||
|
||||
register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
|
||||
o.members.each do |member|
|
||||
map.children << create_scalar("#{member}")
|
||||
@emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
accept o[member]
|
||||
end
|
||||
|
||||
dump_ivars(o, map)
|
||||
dump_ivars o
|
||||
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Exception o
|
||||
tag = ['!ruby/exception', o.class.name].join ':'
|
||||
|
||||
map = append create_mapping(nil, tag, false)
|
||||
|
||||
@stack.push map
|
||||
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
|
||||
|
||||
{
|
||||
'message' => private_iv_get(o, 'mesg'),
|
||||
'backtrace' => private_iv_get(o, 'backtrace'),
|
||||
}.each do |k,v|
|
||||
next unless v
|
||||
map.children << create_scalar(k)
|
||||
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
accept v
|
||||
end
|
||||
|
||||
dump_ivars(o, map)
|
||||
dump_ivars o
|
||||
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Regexp o
|
||||
append create_scalar(o.inspect, nil, '!ruby/regexp', false)
|
||||
@emitter.scalar o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY
|
||||
end
|
||||
|
||||
def visit_Time o
|
||||
|
@ -129,29 +131,34 @@ module Psych
|
|||
formatted += ".%06d %+.2d:00" % [o.usec, o.gmt_offset / 3600]
|
||||
end
|
||||
|
||||
append create_scalar formatted
|
||||
@emitter.scalar formatted, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
|
||||
def visit_Rational o
|
||||
map = append create_mapping(nil, '!ruby/object:Rational', false)
|
||||
@emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
|
||||
|
||||
[
|
||||
'denominator', o.denominator.to_s,
|
||||
'numerator', o.numerator.to_s
|
||||
].each do |m|
|
||||
map.children << create_scalar(m)
|
||||
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Complex o
|
||||
map = append create_mapping(nil, '!ruby/object:Complex', false)
|
||||
@emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
|
||||
|
||||
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
|
||||
map.children << create_scalar(m)
|
||||
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Integer o
|
||||
append create_scalar o.to_s
|
||||
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
alias :visit_TrueClass :visit_Integer
|
||||
alias :visit_FalseClass :visit_Integer
|
||||
|
@ -159,11 +166,12 @@ module Psych
|
|||
|
||||
def visit_Float o
|
||||
if o.nan?
|
||||
append create_scalar '.nan'
|
||||
@emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
|
||||
elsif o.infinite?
|
||||
append create_scalar(o.infinite? > 0 ? '.inf' : '-.inf')
|
||||
@emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
|
||||
nil, nil, true, false, Nodes::Scalar::ANY)
|
||||
else
|
||||
append create_scalar o.to_s
|
||||
@emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -186,19 +194,16 @@ module Psych
|
|||
|
||||
ivars = find_ivars o
|
||||
|
||||
scalar = create_scalar str, nil, tag, plain, quote, style
|
||||
|
||||
if ivars.empty?
|
||||
append scalar
|
||||
@emitter.scalar str, nil, tag, plain, quote, style
|
||||
else
|
||||
mapping = append create_mapping(nil, '!str', false)
|
||||
@emitter.start_mapping nil, '!str', false, Nodes::Mapping::BLOCK
|
||||
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
|
||||
@emitter.scalar str, nil, tag, plain, quote, style
|
||||
|
||||
mapping.children << create_scalar('str')
|
||||
mapping.children << scalar
|
||||
dump_ivars o
|
||||
|
||||
@stack.push mapping
|
||||
dump_ivars o, mapping
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -207,47 +212,47 @@ module Psych
|
|||
end
|
||||
|
||||
def visit_Range o
|
||||
@stack.push append create_mapping(nil, '!ruby/range', false)
|
||||
@emitter.start_mapping nil, '!ruby/range', false, Nodes::Mapping::BLOCK
|
||||
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
|
||||
accept m
|
||||
end
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Hash o
|
||||
@stack.push append register(o, create_mapping)
|
||||
register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
|
||||
|
||||
o.each do |k,v|
|
||||
accept k
|
||||
accept v
|
||||
end
|
||||
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Psych_Set o
|
||||
@stack.push append register(o, create_mapping(nil, '!set', false))
|
||||
register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
|
||||
|
||||
o.each do |k,v|
|
||||
accept k
|
||||
accept v
|
||||
end
|
||||
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
|
||||
def visit_Array o
|
||||
@stack.push append register(o, create_sequence)
|
||||
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
||||
o.each { |c| accept c }
|
||||
@stack.pop
|
||||
@emitter.end_sequence
|
||||
end
|
||||
|
||||
def visit_NilClass o
|
||||
append create_scalar('', nil, 'tag:yaml.org,2002:null', false)
|
||||
@emitter.scalar('', nil, 'tag:yaml.org,2002:null', false, false, Nodes::Scalar::ANY)
|
||||
end
|
||||
|
||||
def visit_Symbol o
|
||||
append create_scalar ":#{o}"
|
||||
@emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -264,11 +269,6 @@ module Psych
|
|||
target.instance_variables
|
||||
end
|
||||
|
||||
def append o
|
||||
@stack.last.children << o
|
||||
o
|
||||
end
|
||||
|
||||
def register target, yaml_obj
|
||||
@st[target.object_id] = yaml_obj
|
||||
yaml_obj
|
||||
|
@ -289,48 +289,31 @@ module Psych
|
|||
def emit_coder c
|
||||
case c.type
|
||||
when :scalar
|
||||
append create_scalar(c.scalar, nil, c.tag, c.tag.nil?)
|
||||
@emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY
|
||||
when :seq
|
||||
@stack.push append create_sequence(nil, c.tag, c.tag.nil?)
|
||||
@emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK
|
||||
c.seq.each do |thing|
|
||||
accept thing
|
||||
end
|
||||
@stack.pop
|
||||
@emitter.end_sequence
|
||||
when :map
|
||||
map = append create_mapping(nil, c.tag, c.implicit, c.style)
|
||||
@stack.push map
|
||||
@emitter.start_mapping nil, c.tag, c.implicit, c.style
|
||||
c.map.each do |k,v|
|
||||
map.children << create_scalar(k)
|
||||
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
|
||||
accept v
|
||||
end
|
||||
@stack.pop
|
||||
@emitter.end_mapping
|
||||
end
|
||||
end
|
||||
|
||||
def dump_ivars target, map
|
||||
def dump_ivars target
|
||||
ivars = find_ivars target
|
||||
|
||||
ivars.each do |iv|
|
||||
map.children << create_scalar("#{iv.to_s.sub(/^@/, '')}")
|
||||
@emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
|
||||
accept target.instance_variable_get(iv)
|
||||
end
|
||||
end
|
||||
|
||||
def create_document version = [], tag_directives = [], implicit = false
|
||||
Nodes::Document.new version, tag_directives, implicit
|
||||
end
|
||||
|
||||
def create_mapping anchor = nil, tag = nil, implicit = true, style = Psych::Nodes::Mapping::BLOCK
|
||||
Nodes::Mapping.new anchor, tag, implicit, style
|
||||
end
|
||||
|
||||
def create_scalar value, anchor = nil, tag = nil, plain = true, quoted = false, style = Nodes::Scalar::ANY
|
||||
Nodes::Scalar.new(value, anchor, tag, plain, quoted, style)
|
||||
end
|
||||
|
||||
def create_sequence anchor = nil, tag = nil, implicit = true, style = Nodes::Sequence::BLOCK
|
||||
Nodes::Sequence.new(anchor, tag, implicit, style)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче