psych 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +18 -0
- data/.gemtest +0 -0
- data/CHANGELOG.rdoc +3 -0
- data/Manifest.txt +87 -0
- data/README.rdoc +50 -0
- data/Rakefile +66 -0
- data/ext/psych/emitter.c +517 -0
- data/ext/psych/emitter.h +8 -0
- data/ext/psych/extconf.rb +22 -0
- data/ext/psych/parser.c +384 -0
- data/ext/psych/parser.h +6 -0
- data/ext/psych/psych.c +34 -0
- data/ext/psych/psych.h +20 -0
- data/ext/psych/to_ruby.c +41 -0
- data/ext/psych/to_ruby.h +8 -0
- data/ext/psych/yaml_tree.c +24 -0
- data/ext/psych/yaml_tree.h +8 -0
- data/lib/psych.rb +263 -0
- data/lib/psych/coder.rb +94 -0
- data/lib/psych/core_ext.rb +39 -0
- data/lib/psych/deprecated.rb +82 -0
- data/lib/psych/handler.rb +221 -0
- data/lib/psych/json.rb +6 -0
- data/lib/psych/json/ruby_events.rb +19 -0
- data/lib/psych/json/stream.rb +15 -0
- data/lib/psych/json/tree_builder.rb +12 -0
- data/lib/psych/json/yaml_events.rb +29 -0
- data/lib/psych/nodes.rb +77 -0
- data/lib/psych/nodes/alias.rb +18 -0
- data/lib/psych/nodes/document.rb +60 -0
- data/lib/psych/nodes/mapping.rb +56 -0
- data/lib/psych/nodes/node.rb +52 -0
- data/lib/psych/nodes/scalar.rb +67 -0
- data/lib/psych/nodes/sequence.rb +81 -0
- data/lib/psych/nodes/stream.rb +37 -0
- data/lib/psych/omap.rb +4 -0
- data/lib/psych/parser.rb +47 -0
- data/lib/psych/scalar_scanner.rb +105 -0
- data/lib/psych/set.rb +4 -0
- data/lib/psych/stream.rb +36 -0
- data/lib/psych/streaming.rb +22 -0
- data/lib/psych/tree_builder.rb +94 -0
- data/lib/psych/visitors.rb +6 -0
- data/lib/psych/visitors/depth_first.rb +26 -0
- data/lib/psych/visitors/emitter.rb +44 -0
- data/lib/psych/visitors/json_tree.rb +21 -0
- data/lib/psych/visitors/to_ruby.rb +267 -0
- data/lib/psych/visitors/visitor.rb +19 -0
- data/lib/psych/visitors/yaml_tree.rb +373 -0
- data/test/psych/helper.rb +63 -0
- data/test/psych/json/test_stream.rb +109 -0
- data/test/psych/nodes/test_enumerable.rb +43 -0
- data/test/psych/test_alias_and_anchor.rb +26 -0
- data/test/psych/test_array.rb +19 -0
- data/test/psych/test_boolean.rb +36 -0
- data/test/psych/test_class.rb +17 -0
- data/test/psych/test_coder.rb +184 -0
- data/test/psych/test_date_time.rb +17 -0
- data/test/psych/test_deprecated.rb +210 -0
- data/test/psych/test_document.rb +46 -0
- data/test/psych/test_emitter.rb +94 -0
- data/test/psych/test_encoding.rb +179 -0
- data/test/psych/test_engine_manager.rb +57 -0
- data/test/psych/test_exception.rb +39 -0
- data/test/psych/test_hash.rb +30 -0
- data/test/psych/test_json_tree.rb +65 -0
- data/test/psych/test_merge_keys.rb +72 -0
- data/test/psych/test_nil.rb +18 -0
- data/test/psych/test_null.rb +19 -0
- data/test/psych/test_object.rb +27 -0
- data/test/psych/test_omap.rb +68 -0
- data/test/psych/test_parser.rb +297 -0
- data/test/psych/test_psych.rb +168 -0
- data/test/psych/test_scalar.rb +11 -0
- data/test/psych/test_scalar_scanner.rb +69 -0
- data/test/psych/test_serialize_subclasses.rb +38 -0
- data/test/psych/test_set.rb +49 -0
- data/test/psych/test_stream.rb +49 -0
- data/test/psych/test_string.rb +49 -0
- data/test/psych/test_struct.rb +51 -0
- data/test/psych/test_symbol.rb +17 -0
- data/test/psych/test_to_yaml_properties.rb +63 -0
- data/test/psych/test_tree_builder.rb +79 -0
- data/test/psych/test_yaml.rb +1256 -0
- data/test/psych/visitors/test_depth_first.rb +49 -0
- data/test/psych/visitors/test_emitter.rb +144 -0
- data/test/psych/visitors/test_to_ruby.rb +325 -0
- data/test/psych/visitors/test_yaml_tree.rb +155 -0
- metadata +232 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# This class represents a {YAML Alias}[http://yaml.org/spec/1.1/#alias].
|
5
|
+
# It points to an +anchor+.
|
6
|
+
#
|
7
|
+
# A Psych::Nodes::Alias is a terminal node and may have no children.
|
8
|
+
class Alias < Psych::Nodes::Node
|
9
|
+
# The anchor this alias links to
|
10
|
+
attr_accessor :anchor
|
11
|
+
|
12
|
+
# Create a new Alias that points to an +anchor+
|
13
|
+
def initialize anchor
|
14
|
+
@anchor = anchor
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# This represents a YAML Document. This node must be a child of
|
5
|
+
# Psych::Nodes::Stream. A Psych::Nodes::Document must have one child,
|
6
|
+
# and that child may be one of the following:
|
7
|
+
#
|
8
|
+
# * Psych::Nodes::Sequence
|
9
|
+
# * Psych::Nodes::Mapping
|
10
|
+
# * Psych::Nodes::Scalar
|
11
|
+
class Document < Psych::Nodes::Node
|
12
|
+
# The version of the YAML document
|
13
|
+
attr_accessor :version
|
14
|
+
|
15
|
+
# A list of tag directives for this document
|
16
|
+
attr_accessor :tag_directives
|
17
|
+
|
18
|
+
# Was this document implicitly created?
|
19
|
+
attr_accessor :implicit
|
20
|
+
|
21
|
+
# Is the end of the document implicit?
|
22
|
+
attr_accessor :implicit_end
|
23
|
+
|
24
|
+
###
|
25
|
+
# Create a new Psych::Nodes::Document object.
|
26
|
+
#
|
27
|
+
# +version+ is a list indicating the YAML version.
|
28
|
+
# +tags_directives+ is a list of tag directive declarations
|
29
|
+
# +implicit+ is a flag indicating whether the document will be implicitly
|
30
|
+
# started.
|
31
|
+
#
|
32
|
+
# == Example:
|
33
|
+
# This creates a YAML document object that represents a YAML 1.1 document
|
34
|
+
# with one tag directive, and has an implicit start:
|
35
|
+
#
|
36
|
+
# Psych::Nodes::Document.new(
|
37
|
+
# [1,1],
|
38
|
+
# [["!", "tag:tenderlovemaking.com,2009:"]],
|
39
|
+
# true
|
40
|
+
# )
|
41
|
+
#
|
42
|
+
# == See Also
|
43
|
+
# See also Psych::Handler#start_document
|
44
|
+
def initialize version = [], tag_directives = [], implicit = false
|
45
|
+
super()
|
46
|
+
@version = version
|
47
|
+
@tag_directives = tag_directives
|
48
|
+
@implicit = implicit
|
49
|
+
@implicit_end = true
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
# Returns the root node. A Document may only have one root node:
|
54
|
+
# http://yaml.org/spec/1.1/#id898031
|
55
|
+
def root
|
56
|
+
children.first
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping].
|
5
|
+
#
|
6
|
+
# A Psych::Nodes::Mapping node may have 0 or more children, but must have
|
7
|
+
# an even number of children. Here are the valid children a
|
8
|
+
# Psych::Nodes::Mapping node may have:
|
9
|
+
#
|
10
|
+
# * Psych::Nodes::Sequence
|
11
|
+
# * Psych::Nodes::Mapping
|
12
|
+
# * Psych::Nodes::Scalar
|
13
|
+
# * Psych::Nodes::Alias
|
14
|
+
class Mapping < Psych::Nodes::Node
|
15
|
+
# Any Map Style
|
16
|
+
ANY = 0
|
17
|
+
|
18
|
+
# Block Map Style
|
19
|
+
BLOCK = 1
|
20
|
+
|
21
|
+
# Flow Map Style
|
22
|
+
FLOW = 2
|
23
|
+
|
24
|
+
# The optional anchor for this mapping
|
25
|
+
attr_accessor :anchor
|
26
|
+
|
27
|
+
# The optional tag for this mapping
|
28
|
+
attr_accessor :tag
|
29
|
+
|
30
|
+
# Is this an implicit mapping?
|
31
|
+
attr_accessor :implicit
|
32
|
+
|
33
|
+
# The style of this mapping
|
34
|
+
attr_accessor :style
|
35
|
+
|
36
|
+
###
|
37
|
+
# Create a new Psych::Nodes::Mapping object.
|
38
|
+
#
|
39
|
+
# +anchor+ is the anchor associated with the map or +nil+.
|
40
|
+
# +tag+ is the tag associated with the map or +nil+.
|
41
|
+
# +implicit+ is a boolean indicating whether or not the map was implicitly
|
42
|
+
# started.
|
43
|
+
# +style+ is an integer indicating the mapping style.
|
44
|
+
#
|
45
|
+
# == See Also
|
46
|
+
# See also Psych::Handler#start_mapping
|
47
|
+
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
|
48
|
+
super()
|
49
|
+
@anchor = anchor
|
50
|
+
@tag = tag
|
51
|
+
@implicit = implicit
|
52
|
+
@style = style
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
module Nodes
|
5
|
+
###
|
6
|
+
# The base class for any Node in a YAML parse tree. This class should
|
7
|
+
# never be instantiated.
|
8
|
+
class Node
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
# The children of this node
|
12
|
+
attr_reader :children
|
13
|
+
|
14
|
+
# An associated tag
|
15
|
+
attr_reader :tag
|
16
|
+
|
17
|
+
# Create a new Psych::Nodes::Node
|
18
|
+
def initialize
|
19
|
+
@children = []
|
20
|
+
end
|
21
|
+
|
22
|
+
###
|
23
|
+
# Iterate over each node in the tree. Yields each node to +block+ depth
|
24
|
+
# first.
|
25
|
+
def each &block
|
26
|
+
return enum_for :each unless block_given?
|
27
|
+
Visitors::DepthFirst.new(block).accept self
|
28
|
+
end
|
29
|
+
|
30
|
+
###
|
31
|
+
# Convert this node to Ruby.
|
32
|
+
#
|
33
|
+
# See also Psych::Visitors::ToRuby
|
34
|
+
def to_ruby
|
35
|
+
Visitors::ToRuby.new.accept self
|
36
|
+
end
|
37
|
+
alias :transform :to_ruby
|
38
|
+
|
39
|
+
###
|
40
|
+
# Convert this node to YAML.
|
41
|
+
#
|
42
|
+
# See also Psych::Visitors::Emitter
|
43
|
+
def to_yaml io = nil, options = {}
|
44
|
+
real_io = io || StringIO.new
|
45
|
+
|
46
|
+
Visitors::Emitter.new(real_io, options).accept self
|
47
|
+
return real_io.string unless io
|
48
|
+
io
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081].
|
5
|
+
#
|
6
|
+
# This node type is a terminal node and should not have any children.
|
7
|
+
class Scalar < Psych::Nodes::Node
|
8
|
+
# Any style scalar, the emitter chooses
|
9
|
+
ANY = 0
|
10
|
+
|
11
|
+
# Plain scalar style
|
12
|
+
PLAIN = 1
|
13
|
+
|
14
|
+
# Single quoted style
|
15
|
+
SINGLE_QUOTED = 2
|
16
|
+
|
17
|
+
# Double quoted style
|
18
|
+
DOUBLE_QUOTED = 3
|
19
|
+
|
20
|
+
# Literal style
|
21
|
+
LITERAL = 4
|
22
|
+
|
23
|
+
# Folded style
|
24
|
+
FOLDED = 5
|
25
|
+
|
26
|
+
# The scalar value
|
27
|
+
attr_accessor :value
|
28
|
+
|
29
|
+
# The anchor value (if there is one)
|
30
|
+
attr_accessor :anchor
|
31
|
+
|
32
|
+
# The tag value (if there is one)
|
33
|
+
attr_accessor :tag
|
34
|
+
|
35
|
+
# Is this a plain scalar?
|
36
|
+
attr_accessor :plain
|
37
|
+
|
38
|
+
# Is this scalar quoted?
|
39
|
+
attr_accessor :quoted
|
40
|
+
|
41
|
+
# The style of this scalar
|
42
|
+
attr_accessor :style
|
43
|
+
|
44
|
+
###
|
45
|
+
# Create a new Psych::Nodes::Scalar object.
|
46
|
+
#
|
47
|
+
# +value+ is the string value of the scalar
|
48
|
+
# +anchor+ is an associated anchor or nil
|
49
|
+
# +tag+ is an associated tag or nil
|
50
|
+
# +plain+ is a boolean value
|
51
|
+
# +quoted+ is a boolean value
|
52
|
+
# +style+ is an integer idicating the string style
|
53
|
+
#
|
54
|
+
# == See Also
|
55
|
+
#
|
56
|
+
# See also Psych::Handler#scalar
|
57
|
+
def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY
|
58
|
+
@value = value
|
59
|
+
@anchor = anchor
|
60
|
+
@tag = tag
|
61
|
+
@plain = plain
|
62
|
+
@quoted = quoted
|
63
|
+
@style = style
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# This class represents a
|
5
|
+
# {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
|
6
|
+
#
|
7
|
+
# A YAML sequence is basically a list, and looks like this:
|
8
|
+
#
|
9
|
+
# %YAML 1.1
|
10
|
+
# ---
|
11
|
+
# - I am
|
12
|
+
# - a Sequence
|
13
|
+
#
|
14
|
+
# A YAML sequence may have an anchor like this:
|
15
|
+
#
|
16
|
+
# %YAML 1.1
|
17
|
+
# ---
|
18
|
+
# &A [
|
19
|
+
# "This sequence",
|
20
|
+
# "has an anchor"
|
21
|
+
# ]
|
22
|
+
#
|
23
|
+
# A YAML sequence may also have a tag like this:
|
24
|
+
#
|
25
|
+
# %YAML 1.1
|
26
|
+
# ---
|
27
|
+
# !!seq [
|
28
|
+
# "This sequence",
|
29
|
+
# "has a tag"
|
30
|
+
# ]
|
31
|
+
#
|
32
|
+
# This class represents a sequence in a YAML document. A
|
33
|
+
# Psych::Nodes::Sequence node may have 0 or more children. Valid children
|
34
|
+
# for this node are:
|
35
|
+
#
|
36
|
+
# * Psych::Nodes::Sequence
|
37
|
+
# * Psych::Nodes::Mapping
|
38
|
+
# * Psych::Nodes::Scalar
|
39
|
+
# * Psych::Nodes::Alias
|
40
|
+
class Sequence < Psych::Nodes::Node
|
41
|
+
# Any Styles, emitter chooses
|
42
|
+
ANY = 0
|
43
|
+
|
44
|
+
# Block style sequence
|
45
|
+
BLOCK = 1
|
46
|
+
|
47
|
+
# Flow style sequence
|
48
|
+
FLOW = 2
|
49
|
+
|
50
|
+
# The anchor for this sequence (if any)
|
51
|
+
attr_accessor :anchor
|
52
|
+
|
53
|
+
# The tag name for this sequence (if any)
|
54
|
+
attr_accessor :tag
|
55
|
+
|
56
|
+
# Is this sequence started implicitly?
|
57
|
+
attr_accessor :implicit
|
58
|
+
|
59
|
+
# The sequece style used
|
60
|
+
attr_accessor :style
|
61
|
+
|
62
|
+
###
|
63
|
+
# Create a new object representing a YAML sequence.
|
64
|
+
#
|
65
|
+
# +anchor+ is the anchor associated with the sequence or nil.
|
66
|
+
# +tag+ is the tag associated with the sequence or nil.
|
67
|
+
# +implicit+ a boolean indicating whether or not the sequence was
|
68
|
+
# implicitly started.
|
69
|
+
# +style+ is an integer indicating the list style.
|
70
|
+
#
|
71
|
+
# See Psych::Handler#start_sequence
|
72
|
+
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
|
73
|
+
super()
|
74
|
+
@anchor = anchor
|
75
|
+
@tag = tag
|
76
|
+
@implicit = implicit
|
77
|
+
@style = style
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Psych
|
2
|
+
module Nodes
|
3
|
+
###
|
4
|
+
# Represents a YAML stream. This is the root node for any YAML parse
|
5
|
+
# tree. This node must have one or more child nodes. The only valid
|
6
|
+
# child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
|
7
|
+
class Stream < Psych::Nodes::Node
|
8
|
+
|
9
|
+
# Encodings supported by Psych (and libyaml)
|
10
|
+
|
11
|
+
# Any encoding
|
12
|
+
ANY = Psych::Parser::ANY
|
13
|
+
|
14
|
+
# UTF-8 encoding
|
15
|
+
UTF8 = Psych::Parser::UTF8
|
16
|
+
|
17
|
+
# UTF-16LE encoding
|
18
|
+
UTF16LE = Psych::Parser::UTF16LE
|
19
|
+
|
20
|
+
# UTF-16BE encoding
|
21
|
+
UTF16BE = Psych::Parser::UTF16BE
|
22
|
+
|
23
|
+
# The encoding used for this stream
|
24
|
+
attr_accessor :encoding
|
25
|
+
|
26
|
+
###
|
27
|
+
# Create a new Psych::Nodes::Stream node with an +encoding+ that
|
28
|
+
# defaults to Psych::Nodes::Stream::UTF8.
|
29
|
+
#
|
30
|
+
# See also Psych::Handler#start_stream
|
31
|
+
def initialize encoding = UTF8
|
32
|
+
super()
|
33
|
+
@encoding = encoding
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/psych/omap.rb
ADDED
data/lib/psych/parser.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Psych
|
2
|
+
###
|
3
|
+
# YAML event parser class. This class parses a YAML document and calls
|
4
|
+
# events on the handler that is passed to the constructor. The events can
|
5
|
+
# be used for things such as constructing a YAML AST or deserializing YAML
|
6
|
+
# documents. It can even be fed back to Psych::Emitter to emit the same
|
7
|
+
# document that was parsed.
|
8
|
+
#
|
9
|
+
# See Psych::Handler for documentation on the events that Psych::Parser emits.
|
10
|
+
#
|
11
|
+
# Here is an example that prints out ever scalar found in a YAML document:
|
12
|
+
#
|
13
|
+
# # Handler for detecting scalar values
|
14
|
+
# class ScalarHandler < Psych::Handler
|
15
|
+
# def scalar value, anchor, tag, plain, quoted, style
|
16
|
+
# puts value
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# parser = Psych::Parser.new(ScalarHandler.new)
|
21
|
+
# parser.parse(yaml_document)
|
22
|
+
#
|
23
|
+
# Here is an example that feeds the parser back in to Psych::Emitter. The
|
24
|
+
# YAML document is read from STDIN and written back out to STDERR:
|
25
|
+
#
|
26
|
+
# parser = Psych::Parser.new(Psych::Emitter.new($stderr))
|
27
|
+
# parser.parse($stdin)
|
28
|
+
#
|
29
|
+
# Psych uses Psych::Parser in combination with Psych::TreeBuilder to
|
30
|
+
# construct an AST of the parsed YAML document.
|
31
|
+
|
32
|
+
class Parser
|
33
|
+
class Mark < Struct.new(:index, :line, :column)
|
34
|
+
end
|
35
|
+
|
36
|
+
# The handler on which events will be called
|
37
|
+
attr_accessor :handler
|
38
|
+
|
39
|
+
###
|
40
|
+
# Creates a new Psych::Parser instance with +handler+. YAML events will
|
41
|
+
# be called on +handler+. See Psych::Parser for more details.
|
42
|
+
|
43
|
+
def initialize handler = Handler.new
|
44
|
+
@handler = handler
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
###
|
5
|
+
# Scan scalars for built in types
|
6
|
+
class ScalarScanner
|
7
|
+
# Taken from http://yaml.org/type/timestamp.html
|
8
|
+
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)?)?/
|
9
|
+
|
10
|
+
# Create a new scanner
|
11
|
+
def initialize
|
12
|
+
@string_cache = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Tokenize +string+ returning the ruby object
|
16
|
+
def tokenize string
|
17
|
+
return nil if string.empty?
|
18
|
+
return string if @string_cache.key?(string)
|
19
|
+
|
20
|
+
case string
|
21
|
+
when /^[A-Za-z~]/
|
22
|
+
if string.length > 5
|
23
|
+
@string_cache[string] = true
|
24
|
+
return string
|
25
|
+
end
|
26
|
+
|
27
|
+
case string
|
28
|
+
when /^[^ytonf~]/i
|
29
|
+
@string_cache[string] = true
|
30
|
+
string
|
31
|
+
when '~', /^null$/i
|
32
|
+
nil
|
33
|
+
when /^(yes|true|on)$/i
|
34
|
+
true
|
35
|
+
when /^(no|false|off)$/i
|
36
|
+
false
|
37
|
+
else
|
38
|
+
@string_cache[string] = true
|
39
|
+
string
|
40
|
+
end
|
41
|
+
when TIME
|
42
|
+
parse_time string
|
43
|
+
when /^\d{4}-\d{1,2}-\d{1,2}$/
|
44
|
+
require 'date'
|
45
|
+
Date.strptime(string, '%Y-%m-%d')
|
46
|
+
when /^\.inf$/i
|
47
|
+
1 / 0.0
|
48
|
+
when /^-\.inf$/i
|
49
|
+
-1 / 0.0
|
50
|
+
when /^\.nan$/i
|
51
|
+
0.0 / 0.0
|
52
|
+
when /^:./
|
53
|
+
if string =~ /^:(["'])(.*)\1/
|
54
|
+
$2.sub(/^:/, '').to_sym
|
55
|
+
else
|
56
|
+
string.sub(/^:/, '').to_sym
|
57
|
+
end
|
58
|
+
when /^[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+$/
|
59
|
+
i = 0
|
60
|
+
string.split(':').each_with_index do |n,e|
|
61
|
+
i += (n.to_i * 60 ** (e - 2).abs)
|
62
|
+
end
|
63
|
+
i
|
64
|
+
when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]*$/
|
65
|
+
i = 0
|
66
|
+
string.split(':').each_with_index do |n,e|
|
67
|
+
i += (n.to_f * 60 ** (e - 2).abs)
|
68
|
+
end
|
69
|
+
i
|
70
|
+
else
|
71
|
+
return Integer(string.gsub(/[,_]/, '')) rescue ArgumentError
|
72
|
+
return Float(string.gsub(/[,_]/, '')) rescue ArgumentError
|
73
|
+
@string_cache[string] = true
|
74
|
+
string
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
###
|
79
|
+
# Parse and return a Time from +string+
|
80
|
+
def parse_time string
|
81
|
+
date, time = *(string.split(/[ tT]/, 2))
|
82
|
+
(yy, m, dd) = date.split('-').map { |x| x.to_i }
|
83
|
+
md = time.match(/(\d+:\d+:\d+)(\.\d*)?\s*(Z|[-+]\d+(:\d\d)?)?/)
|
84
|
+
|
85
|
+
(hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
|
86
|
+
us = (md[2] ? Rational(md[2].sub(/^\./, '0.')) : 0) * 1000000
|
87
|
+
|
88
|
+
time = Time.utc(yy, m, dd, hh, mm, ss, us)
|
89
|
+
|
90
|
+
return time if 'Z' == md[3]
|
91
|
+
return Time.at(time.to_i, us) unless md[3]
|
92
|
+
|
93
|
+
tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
|
94
|
+
offset = tz.first * 3600
|
95
|
+
|
96
|
+
if offset < 0
|
97
|
+
offset -= ((tz[1] || 0) * 60)
|
98
|
+
else
|
99
|
+
offset += ((tz[1] || 0) * 60)
|
100
|
+
end
|
101
|
+
|
102
|
+
Time.at((time - offset).to_i, us)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|