1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
# frozen_string_literal: true
require_relative 'handler'
module Psych
###
# This class works in conjunction with Psych::Parser to build an in-memory
# parse tree that represents a YAML document.
#
# == Example
#
# parser = Psych::Parser.new Psych::TreeBuilder.new
# parser.parse('--- foo')
# tree = parser.handler.root
#
# See Psych::Handler for documentation on the event methods used in this
# class.
class TreeBuilder < Psych::Handler
# Returns the root node for the built tree
attr_reader :root
# Create a new TreeBuilder instance
def initialize
@stack = []
@last = nil
@root = nil
@start_line = nil
@start_column = nil
@end_line = nil
@end_column = nil
end
def event_location(start_line, start_column, end_line, end_column)
@start_line = start_line
@start_column = start_column
@end_line = end_line
@end_column = end_column
end
%w{
Sequence
Mapping
}.each do |node|
class_eval %{
def start_#{node.downcase}(anchor, tag, implicit, style)
n = Nodes::#{node}.new(anchor, tag, implicit, style)
set_start_location(n)
@last.children << n
push n
end
def end_#{node.downcase}
n = pop
set_end_location(n)
n
end
}
end
###
# Handles start_document events with +version+, +tag_directives+,
# and +implicit+ styling.
#
# See Psych::Handler#start_document
def start_document version, tag_directives, implicit
n = Nodes::Document.new version, tag_directives, implicit
set_start_location(n)
@last.children << n
push n
end
###
# Handles end_document events with +version+, +tag_directives+,
# and +implicit+ styling.
#
# See Psych::Handler#start_document
def end_document implicit_end = !streaming?
@last.implicit_end = implicit_end
n = pop
set_end_location(n)
n
end
def start_stream encoding
@root = Nodes::Stream.new(encoding)
set_start_location(@root)
push @root
end
def end_stream
n = pop
set_end_location(n)
n
end
def scalar value, anchor, tag, plain, quoted, style
s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
set_location(s)
@last.children << s
s
end
def alias anchor
a = Nodes::Alias.new(anchor)
set_location(a)
@last.children << a
a
end
private
def push value
@stack.push value
@last = value
end
def pop
x = @stack.pop
@last = @stack.last
x
end
def set_location(node)
set_start_location(node)
set_end_location(node)
end
def set_start_location(node)
node.start_line = @start_line
node.start_column = @start_column
end
def set_end_location(node)
node.end_line = @end_line
node.end_column = @end_column
end
end
end
|