summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2009-09-30 14:32:35 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2009-09-30 14:32:35 -0700
commit0fdc41a6e3ab790e58db0e0f54affe5d2a8277f2 (patch)
tree023b528b6e33f4756c03960fccf96b8258ee9790
parent211251bab57a5535e47832b75176096e087c89b0 (diff)
downloadpsych-0fdc41a6e3ab790e58db0e0f54affe5d2a8277f2.zip
using the same logic for string emitting and parsing
-rw-r--r--lib/psych/scalar_scanner.rb47
-rw-r--r--lib/psych/visitors/to_ruby.rb19
-rw-r--r--lib/psych/visitors/yast_builder.rb6
-rw-r--r--test/test_scalar_scanner.rb51
-rw-r--r--test/visitors/test_to_ruby.rb18
5 files changed, 120 insertions, 21 deletions
diff --git a/lib/psych/scalar_scanner.rb b/lib/psych/scalar_scanner.rb
new file mode 100644
index 0000000..538edb3
--- /dev/null
+++ b/lib/psych/scalar_scanner.rb
@@ -0,0 +1,47 @@
+require 'strscan'
+
+module Psych
+ ###
+ # Scan scalars for built in types
+ class ScalarScanner
+ def initialize string
+ @string = string
+ end
+
+ def tokenize
+ return [:NULL, nil] if @string.empty?
+
+ case @string
+ 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 /^(null|~)$/i
+ [:NULL, nil]
+ when /^:/i
+ [:SYMBOL, @string.sub(/^:/, '').to_sym]
+ when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/
+ i = 0
+ @string.split(':').each_with_index do |n,e|
+ i += (n.to_f * 60 ** (e - 2).abs)
+ end
+
+ [:FLOAT, i]
+ when /^[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+$/
+ i = 0
+ @string.split(':').each_with_index do |n,e|
+ i += (n.to_i * 60 ** (e - 2).abs)
+ end
+
+ [:INTEGER, i]
+ else
+ return [:FLOAT, Float(@string.gsub(/[,_]/, ''))] rescue ArgumentError
+ return [:INTEGER, Integer(@string.gsub(/[,_]/, ''))] rescue ArgumentError
+
+ [:SCALAR, @string]
+ end
+ end
+ end
+end
diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb
index c0ee101..84813ed 100644
--- a/lib/psych/visitors/to_ruby.rb
+++ b/lib/psych/visitors/to_ruby.rb
@@ -1,3 +1,5 @@
+require 'psych/scalar_scanner'
+
module Psych
module Visitors
###
@@ -11,22 +13,7 @@ module Psych
def visit_Psych_Nodes_Scalar o
@st[o.anchor] = o.value if o.anchor
- return nil if o.tag == 'tag:yaml.org,2002:null'
- return Integer(o.value) if o.tag == 'tag:yaml.org,2002:int'
-
- unless o.quoted
-
- return 0.0 / 0.0 if o.value =~ /^\.nan$/i
- return 1 / 0.0 if o.value =~ /^\.inf$/i
- return -1 / 0.0 if o.value =~ /^\-\.inf$/i
- return Float(o.value) if o.tag == 'tag:yaml.org,2002:float'
-
- return Integer(o.value) rescue ArgumentError
- return Float(o.value) rescue ArgumentError
-
- return nil if o.value =~ /^(null|~)$/i or o.value.empty?
- return o.value.sub(/^:/,'').to_sym if o.value =~ /^:/
- end
+ return ScalarScanner.new(o.value).tokenize.last unless o.quoted
o.value
end
diff --git a/lib/psych/visitors/yast_builder.rb b/lib/psych/visitors/yast_builder.rb
index c88cc49..5de56ae 100644
--- a/lib/psych/visitors/yast_builder.rb
+++ b/lib/psych/visitors/yast_builder.rb
@@ -35,11 +35,7 @@ module Psych
end
def visit_String o
- quote = false
-
- quote = true if Integer(o) rescue ArgumentError
- quote = true if Float(o) rescue ArgumentError
- quote = true if(o =~ /^(null|~|[\d.]+)$/i or o =~ /^:/ or o.empty?)
+ quote = ScalarScanner.new(o).tokenize.first != :SCALAR
scalar = Nodes::Scalar.new(o, nil, nil, !quote, quote)
@stack.last.children << scalar
diff --git a/test/test_scalar_scanner.rb b/test/test_scalar_scanner.rb
new file mode 100644
index 0000000..5311249
--- /dev/null
+++ b/test/test_scalar_scanner.rb
@@ -0,0 +1,51 @@
+require 'minitest/autorun'
+require 'psych'
+
+class TestScalarScanner < MiniTest::Unit::TestCase
+ def test_scan_inf
+ ss = Psych::ScalarScanner.new('.inf')
+ assert_equal [:POSITIVE_INFINITY, 1 / 0.0], ss.tokenize
+ end
+
+ def test_scan_minus_inf
+ ss = Psych::ScalarScanner.new('-.inf')
+ assert_equal [:NEGATIVE_INFINITY, -1 / 0.0], ss.tokenize
+ end
+
+ def test_scan_nan
+ ss = Psych::ScalarScanner.new('.nan')
+ assert_equal :NAN, ss.tokenize.first
+ assert ss.tokenize.last.nan?
+ end
+
+ def test_scan_null
+ ss = Psych::ScalarScanner.new('null')
+ assert_equal [:NULL, nil], ss.tokenize
+
+ ss = Psych::ScalarScanner.new('~')
+ assert_equal [:NULL, nil], ss.tokenize
+
+ ss = Psych::ScalarScanner.new('')
+ assert_equal [:NULL, nil], ss.tokenize
+ end
+
+ def test_scan_symbol
+ ss = Psych::ScalarScanner.new(':foo')
+ assert_equal [:SYMBOL, :foo], ss.tokenize
+ end
+
+ def test_scan_sexagesimal_float
+ ss = Psych::ScalarScanner.new('190:20:30.15')
+ assert_equal [:FLOAT, 685230.15], ss.tokenize
+ end
+
+ def test_scan_sexagesimal_int
+ ss = Psych::ScalarScanner.new('190:20:30')
+ assert_equal [:INTEGER, 685230], ss.tokenize
+ end
+
+ def test_scan_float
+ ss = Psych::ScalarScanner.new('1.2')
+ assert_equal [:FLOAT, 1.2], ss.tokenize
+ end
+end
diff --git a/test/visitors/test_to_ruby.rb b/test/visitors/test_to_ruby.rb
index 6facc68..0dafbd8 100644
--- a/test/visitors/test_to_ruby.rb
+++ b/test/visitors/test_to_ruby.rb
@@ -21,6 +21,24 @@ module Psych
assert_equal 1, Nodes::Scalar.new('+1').to_ruby
end
+ def test_int_ignore
+ ['1,000', '1_000'].each do |num|
+ i = Nodes::Scalar.new(num, nil, 'tag:yaml.org,2002:int')
+ assert_equal 1000, i.to_ruby
+
+ assert_equal 1000, Nodes::Scalar.new(num).to_ruby
+ end
+ end
+
+ def test_float_ignore
+ ['1,000.3', '1_000.3'].each do |num|
+ i = Nodes::Scalar.new(num, nil, 'tag:yaml.org,2002:float')
+ assert_equal 1000.3, i.to_ruby
+
+ assert_equal 1000.3, Nodes::Scalar.new(num).to_ruby
+ end
+ end
+
def test_float
i = Nodes::Scalar.new('1.2', nil, 'tag:yaml.org,2002:float')
assert_equal 1.2, i.to_ruby