psych 3.0.0.beta2-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.travis.yml +20 -0
- data/CHANGELOG.rdoc +576 -0
- data/Gemfile +3 -0
- data/Mavenfile +7 -0
- data/README.md +73 -0
- data/Rakefile +46 -0
- data/bin/console +7 -0
- data/bin/setup +6 -0
- data/ext/psych/.gitignore +11 -0
- data/ext/psych/depend +3 -0
- data/ext/psych/extconf.rb +39 -0
- data/ext/psych/psych.c +34 -0
- data/ext/psych/psych.h +17 -0
- data/ext/psych/psych_emitter.c +554 -0
- data/ext/psych/psych_emitter.h +8 -0
- data/ext/psych/psych_parser.c +568 -0
- data/ext/psych/psych_parser.h +6 -0
- data/ext/psych/psych_to_ruby.c +39 -0
- data/ext/psych/psych_to_ruby.h +8 -0
- data/ext/psych/psych_yaml_tree.c +24 -0
- data/ext/psych/psych_yaml_tree.h +8 -0
- data/ext/psych/yaml/LICENSE +19 -0
- data/ext/psych/yaml/api.c +1392 -0
- data/ext/psych/yaml/config.h +10 -0
- data/ext/psych/yaml/dumper.c +394 -0
- data/ext/psych/yaml/emitter.c +2329 -0
- data/ext/psych/yaml/loader.c +444 -0
- data/ext/psych/yaml/parser.c +1374 -0
- data/ext/psych/yaml/reader.c +469 -0
- data/ext/psych/yaml/scanner.c +3576 -0
- data/ext/psych/yaml/writer.c +141 -0
- data/ext/psych/yaml/yaml.h +1971 -0
- data/ext/psych/yaml/yaml_private.h +662 -0
- data/lib/2.2/psych.so +0 -0
- data/lib/2.3/psych.so +0 -0
- data/lib/2.4/psych.so +0 -0
- data/lib/psych/class_loader.rb +102 -0
- data/lib/psych/coder.rb +95 -0
- data/lib/psych/core_ext.rb +19 -0
- data/lib/psych/exception.rb +14 -0
- data/lib/psych/handler.rb +250 -0
- data/lib/psych/handlers/document_stream.rb +23 -0
- data/lib/psych/handlers/recorder.rb +40 -0
- data/lib/psych/json/ruby_events.rb +20 -0
- data/lib/psych/json/stream.rb +17 -0
- data/lib/psych/json/tree_builder.rb +13 -0
- data/lib/psych/json/yaml_events.rb +30 -0
- data/lib/psych/nodes/alias.rb +19 -0
- data/lib/psych/nodes/document.rb +61 -0
- data/lib/psych/nodes/mapping.rb +57 -0
- data/lib/psych/nodes/node.rb +56 -0
- data/lib/psych/nodes/scalar.rb +68 -0
- data/lib/psych/nodes/sequence.rb +82 -0
- data/lib/psych/nodes/stream.rb +38 -0
- data/lib/psych/nodes.rb +78 -0
- data/lib/psych/omap.rb +5 -0
- data/lib/psych/parser.rb +52 -0
- data/lib/psych/scalar_scanner.rb +149 -0
- data/lib/psych/set.rb +5 -0
- data/lib/psych/stream.rb +38 -0
- data/lib/psych/streaming.rb +28 -0
- data/lib/psych/syntax_error.rb +22 -0
- data/lib/psych/tree_builder.rb +97 -0
- data/lib/psych/versions.rb +9 -0
- data/lib/psych/visitors/depth_first.rb +27 -0
- data/lib/psych/visitors/emitter.rb +52 -0
- data/lib/psych/visitors/json_tree.rb +25 -0
- data/lib/psych/visitors/to_ruby.rb +401 -0
- data/lib/psych/visitors/visitor.rb +20 -0
- data/lib/psych/visitors/yaml_tree.rb +551 -0
- data/lib/psych/visitors.rb +7 -0
- data/lib/psych/y.rb +10 -0
- data/lib/psych.rb +511 -0
- data/psych.gemspec +64 -0
- metadata +175 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
module Nodes
|
4
|
+
###
|
5
|
+
# This represents a YAML Document. This node must be a child of
|
6
|
+
# Psych::Nodes::Stream. A Psych::Nodes::Document must have one child,
|
7
|
+
# and that child may be one of the following:
|
8
|
+
#
|
9
|
+
# * Psych::Nodes::Sequence
|
10
|
+
# * Psych::Nodes::Mapping
|
11
|
+
# * Psych::Nodes::Scalar
|
12
|
+
class Document < Psych::Nodes::Node
|
13
|
+
# The version of the YAML document
|
14
|
+
attr_accessor :version
|
15
|
+
|
16
|
+
# A list of tag directives for this document
|
17
|
+
attr_accessor :tag_directives
|
18
|
+
|
19
|
+
# Was this document implicitly created?
|
20
|
+
attr_accessor :implicit
|
21
|
+
|
22
|
+
# Is the end of the document implicit?
|
23
|
+
attr_accessor :implicit_end
|
24
|
+
|
25
|
+
###
|
26
|
+
# Create a new Psych::Nodes::Document object.
|
27
|
+
#
|
28
|
+
# +version+ is a list indicating the YAML version.
|
29
|
+
# +tags_directives+ is a list of tag directive declarations
|
30
|
+
# +implicit+ is a flag indicating whether the document will be implicitly
|
31
|
+
# started.
|
32
|
+
#
|
33
|
+
# == Example:
|
34
|
+
# This creates a YAML document object that represents a YAML 1.1 document
|
35
|
+
# with one tag directive, and has an implicit start:
|
36
|
+
#
|
37
|
+
# Psych::Nodes::Document.new(
|
38
|
+
# [1,1],
|
39
|
+
# [["!", "tag:tenderlovemaking.com,2009:"]],
|
40
|
+
# true
|
41
|
+
# )
|
42
|
+
#
|
43
|
+
# == See Also
|
44
|
+
# See also Psych::Handler#start_document
|
45
|
+
def initialize version = [], tag_directives = [], implicit = false
|
46
|
+
super()
|
47
|
+
@version = version
|
48
|
+
@tag_directives = tag_directives
|
49
|
+
@implicit = implicit
|
50
|
+
@implicit_end = true
|
51
|
+
end
|
52
|
+
|
53
|
+
###
|
54
|
+
# Returns the root node. A Document may only have one root node:
|
55
|
+
# http://yaml.org/spec/1.1/#id898031
|
56
|
+
def root
|
57
|
+
children.first
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
module Nodes
|
4
|
+
###
|
5
|
+
# This class represents a {YAML Mapping}[http://yaml.org/spec/1.1/#mapping].
|
6
|
+
#
|
7
|
+
# A Psych::Nodes::Mapping node may have 0 or more children, but must have
|
8
|
+
# an even number of children. Here are the valid children a
|
9
|
+
# Psych::Nodes::Mapping node may have:
|
10
|
+
#
|
11
|
+
# * Psych::Nodes::Sequence
|
12
|
+
# * Psych::Nodes::Mapping
|
13
|
+
# * Psych::Nodes::Scalar
|
14
|
+
# * Psych::Nodes::Alias
|
15
|
+
class Mapping < Psych::Nodes::Node
|
16
|
+
# Any Map Style
|
17
|
+
ANY = 0
|
18
|
+
|
19
|
+
# Block Map Style
|
20
|
+
BLOCK = 1
|
21
|
+
|
22
|
+
# Flow Map Style
|
23
|
+
FLOW = 2
|
24
|
+
|
25
|
+
# The optional anchor for this mapping
|
26
|
+
attr_accessor :anchor
|
27
|
+
|
28
|
+
# The optional tag for this mapping
|
29
|
+
attr_accessor :tag
|
30
|
+
|
31
|
+
# Is this an implicit mapping?
|
32
|
+
attr_accessor :implicit
|
33
|
+
|
34
|
+
# The style of this mapping
|
35
|
+
attr_accessor :style
|
36
|
+
|
37
|
+
###
|
38
|
+
# Create a new Psych::Nodes::Mapping object.
|
39
|
+
#
|
40
|
+
# +anchor+ is the anchor associated with the map or +nil+.
|
41
|
+
# +tag+ is the tag associated with the map or +nil+.
|
42
|
+
# +implicit+ is a boolean indicating whether or not the map was implicitly
|
43
|
+
# started.
|
44
|
+
# +style+ is an integer indicating the mapping style.
|
45
|
+
#
|
46
|
+
# == See Also
|
47
|
+
# See also Psych::Handler#start_mapping
|
48
|
+
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
|
49
|
+
super()
|
50
|
+
@anchor = anchor
|
51
|
+
@tag = tag
|
52
|
+
@implicit = implicit
|
53
|
+
@style = style
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'stringio'
|
3
|
+
require 'psych/class_loader'
|
4
|
+
require 'psych/scalar_scanner'
|
5
|
+
|
6
|
+
module Psych
|
7
|
+
module Nodes
|
8
|
+
###
|
9
|
+
# The base class for any Node in a YAML parse tree. This class should
|
10
|
+
# never be instantiated.
|
11
|
+
class Node
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
# The children of this node
|
15
|
+
attr_reader :children
|
16
|
+
|
17
|
+
# An associated tag
|
18
|
+
attr_reader :tag
|
19
|
+
|
20
|
+
# Create a new Psych::Nodes::Node
|
21
|
+
def initialize
|
22
|
+
@children = []
|
23
|
+
end
|
24
|
+
|
25
|
+
###
|
26
|
+
# Iterate over each node in the tree. Yields each node to +block+ depth
|
27
|
+
# first.
|
28
|
+
def each &block
|
29
|
+
return enum_for :each unless block_given?
|
30
|
+
Visitors::DepthFirst.new(block).accept self
|
31
|
+
end
|
32
|
+
|
33
|
+
###
|
34
|
+
# Convert this node to Ruby.
|
35
|
+
#
|
36
|
+
# See also Psych::Visitors::ToRuby
|
37
|
+
def to_ruby
|
38
|
+
Visitors::ToRuby.create.accept(self)
|
39
|
+
end
|
40
|
+
alias :transform :to_ruby
|
41
|
+
|
42
|
+
###
|
43
|
+
# Convert this node to YAML.
|
44
|
+
#
|
45
|
+
# See also Psych::Visitors::Emitter
|
46
|
+
def yaml io = nil, options = {}
|
47
|
+
real_io = io || StringIO.new(''.encode('utf-8'))
|
48
|
+
|
49
|
+
Visitors::Emitter.new(real_io, options).accept self
|
50
|
+
return real_io.string unless io
|
51
|
+
io
|
52
|
+
end
|
53
|
+
alias :to_yaml :yaml
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
module Nodes
|
4
|
+
###
|
5
|
+
# This class represents a {YAML Scalar}[http://yaml.org/spec/1.1/#id858081].
|
6
|
+
#
|
7
|
+
# This node type is a terminal node and should not have any children.
|
8
|
+
class Scalar < Psych::Nodes::Node
|
9
|
+
# Any style scalar, the emitter chooses
|
10
|
+
ANY = 0
|
11
|
+
|
12
|
+
# Plain scalar style
|
13
|
+
PLAIN = 1
|
14
|
+
|
15
|
+
# Single quoted style
|
16
|
+
SINGLE_QUOTED = 2
|
17
|
+
|
18
|
+
# Double quoted style
|
19
|
+
DOUBLE_QUOTED = 3
|
20
|
+
|
21
|
+
# Literal style
|
22
|
+
LITERAL = 4
|
23
|
+
|
24
|
+
# Folded style
|
25
|
+
FOLDED = 5
|
26
|
+
|
27
|
+
# The scalar value
|
28
|
+
attr_accessor :value
|
29
|
+
|
30
|
+
# The anchor value (if there is one)
|
31
|
+
attr_accessor :anchor
|
32
|
+
|
33
|
+
# The tag value (if there is one)
|
34
|
+
attr_accessor :tag
|
35
|
+
|
36
|
+
# Is this a plain scalar?
|
37
|
+
attr_accessor :plain
|
38
|
+
|
39
|
+
# Is this scalar quoted?
|
40
|
+
attr_accessor :quoted
|
41
|
+
|
42
|
+
# The style of this scalar
|
43
|
+
attr_accessor :style
|
44
|
+
|
45
|
+
###
|
46
|
+
# Create a new Psych::Nodes::Scalar object.
|
47
|
+
#
|
48
|
+
# +value+ is the string value of the scalar
|
49
|
+
# +anchor+ is an associated anchor or nil
|
50
|
+
# +tag+ is an associated tag or nil
|
51
|
+
# +plain+ is a boolean value
|
52
|
+
# +quoted+ is a boolean value
|
53
|
+
# +style+ is an integer idicating the string style
|
54
|
+
#
|
55
|
+
# == See Also
|
56
|
+
#
|
57
|
+
# See also Psych::Handler#scalar
|
58
|
+
def initialize value, anchor = nil, tag = nil, plain = true, quoted = false, style = ANY
|
59
|
+
@value = value
|
60
|
+
@anchor = anchor
|
61
|
+
@tag = tag
|
62
|
+
@plain = plain
|
63
|
+
@quoted = quoted
|
64
|
+
@style = style
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
module Nodes
|
4
|
+
###
|
5
|
+
# This class represents a
|
6
|
+
# {YAML sequence}[http://yaml.org/spec/1.1/#sequence/syntax].
|
7
|
+
#
|
8
|
+
# A YAML sequence is basically a list, and looks like this:
|
9
|
+
#
|
10
|
+
# %YAML 1.1
|
11
|
+
# ---
|
12
|
+
# - I am
|
13
|
+
# - a Sequence
|
14
|
+
#
|
15
|
+
# A YAML sequence may have an anchor like this:
|
16
|
+
#
|
17
|
+
# %YAML 1.1
|
18
|
+
# ---
|
19
|
+
# &A [
|
20
|
+
# "This sequence",
|
21
|
+
# "has an anchor"
|
22
|
+
# ]
|
23
|
+
#
|
24
|
+
# A YAML sequence may also have a tag like this:
|
25
|
+
#
|
26
|
+
# %YAML 1.1
|
27
|
+
# ---
|
28
|
+
# !!seq [
|
29
|
+
# "This sequence",
|
30
|
+
# "has a tag"
|
31
|
+
# ]
|
32
|
+
#
|
33
|
+
# This class represents a sequence in a YAML document. A
|
34
|
+
# Psych::Nodes::Sequence node may have 0 or more children. Valid children
|
35
|
+
# for this node are:
|
36
|
+
#
|
37
|
+
# * Psych::Nodes::Sequence
|
38
|
+
# * Psych::Nodes::Mapping
|
39
|
+
# * Psych::Nodes::Scalar
|
40
|
+
# * Psych::Nodes::Alias
|
41
|
+
class Sequence < Psych::Nodes::Node
|
42
|
+
# Any Styles, emitter chooses
|
43
|
+
ANY = 0
|
44
|
+
|
45
|
+
# Block style sequence
|
46
|
+
BLOCK = 1
|
47
|
+
|
48
|
+
# Flow style sequence
|
49
|
+
FLOW = 2
|
50
|
+
|
51
|
+
# The anchor for this sequence (if any)
|
52
|
+
attr_accessor :anchor
|
53
|
+
|
54
|
+
# The tag name for this sequence (if any)
|
55
|
+
attr_accessor :tag
|
56
|
+
|
57
|
+
# Is this sequence started implicitly?
|
58
|
+
attr_accessor :implicit
|
59
|
+
|
60
|
+
# The sequence style used
|
61
|
+
attr_accessor :style
|
62
|
+
|
63
|
+
###
|
64
|
+
# Create a new object representing a YAML sequence.
|
65
|
+
#
|
66
|
+
# +anchor+ is the anchor associated with the sequence or nil.
|
67
|
+
# +tag+ is the tag associated with the sequence or nil.
|
68
|
+
# +implicit+ a boolean indicating whether or not the sequence was
|
69
|
+
# implicitly started.
|
70
|
+
# +style+ is an integer indicating the list style.
|
71
|
+
#
|
72
|
+
# See Psych::Handler#start_sequence
|
73
|
+
def initialize anchor = nil, tag = nil, implicit = true, style = BLOCK
|
74
|
+
super()
|
75
|
+
@anchor = anchor
|
76
|
+
@tag = tag
|
77
|
+
@implicit = implicit
|
78
|
+
@style = style
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
module Nodes
|
4
|
+
###
|
5
|
+
# Represents a YAML stream. This is the root node for any YAML parse
|
6
|
+
# tree. This node must have one or more child nodes. The only valid
|
7
|
+
# child node for a Psych::Nodes::Stream node is Psych::Nodes::Document.
|
8
|
+
class Stream < Psych::Nodes::Node
|
9
|
+
|
10
|
+
# Encodings supported by Psych (and libyaml)
|
11
|
+
|
12
|
+
# Any encoding
|
13
|
+
ANY = Psych::Parser::ANY
|
14
|
+
|
15
|
+
# UTF-8 encoding
|
16
|
+
UTF8 = Psych::Parser::UTF8
|
17
|
+
|
18
|
+
# UTF-16LE encoding
|
19
|
+
UTF16LE = Psych::Parser::UTF16LE
|
20
|
+
|
21
|
+
# UTF-16BE encoding
|
22
|
+
UTF16BE = Psych::Parser::UTF16BE
|
23
|
+
|
24
|
+
# The encoding used for this stream
|
25
|
+
attr_accessor :encoding
|
26
|
+
|
27
|
+
###
|
28
|
+
# Create a new Psych::Nodes::Stream node with an +encoding+ that
|
29
|
+
# defaults to Psych::Nodes::Stream::UTF8.
|
30
|
+
#
|
31
|
+
# See also Psych::Handler#start_stream
|
32
|
+
def initialize encoding = UTF8
|
33
|
+
super()
|
34
|
+
@encoding = encoding
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/psych/nodes.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'psych/nodes/node'
|
3
|
+
require 'psych/nodes/stream'
|
4
|
+
require 'psych/nodes/document'
|
5
|
+
require 'psych/nodes/sequence'
|
6
|
+
require 'psych/nodes/scalar'
|
7
|
+
require 'psych/nodes/mapping'
|
8
|
+
require 'psych/nodes/alias'
|
9
|
+
|
10
|
+
module Psych
|
11
|
+
###
|
12
|
+
# = Overview
|
13
|
+
#
|
14
|
+
# When using Psych.load to deserialize a YAML document, the document is
|
15
|
+
# translated to an intermediary AST. That intermediary AST is then
|
16
|
+
# translated in to a Ruby object graph.
|
17
|
+
#
|
18
|
+
# In the opposite direction, when using Psych.dump, the Ruby object graph is
|
19
|
+
# translated to an intermediary AST which is then converted to a YAML
|
20
|
+
# document.
|
21
|
+
#
|
22
|
+
# Psych::Nodes contains all of the classes that make up the nodes of a YAML
|
23
|
+
# AST. You can manually build an AST and use one of the visitors (see
|
24
|
+
# Psych::Visitors) to convert that AST to either a YAML document or to a
|
25
|
+
# Ruby object graph.
|
26
|
+
#
|
27
|
+
# Here is an example of building an AST that represents a list with one
|
28
|
+
# scalar:
|
29
|
+
#
|
30
|
+
# # Create our nodes
|
31
|
+
# stream = Psych::Nodes::Stream.new
|
32
|
+
# doc = Psych::Nodes::Document.new
|
33
|
+
# seq = Psych::Nodes::Sequence.new
|
34
|
+
# scalar = Psych::Nodes::Scalar.new('foo')
|
35
|
+
#
|
36
|
+
# # Build up our tree
|
37
|
+
# stream.children << doc
|
38
|
+
# doc.children << seq
|
39
|
+
# seq.children << scalar
|
40
|
+
#
|
41
|
+
# The stream is the root of the tree. We can then convert the tree to YAML:
|
42
|
+
#
|
43
|
+
# stream.to_yaml => "---\n- foo\n"
|
44
|
+
#
|
45
|
+
# Or convert it to Ruby:
|
46
|
+
#
|
47
|
+
# stream.to_ruby => [["foo"]]
|
48
|
+
#
|
49
|
+
# == YAML AST Requirements
|
50
|
+
#
|
51
|
+
# A valid YAML AST *must* have one Psych::Nodes::Stream at the root. A
|
52
|
+
# Psych::Nodes::Stream node must have 1 or more Psych::Nodes::Document nodes
|
53
|
+
# as children.
|
54
|
+
#
|
55
|
+
# Psych::Nodes::Document nodes must have one and *only* one child. That child
|
56
|
+
# may be one of:
|
57
|
+
#
|
58
|
+
# * Psych::Nodes::Sequence
|
59
|
+
# * Psych::Nodes::Mapping
|
60
|
+
# * Psych::Nodes::Scalar
|
61
|
+
#
|
62
|
+
# Psych::Nodes::Sequence and Psych::Nodes::Mapping nodes may have many
|
63
|
+
# children, but Psych::Nodes::Mapping nodes should have an even number of
|
64
|
+
# children.
|
65
|
+
#
|
66
|
+
# All of these are valid children for Psych::Nodes::Sequence and
|
67
|
+
# Psych::Nodes::Mapping nodes:
|
68
|
+
#
|
69
|
+
# * Psych::Nodes::Sequence
|
70
|
+
# * Psych::Nodes::Mapping
|
71
|
+
# * Psych::Nodes::Scalar
|
72
|
+
# * Psych::Nodes::Alias
|
73
|
+
#
|
74
|
+
# Psych::Nodes::Scalar and Psych::Nodes::Alias are both terminal nodes and
|
75
|
+
# should not have any children.
|
76
|
+
module Nodes
|
77
|
+
end
|
78
|
+
end
|
data/lib/psych/omap.rb
ADDED
data/lib/psych/parser.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
###
|
4
|
+
# YAML event parser class. This class parses a YAML document and calls
|
5
|
+
# events on the handler that is passed to the constructor. The events can
|
6
|
+
# be used for things such as constructing a YAML AST or deserializing YAML
|
7
|
+
# documents. It can even be fed back to Psych::Emitter to emit the same
|
8
|
+
# document that was parsed.
|
9
|
+
#
|
10
|
+
# See Psych::Handler for documentation on the events that Psych::Parser emits.
|
11
|
+
#
|
12
|
+
# Here is an example that prints out ever scalar found in a YAML document:
|
13
|
+
#
|
14
|
+
# # Handler for detecting scalar values
|
15
|
+
# class ScalarHandler < Psych::Handler
|
16
|
+
# def scalar value, anchor, tag, plain, quoted, style
|
17
|
+
# puts value
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# parser = Psych::Parser.new(ScalarHandler.new)
|
22
|
+
# parser.parse(yaml_document)
|
23
|
+
#
|
24
|
+
# Here is an example that feeds the parser back in to Psych::Emitter. The
|
25
|
+
# YAML document is read from STDIN and written back out to STDERR:
|
26
|
+
#
|
27
|
+
# parser = Psych::Parser.new(Psych::Emitter.new($stderr))
|
28
|
+
# parser.parse($stdin)
|
29
|
+
#
|
30
|
+
# Psych uses Psych::Parser in combination with Psych::TreeBuilder to
|
31
|
+
# construct an AST of the parsed YAML document.
|
32
|
+
|
33
|
+
class Parser
|
34
|
+
class Mark < Struct.new(:index, :line, :column)
|
35
|
+
end
|
36
|
+
|
37
|
+
# The handler on which events will be called
|
38
|
+
attr_accessor :handler
|
39
|
+
|
40
|
+
# Set the encoding for this parser to +encoding+
|
41
|
+
attr_writer :external_encoding
|
42
|
+
|
43
|
+
###
|
44
|
+
# Creates a new Psych::Parser instance with +handler+. YAML events will
|
45
|
+
# be called on +handler+. See Psych::Parser for more details.
|
46
|
+
|
47
|
+
def initialize handler = Handler.new
|
48
|
+
@handler = handler
|
49
|
+
@external_encoding = ANY
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
module Psych
|
5
|
+
###
|
6
|
+
# Scan scalars for built in types
|
7
|
+
class ScalarScanner
|
8
|
+
# Taken from http://yaml.org/type/timestamp.html
|
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
|
+
|
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
|
15
|
+
|
16
|
+
# 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
|
21
|
+
|
22
|
+
attr_reader :class_loader
|
23
|
+
|
24
|
+
# Create a new scanner
|
25
|
+
def initialize class_loader
|
26
|
+
@string_cache = {}
|
27
|
+
@symbol_cache = {}
|
28
|
+
@class_loader = class_loader
|
29
|
+
end
|
30
|
+
|
31
|
+
# Tokenize +string+ returning the Ruby object
|
32
|
+
def tokenize string
|
33
|
+
return nil if string.empty?
|
34
|
+
return string if @string_cache.key?(string)
|
35
|
+
return @symbol_cache[string] if @symbol_cache.key?(string)
|
36
|
+
|
37
|
+
case string
|
38
|
+
# Check for a String type, being careful not to get caught by hash keys, hex values, and
|
39
|
+
# 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
|
45
|
+
|
46
|
+
case string
|
47
|
+
when /^[^ytonf~]/i
|
48
|
+
@string_cache[string] = true
|
49
|
+
string
|
50
|
+
when '~', /^null$/i
|
51
|
+
nil
|
52
|
+
when /^(yes|true|on)$/i
|
53
|
+
true
|
54
|
+
when /^(no|false|off)$/i
|
55
|
+
false
|
56
|
+
else
|
57
|
+
@string_cache[string] = true
|
58
|
+
string
|
59
|
+
end
|
60
|
+
when TIME
|
61
|
+
begin
|
62
|
+
parse_time string
|
63
|
+
rescue ArgumentError
|
64
|
+
string
|
65
|
+
end
|
66
|
+
when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
|
67
|
+
require 'date'
|
68
|
+
begin
|
69
|
+
class_loader.date.strptime(string, '%Y-%m-%d')
|
70
|
+
rescue ArgumentError
|
71
|
+
string
|
72
|
+
end
|
73
|
+
when /^\.inf$/i
|
74
|
+
Float::INFINITY
|
75
|
+
when /^-\.inf$/i
|
76
|
+
-Float::INFINITY
|
77
|
+
when /^\.nan$/i
|
78
|
+
Float::NAN
|
79
|
+
when /^:./
|
80
|
+
if string =~ /^:(["'])(.*)\1/
|
81
|
+
@symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
|
82
|
+
else
|
83
|
+
@symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
|
84
|
+
end
|
85
|
+
when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/
|
86
|
+
i = 0
|
87
|
+
string.split(':').each_with_index do |n,e|
|
88
|
+
i += (n.to_i * 60 ** (e - 2).abs)
|
89
|
+
end
|
90
|
+
i
|
91
|
+
when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/
|
92
|
+
i = 0
|
93
|
+
string.split(':').each_with_index do |n,e|
|
94
|
+
i += (n.to_f * 60 ** (e - 2).abs)
|
95
|
+
end
|
96
|
+
i
|
97
|
+
when FLOAT
|
98
|
+
if string =~ /\A[-+]?\.\Z/
|
99
|
+
@string_cache[string] = true
|
100
|
+
string
|
101
|
+
else
|
102
|
+
Float(string.gsub(/[,_]|\.([Ee]|$)/, '\1'))
|
103
|
+
end
|
104
|
+
else
|
105
|
+
int = parse_int string.gsub(/[,_]/, '')
|
106
|
+
return int if int
|
107
|
+
|
108
|
+
@string_cache[string] = true
|
109
|
+
string
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
###
|
114
|
+
# Parse and return an int from +string+
|
115
|
+
def parse_int string
|
116
|
+
return unless INTEGER === string
|
117
|
+
Integer(string)
|
118
|
+
end
|
119
|
+
|
120
|
+
###
|
121
|
+
# Parse and return a Time from +string+
|
122
|
+
def parse_time string
|
123
|
+
klass = class_loader.load 'Time'
|
124
|
+
|
125
|
+
date, time = *(string.split(/[ tT]/, 2))
|
126
|
+
(yy, m, dd) = date.match(/^(-?\d{4})-(\d{1,2})-(\d{1,2})/).captures.map { |x| x.to_i }
|
127
|
+
md = time.match(/(\d+:\d+:\d+)(?:\.(\d*))?\s*(Z|[-+]\d+(:\d\d)?)?/)
|
128
|
+
|
129
|
+
(hh, mm, ss) = md[1].split(':').map { |x| x.to_i }
|
130
|
+
us = (md[2] ? Rational("0.#{md[2]}") : 0) * 1000000
|
131
|
+
|
132
|
+
time = klass.utc(yy, m, dd, hh, mm, ss, us)
|
133
|
+
|
134
|
+
return time if 'Z' == md[3]
|
135
|
+
return klass.at(time.to_i, us) unless md[3]
|
136
|
+
|
137
|
+
tz = md[3].match(/^([+\-]?\d{1,2})\:?(\d{1,2})?$/)[1..-1].compact.map { |digit| Integer(digit, 10) }
|
138
|
+
offset = tz.first * 3600
|
139
|
+
|
140
|
+
if offset < 0
|
141
|
+
offset -= ((tz[1] || 0) * 60)
|
142
|
+
else
|
143
|
+
offset += ((tz[1] || 0) * 60)
|
144
|
+
end
|
145
|
+
|
146
|
+
klass.new(yy, m, dd, hh, mm, ss+us/(1_000_000r), offset)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/psych/set.rb
ADDED
data/lib/psych/stream.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Psych
|
3
|
+
###
|
4
|
+
# Psych::Stream is a streaming YAML emitter. It will not buffer your YAML,
|
5
|
+
# but send it straight to an IO.
|
6
|
+
#
|
7
|
+
# Here is an example use:
|
8
|
+
#
|
9
|
+
# stream = Psych::Stream.new($stdout)
|
10
|
+
# stream.start
|
11
|
+
# stream.push({:foo => 'bar'})
|
12
|
+
# stream.finish
|
13
|
+
#
|
14
|
+
# YAML will be immediately emitted to $stdout with no buffering.
|
15
|
+
#
|
16
|
+
# Psych::Stream#start will take a block and ensure that Psych::Stream#finish
|
17
|
+
# is called, so you can do this form:
|
18
|
+
#
|
19
|
+
# stream = Psych::Stream.new($stdout)
|
20
|
+
# stream.start do |em|
|
21
|
+
# em.push(:foo => 'bar')
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
class Stream < Psych::Visitors::YAMLTree
|
25
|
+
class Emitter < Psych::Emitter # :nodoc:
|
26
|
+
def end_document implicit_end = !streaming?
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def streaming?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
include Psych::Streaming
|
36
|
+
extend Psych::Streaming::ClassMethods
|
37
|
+
end
|
38
|
+
end
|