diff options
-rw-r--r-- | lib/psych/nodes/node.rb | 1 | ||||
-rw-r--r-- | lib/psych/scalar_scanner.rb | 10 | ||||
-rw-r--r-- | lib/psych/visitors/to_ruby.rb | 43 | ||||
-rw-r--r-- | lib/psych/visitors/visitor.rb | 24 | ||||
-rw-r--r-- | test/test_scalar_scanner.rb | 6 |
5 files changed, 46 insertions, 38 deletions
diff --git a/lib/psych/nodes/node.rb b/lib/psych/nodes/node.rb index 6aaba15..7b5269e 100644 --- a/lib/psych/nodes/node.rb +++ b/lib/psych/nodes/node.rb @@ -9,6 +9,7 @@ module Psych include Psych::Visitable attr_reader :children + attr_reader :tag def initialize @children = [] diff --git a/lib/psych/scalar_scanner.rb b/lib/psych/scalar_scanner.rb index 6a18fa1..3afb7c6 100644 --- a/lib/psych/scalar_scanner.rb +++ b/lib/psych/scalar_scanner.rb @@ -16,8 +16,11 @@ module Psych case @string when /^[A-Za-z~]/ + return [:SCALAR, @string] if @string.length > 5 case @string - when /^(null|~)$/i + when /^[^ytonf~]/i + [:SCALAR, @string] + when '~', /^null$/i [:NULL, nil] when /^(yes|true|on)$/i [:BOOLEAN, true] @@ -29,14 +32,15 @@ module Psych when TIME [:TIME, @string] when /^\d{4}-\d{1,2}-\d{1,2}$/ - [:DATE, @string] + require 'date' + [:DATE, Date.strptime(@string, '%Y-%m-%d')] when /^\.inf$/i [:POSITIVE_INFINITY, 1 / 0.0] when /^-\.inf$/i [:NEGATIVE_INFINITY, -1 / 0.0] when /^\.nan$/i [:NAN, 0.0 / 0.0] - when /^:.+/ + when /^:./ if @string =~ /^:(["'])(.*)\1/ [:SYMBOL, $2.sub(/^:/, '').to_sym] else diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index f9fd2f9..fa13d2e 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -13,14 +13,14 @@ module Psych def accept target result = super return result if Psych.domain_types.empty? + return result unless target.tag - if target.respond_to?(:tag) && target.tag - short_name = target.tag.sub(/^!/, '').split('/', 2).last - if Psych.domain_types.key? short_name - url, block = Psych.domain_types[short_name] - return block.call "http://#{url}:#{short_name}", result - end + short_name = target.tag.sub(/^!/, '').split('/', 2).last + if Psych.domain_types.key? short_name + url, block = Psych.domain_types[short_name] + return block.call "http://#{url}:#{short_name}", result end + result end @@ -201,31 +201,22 @@ module Psych end def resolve_unknown o - token = ScalarScanner.new(o.value).tokenize - - case token.first - when :DATE - require 'date' - Date.strptime token.last, '%Y-%m-%d' - when :TIME - lexeme = token.last + type, lexeme = ScalarScanner.new(o.value).tokenize + return lexeme unless :TIME == type - date, time = *(lexeme.split(/[ tT]/, 2)) - (yy, m, dd) = date.split('-').map { |x| x.to_i } - md = time.match(/(\d+:\d+:\d+)(\.\d*)?\s*(Z|[-+]\d+(:\d\d)?)?/) + date, time = *(lexeme.split(/[ tT]/, 2)) + (yy, m, dd) = date.split('-').map { |x| x.to_i } + md = time.match(/(\d+:\d+:\d+)(\.\d*)?\s*(Z|[-+]\d+(:\d\d)?)?/) - (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } - us = (md[2] ? Rational(md[2].sub(/^\./, '0.')) : 0) * 1000000 + (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } + us = (md[2] ? Rational(md[2].sub(/^\./, '0.')) : 0) * 1000000 - time = Time.utc(yy, m, dd, hh, mm, ss, us) + time = Time.utc(yy, m, dd, hh, mm, ss, us) - return time if 'Z' == md[3] + return time if 'Z' == md[3] - tz = md[3] ? Integer(md[3].split(':').first) : 0 - Time.at((time - (tz * 3600)).to_i, us) - else - token.last - end + tz = md[3] ? Integer(md[3].split(':').first) : 0 + Time.at((time - (tz * 3600)).to_i, us) end end end diff --git a/lib/psych/visitors/visitor.rb b/lib/psych/visitors/visitor.rb index 56be391..da0bf4c 100644 --- a/lib/psych/visitors/visitor.rb +++ b/lib/psych/visitors/visitor.rb @@ -1,15 +1,23 @@ module Psych module Visitors class Visitor - YAML_NODE_DISPATCH_TABLE = Hash[ - *Nodes.constants.map { |k| - k = Nodes.const_get k - [k, :"visit_#{k.name.split('::').join('_')}"] - }.flatten - ] - def accept target - send(YAML_NODE_DISPATCH_TABLE[target.class], target) + case target + when Psych::Nodes::Scalar + visit_Psych_Nodes_Scalar target + when Psych::Nodes::Mapping + visit_Psych_Nodes_Mapping target + when Psych::Nodes::Sequence + visit_Psych_Nodes_Sequence target + when Psych::Nodes::Document + visit_Psych_Nodes_Document target + when Psych::Nodes::Stream + visit_Psych_Nodes_Stream target + when Psych::Nodes::Alias + visit_Psych_Nodes_Alias target + else + raise "Can't handle #{target}" + end end end end diff --git a/test/test_scalar_scanner.rb b/test/test_scalar_scanner.rb index 31e3041..eccb2b4 100644 --- a/test/test_scalar_scanner.rb +++ b/test/test_scalar_scanner.rb @@ -16,7 +16,11 @@ class TestScalarScanner < MiniTest::Unit::TestCase def test_scan_date date = '1980-12-16' ss = Psych::ScalarScanner.new date - assert_equal [:DATE, date], ss.tokenize + type, token = ss.tokenize + assert_equal :DATE, type + assert_equal 1980, token.year + assert_equal 12, token.month + assert_equal 16, token.day end def test_scan_inf |