psych 2.0.14-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.autotest +18 -0
- data/.gemtest +0 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.rdoc +576 -0
- data/Manifest.txt +114 -0
- data/README.rdoc +71 -0
- data/Rakefile +123 -0
- data/ext/psych/depend +3 -0
- data/ext/psych/extconf.rb +38 -0
- data/ext/psych/psych.c +34 -0
- data/ext/psych/psych.h +20 -0
- data/ext/psych/psych_emitter.c +555 -0
- data/ext/psych/psych_emitter.h +8 -0
- data/ext/psych/psych_parser.c +597 -0
- data/ext/psych/psych_parser.h +6 -0
- data/ext/psych/psych_to_ruby.c +43 -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 +1415 -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 +459 -0
- data/ext/psych/yaml/parser.c +1370 -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 +664 -0
- data/lib/psych.jar +0 -0
- data/lib/psych.rb +504 -0
- data/lib/psych/class_loader.rb +101 -0
- data/lib/psych/coder.rb +94 -0
- data/lib/psych/core_ext.rb +35 -0
- data/lib/psych/deprecated.rb +85 -0
- data/lib/psych/exception.rb +13 -0
- data/lib/psych/handler.rb +249 -0
- data/lib/psych/handlers/document_stream.rb +22 -0
- data/lib/psych/handlers/recorder.rb +39 -0
- data/lib/psych/json/ruby_events.rb +19 -0
- data/lib/psych/json/stream.rb +16 -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 +55 -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 +51 -0
- data/lib/psych/scalar_scanner.rb +149 -0
- data/lib/psych/set.rb +4 -0
- data/lib/psych/stream.rb +37 -0
- data/lib/psych/streaming.rb +27 -0
- data/lib/psych/syntax_error.rb +21 -0
- data/lib/psych/tree_builder.rb +96 -0
- data/lib/psych/versions.rb +3 -0
- data/lib/psych/visitors.rb +6 -0
- data/lib/psych/visitors/depth_first.rb +26 -0
- data/lib/psych/visitors/emitter.rb +51 -0
- data/lib/psych/visitors/json_tree.rb +24 -0
- data/lib/psych/visitors/to_ruby.rb +404 -0
- data/lib/psych/visitors/visitor.rb +19 -0
- data/lib/psych/visitors/yaml_tree.rb +605 -0
- data/lib/psych/y.rb +9 -0
- data/lib/psych_jars.rb +5 -0
- data/test/psych/handlers/test_recorder.rb +25 -0
- data/test/psych/helper.rb +121 -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 +96 -0
- data/test/psych/test_array.rb +57 -0
- data/test/psych/test_boolean.rb +36 -0
- data/test/psych/test_class.rb +36 -0
- data/test/psych/test_coder.rb +206 -0
- data/test/psych/test_date_time.rb +38 -0
- data/test/psych/test_deprecated.rb +214 -0
- data/test/psych/test_document.rb +46 -0
- data/test/psych/test_emitter.rb +93 -0
- data/test/psych/test_encoding.rb +259 -0
- data/test/psych/test_exception.rb +157 -0
- data/test/psych/test_hash.rb +94 -0
- data/test/psych/test_json_tree.rb +65 -0
- data/test/psych/test_merge_keys.rb +180 -0
- data/test/psych/test_nil.rb +18 -0
- data/test/psych/test_null.rb +19 -0
- data/test/psych/test_numeric.rb +45 -0
- data/test/psych/test_object.rb +44 -0
- data/test/psych/test_object_references.rb +71 -0
- data/test/psych/test_omap.rb +75 -0
- data/test/psych/test_parser.rb +339 -0
- data/test/psych/test_psych.rb +168 -0
- data/test/psych/test_safe_load.rb +97 -0
- data/test/psych/test_scalar.rb +11 -0
- data/test/psych/test_scalar_scanner.rb +106 -0
- data/test/psych/test_serialize_subclasses.rb +38 -0
- data/test/psych/test_set.rb +49 -0
- data/test/psych/test_stream.rb +93 -0
- data/test/psych/test_string.rb +226 -0
- data/test/psych/test_struct.rb +49 -0
- data/test/psych/test_symbol.rb +25 -0
- data/test/psych/test_tainted.rb +130 -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 +1292 -0
- data/test/psych/test_yamldbm.rb +193 -0
- data/test/psych/test_yamlstore.rb +85 -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 +333 -0
- data/test/psych/visitors/test_yaml_tree.rb +173 -0
- metadata +240 -0
@@ -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 sequence 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,51 @@
|
|
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
|
+
# Set the encoding for this parser to +encoding+
|
40
|
+
attr_writer :external_encoding
|
41
|
+
|
42
|
+
###
|
43
|
+
# Creates a new Psych::Parser instance with +handler+. YAML events will
|
44
|
+
# be called on +handler+. See Psych::Parser for more details.
|
45
|
+
|
46
|
+
def initialize handler = Handler.new
|
47
|
+
@handler = handler
|
48
|
+
@external_encoding = ANY
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,149 @@
|
|
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
|
+
# Taken from http://yaml.org/type/float.html
|
11
|
+
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10)
|
12
|
+
|[-+]?[0-9][0-9_,]*(:[0-5]?[0-9])+\.[0-9_]*(?# base 60)
|
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])+$/
|
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])+\.[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(/[,_]|\.$/, ''))
|
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.at((time - offset).to_i, us)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/psych/set.rb
ADDED
data/lib/psych/stream.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Psych
|
2
|
+
###
|
3
|
+
# Psych::Stream is a streaming YAML emitter. It will not buffer your YAML,
|
4
|
+
# but send it straight to an IO.
|
5
|
+
#
|
6
|
+
# Here is an example use:
|
7
|
+
#
|
8
|
+
# stream = Psych::Stream.new($stdout)
|
9
|
+
# stream.start
|
10
|
+
# stream.push({:foo => 'bar'})
|
11
|
+
# stream.finish
|
12
|
+
#
|
13
|
+
# YAML will be immediately emitted to $stdout with no buffering.
|
14
|
+
#
|
15
|
+
# Psych::Stream#start will take a block and ensure that Psych::Stream#finish
|
16
|
+
# is called, so you can do this form:
|
17
|
+
#
|
18
|
+
# stream = Psych::Stream.new($stdout)
|
19
|
+
# stream.start do |em|
|
20
|
+
# em.push(:foo => 'bar')
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class Stream < Psych::Visitors::YAMLTree
|
24
|
+
class Emitter < Psych::Emitter # :nodoc:
|
25
|
+
def end_document implicit_end = !streaming?
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def streaming?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
include Psych::Streaming
|
35
|
+
extend Psych::Streaming::ClassMethods
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Psych
|
2
|
+
module Streaming
|
3
|
+
module ClassMethods
|
4
|
+
###
|
5
|
+
# Create a new streaming emitter. Emitter will print to +io+. See
|
6
|
+
# Psych::Stream for an example.
|
7
|
+
def new io
|
8
|
+
emitter = const_get(:Emitter).new(io)
|
9
|
+
class_loader = ClassLoader.new
|
10
|
+
ss = ScalarScanner.new class_loader
|
11
|
+
super(emitter, ss, {})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
###
|
16
|
+
# Start streaming using +encoding+
|
17
|
+
def start encoding = Nodes::Stream::UTF8
|
18
|
+
super.tap { yield self if block_given? }
|
19
|
+
ensure
|
20
|
+
finish if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def register target, obj
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'psych/exception'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
class SyntaxError < Psych::Exception
|
5
|
+
attr_reader :file, :line, :column, :offset, :problem, :context
|
6
|
+
|
7
|
+
def initialize file, line, col, offset, problem, context
|
8
|
+
err = [problem, context].compact.join ' '
|
9
|
+
filename = file || '<unknown>'
|
10
|
+
message = "(%s): %s at line %d column %d" % [filename, err, line, col]
|
11
|
+
|
12
|
+
@file = file
|
13
|
+
@line = line
|
14
|
+
@column = col
|
15
|
+
@offset = offset
|
16
|
+
@problem = problem
|
17
|
+
@context = context
|
18
|
+
super(message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'psych/handler'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
###
|
5
|
+
# This class works in conjunction with Psych::Parser to build an in-memory
|
6
|
+
# parse tree that represents a YAML document.
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# parser = Psych::Parser.new Psych::TreeBuilder.new
|
11
|
+
# parser.parse('--- foo')
|
12
|
+
# tree = parser.handler.root
|
13
|
+
#
|
14
|
+
# See Psych::Handler for documentation on the event methods used in this
|
15
|
+
# class.
|
16
|
+
class TreeBuilder < Psych::Handler
|
17
|
+
# Returns the root node for the built tree
|
18
|
+
attr_reader :root
|
19
|
+
|
20
|
+
# Create a new TreeBuilder instance
|
21
|
+
def initialize
|
22
|
+
@stack = []
|
23
|
+
@last = nil
|
24
|
+
@root = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
%w{
|
28
|
+
Sequence
|
29
|
+
Mapping
|
30
|
+
}.each do |node|
|
31
|
+
class_eval %{
|
32
|
+
def start_#{node.downcase}(anchor, tag, implicit, style)
|
33
|
+
n = Nodes::#{node}.new(anchor, tag, implicit, style)
|
34
|
+
@last.children << n
|
35
|
+
push n
|
36
|
+
end
|
37
|
+
|
38
|
+
def end_#{node.downcase}
|
39
|
+
pop
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
###
|
45
|
+
# Handles start_document events with +version+, +tag_directives+,
|
46
|
+
# and +implicit+ styling.
|
47
|
+
#
|
48
|
+
# See Psych::Handler#start_document
|
49
|
+
def start_document version, tag_directives, implicit
|
50
|
+
n = Nodes::Document.new version, tag_directives, implicit
|
51
|
+
@last.children << n
|
52
|
+
push n
|
53
|
+
end
|
54
|
+
|
55
|
+
###
|
56
|
+
# Handles end_document events with +version+, +tag_directives+,
|
57
|
+
# and +implicit+ styling.
|
58
|
+
#
|
59
|
+
# See Psych::Handler#start_document
|
60
|
+
def end_document implicit_end = !streaming?
|
61
|
+
@last.implicit_end = implicit_end
|
62
|
+
pop
|
63
|
+
end
|
64
|
+
|
65
|
+
def start_stream encoding
|
66
|
+
@root = Nodes::Stream.new(encoding)
|
67
|
+
push @root
|
68
|
+
end
|
69
|
+
|
70
|
+
def end_stream
|
71
|
+
pop
|
72
|
+
end
|
73
|
+
|
74
|
+
def scalar value, anchor, tag, plain, quoted, style
|
75
|
+
s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
|
76
|
+
@last.children << s
|
77
|
+
s
|
78
|
+
end
|
79
|
+
|
80
|
+
def alias anchor
|
81
|
+
@last.children << Nodes::Alias.new(anchor)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def push value
|
86
|
+
@stack.push value
|
87
|
+
@last = value
|
88
|
+
end
|
89
|
+
|
90
|
+
def pop
|
91
|
+
x = @stack.pop
|
92
|
+
@last = @stack.last
|
93
|
+
x
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|