kwalify 0.6.1 → 0.7.0
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.
- data/CHANGES.txt +232 -0
- data/MIT-LICENSE +20 -0
- data/README.txt +16 -19
- data/bin/kwalify +3 -3
- data/contrib/inline-require +6 -4
- data/contrib/kwalify +3719 -2427
- data/doc-api/classes/CommandOptionError.html +17 -17
- data/doc-api/classes/CommandOptionParser.html +63 -63
- data/doc-api/classes/Kwalify.html +29 -7
- data/doc-api/classes/Kwalify/AssertionError.html +9 -9
- data/doc-api/classes/Kwalify/BaseError.html +72 -71
- data/doc-api/classes/Kwalify/BaseParser.html +461 -0
- data/doc-api/classes/Kwalify/CommandOptionError.html +11 -11
- data/doc-api/classes/Kwalify/ErrorHelper.html +51 -46
- data/doc-api/classes/Kwalify/HashInterface.html +13 -135
- data/doc-api/classes/Kwalify/Json.html +105 -0
- data/doc-api/classes/Kwalify/Main.html +129 -126
- data/doc-api/classes/Kwalify/MetaValidator.html +248 -232
- data/doc-api/classes/Kwalify/Parser.html +12 -12
- data/doc-api/classes/Kwalify/PlainYamlParser.html +166 -163
- data/doc-api/classes/Kwalify/PlainYamlParser/Alias.html +11 -11
- data/doc-api/classes/Kwalify/Rule.html +152 -130
- data/doc-api/classes/Kwalify/SchemaError.html +10 -10
- data/doc-api/classes/Kwalify/SyntaxError.html +185 -0
- data/doc-api/classes/Kwalify/Types.html +26 -25
- data/doc-api/classes/Kwalify/Util.html +389 -0
- data/doc-api/classes/Kwalify/Util/HashLike.html +246 -0
- data/doc-api/classes/Kwalify/Util/OrderedHash.html +330 -0
- data/doc-api/classes/Kwalify/ValidationError.html +10 -10
- data/doc-api/classes/Kwalify/Validator.html +153 -86
- data/doc-api/classes/Kwalify/Yaml.html +181 -0
- data/doc-api/classes/Kwalify/Yaml/Parser.html +1538 -0
- data/doc-api/classes/Kwalify/YamlParser.html +190 -183
- data/doc-api/classes/Kwalify/YamlSyntaxError.html +8 -57
- data/doc-api/created.rid +1 -1
- data/doc-api/files/__/README_txt.html +17 -22
- data/doc-api/files/kwalify/errors_rb.html +2 -2
- data/doc-api/files/kwalify/main_rb.html +4 -3
- data/doc-api/files/kwalify/messages_rb.html +2 -2
- data/doc-api/files/kwalify/meta-validator_rb.html +3 -3
- data/doc-api/files/kwalify/{util/yaml-helper_rb.html → parser/base_rb.html} +8 -6
- data/doc-api/files/kwalify/parser/yaml_rb.html +117 -0
- data/doc-api/files/kwalify/rule_rb.html +2 -2
- data/doc-api/files/kwalify/types_rb.html +2 -2
- data/doc-api/files/kwalify/util/assert-text-equal_rb.html +2 -2
- data/doc-api/files/kwalify/util/hash-interface_rb.html +9 -2
- data/doc-api/files/kwalify/util/hashlike_rb.html +107 -0
- data/doc-api/files/kwalify/util/option-parser_rb.html +2 -2
- data/doc-api/files/kwalify/util/ordered-hash_rb.html +107 -0
- data/doc-api/files/kwalify/util/testcase-helper_rb.html +2 -2
- data/doc-api/files/kwalify/util_rb.html +107 -0
- data/doc-api/files/kwalify/validator_rb.html +2 -2
- data/doc-api/files/kwalify/yaml-parser_rb.html +2 -2
- data/doc-api/files/kwalify_rb.html +3 -2
- data/doc-api/fr_class_index.html +8 -1
- data/doc-api/fr_file_index.html +5 -1
- data/doc-api/fr_method_index.html +128 -69
- data/doc/img/fig01.png +0 -0
- data/doc/users-guide.html +882 -717
- data/examples/address-book/address-book.schema.yaml +2 -2
- data/examples/data-binding/BABEL.data.yaml +63 -0
- data/examples/data-binding/BABEL.schema.yaml +31 -0
- data/examples/data-binding/Makefile +8 -0
- data/examples/data-binding/Rakefile +13 -0
- data/examples/data-binding/main.rb +27 -0
- data/examples/invoice/invoice.schema.yaml +3 -3
- data/examples/tapkit/tapkit.schema.yaml +2 -2
- data/lib/kwalify.rb +41 -4
- data/lib/kwalify/errors.rb +118 -96
- data/lib/kwalify/kwalify.schema.yaml +58 -0
- data/lib/kwalify/main.rb +384 -377
- data/lib/kwalify/messages.rb +41 -27
- data/lib/kwalify/meta-validator.rb +251 -331
- data/lib/kwalify/parser/base.rb +127 -0
- data/lib/kwalify/parser/yaml.rb +837 -0
- data/lib/kwalify/rule.rb +545 -487
- data/lib/kwalify/templates/genclass-java.eruby +189 -162
- data/lib/kwalify/templates/genclass-php.eruby +104 -0
- data/lib/kwalify/templates/genclass-ruby.eruby +95 -66
- data/lib/kwalify/types.rb +107 -106
- data/lib/kwalify/util.rb +157 -0
- data/lib/kwalify/util/assert-text-equal.rb +33 -31
- data/lib/kwalify/util/hash-interface.rb +11 -30
- data/lib/kwalify/util/hashlike.rb +51 -0
- data/lib/kwalify/util/option-parser.rb +144 -144
- data/lib/kwalify/util/ordered-hash.rb +57 -0
- data/lib/kwalify/util/testcase-helper.rb +3 -3
- data/lib/kwalify/validator.rb +267 -212
- data/lib/kwalify/yaml-parser.rb +822 -768
- data/setup.rb +861 -607
- data/test/Rookbook.yaml +10 -0
- data/test/{tmp.dir/Context.java → data/users-guide/AddressBook.java.expected} +11 -11
- data/test/data/users-guide/BABEL.data.yaml +24 -0
- data/test/data/users-guide/BABEL.schema.yaml +30 -0
- data/test/data/users-guide/ExampleAddressBook.java +47 -0
- data/test/{tmp.dir/Group.java → data/users-guide/Group.java.expected} +2 -11
- data/test/data/users-guide/Person.java.expected +44 -0
- data/test/data/users-guide/address_book.rb +52 -0
- data/test/data/users-guide/address_book.schema.yaml +28 -0
- data/test/data/users-guide/address_book.yaml +27 -0
- data/test/data/users-guide/answers-schema.yaml +12 -0
- data/test/data/users-guide/answers-validator.rb +52 -0
- data/test/data/users-guide/babel_genclass.result +26 -0
- data/test/data/users-guide/config.schema.yaml +7 -0
- data/test/data/users-guide/config.yaml +4 -0
- data/test/{tmp.dir/silent1.document → data/users-guide/document01a.yaml} +0 -0
- data/test/data/users-guide/document01b.yaml +3 -0
- data/test/data/users-guide/document02a.yaml +4 -0
- data/test/data/users-guide/document02b.yaml +4 -0
- data/test/data/users-guide/document03a.yaml +6 -0
- data/test/data/users-guide/document03b.yaml +6 -0
- data/test/data/users-guide/document04a.yaml +9 -0
- data/test/data/users-guide/document04b.yaml +9 -0
- data/test/data/users-guide/document05a.yaml +11 -0
- data/test/data/users-guide/document05b.yaml +12 -0
- data/test/data/users-guide/document06a.yaml +15 -0
- data/test/data/users-guide/document06b.yaml +16 -0
- data/test/data/users-guide/document07a.yaml +9 -0
- data/test/data/users-guide/document07b.yaml +7 -0
- data/test/data/users-guide/document12a.json +10 -0
- data/test/data/users-guide/document12b.json +6 -0
- data/test/data/users-guide/document13a.yaml +17 -0
- data/test/data/users-guide/document14a.yaml +3 -0
- data/test/data/users-guide/document14b.yaml +3 -0
- data/test/data/users-guide/document15a.yaml +6 -0
- data/test/data/users-guide/document15b.yaml +5 -0
- data/test/data/users-guide/example_address_book.rb +10 -0
- data/test/data/users-guide/example_address_book_java.result +32 -0
- data/test/data/users-guide/example_address_book_ruby.result +31 -0
- data/test/data/users-guide/genclass_java.result +4 -0
- data/test/data/users-guide/howto-validation-with-parsing.rb +28 -0
- data/test/data/users-guide/howto-validation.rb +25 -0
- data/test/data/users-guide/howto3.rb +6 -0
- data/test/data/users-guide/howto3.result +5 -0
- data/test/data/users-guide/howto3.yaml +8 -0
- data/test/data/users-guide/howto5_databinding.result +111 -0
- data/test/data/users-guide/invalid01.result +3 -0
- data/test/data/users-guide/invalid02.result +5 -0
- data/test/data/users-guide/invalid03.result +5 -0
- data/test/data/users-guide/invalid04.result +4 -0
- data/test/data/users-guide/invalid05.result +11 -0
- data/test/data/users-guide/invalid06.result +4 -0
- data/test/data/users-guide/invalid07.result +3 -0
- data/test/data/users-guide/invalid08.result +3 -0
- data/test/data/users-guide/invalid12.json +8 -0
- data/test/data/users-guide/invalid14.result +4 -0
- data/test/data/users-guide/invalid15.result +4 -0
- data/test/data/users-guide/loadbabel.rb +27 -0
- data/test/data/users-guide/loadconfig.rb +15 -0
- data/test/data/users-guide/loadconfig.result +2 -0
- data/test/data/users-guide/models.rb +22 -0
- data/test/data/users-guide/option_ha.result +6 -0
- data/test/data/users-guide/option_ha_genclass_java.result +7 -0
- data/test/{tmp.dir/meta1.schema → data/users-guide/schema01.yaml} +0 -0
- data/test/data/users-guide/schema02.yaml +12 -0
- data/test/data/users-guide/schema03.yaml +9 -0
- data/test/data/users-guide/schema04.yaml +20 -0
- data/test/data/users-guide/schema05.yaml +29 -0
- data/test/data/users-guide/schema06.yaml +11 -0
- data/test/data/users-guide/schema12.json +12 -0
- data/test/data/users-guide/schema13.yaml +13 -0
- data/test/data/users-guide/schema14.yaml +5 -0
- data/test/data/users-guide/schema15.yaml +21 -0
- data/test/data/users-guide/valid01.result +2 -0
- data/test/data/users-guide/valid02.result +2 -0
- data/test/data/users-guide/valid03.result +2 -0
- data/test/data/users-guide/valid04.result +2 -0
- data/test/data/users-guide/valid05.result +2 -0
- data/test/data/users-guide/valid06.result +2 -0
- data/test/data/users-guide/valid07.result +2 -0
- data/test/data/users-guide/valid08.result +2 -0
- data/test/data/users-guide/valid12.result +2 -0
- data/test/data/users-guide/valid13.result +2 -0
- data/test/data/users-guide/valid14.result +2 -0
- data/test/data/users-guide/valid15.result +2 -0
- data/test/data/users-guide/validate08.rb +37 -0
- data/test/test-action.rb +78 -0
- data/test/test-action.yaml +738 -0
- data/test/test-databinding.rb +80 -0
- data/test/test-databinding.yaml +301 -0
- data/test/test-main.rb +129 -150
- data/test/test-main.yaml +126 -321
- data/test/test-metavalidator.rb +47 -47
- data/test/test-metavalidator.yaml +77 -21
- data/test/test-parser-yaml.rb +57 -0
- data/test/test-parser-yaml.yaml +1749 -0
- data/test/test-rule.rb +14 -15
- data/test/test-rule.yaml +6 -3
- data/test/test-users-guide.rb +75 -0
- data/test/test-validator.rb +77 -52
- data/test/test-validator.yaml +168 -6
- data/test/test-yaml-parser.rb +47 -0
- data/test/{test-yamlparser.yaml → test-yaml-parser.yaml} +159 -52
- data/test/test.rb +37 -21
- metadata +136 -37
- data/COPYING +0 -340
- data/ChangeLog +0 -70
- data/doc-api/classes/YamlHelper.html +0 -259
- data/lib/kwalify/util/yaml-helper.rb +0 -82
- data/test/test-yamlparser.rb +0 -58
- data/test/tmp.dir/User.java +0 -43
- data/test/tmp.dir/action1.document +0 -18
- data/test/tmp.dir/action1.schema +0 -32
- data/test/tmp.dir/action2.document +0 -18
- data/test/tmp.dir/action2.schema +0 -32
- data/test/tmp.dir/emacs.document +0 -6
- data/test/tmp.dir/emacs.schema +0 -6
- data/test/tmp.dir/meta1.document +0 -0
- data/test/tmp.dir/meta2.document +0 -0
- data/test/tmp.dir/meta2.schema +0 -3
- data/test/tmp.dir/silent1.schema +0 -3
- data/test/tmp.dir/silent2.document +0 -7
- data/test/tmp.dir/silent2.schema +0 -3
- data/test/tmp.dir/stream.invalid +0 -8
- data/test/tmp.dir/stream.schema +0 -3
- data/test/tmp.dir/stream.valid +0 -8
- data/test/tmp.dir/untabify.document +0 -5
- data/test/tmp.dir/untabify.schema +0 -10
- data/todo.txt +0 -34
data/lib/kwalify/yaml-parser.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
###
|
2
|
-
### $Rev:
|
3
|
-
### $Release: 0.
|
4
|
-
### copyright(c) 2005 kuwata-lab all rights reserved.
|
2
|
+
### $Rev: 81 $
|
3
|
+
### $Release: 0.7.0 $
|
4
|
+
### copyright(c) 2005-2008 kuwata-lab all rights reserved.
|
5
5
|
###
|
6
6
|
|
7
7
|
require 'kwalify/messages'
|
@@ -13,804 +13,858 @@ require 'date'
|
|
13
13
|
|
14
14
|
module Kwalify
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
##
|
17
|
+
## base class of yaml parser
|
18
|
+
##
|
19
|
+
## ex.
|
20
|
+
## str = ARGF.read()
|
21
|
+
## parser = Kwalify::PlainYamlParser.new(str)
|
22
|
+
## doc = parser.parse()
|
23
|
+
## p doc
|
24
|
+
##
|
25
|
+
class PlainYamlParser
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
attr_reader :label, :linenum
|
27
|
+
class Alias
|
28
|
+
def initialize(label, linenum)
|
29
|
+
@label = label
|
30
|
+
@linenum = linenum
|
31
31
|
end
|
32
|
+
attr_reader :label, :linenum
|
33
|
+
end
|
32
34
|
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def parse()
|
44
|
-
data = parse_child(0)
|
45
|
-
if data.nil? && @end_flag == '---'
|
46
|
-
data = parse_child(0)
|
47
|
-
end
|
48
|
-
resolve_aliases(data) unless @aliases.empty?
|
49
|
-
return data
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
|
-
def has_next?
|
54
|
-
return @end_flag != 'EOF'
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
def parse_all
|
59
|
-
list = []
|
60
|
-
while has_next()
|
61
|
-
doc = parse()
|
62
|
-
list << doc
|
63
|
-
end
|
64
|
-
return list
|
65
|
-
end
|
66
|
-
|
36
|
+
def initialize(yaml_str)
|
37
|
+
@lines = yaml_str.to_a()
|
38
|
+
@line = nil
|
39
|
+
@linenum = 0
|
40
|
+
@anchors = {}
|
41
|
+
@aliases = {}
|
42
|
+
end
|
67
43
|
|
68
|
-
protected
|
69
44
|
|
70
|
-
|
71
|
-
|
72
|
-
|
45
|
+
def parse()
|
46
|
+
data = parse_child(0)
|
47
|
+
if data.nil? && @end_flag == '---'
|
48
|
+
data = parse_child(0)
|
73
49
|
end
|
50
|
+
resolve_aliases(data) unless @aliases.empty?
|
51
|
+
return data
|
52
|
+
end
|
74
53
|
|
75
|
-
def add_to_seq(seq, value, linenum)
|
76
|
-
seq << value
|
77
|
-
end
|
78
54
|
|
79
|
-
|
80
|
-
|
81
|
-
|
55
|
+
def has_next?
|
56
|
+
return @end_flag != 'EOF'
|
57
|
+
end
|
82
58
|
|
83
|
-
def create_mapping(linenum=nil)
|
84
|
-
return {}
|
85
|
-
end
|
86
59
|
|
87
|
-
|
88
|
-
|
60
|
+
def parse_all
|
61
|
+
list = []
|
62
|
+
while has_next()
|
63
|
+
doc = parse()
|
64
|
+
list << doc
|
89
65
|
end
|
66
|
+
return list
|
67
|
+
end
|
90
68
|
|
91
|
-
def set_map_with(map, key, value, linenum)
|
92
|
-
map[key] = value
|
93
|
-
end
|
94
69
|
|
95
|
-
|
96
|
-
map.value = value
|
97
|
-
end
|
70
|
+
protected
|
98
71
|
|
99
|
-
def merge_map(map, map2, linenum)
|
100
|
-
map2.each do |key, val|
|
101
|
-
map[key] = value unless map.key?(key)
|
102
|
-
end
|
103
|
-
end
|
104
72
|
|
105
|
-
|
106
|
-
|
107
|
-
|
73
|
+
def create_sequence(linenum=nil)
|
74
|
+
return []
|
75
|
+
end
|
108
76
|
|
77
|
+
def add_to_seq(seq, value, linenum)
|
78
|
+
seq << value
|
79
|
+
end
|
109
80
|
|
110
|
-
|
111
|
-
|
112
|
-
|
81
|
+
def set_seq_at(seq, i, value, linenum)
|
82
|
+
seq[i] = value
|
83
|
+
end
|
113
84
|
|
114
|
-
|
115
|
-
|
116
|
-
|
85
|
+
def create_mapping(linenum=nil)
|
86
|
+
return {}
|
87
|
+
end
|
117
88
|
|
89
|
+
def add_to_map(map, key, value, linenum)
|
90
|
+
map[key] = value
|
91
|
+
end
|
118
92
|
|
119
|
-
|
93
|
+
def set_map_with(map, key, value, linenum)
|
94
|
+
map[key] = value
|
95
|
+
end
|
120
96
|
|
97
|
+
def set_default(map, value, linenum)
|
98
|
+
map.value = value
|
99
|
+
end
|
121
100
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
return line
|
101
|
+
def merge_map(map, map2, linenum)
|
102
|
+
map2.each do |key, val|
|
103
|
+
map[key] = value unless map.key?(key)
|
126
104
|
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_scalar(value, linenum=nil)
|
108
|
+
return value
|
109
|
+
end
|
127
110
|
|
128
|
-
def _getline
|
129
|
-
@line = @lines[@linenum]
|
130
|
-
@linenum += 1
|
131
|
-
case @line
|
132
|
-
when nil ; @end_flag = 'EOF'
|
133
|
-
when /^\.\.\.$/ ; @end_flag = '...'; @line = nil
|
134
|
-
when /^---(\s+.*)?$/ ; @end_flag = '---'; @line = nil
|
135
|
-
else ; @end_flag = nil
|
136
|
-
end
|
137
|
-
return @line
|
138
|
-
end
|
139
111
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
112
|
+
def current_line
|
113
|
+
return @line
|
114
|
+
end
|
115
|
+
|
116
|
+
def current_linenum
|
117
|
+
return @linenum
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
|
124
|
+
def getline
|
125
|
+
line = _getline()
|
126
|
+
line = _getline() while line && line =~ /^\s*($|\#)/
|
127
|
+
return line
|
128
|
+
end
|
129
|
+
|
130
|
+
def _getline
|
131
|
+
@line = @lines[@linenum]
|
132
|
+
@linenum += 1
|
133
|
+
case @line
|
134
|
+
when nil ; @end_flag = 'EOF'
|
135
|
+
when /^\.\.\.$/ ; @end_flag = '...'; @line = nil
|
136
|
+
when /^---(\s+.*)?$/ ; @end_flag = '---'; @line = nil
|
137
|
+
else ; @end_flag = nil
|
138
|
+
end
|
139
|
+
return @line
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def reset_sbuf(str)
|
144
|
+
@sbuf = str[-1] == ?\n ? str : str + "\n"
|
145
|
+
@index = -1
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def _getchar
|
150
|
+
@index += 1
|
151
|
+
ch = @sbuf[@index]
|
152
|
+
while ch.nil?
|
153
|
+
break if (line = getline()).nil?
|
154
|
+
reset_sbuf(line)
|
155
|
+
@index += 1
|
156
|
+
ch = @sbuf[@index]
|
157
|
+
end
|
158
|
+
return ch
|
159
|
+
end
|
160
|
+
|
161
|
+
def getchar
|
162
|
+
ch = _getchar()
|
163
|
+
ch = _getchar() while ch && white?(ch)
|
164
|
+
return ch
|
165
|
+
end
|
166
|
+
|
167
|
+
def getchar_or_nl
|
168
|
+
ch = _getchar()
|
169
|
+
ch = _getchar() while ch && white?(ch) && ch != ?\n
|
170
|
+
return ch
|
171
|
+
end
|
172
|
+
|
173
|
+
def current_char
|
174
|
+
return @sbuf[@index]
|
175
|
+
end
|
176
|
+
|
177
|
+
def getlabel
|
178
|
+
if @sbuf[@index..-1] =~ /\A\w[-\w]*/
|
179
|
+
label = $&
|
180
|
+
@index += label.length
|
181
|
+
else
|
182
|
+
label = nil
|
183
|
+
end
|
184
|
+
return label
|
185
|
+
end
|
186
|
+
|
187
|
+
#--
|
188
|
+
#def syntax_error(error_symbol, linenum=@linenum)
|
189
|
+
# msg = Kwalify.msg(error_symbol) % [linenum]
|
190
|
+
# return Kwalify::YamlSyntaxError.new(msg, linenum,error_symbol)
|
191
|
+
#end
|
192
|
+
#++
|
193
|
+
def syntax_error(error_symbol, arg=nil, linenum=@linenum)
|
194
|
+
msg = Kwalify.msg(error_symbol)
|
195
|
+
msg = msg % arg.to_a unless arg.nil?
|
196
|
+
return Kwalify::YamlSyntaxError.new(msg, linenum, error_symbol)
|
197
|
+
end
|
198
|
+
|
199
|
+
def parse_child(column)
|
200
|
+
line = getline()
|
201
|
+
return create_scalar(nil) if !line
|
202
|
+
line =~ /^( *)(.*)/
|
203
|
+
indent = $1.length
|
204
|
+
return create_scalar(nil) if indent < column
|
205
|
+
value = $2
|
206
|
+
return parse_value(column, value, indent)
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
def parse_value(column, value, value_start_column)
|
211
|
+
case value
|
212
|
+
when /^-( |$)/
|
213
|
+
data = parse_sequence(value_start_column, value)
|
214
|
+
when /^(:?:?[-.\w]+\*?|'.*?'|".*?"|=|<<) *:( |$)/
|
215
|
+
#when /^:?["']?[-.\w]+["']? *:( |$)/ #'
|
216
|
+
data = parse_mapping(value_start_column, value)
|
217
|
+
when /^\[/, /^\{/
|
218
|
+
data = parse_flowstyle(column, value)
|
219
|
+
when /^\&[-\w]+( |$)/
|
220
|
+
data = parse_anchor(column, value)
|
221
|
+
when /^\*[-\w]+( |$)/
|
222
|
+
data = parse_alias(column, value)
|
223
|
+
when /^[|>]/
|
224
|
+
data = parse_block_text(column, value)
|
225
|
+
when /^!/
|
226
|
+
data = parse_tag(column, value)
|
227
|
+
when /^\#/
|
228
|
+
data = parse_child(column)
|
229
|
+
else
|
230
|
+
data = parse_scalar(column, value)
|
231
|
+
end
|
232
|
+
return data
|
233
|
+
end
|
234
|
+
|
235
|
+
def white?(ch)
|
236
|
+
return ch == ?\ || ch == ?\t || ch == ?\n || ch == ?\r
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
##
|
241
|
+
## flowstyle ::= flow_seq | flow_map | flow_scalar | alias
|
242
|
+
##
|
243
|
+
## flow_seq ::= '[' [ flow_seq_item { ',' sp flow_seq_item } ] ']'
|
244
|
+
## flow_seq_item ::= flowstyle
|
245
|
+
##
|
246
|
+
## flow_map ::= '{' [ flow_map_item { ',' sp flow_map_item } ] '}'
|
247
|
+
## flow_map_item ::= flowstyle ':' sp flowstyle
|
248
|
+
##
|
249
|
+
## flow_scalar ::= string | number | boolean | symbol | date
|
250
|
+
##
|
251
|
+
|
252
|
+
def parse_flowstyle(column, value)
|
253
|
+
reset_sbuf(value)
|
254
|
+
getchar()
|
255
|
+
data = parse_flow(0)
|
256
|
+
ch = current_char
|
257
|
+
assert ch == ?] || ch == ?}
|
258
|
+
ch = getchar_or_nl()
|
259
|
+
unless ch == ?\n || ch == ?# || ch.nil?
|
260
|
+
#* key=:flow_hastail msg="flow style sequence is closed but got '%s'."
|
261
|
+
raise syntax_error(:flow_hastail, [ch.chr])
|
262
|
+
end
|
263
|
+
getline() if !ch.nil?
|
264
|
+
return data
|
265
|
+
end
|
266
|
+
|
267
|
+
def parse_flow(depth)
|
268
|
+
ch = current_char()
|
269
|
+
#ch = getchar()
|
270
|
+
if ch.nil?
|
271
|
+
#* key=:flow_eof msg="found EOF when parsing flow style."
|
272
|
+
rase syntax_error(:flow_eof)
|
273
|
+
end
|
274
|
+
## alias
|
275
|
+
if ch == ?*
|
276
|
+
_getchar()
|
277
|
+
label = getlabel()
|
278
|
+
unless label
|
279
|
+
#* key=:flow_alias_label msg="alias name expected."
|
280
|
+
rase syntax_error(:flow_alias_label)
|
281
|
+
end
|
282
|
+
data = @anchors[label]
|
283
|
+
unless data
|
284
|
+
data = register_alias(label)
|
285
|
+
#raise syntax_error("anchor '#{label}' not found (cannot refer to backward or child anchor).")
|
286
|
+
end
|
287
|
+
return data
|
288
|
+
end
|
289
|
+
## anchor
|
290
|
+
label = nil
|
291
|
+
if ch == ?&
|
292
|
+
_getchar()
|
293
|
+
label = getlabel()
|
294
|
+
unless label
|
295
|
+
#* key=:flow_anchor_label msg="anchor name expected."
|
296
|
+
rase syntax_error(:flow_anchor_label)
|
297
|
+
end
|
298
|
+
ch = current_char()
|
299
|
+
ch = getchar() if white?(ch)
|
300
|
+
end
|
301
|
+
## flow data
|
302
|
+
if ch == ?[
|
303
|
+
data = parse_flow_seq(depth)
|
304
|
+
elsif ch == ?{
|
305
|
+
data = parse_flow_map(depth)
|
306
|
+
else
|
307
|
+
data = parse_flow_scalar(depth)
|
308
|
+
end
|
309
|
+
## register anchor
|
310
|
+
register_anchor(label, data) if label
|
311
|
+
return data
|
312
|
+
end
|
313
|
+
|
314
|
+
def parse_flow_seq(depth)
|
315
|
+
assert current_char() == ?[
|
316
|
+
seq = create_sequence() # []
|
317
|
+
ch = getchar()
|
318
|
+
if ch != ?}
|
319
|
+
linenum = current_linenum()
|
320
|
+
#seq << parse_flow_seq_item(depth + 1)
|
321
|
+
add_to_seq(seq, parse_flow_seq_item(depth + 1), linenum)
|
322
|
+
while (ch = current_char()) == ?,
|
323
|
+
ch = getchar()
|
324
|
+
if ch == ?]
|
325
|
+
#* key=:flow_noseqitem msg="sequence item required (or last comma is extra)."
|
326
|
+
raise syntax_error(:flow_noseqitem)
|
327
|
+
end
|
328
|
+
#break if ch == ?]
|
329
|
+
linenum = current_linenum()
|
330
|
+
#seq << parse_flow_seq_item(depth + 1)
|
331
|
+
add_to_seq(seq, parse_flow_seq_item(depth + 1), linenum)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
unless current_char() == ?]
|
335
|
+
#* key=:flow_seqnotclosed msg="flow style sequence requires ']'."
|
336
|
+
raise syntax_error(:flow_seqnotclosed)
|
337
|
+
end
|
338
|
+
getchar() if depth > 0
|
339
|
+
return seq
|
340
|
+
end
|
341
|
+
|
342
|
+
def parse_flow_seq_item(depth)
|
343
|
+
return parse_flow(depth)
|
344
|
+
end
|
345
|
+
|
346
|
+
def parse_flow_map(depth)
|
347
|
+
assert current_char() == ?{ #}
|
348
|
+
map = create_mapping() # {}
|
349
|
+
ch = getchar()
|
350
|
+
if ch != ?}
|
351
|
+
linenum = current_linenum()
|
352
|
+
key, value = parse_flow_map_item(depth + 1)
|
353
|
+
#map[key] = value
|
354
|
+
add_to_map(map, key, value, linenum)
|
355
|
+
while (ch = current_char()) == ?,
|
356
|
+
ch = getchar()
|
357
|
+
if ch == ?}
|
358
|
+
#* key=:flow_mapnoitem msg="mapping item required (or last comma is extra)."
|
359
|
+
raise syntax_error(:flow_mapnoitem)
|
360
|
+
end
|
361
|
+
#break if ch == ?}
|
362
|
+
linenum = current_linenum()
|
363
|
+
key, value = parse_flow_map_item(depth + 1)
|
364
|
+
#map[key] = value
|
365
|
+
add_to_map(map, key, value, linenum)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
unless current_char() == ?}
|
369
|
+
#* key=:flow_mapnotclosed msg="flow style mapping requires '}'."
|
370
|
+
raise syntax_error(:flow_mapnotclosed)
|
371
|
+
end
|
372
|
+
getchar() if depth > 0
|
373
|
+
return map
|
374
|
+
end
|
375
|
+
|
376
|
+
def parse_flow_map_item(depth)
|
377
|
+
key = parse_flow(depth)
|
378
|
+
unless (ch = current_char()) == ?:
|
379
|
+
$stderr.puts "*** debug: key=#{key.inspect}"
|
380
|
+
s = ch ? "'#{ch.chr}'" : "EOF"
|
381
|
+
#* key=:flow_nocolon msg="':' expected but got %s."
|
382
|
+
raise syntax_error(:flow_nocolon, [s])
|
383
|
+
end
|
384
|
+
getchar()
|
385
|
+
value = parse_flow(depth)
|
386
|
+
return key, value
|
387
|
+
end
|
388
|
+
|
389
|
+
def parse_flow_scalar(depth)
|
390
|
+
case ch = current_char()
|
391
|
+
when ?", ?' #"
|
392
|
+
endch = ch
|
393
|
+
s = ''
|
394
|
+
while (ch = _getchar()) != nil && ch != endch
|
395
|
+
if ch == ?\\
|
396
|
+
ch = _getchar()
|
397
|
+
if ch.nil?
|
398
|
+
#* key=:flow_str_notclosed msg="%s: string not closed."
|
399
|
+
raise syntax_error(:flow_str_notclosed, endch == ?" ? "'\"'" : '"\'"')
|
379
400
|
end
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
data = parse_child(column)
|
397
|
-
end
|
398
|
-
return data
|
399
|
-
end
|
400
|
-
|
401
|
-
|
402
|
-
def parse_anchor(column, value)
|
403
|
-
assert value =~ /^\&([-\w]+)(( *)(.*))?$/
|
404
|
-
label = $1
|
405
|
-
space = $3
|
406
|
-
value2 = $4
|
407
|
-
if value2 && !value2.empty?
|
408
|
-
#column2 = column + 1 + label.length + space.length
|
409
|
-
#data = parse_value(column2, value2)
|
410
|
-
value_start_column = column + 1 + label.length + space.length
|
411
|
-
data = parse_value(column, value2, value_start_column)
|
412
|
-
else
|
413
|
-
#column2 = column + 1
|
414
|
-
#data = parse_child(column2)
|
415
|
-
data = parse_child(column)
|
416
|
-
end
|
417
|
-
register_anchor(label, data)
|
418
|
-
return data
|
419
|
-
end
|
420
|
-
|
421
|
-
def register_anchor(label, data)
|
422
|
-
if @anchors[label]
|
423
|
-
#* key=:anchor_duplicated msg="anchor '%s' is already used."
|
424
|
-
raise syntax_error(:anchor_duplicated, [label])
|
425
|
-
end
|
426
|
-
@anchors[label] = data
|
427
|
-
end
|
428
|
-
|
429
|
-
def parse_alias(column, value)
|
430
|
-
assert value =~ /^\*([-\w]+)(( *)(.*))?$/
|
431
|
-
label = $1
|
432
|
-
space = $3
|
433
|
-
value2 = $4
|
434
|
-
if value2 && !value2.empty? && value2[0] != ?\#
|
435
|
-
#* key=:alias_extradata msg="alias cannot take any data."
|
436
|
-
raise syntax_error(:alias_extradata)
|
437
|
-
end
|
438
|
-
data = @anchors[label]
|
439
|
-
unless data
|
440
|
-
data = register_alias(label)
|
441
|
-
#raise syntax_error("anchor '#{label}' not found (cannot refer to backward or child anchor).")
|
442
|
-
end
|
443
|
-
getline()
|
444
|
-
return data
|
445
|
-
end
|
446
|
-
|
447
|
-
def register_alias(label)
|
448
|
-
@aliases[label] ||= 0
|
449
|
-
@aliases[label] += 1
|
450
|
-
return Alias.new(label, @linenum)
|
451
|
-
end
|
452
|
-
|
453
|
-
|
454
|
-
def resolve_aliases(data)
|
455
|
-
@resolved ||= {}
|
456
|
-
return if @resolved[data.__id__]
|
457
|
-
@resolved[data.__id__] = data
|
458
|
-
case data
|
459
|
-
when Array
|
460
|
-
seq = data
|
461
|
-
seq.each_with_index do |val, i|
|
462
|
-
if val.is_a?(Alias)
|
463
|
-
anchor = val
|
464
|
-
if @anchors.key?(anchor.label)
|
465
|
-
#seq[i] = @anchors[anchor.label]
|
466
|
-
set_seq_at(seq, i, @anchors[anchor.label], anchor.linenum)
|
467
|
-
else
|
468
|
-
#* key=:anchor_notfound msg="anchor '%s' not found"
|
469
|
-
raise syntax_error(:anchor_notfound, [val.linenum])
|
470
|
-
end
|
471
|
-
elsif val.is_a?(Array) || val.is_a?(Hash)
|
472
|
-
resolve_aliases(val)
|
473
|
-
end
|
401
|
+
if endch == ?"
|
402
|
+
case ch
|
403
|
+
when ?\\ ; s << "\\"
|
404
|
+
when ?" ; s << "\""
|
405
|
+
when ?n ; s << "\n"
|
406
|
+
when ?r ; s << "\r"
|
407
|
+
when ?t ; s << "\t"
|
408
|
+
when ?b ; s << "\b"
|
409
|
+
else ; s << "\\" << ch.chr
|
410
|
+
end
|
411
|
+
elsif endch == ?'
|
412
|
+
case ch
|
413
|
+
when ?\\ ; s << '\\'
|
414
|
+
when ?' ; s << '\''
|
415
|
+
else ; s << '\\' << ch.chr
|
416
|
+
end
|
474
417
|
end
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
end
|
574
|
-
|
575
|
-
|
576
|
-
def parse_mapping(column, value)
|
577
|
-
#assert value =~ /^(:?["']?[-.\w]+["']? *):(( +)(.*))?$/ #'
|
578
|
-
assert value =~ /^((?::?[-.\w]+\*?|'.*?'|".*?"|=|<<) *):(( +)(.*))?$/
|
579
|
-
map = create_mapping() # {}
|
580
|
-
while true
|
581
|
-
#unless value =~ /^(:?["']?[-.\w]+["']? *):(( +)(.*))?$/ #'
|
582
|
-
unless value =~ /^((?::?[-.\w]+\*?|'.*?'|".*?"|=|<<) *):(( +)(.*))?$/
|
583
|
-
#* key=:mapping_noitem msg="mapping item is expected."
|
584
|
-
raise syntax_error(:mapping_noitem)
|
585
|
-
end
|
586
|
-
v = $1.strip
|
587
|
-
key = to_scalar(v)
|
588
|
-
value2 = $4
|
589
|
-
column2 = column + 1
|
590
|
-
linenum = current_linenum()
|
591
|
-
#
|
592
|
-
if !value2 || value2.empty?
|
593
|
-
elem = parse_child(column2)
|
418
|
+
else
|
419
|
+
s << ch.chr
|
420
|
+
end
|
421
|
+
end
|
422
|
+
getchar()
|
423
|
+
scalar = s
|
424
|
+
else
|
425
|
+
s = ch.chr
|
426
|
+
while (ch = _getchar()) != nil && ch != ?: && ch != ?, && ch != ?] && ch != ?}
|
427
|
+
s << ch.chr
|
428
|
+
end
|
429
|
+
scalar = to_scalar(s.strip)
|
430
|
+
end
|
431
|
+
return create_scalar(scalar)
|
432
|
+
end
|
433
|
+
|
434
|
+
|
435
|
+
def parse_tag(column, value)
|
436
|
+
assert value =~ /^!\S+/
|
437
|
+
value =~ /^!(\S+)((\s+)(.*))?$/
|
438
|
+
tag = $1
|
439
|
+
space = $3
|
440
|
+
value2 = $4
|
441
|
+
if value2 && !value2.empty?
|
442
|
+
value_start_column = column + 1 + tag.length + space.length
|
443
|
+
data = parse_value(column, value2, value_start_column)
|
444
|
+
else
|
445
|
+
data = parse_child(column)
|
446
|
+
end
|
447
|
+
return data
|
448
|
+
end
|
449
|
+
|
450
|
+
|
451
|
+
def parse_anchor(column, value)
|
452
|
+
assert value =~ /^\&([-\w]+)(( *)(.*))?$/
|
453
|
+
label = $1
|
454
|
+
space = $3
|
455
|
+
value2 = $4
|
456
|
+
if value2 && !value2.empty?
|
457
|
+
#column2 = column + 1 + label.length + space.length
|
458
|
+
#data = parse_value(column2, value2)
|
459
|
+
value_start_column = column + 1 + label.length + space.length
|
460
|
+
data = parse_value(column, value2, value_start_column)
|
461
|
+
else
|
462
|
+
#column2 = column + 1
|
463
|
+
#data = parse_child(column2)
|
464
|
+
data = parse_child(column)
|
465
|
+
end
|
466
|
+
register_anchor(label, data)
|
467
|
+
return data
|
468
|
+
end
|
469
|
+
|
470
|
+
def register_anchor(label, data)
|
471
|
+
if @anchors[label]
|
472
|
+
#* key=:anchor_duplicated msg="anchor '%s' is already used."
|
473
|
+
raise syntax_error(:anchor_duplicated, [label])
|
474
|
+
end
|
475
|
+
@anchors[label] = data
|
476
|
+
end
|
477
|
+
|
478
|
+
def parse_alias(column, value)
|
479
|
+
assert value =~ /^\*([-\w]+)(( *)(.*))?$/
|
480
|
+
label = $1
|
481
|
+
space = $3
|
482
|
+
value2 = $4
|
483
|
+
if value2 && !value2.empty? && value2[0] != ?\#
|
484
|
+
#* key=:alias_extradata msg="alias cannot take any data."
|
485
|
+
raise syntax_error(:alias_extradata)
|
486
|
+
end
|
487
|
+
data = @anchors[label]
|
488
|
+
unless data
|
489
|
+
data = register_alias(label)
|
490
|
+
#raise syntax_error("anchor '#{label}' not found (cannot refer to backward or child anchor).")
|
491
|
+
end
|
492
|
+
getline()
|
493
|
+
return data
|
494
|
+
end
|
495
|
+
|
496
|
+
def register_alias(label)
|
497
|
+
@aliases[label] ||= 0
|
498
|
+
@aliases[label] += 1
|
499
|
+
return Alias.new(label, @linenum)
|
500
|
+
end
|
501
|
+
|
502
|
+
|
503
|
+
def resolve_aliases(data)
|
504
|
+
@resolved ||= {}
|
505
|
+
return if @resolved[data.__id__]
|
506
|
+
@resolved[data.__id__] = data
|
507
|
+
case data
|
508
|
+
when Array
|
509
|
+
seq = data
|
510
|
+
seq.each_with_index do |val, i|
|
511
|
+
if val.is_a?(Alias)
|
512
|
+
anchor = val
|
513
|
+
if @anchors.key?(anchor.label)
|
514
|
+
#seq[i] = @anchors[anchor.label]
|
515
|
+
set_seq_at(seq, i, @anchors[anchor.label], anchor.linenum)
|
594
516
|
else
|
595
|
-
|
596
|
-
|
517
|
+
#* key=:anchor_notfound msg="anchor '%s' not found"
|
518
|
+
raise syntax_error(:anchor_notfound, [anchor.label], val.linenum)
|
597
519
|
end
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
520
|
+
elsif val.is_a?(Array) || val.is_a?(Hash)
|
521
|
+
resolve_aliases(val)
|
522
|
+
end
|
523
|
+
end
|
524
|
+
when Hash
|
525
|
+
map = data
|
526
|
+
map.each do |key, val|
|
527
|
+
if val.is_a?(Alias)
|
528
|
+
if @anchors.key?(val.label)
|
529
|
+
anchor = val
|
530
|
+
#map[key] = @anchors[anchor.label]
|
531
|
+
set_map_with(map, key, @anchors[anchor.label], anchor.linenum)
|
603
532
|
else
|
604
|
-
|
533
|
+
## :anchor_notfound is already defined on above
|
534
|
+
raise syntax_error(:anchor_notfound, [val.label], val.linenum)
|
605
535
|
end
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
def set_default(map, value, linenum)
|
781
|
-
map.default = value
|
782
|
-
@linenums_table[map.__id__][:'='] = linenum
|
783
|
-
end
|
784
|
-
|
785
|
-
def merge_map(map, collection, linenum)
|
786
|
-
t = @linenums_table[map.__id__]
|
787
|
-
list = collection.is_a?(Array) ? collection : [ collection ]
|
788
|
-
list.each do |m|
|
789
|
-
t2 = @linenums_table[m.__id__]
|
790
|
-
m.each do |key, val|
|
791
|
-
unless map.key?(key)
|
792
|
-
map[key] = val
|
793
|
-
t[key] = t2[key]
|
794
|
-
end
|
536
|
+
elsif val.is_a?(Array) || val.is_a?(Hash)
|
537
|
+
resolve_aliases(val)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
else
|
541
|
+
assert !data.is_a?(Alias)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
|
546
|
+
def parse_block_text(column, value)
|
547
|
+
assert value =~ /^[>|\|]/
|
548
|
+
value =~ /^([>|\|])([-+]?)(\d+)?\s*(.*)$/
|
549
|
+
char = $1
|
550
|
+
indicator = $2
|
551
|
+
sep = char == "|" ? "\n" : " "
|
552
|
+
margin = $3 && !$3.empty? ? $3.to_i : nil
|
553
|
+
#text = $4.empty? ? '' : $4 + sep
|
554
|
+
text = $4
|
555
|
+
s = ''
|
556
|
+
empty = ''
|
557
|
+
min_indent = -1
|
558
|
+
while line = _getline()
|
559
|
+
line =~ /^( *)(.*)/
|
560
|
+
indent = $1.length
|
561
|
+
if $2.empty?
|
562
|
+
empty << "\n"
|
563
|
+
elsif indent < column
|
564
|
+
break
|
565
|
+
else
|
566
|
+
min_indent = indent if min_indent < 0 || min_indent > indent
|
567
|
+
s << empty << line
|
568
|
+
empty = ''
|
569
|
+
end
|
570
|
+
end
|
571
|
+
s << empty if indicator == '+' && char != '>'
|
572
|
+
s[-1] = "" if indicator == '-'
|
573
|
+
min_indent = column + margin - 1 if margin
|
574
|
+
if min_indent > 0
|
575
|
+
sp = ' ' * min_indent
|
576
|
+
s.gsub!(/^#{sp}/, '')
|
577
|
+
end
|
578
|
+
if char == '>'
|
579
|
+
s.gsub!(/([^\n])\n([^\n])/, '\1 \2')
|
580
|
+
s.gsub!(/\n(\n+)/, '\1')
|
581
|
+
s << empty if indicator == '+'
|
582
|
+
end
|
583
|
+
getline() if current_line() =~ /^\s*\#/
|
584
|
+
return create_scalar(text + s)
|
585
|
+
end
|
586
|
+
|
587
|
+
|
588
|
+
def parse_sequence(column, value)
|
589
|
+
assert value =~ /^-(( +)(.*))?$/
|
590
|
+
seq = create_sequence() # []
|
591
|
+
while true
|
592
|
+
unless value =~ /^-(( +)(.*))?$/
|
593
|
+
#* key=:sequence_noitem msg="sequence item is expected."
|
594
|
+
raise syntax_error(:sequence_noitem)
|
595
|
+
end
|
596
|
+
value2 = $3
|
597
|
+
space = $2
|
598
|
+
column2 = column + 1
|
599
|
+
linenum = current_linenum()
|
600
|
+
#
|
601
|
+
if !value2 || value2.empty?
|
602
|
+
elem = parse_child(column2)
|
603
|
+
else
|
604
|
+
value_start_column = column2 + space.length
|
605
|
+
elem = parse_value(column2, value2, value_start_column)
|
606
|
+
end
|
607
|
+
add_to_seq(seq, elem, linenum) #seq << elem
|
608
|
+
#
|
609
|
+
line = current_line()
|
610
|
+
break unless line
|
611
|
+
line =~ /^( *)(.*)/
|
612
|
+
indent = $1.length
|
613
|
+
if indent < column
|
614
|
+
break
|
615
|
+
elsif indent > column
|
616
|
+
#* key=:sequence_badindent msg="illegal indent of sequence."
|
617
|
+
raise syntax_error(:sequence_badindent)
|
618
|
+
end
|
619
|
+
value = $2
|
620
|
+
end
|
621
|
+
return seq
|
622
|
+
end
|
623
|
+
|
624
|
+
|
625
|
+
def parse_mapping(column, value)
|
626
|
+
#assert value =~ /^(:?["']?[-.\w]+["']? *):(( +)(.*))?$/ #'
|
627
|
+
assert value =~ /^((?::?[-.\w]+\*?|'.*?'|".*?"|=|<<) *):(( +)(.*))?$/
|
628
|
+
map = create_mapping() # {}
|
629
|
+
while true
|
630
|
+
#unless value =~ /^(:?["']?[-.\w]+["']? *):(( +)(.*))?$/ #'
|
631
|
+
unless value =~ /^((?::?[-.\w]+\*?|'.*?'|".*?"|=|<<) *):(( +)(.*))?$/
|
632
|
+
#* key=:mapping_noitem msg="mapping item is expected."
|
633
|
+
raise syntax_error(:mapping_noitem)
|
634
|
+
end
|
635
|
+
v = $1.strip
|
636
|
+
key = to_scalar(v)
|
637
|
+
value2 = $4
|
638
|
+
column2 = column + 1
|
639
|
+
linenum = current_linenum()
|
640
|
+
#
|
641
|
+
if !value2 || value2.empty?
|
642
|
+
elem = parse_child(column2)
|
643
|
+
else
|
644
|
+
value_start_column = column2 + $1.length + $3.length
|
645
|
+
elem = parse_value(column2, value2, value_start_column)
|
646
|
+
end
|
647
|
+
case v
|
648
|
+
when '='
|
649
|
+
set_default(map, elem, linenum)
|
650
|
+
when '<<'
|
651
|
+
merge_map(map, elem, linenum)
|
652
|
+
else
|
653
|
+
add_to_map(map, key, elem, linenum) # map[key] = elem
|
654
|
+
end
|
655
|
+
#
|
656
|
+
line = current_line()
|
657
|
+
break unless line
|
658
|
+
line =~ /^( *)(.*)/
|
659
|
+
indent = $1.length
|
660
|
+
if indent < column
|
661
|
+
break
|
662
|
+
elsif indent > column
|
663
|
+
#* key=:mapping_badindent msg="illegal indent of mapping."
|
664
|
+
raise syntax_error(:mapping_badindent)
|
665
|
+
end
|
666
|
+
value = $2
|
667
|
+
end
|
668
|
+
return map
|
669
|
+
end
|
670
|
+
|
671
|
+
|
672
|
+
def parse_scalar(indent, value)
|
673
|
+
data = create_scalar(to_scalar(value))
|
674
|
+
getline()
|
675
|
+
return data
|
676
|
+
end
|
677
|
+
|
678
|
+
|
679
|
+
def to_scalar(str)
|
680
|
+
case str
|
681
|
+
when /^"(.*)"([ \t]*\#.*$)?/ ; return $1
|
682
|
+
when /^'(.*)'([ \t]*\#.*$)?/ ; return $1
|
683
|
+
when /^(.*\S)[ \t]*\#/ ; str = $1
|
684
|
+
end
|
685
|
+
|
686
|
+
case str
|
687
|
+
when /^-?\d+$/ ; return str.to_i # integer
|
688
|
+
when /^-?\d+\.\d+$/ ; return str.to_f # float
|
689
|
+
when "true", "yes", "on" ; return true # true
|
690
|
+
when "false", "no", "off" ; return false # false
|
691
|
+
when "null", "~" ; return nil # nil
|
692
|
+
#when /^"(.*)"$/ ; return $1 # "string"
|
693
|
+
#when /^'(.*)'$/ ; return $1 # 'string'
|
694
|
+
when /^:(\w+)$/ ; return $1.intern # :symbol
|
695
|
+
when /^(\d\d\d\d)-(\d\d)-(\d\d)$/ # date
|
696
|
+
year, month, day = $1.to_i, $2.to_i, $3.to_i
|
697
|
+
return Date.new(year, month, day)
|
698
|
+
when /^(\d\d\d\d)-(\d\d)-(\d\d)(?:[Tt]|[ \t]+)(\d\d?):(\d\d):(\d\d)(\.\d*)?(?:Z|[ \t]*([-+]\d\d?)(?::(\d\d))?)?$/
|
699
|
+
year, mon, mday, hour, min, sec, usec, tzone_h, tzone_m = $1, $2, $3, $4, $5, $6, $7, $8, $9
|
700
|
+
#Time.utc(sec, min, hour, mday, mon, year, wday, yday, isdst, zone)
|
701
|
+
#t = Time.utc(sec, min, hour, mday, mon, year, nil, nil, nil, nil)
|
702
|
+
#Time.utc(year[, mon[, day[, hour[, min[, sec[, usec]]]]]])
|
703
|
+
time = Time.utc(year, mon, day, hour, min, sec, usec)
|
704
|
+
if tzone_h
|
705
|
+
diff_sec = tzone_h.to_i * 60 * 60
|
706
|
+
if tzone_m
|
707
|
+
if diff_sec > 0 ; diff_sec += tzone_m.to_i * 60
|
708
|
+
else ; diff_sec -= tzone_m.to_i * 60
|
795
709
|
end
|
796
|
-
|
797
|
-
|
710
|
+
end
|
711
|
+
p diff_sec
|
712
|
+
time -= diff_sec
|
713
|
+
end
|
714
|
+
return time
|
715
|
+
end
|
716
|
+
return str
|
717
|
+
end
|
718
|
+
|
719
|
+
|
720
|
+
def assert(bool_expr)
|
721
|
+
raise "*** assertion error" unless bool_expr
|
722
|
+
end
|
723
|
+
|
724
|
+
end
|
725
|
+
|
726
|
+
|
727
|
+
|
728
|
+
##
|
729
|
+
## (OBSOLETE) yaml parser
|
730
|
+
##
|
731
|
+
## this class has been obsoleted. use Kwalify::Yaml::Parser instead.
|
732
|
+
##
|
733
|
+
## ex.
|
734
|
+
## # load document with YamlParser
|
735
|
+
## str = ARGF.read()
|
736
|
+
## parser = Kwalify::YamlParser.new(str)
|
737
|
+
## document = parser.parse()
|
738
|
+
##
|
739
|
+
## # validate document
|
740
|
+
## schema = YAML.load(File.read('schema.yaml'))
|
741
|
+
## validator = Kwalify::Validator.new(schema)
|
742
|
+
## errors = validator.validate(document)
|
743
|
+
##
|
744
|
+
## # print validation result
|
745
|
+
## if errors && !errors.empty?
|
746
|
+
## parser.set_errors_linenum(errors)
|
747
|
+
## errors.sort.each do |error|
|
748
|
+
## print "line %d: path %s: %s" % [error.linenum, error.path, error.message]
|
749
|
+
## end
|
750
|
+
## end
|
751
|
+
##
|
752
|
+
class YamlParser < PlainYamlParser
|
753
|
+
|
754
|
+
def initialize(*args)
|
755
|
+
super
|
756
|
+
@linenums_table = {} # object_id -> hash or array
|
757
|
+
end
|
758
|
+
|
759
|
+
def parse()
|
760
|
+
@doc = super()
|
761
|
+
return @doc
|
762
|
+
end
|
763
|
+
|
764
|
+
def path_linenum(path)
|
765
|
+
return 1 if path.empty? || path == '/'
|
766
|
+
elems = path.split('/')
|
767
|
+
elems.shift if path[0] == ?/ # delete empty string on head
|
768
|
+
last_elem = elems.pop
|
769
|
+
c = @doc # collection
|
770
|
+
elems.each do |elem|
|
771
|
+
if c.is_a?(Array)
|
772
|
+
c = c[elem.to_i]
|
773
|
+
elsif c.is_a?(Hash)
|
774
|
+
c = c[elem]
|
775
|
+
else
|
776
|
+
assert false
|
777
|
+
end
|
778
|
+
end
|
779
|
+
linenums = @linenums_table[c.__id__]
|
780
|
+
if c.is_a?(Array)
|
781
|
+
linenum = linenums[last_elem.to_i]
|
782
|
+
elsif c.is_a?(Hash)
|
783
|
+
linenum = linenums[last_elem]
|
784
|
+
end
|
785
|
+
return linenum
|
786
|
+
end
|
787
|
+
|
788
|
+
def set_errors_linenum(errors)
|
789
|
+
errors.each do |error|
|
790
|
+
error.linenum = path_linenum(error.path)
|
791
|
+
end
|
792
|
+
end
|
793
|
+
|
794
|
+
def set_error_linenums(errors)
|
795
|
+
warn "*** Kwalify::YamlParser#set_error_linenums() is obsolete. You should use set_errors_linenum() instead."
|
796
|
+
set_errors_linenum(errors)
|
797
|
+
end
|
798
|
+
|
799
|
+
protected
|
800
|
+
|
801
|
+
def create_sequence(linenum=current_linenum())
|
802
|
+
seq = []
|
803
|
+
@linenums_table[seq.__id__] = []
|
804
|
+
return seq
|
805
|
+
end
|
806
|
+
|
807
|
+
def add_to_seq(seq, value, linenum)
|
808
|
+
seq << value
|
809
|
+
@linenums_table[seq.__id__] << linenum
|
810
|
+
end
|
811
|
+
|
812
|
+
def set_seq_at(seq, i, value, linenum)
|
813
|
+
seq[i] = value
|
814
|
+
@linenums_table[seq.__id__][i] = linenum
|
815
|
+
end
|
816
|
+
|
817
|
+
def create_mapping(linenum=current_linenum())
|
818
|
+
map = {}
|
819
|
+
@linenums_table[map.__id__] = {}
|
820
|
+
return map
|
821
|
+
end
|
822
|
+
|
823
|
+
def add_to_map(map, key, value, linenum)
|
824
|
+
map[key] = value
|
825
|
+
@linenums_table[map.__id__][key] = linenum
|
826
|
+
end
|
827
|
+
|
828
|
+
def set_map_with(map, key, value, linenum)
|
829
|
+
map[key] = value
|
830
|
+
@linenums_table[map.__id__][key] = linenum
|
831
|
+
end
|
832
|
+
|
833
|
+
def set_default(map, value, linenum)
|
834
|
+
map.default = value
|
835
|
+
@linenums_table[map.__id__][:'='] = linenum
|
836
|
+
end
|
837
|
+
|
838
|
+
def merge_map(map, collection, linenum)
|
839
|
+
t = @linenums_table[map.__id__]
|
840
|
+
list = collection.is_a?(Array) ? collection : [ collection ]
|
841
|
+
list.each do |m|
|
842
|
+
t2 = @linenums_table[m.__id__]
|
843
|
+
m.each do |key, val|
|
844
|
+
unless map.key?(key)
|
845
|
+
map[key] = val
|
846
|
+
t[key] = t2[key]
|
847
|
+
end
|
848
|
+
end
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
def create_scalar(value, linenum=current_linenum())
|
853
|
+
data = super(value)
|
854
|
+
#return Scalar.new(data, linenum)
|
855
|
+
return data
|
856
|
+
end
|
857
|
+
|
858
|
+
end
|
859
|
+
|
860
|
+
|
861
|
+
## alias of YamlParser class
|
862
|
+
class Parser < YamlParser
|
863
|
+
def initialize(yaml_str)
|
864
|
+
super(yaml_str)
|
865
|
+
#warn "*** class Kwalify::Parser is obsolete. Please use Kwalify::YamlParser instead."
|
866
|
+
end
|
867
|
+
end
|
798
868
|
|
799
|
-
def create_scalar(value, linenum=current_linenum())
|
800
|
-
data = super(value)
|
801
|
-
#return Scalar.new(data, linenum)
|
802
|
-
return data
|
803
|
-
end
|
804
|
-
|
805
|
-
end
|
806
|
-
|
807
|
-
|
808
|
-
## obsolete
|
809
|
-
class Parser < YamlParser
|
810
|
-
def initialize(yaml_str)
|
811
|
-
super(yaml_str)
|
812
|
-
$stderr.puts "*** class Kwalify::Parser is obsolete. Please use Kwalify::YamlParser instead."
|
813
|
-
end
|
814
|
-
end
|
815
869
|
|
816
870
|
end
|