kdl 1.0.5 → 2.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -1
- data/.gitignore +1 -0
- data/.gitmodules +4 -0
- data/Gemfile +6 -1
- data/README.md +51 -7
- data/Rakefile +6 -1
- data/bin/kdl +1 -1
- data/kdl.gemspec +2 -2
- data/lib/kdl/document.rb +58 -2
- data/lib/kdl/kdl.tab.rb +303 -228
- data/lib/kdl/kdl.yy +57 -49
- data/lib/kdl/node.rb +113 -12
- data/lib/kdl/parser_common.rb +26 -0
- data/lib/kdl/string_dumper.rb +30 -33
- data/lib/kdl/tokenizer.rb +350 -113
- data/lib/kdl/types/base64.rb +1 -1
- data/lib/kdl/types/country/iso3166_countries.rb +1 -1
- data/lib/kdl/types/country/iso3166_subdivisions.rb +1 -1
- data/lib/kdl/types/country.rb +2 -2
- data/lib/kdl/types/currency/iso4217_currencies.rb +1 -1
- data/lib/kdl/types/currency.rb +1 -1
- data/lib/kdl/types/date_time.rb +3 -3
- data/lib/kdl/types/decimal.rb +1 -1
- data/lib/kdl/types/duration/iso8601_parser.rb +1 -1
- data/lib/kdl/types/duration.rb +1 -1
- data/lib/kdl/types/email/parser.rb +2 -2
- data/lib/kdl/types/email.rb +1 -1
- data/lib/kdl/types/hostname/validator.rb +1 -1
- data/lib/kdl/types/hostname.rb +1 -1
- data/lib/kdl/types/ip.rb +1 -1
- data/lib/kdl/types/irl/parser.rb +1 -1
- data/lib/kdl/types/irl.rb +1 -1
- data/lib/kdl/types/regex.rb +1 -1
- data/lib/kdl/types/url.rb +1 -1
- data/lib/kdl/types/url_template.rb +1 -1
- data/lib/kdl/types/uuid.rb +1 -1
- data/lib/kdl/v1/document.rb +17 -0
- data/lib/kdl/v1/kdl.tab.rb +594 -0
- data/lib/kdl/v1/kdl.yy +89 -0
- data/lib/kdl/v1/node.rb +30 -0
- data/lib/kdl/v1/string_dumper.rb +28 -0
- data/lib/kdl/v1/tokenizer.rb +296 -0
- data/lib/kdl/v1/value.rb +89 -0
- data/lib/kdl/v1.rb +11 -0
- data/lib/kdl/value.rb +81 -12
- data/lib/kdl/version.rb +1 -1
- data/lib/kdl.rb +40 -1
- metadata +13 -4
@@ -0,0 +1,28 @@
|
|
1
|
+
module KDL
|
2
|
+
module V1
|
3
|
+
module StringDumper
|
4
|
+
include ::KDL::StringDumper
|
5
|
+
|
6
|
+
def call(string)
|
7
|
+
%("#{string.each_char.map { |char| escape(char) }.join}")
|
8
|
+
end
|
9
|
+
|
10
|
+
def stringify_identifier(ident)
|
11
|
+
if bare_identifier?(ident)
|
12
|
+
ident
|
13
|
+
else
|
14
|
+
call(ident)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def bare_identifier?(name)
|
21
|
+
escape_chars = '\\\/(){}<>;\[\]=,"'
|
22
|
+
name =~ /^([^0-9\-+\s#{escape_chars}][^\s#{escape_chars}]*|[\-+](?!true|false|null)[^0-9\s#{escape_chars}][^\s#{escape_chars}]*)$/
|
23
|
+
end
|
24
|
+
|
25
|
+
extend self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
module KDL
|
2
|
+
module V1
|
3
|
+
class Tokenizer < KDL::Tokenizer
|
4
|
+
NON_IDENTIFIER_CHARS = Regexp.escape "#{SYMBOLS.keys.join}()/\\<>[]\",#{WHITESPACE.join}#{OTHER_NON_IDENTIFIER_CHARS.join}"
|
5
|
+
IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}]/
|
6
|
+
INITIAL_IDENTIFIER_CHARS = /[^#{NON_IDENTIFIER_CHARS}0-9]/
|
7
|
+
|
8
|
+
def next_token
|
9
|
+
@context = nil
|
10
|
+
@previous_context = nil
|
11
|
+
@line_at_start = @line
|
12
|
+
@column_at_start = @column
|
13
|
+
loop do
|
14
|
+
c = self[@index]
|
15
|
+
case @context
|
16
|
+
when nil
|
17
|
+
case c
|
18
|
+
when '"'
|
19
|
+
self.context = :string
|
20
|
+
@buffer = ''
|
21
|
+
traverse(1)
|
22
|
+
when 'r'
|
23
|
+
if @str[@index + 1] == '"'
|
24
|
+
self.context = :rawstring
|
25
|
+
traverse(2)
|
26
|
+
@rawstring_hashes = 0
|
27
|
+
@buffer = ''
|
28
|
+
next
|
29
|
+
elsif @str[@index + 1] == '#'
|
30
|
+
i = @index + 1
|
31
|
+
@rawstring_hashes = 0
|
32
|
+
while @str[i] == '#'
|
33
|
+
@rawstring_hashes += 1
|
34
|
+
i += 1
|
35
|
+
end
|
36
|
+
if @str[i] == '"'
|
37
|
+
self.context = :rawstring
|
38
|
+
@index = i + 1
|
39
|
+
@buffer = ''
|
40
|
+
next
|
41
|
+
end
|
42
|
+
end
|
43
|
+
self.context = :ident
|
44
|
+
@buffer = c
|
45
|
+
traverse(1)
|
46
|
+
when '-'
|
47
|
+
n = self[@index + 1]
|
48
|
+
if n =~ /[0-9]/
|
49
|
+
n2 = self[@index + 2]
|
50
|
+
if n == '0' && n2 =~ /[box]/
|
51
|
+
self.context = integer_context(n2)
|
52
|
+
traverse(3)
|
53
|
+
else
|
54
|
+
self.context = :decimal
|
55
|
+
traverse(1)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
self.context = :ident
|
59
|
+
traverse(1)
|
60
|
+
end
|
61
|
+
@buffer = c
|
62
|
+
when /[0-9+]/
|
63
|
+
n = self[@index + 1]
|
64
|
+
if c == '0' && n =~ /[box]/
|
65
|
+
traverse(2)
|
66
|
+
@buffer = ''
|
67
|
+
self.context = integer_context(n)
|
68
|
+
else
|
69
|
+
self.context = :decimal
|
70
|
+
@buffer = c
|
71
|
+
traverse(1)
|
72
|
+
end
|
73
|
+
when '\\'
|
74
|
+
t = Tokenizer.new(@str, @index + 1)
|
75
|
+
la = t.next_token
|
76
|
+
if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF)
|
77
|
+
traverse_to(t.index)
|
78
|
+
@buffer = "#{c}#{la[1].value}"
|
79
|
+
@buffer += "\n" if lan == :NEWLINE
|
80
|
+
self.context = :whitespace
|
81
|
+
else
|
82
|
+
raise_error "Unexpected '\\' (#{la[0]})"
|
83
|
+
end
|
84
|
+
when *SYMBOLS.keys
|
85
|
+
return token(SYMBOLS[c], c).tap { traverse(1) }
|
86
|
+
when *NEWLINES, "\r"
|
87
|
+
nl = expect_newline
|
88
|
+
return token(:NEWLINE, nl).tap do
|
89
|
+
traverse(nl.length)
|
90
|
+
end
|
91
|
+
when "/"
|
92
|
+
if self[@index + 1] == '/'
|
93
|
+
self.context = :single_line_comment
|
94
|
+
traverse(2)
|
95
|
+
elsif self[@index + 1] == '*'
|
96
|
+
self.context = :multi_line_comment
|
97
|
+
@comment_nesting = 1
|
98
|
+
traverse(2)
|
99
|
+
elsif self[@index + 1] == '-'
|
100
|
+
return token(:SLASHDASH, '/-').tap { traverse(2) }
|
101
|
+
else
|
102
|
+
self.context = :ident
|
103
|
+
@buffer = c
|
104
|
+
traverse(1)
|
105
|
+
end
|
106
|
+
when *WHITESPACE
|
107
|
+
self.context = :whitespace
|
108
|
+
@buffer = c
|
109
|
+
traverse(1)
|
110
|
+
when nil
|
111
|
+
return [false, token(:EOF, :EOF)[1]] if @done
|
112
|
+
|
113
|
+
@done = true
|
114
|
+
return token(:EOF, :EOF)
|
115
|
+
when INITIAL_IDENTIFIER_CHARS
|
116
|
+
self.context = :ident
|
117
|
+
@buffer = c
|
118
|
+
traverse(1)
|
119
|
+
when '('
|
120
|
+
@type_context = true
|
121
|
+
return token(:LPAREN, c).tap { traverse(1) }
|
122
|
+
when ')'
|
123
|
+
@type_context = false
|
124
|
+
return token(:RPAREN, c).tap { traverse(1) }
|
125
|
+
else
|
126
|
+
raise_error "Unexpected character #{c.inspect}"
|
127
|
+
end
|
128
|
+
when :ident
|
129
|
+
case c
|
130
|
+
when IDENTIFIER_CHARS
|
131
|
+
traverse(1)
|
132
|
+
@buffer += c
|
133
|
+
else
|
134
|
+
case @buffer
|
135
|
+
when 'true' then return token(:TRUE, true)
|
136
|
+
when 'false' then return token(:FALSE, false)
|
137
|
+
when 'null' then return token(:NULL, nil)
|
138
|
+
else return token(:IDENT, @buffer)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
when :string
|
142
|
+
case c
|
143
|
+
when '\\'
|
144
|
+
c2 = self[@index + 1]
|
145
|
+
if c2.match?(NEWLINES_PATTERN)
|
146
|
+
i = 2
|
147
|
+
while self[@index + i].match?(NEWLINES_PATTERN)
|
148
|
+
i+=1
|
149
|
+
end
|
150
|
+
traverse(i)
|
151
|
+
else
|
152
|
+
@buffer += c
|
153
|
+
@buffer += c2
|
154
|
+
traverse(2)
|
155
|
+
end
|
156
|
+
when '"'
|
157
|
+
return token(:STRING, unescape(@buffer)).tap { traverse(1) }
|
158
|
+
when nil
|
159
|
+
raise_error "Unterminated string literal"
|
160
|
+
else
|
161
|
+
@buffer += c
|
162
|
+
traverse(1)
|
163
|
+
end
|
164
|
+
when :rawstring
|
165
|
+
raise_error "Unterminated rawstring literal" if c.nil?
|
166
|
+
|
167
|
+
if c == '"'
|
168
|
+
h = 0
|
169
|
+
h += 1 while self[@index + 1 + h] == '#' && h < @rawstring_hashes
|
170
|
+
if h == @rawstring_hashes
|
171
|
+
return token(:RAWSTRING, @buffer).tap { traverse(1 + h) }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
@buffer += c
|
176
|
+
traverse(1)
|
177
|
+
when :decimal
|
178
|
+
case c
|
179
|
+
when /[0-9.\-+_eE]/
|
180
|
+
traverse(1)
|
181
|
+
@buffer += c
|
182
|
+
else
|
183
|
+
return parse_decimal(@buffer)
|
184
|
+
end
|
185
|
+
when :hexadecimal
|
186
|
+
case c
|
187
|
+
when /[0-9a-fA-F_]/
|
188
|
+
traverse(1)
|
189
|
+
@buffer += c
|
190
|
+
else
|
191
|
+
return parse_hexadecimal(@buffer)
|
192
|
+
end
|
193
|
+
when :octal
|
194
|
+
case c
|
195
|
+
when /[0-7_]/
|
196
|
+
traverse(1)
|
197
|
+
@buffer += c
|
198
|
+
else
|
199
|
+
return parse_octal(@buffer)
|
200
|
+
end
|
201
|
+
when :binary
|
202
|
+
case c
|
203
|
+
when /[01_]/
|
204
|
+
traverse(1)
|
205
|
+
@buffer += c
|
206
|
+
else
|
207
|
+
return parse_binary(@buffer)
|
208
|
+
end
|
209
|
+
when :single_line_comment
|
210
|
+
case c
|
211
|
+
when *NEWLINES, "\r"
|
212
|
+
self.context = nil
|
213
|
+
@column_at_start = @column
|
214
|
+
next
|
215
|
+
when nil
|
216
|
+
@done = true
|
217
|
+
return token(:EOF, :EOF)
|
218
|
+
else
|
219
|
+
traverse(1)
|
220
|
+
end
|
221
|
+
when :multi_line_comment
|
222
|
+
if c == '/' && self[@index + 1] == '*'
|
223
|
+
@comment_nesting += 1
|
224
|
+
traverse(2)
|
225
|
+
elsif c == '*' && self[@index + 1] == '/'
|
226
|
+
@comment_nesting -= 1
|
227
|
+
traverse(2)
|
228
|
+
if @comment_nesting == 0
|
229
|
+
revert_context
|
230
|
+
end
|
231
|
+
else
|
232
|
+
traverse(1)
|
233
|
+
end
|
234
|
+
when :whitespace
|
235
|
+
if WHITESPACE.include?(c)
|
236
|
+
traverse(1)
|
237
|
+
@buffer += c
|
238
|
+
elsif c == "/" && self[@index + 1] == '*'
|
239
|
+
self.context = :multi_line_comment
|
240
|
+
@comment_nesting = 1
|
241
|
+
traverse(2)
|
242
|
+
elsif c == "\\"
|
243
|
+
t = Tokenizer.new(@str, @index + 1)
|
244
|
+
la = t.next_token
|
245
|
+
if la[0] == :NEWLINE || la[0] == :EOF || (la[0] == :WS && (lan = t.next_token[0]) == :NEWLINE || lan == :EOF)
|
246
|
+
traverse_to(t.index)
|
247
|
+
@buffer += "#{c}#{la[1].value}"
|
248
|
+
@buffer += "\n" if lan == :NEWLINE
|
249
|
+
else
|
250
|
+
raise_error "Unexpected '\\' (#{la[0]})"
|
251
|
+
end
|
252
|
+
else
|
253
|
+
return token(:WS, @buffer)
|
254
|
+
end
|
255
|
+
else
|
256
|
+
# :nocov:
|
257
|
+
raise_error "Unknown context `#{@context}'"
|
258
|
+
# :nocov:
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
private
|
264
|
+
|
265
|
+
def allowed_in_type?(val)
|
266
|
+
%i[ident string rawstring].include?(val)
|
267
|
+
end
|
268
|
+
|
269
|
+
def allowed_after_type?(val)
|
270
|
+
!%i[single_line_comment multi_line_comment].include?(val)
|
271
|
+
end
|
272
|
+
|
273
|
+
def unescape(string)
|
274
|
+
string.gsub(/\\[^u]/) do |m|
|
275
|
+
case m
|
276
|
+
when '\n' then "\n"
|
277
|
+
when '\r' then "\r"
|
278
|
+
when '\t' then "\t"
|
279
|
+
when '\\\\' then "\\"
|
280
|
+
when '\"' then "\""
|
281
|
+
when '\b' then "\b"
|
282
|
+
when '\f' then "\f"
|
283
|
+
when '\/' then "/"
|
284
|
+
else raise_error "Unexpected escape #{m.inspect}"
|
285
|
+
end
|
286
|
+
end.gsub(/\\u\{[0-9a-fA-F]{0,6}\}/) do |m|
|
287
|
+
i = Integer(m[3..-2], 16)
|
288
|
+
if i < 0 || i > 0x10FFFF
|
289
|
+
raise_error "Invalid code point #{u}"
|
290
|
+
end
|
291
|
+
i.chr(Encoding::UTF_8)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
data/lib/kdl/v1/value.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
module KDL
|
2
|
+
module V1
|
3
|
+
class Value < ::KDL::Value
|
4
|
+
module Methods
|
5
|
+
def to_s
|
6
|
+
return stringify_value unless type
|
7
|
+
|
8
|
+
"(#{StringDumper.stringify_identifier type})#{stringify_value}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
return self == other.value if other.is_a?(self.class.superclass)
|
13
|
+
|
14
|
+
value == other
|
15
|
+
end
|
16
|
+
|
17
|
+
def version
|
18
|
+
1
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_v1
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_v2
|
26
|
+
self.class.superclass.new(value, format:, type:)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
include Methods
|
31
|
+
|
32
|
+
class Int < ::KDL::Value::Int
|
33
|
+
include Methods
|
34
|
+
end
|
35
|
+
|
36
|
+
class Float < ::KDL::Value::Float
|
37
|
+
include Methods
|
38
|
+
|
39
|
+
def stringify_value
|
40
|
+
if value.nan? || value.infinite?
|
41
|
+
warn "[WARNING] Attempting to serialize non-finite Float using KDL v1"
|
42
|
+
return Null.stringify_value
|
43
|
+
end
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Boolean < ::KDL::Value::Boolean
|
49
|
+
include Methods
|
50
|
+
|
51
|
+
def stringify_value
|
52
|
+
value.to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class String < ::KDL::Value::String
|
57
|
+
include Methods
|
58
|
+
|
59
|
+
def stringify_value
|
60
|
+
StringDumper.call(value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class NullImpl < ::KDL::Value::NullImpl
|
65
|
+
include Methods
|
66
|
+
|
67
|
+
def stringify_value
|
68
|
+
"null"
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_v2
|
72
|
+
type ? ::KDL::Value::NullImpl.new(type:) : ::KDL::Value::Null
|
73
|
+
end
|
74
|
+
end
|
75
|
+
Null = NullImpl.new
|
76
|
+
|
77
|
+
def self.from(value)
|
78
|
+
case value
|
79
|
+
when ::String then String.new(value)
|
80
|
+
when Integer then Int.new(value)
|
81
|
+
when ::Float then Float.new(value)
|
82
|
+
when TrueClass, FalseClass then Boolean.new(value)
|
83
|
+
when NilClass then Null
|
84
|
+
else raise Error("Unsupported value type: #{value.class}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/kdl/v1.rb
ADDED
data/lib/kdl/value.rb
CHANGED
@@ -15,18 +15,30 @@ module KDL
|
|
15
15
|
result = parser.call(self, type)
|
16
16
|
return self.as_type(type) if result.nil?
|
17
17
|
|
18
|
-
unless result.is_a?(::KDL::Value)
|
19
|
-
raise ArgumentError, "expected parser to return an instance of ::KDL::Value, got `#{result.class}'"
|
18
|
+
unless result.is_a?(::KDL::Value::Custom)
|
19
|
+
raise ArgumentError, "expected parser to return an instance of ::KDL::Value::Custom, got `#{result.class}'"
|
20
20
|
end
|
21
21
|
|
22
22
|
result
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
def ==(other)
|
27
|
+
return self == other.value if other.is_a?(self.class)
|
28
|
+
|
29
|
+
value == other
|
30
|
+
end
|
31
|
+
|
26
32
|
def to_s
|
27
33
|
return stringify_value unless type
|
28
34
|
|
29
|
-
"(#{StringDumper.
|
35
|
+
"(#{StringDumper.call type})#{stringify_value}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect
|
39
|
+
return value.inspect unless type
|
40
|
+
|
41
|
+
"(#{type.inspect})#{value.inspect}"
|
30
42
|
end
|
31
43
|
|
32
44
|
def stringify_value
|
@@ -35,18 +47,40 @@ module KDL
|
|
35
47
|
value.to_s
|
36
48
|
end
|
37
49
|
|
50
|
+
def version
|
51
|
+
2
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_v2
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(name, *args, **kwargs, &block)
|
59
|
+
value.public_send(name, *args, **kwargs, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def respond_to_missing?(name, include_all = false)
|
63
|
+
value.respond_to?(name, include_all)
|
64
|
+
end
|
65
|
+
|
38
66
|
class Int < Value
|
39
|
-
def
|
40
|
-
|
67
|
+
def to_v1
|
68
|
+
V1::Value::Int.new(value, format:, type:)
|
41
69
|
end
|
42
70
|
end
|
43
71
|
|
44
72
|
class Float < Value
|
45
73
|
def ==(other)
|
46
|
-
other.is_a?(Float)
|
74
|
+
return self == other.value if other.is_a?(Float)
|
75
|
+
return other.nan? if value.nan?
|
76
|
+
|
77
|
+
value == other
|
47
78
|
end
|
48
79
|
|
49
80
|
def stringify_value
|
81
|
+
return '#nan' if value.nan?
|
82
|
+
return '#inf' if value == ::Float::INFINITY
|
83
|
+
return '#-inf' if value == -::Float::INFINITY
|
50
84
|
return super.upcase unless value.is_a?(BigDecimal)
|
51
85
|
|
52
86
|
sign, digits, _, exponent = value.split
|
@@ -55,11 +89,22 @@ module KDL
|
|
55
89
|
s += "E#{exponent.negative? ? '' : '+'}#{exponent - 1}"
|
56
90
|
s
|
57
91
|
end
|
92
|
+
|
93
|
+
def to_v1
|
94
|
+
if value.nan? || value.infinite?
|
95
|
+
warn "[WARNING] Converting non-finite Float to KDL v1"
|
96
|
+
end
|
97
|
+
V1::Value::Float.new(value, format:, type:)
|
98
|
+
end
|
58
99
|
end
|
59
100
|
|
60
101
|
class Boolean < Value
|
61
|
-
def
|
62
|
-
|
102
|
+
def stringify_value
|
103
|
+
"##{value}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_v1
|
107
|
+
V1::Value::Boolean.new(value, format:, type:)
|
63
108
|
end
|
64
109
|
end
|
65
110
|
|
@@ -68,8 +113,8 @@ module KDL
|
|
68
113
|
StringDumper.call(value)
|
69
114
|
end
|
70
115
|
|
71
|
-
def
|
72
|
-
|
116
|
+
def to_v1
|
117
|
+
V1::Value::String.new(value, format:, type:)
|
73
118
|
end
|
74
119
|
end
|
75
120
|
|
@@ -79,15 +124,39 @@ module KDL
|
|
79
124
|
end
|
80
125
|
|
81
126
|
def stringify_value
|
82
|
-
"null"
|
127
|
+
"#null"
|
83
128
|
end
|
84
129
|
|
85
130
|
def ==(other)
|
86
|
-
other.is_a?(NullImpl)
|
131
|
+
other.is_a?(NullImpl) || other.nil?
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_v1
|
135
|
+
type ? V1::Value::NullImpl.new(type:) : V1::Value::Null
|
87
136
|
end
|
88
137
|
end
|
89
138
|
Null = NullImpl.new
|
90
139
|
|
140
|
+
class Custom < Value
|
141
|
+
attr_reader :oriinal_value
|
142
|
+
|
143
|
+
def self.call(value, type)
|
144
|
+
new(value, type:)
|
145
|
+
end
|
146
|
+
|
147
|
+
def version
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_v1
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_v2
|
156
|
+
self
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
91
160
|
def self.from(value)
|
92
161
|
case value
|
93
162
|
when ::String then String.new(value)
|
data/lib/kdl/version.rb
CHANGED
data/lib/kdl.rb
CHANGED
@@ -5,10 +5,49 @@ require "kdl/value"
|
|
5
5
|
require "kdl/node"
|
6
6
|
require "kdl/string_dumper"
|
7
7
|
require "kdl/types"
|
8
|
+
require "kdl/parser_common"
|
8
9
|
require "kdl/kdl.tab"
|
10
|
+
require "kdl/v1"
|
9
11
|
|
10
12
|
module KDL
|
13
|
+
class << self
|
14
|
+
attr_accessor :default_version
|
15
|
+
attr_accessor :default_output_version
|
16
|
+
end
|
17
|
+
|
11
18
|
def self.parse_document(input, options = {})
|
12
|
-
|
19
|
+
warn "[DEPRECATION] `KDL.parse_document' is deprecated. Please use `KDL.parse' instead."
|
20
|
+
parse(input, **options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.parse(input, version: default_version, output_version: default_output_version, **options)
|
24
|
+
case version
|
25
|
+
when 2
|
26
|
+
Parser.new(output_module: output_module(output_version || 2), **options).parse(input)
|
27
|
+
when 1
|
28
|
+
V1::Parser.new.parse(input, output_module: output_module(output_version || 1), **options)
|
29
|
+
else
|
30
|
+
auto_parse(input, output_version:, **options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.load_file(filespec, **options)
|
35
|
+
parse(File.read(filespec, encoding: Encoding::UTF_8), **options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.auto_parse(input, output_version: default_output_version, **options)
|
39
|
+
parse(input, version: 2, output_version: output_version || 2, **options)
|
40
|
+
rescue => e
|
41
|
+
parse(input, version: 1, output_version: output_version || 1, **options) rescue raise e
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.output_module(version)
|
45
|
+
case version
|
46
|
+
when 1 then KDL::V1
|
47
|
+
when 2 then KDL
|
48
|
+
else
|
49
|
+
warn "Unknown output_version `#{version}', defaulting to v2"
|
50
|
+
KDL
|
51
|
+
end
|
13
52
|
end
|
14
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kdl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danielle Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: racc
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- lib/kdl/kdl.tab.rb
|
93
93
|
- lib/kdl/kdl.yy
|
94
94
|
- lib/kdl/node.rb
|
95
|
+
- lib/kdl/parser_common.rb
|
95
96
|
- lib/kdl/string_dumper.rb
|
96
97
|
- lib/kdl/tokenizer.rb
|
97
98
|
- lib/kdl/types.rb
|
@@ -116,6 +117,14 @@ files:
|
|
116
117
|
- lib/kdl/types/url.rb
|
117
118
|
- lib/kdl/types/url_template.rb
|
118
119
|
- lib/kdl/types/uuid.rb
|
120
|
+
- lib/kdl/v1.rb
|
121
|
+
- lib/kdl/v1/document.rb
|
122
|
+
- lib/kdl/v1/kdl.tab.rb
|
123
|
+
- lib/kdl/v1/kdl.yy
|
124
|
+
- lib/kdl/v1/node.rb
|
125
|
+
- lib/kdl/v1/string_dumper.rb
|
126
|
+
- lib/kdl/v1/tokenizer.rb
|
127
|
+
- lib/kdl/v1/value.rb
|
119
128
|
- lib/kdl/value.rb
|
120
129
|
- lib/kdl/version.rb
|
121
130
|
homepage: https://kdl.dev
|
@@ -133,14 +142,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
142
|
requirements:
|
134
143
|
- - ">="
|
135
144
|
- !ruby/object:Gem::Version
|
136
|
-
version:
|
145
|
+
version: 3.1.0
|
137
146
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
147
|
requirements:
|
139
148
|
- - ">="
|
140
149
|
- !ruby/object:Gem::Version
|
141
150
|
version: '0'
|
142
151
|
requirements: []
|
143
|
-
rubygems_version: 3.5.
|
152
|
+
rubygems_version: 3.5.22
|
144
153
|
signing_key:
|
145
154
|
specification_version: 4
|
146
155
|
summary: KDL Document Language
|