kdl 0.1.1 → 0.1.2
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/README.md +1 -1
- data/lib/kdl/kdl.yy +6 -6
- data/lib/kdl/tokenizer.rb +121 -65
- data/lib/kdl/version.rb +1 -1
- metadata +2 -3
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfb8d87e0f543090b994347f56085b076d82ce8050f52e49e112a2e723aafc09
|
4
|
+
data.tar.gz: 33443ec26405e8cd235275ab262378d2afc6bfebf4bf186a22580d6c62d8db07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0396991421855a4b2c9b40263a50b255c8ab78b493604254437a6fe2cae9a05d8ac967c6fa19893e8712f210d5e882d6f98338331d56fa2b80e01c24c33b980e'
|
7
|
+
data.tar.gz: 9a3af62eae607011f76a1b154cf4604afd9d6cb38dacdaccc28f735720b8caec9789d6d75766904d395a4969a44b903e890363b7df17533349b8d8c2186a790e
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# KDL
|
2
2
|
|
3
|
-
[](https://github.com/jellymann/kdl-rb
|
3
|
+
[](https://github.com/jellymann/kdl-rb/actions)
|
4
4
|
|
5
5
|
This is a Ruby implementation of the [KDL Document Language](https://kdl.dev)
|
6
6
|
|
data/lib/kdl/kdl.yy
CHANGED
@@ -33,15 +33,15 @@ rule
|
|
33
33
|
node_term: linespaces | semicolon_term
|
34
34
|
semicolon_term: SEMICOLON | SEMICOLON linespaces
|
35
35
|
|
36
|
-
identifier: IDENT { val[0] }
|
37
|
-
| STRING { val[0] }
|
36
|
+
identifier: IDENT { val[0].value }
|
37
|
+
| STRING { val[0].value }
|
38
38
|
|
39
39
|
property: identifier EQUALS value { [val[0], val[2]] }
|
40
40
|
|
41
|
-
value : STRING { KDL::Value::String.new(val[0]) }
|
42
|
-
| RAWSTRING { KDL::Value::String.new(val[0]) }
|
43
|
-
| INTEGER { KDL::Value::Int.new(val[0]) }
|
44
|
-
| FLOAT { KDL::Value::Float.new(val[0]) }
|
41
|
+
value : STRING { KDL::Value::String.new(val[0].value) }
|
42
|
+
| RAWSTRING { KDL::Value::String.new(val[0].value) }
|
43
|
+
| INTEGER { KDL::Value::Int.new(val[0].value) }
|
44
|
+
| FLOAT { KDL::Value::Float.new(val[0].value) }
|
45
45
|
| boolean { KDL::Value::Boolean.new(val[0]) }
|
46
46
|
| NULL { KDL::Value::Null }
|
47
47
|
|
data/lib/kdl/tokenizer.rb
CHANGED
@@ -1,6 +1,32 @@
|
|
1
1
|
module KDL
|
2
2
|
class Tokenizer
|
3
|
-
class Error < StandardError
|
3
|
+
class Error < StandardError
|
4
|
+
def initialize(message, line, column)
|
5
|
+
super("#{message} (#{line}:#{column})")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Token
|
10
|
+
attr_reader :type, :value, :line, :column
|
11
|
+
|
12
|
+
def initialize(type, value, line, column)
|
13
|
+
@type = type
|
14
|
+
@value = value
|
15
|
+
@line = line
|
16
|
+
@column = column
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
return false unless other.is_a?(Token)
|
21
|
+
|
22
|
+
type == other.type && value == other.value && line == other.line && column == other.column
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"#{value.inspect} (#{line}:#{column})"
|
27
|
+
end
|
28
|
+
alias inspect to_s
|
29
|
+
end
|
4
30
|
|
5
31
|
attr_reader :index
|
6
32
|
|
@@ -32,11 +58,15 @@ module KDL
|
|
32
58
|
@buffer = ""
|
33
59
|
@done = false
|
34
60
|
@previous_context = nil
|
61
|
+
@line = 1
|
62
|
+
@column = 1
|
35
63
|
end
|
36
64
|
|
37
65
|
def next_token
|
38
66
|
@context = nil
|
39
67
|
@previous_context = nil
|
68
|
+
@line_at_start = @line
|
69
|
+
@column_at_start = @column
|
40
70
|
loop do
|
41
71
|
c = @str[@index]
|
42
72
|
case @context
|
@@ -45,11 +75,11 @@ module KDL
|
|
45
75
|
when '"'
|
46
76
|
self.context = :string
|
47
77
|
@buffer = ''
|
48
|
-
|
78
|
+
traverse(1)
|
49
79
|
when 'r'
|
50
80
|
if @str[@index + 1] == '"'
|
51
81
|
self.context = :rawstring
|
52
|
-
|
82
|
+
traverse(2)
|
53
83
|
@rawstring_hashes = 0
|
54
84
|
@buffer = ''
|
55
85
|
next
|
@@ -69,20 +99,20 @@ module KDL
|
|
69
99
|
end
|
70
100
|
self.context = :ident
|
71
101
|
@buffer = c
|
72
|
-
|
102
|
+
traverse(1)
|
73
103
|
when /[0-9\-+]/
|
74
104
|
n = @str[@index + 1]
|
75
105
|
if c == '0' && n =~ /[box]/
|
76
|
-
|
106
|
+
traverse(2)
|
77
107
|
@buffer = ''
|
78
108
|
self.context = case n
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
109
|
+
when 'b' then :binary
|
110
|
+
when 'o' then :octal
|
111
|
+
when 'x' then :hexadecimal
|
112
|
+
end
|
83
113
|
else
|
84
114
|
self.context = :decimal
|
85
|
-
|
115
|
+
traverse(1)
|
86
116
|
@buffer = c
|
87
117
|
end
|
88
118
|
when '\\'
|
@@ -90,68 +120,74 @@ module KDL
|
|
90
120
|
la = t.next_token[0]
|
91
121
|
if la == :NEWLINE
|
92
122
|
@index = t.index
|
123
|
+
new_line
|
93
124
|
elsif la == :WS && (lan = t.next_token[0]) == :NEWLINE
|
94
125
|
@index = t.index
|
126
|
+
new_line
|
95
127
|
else
|
96
|
-
|
128
|
+
raise_error "Unexpected '\\'"
|
97
129
|
end
|
98
130
|
when *SYMBOLS.keys
|
99
|
-
|
100
|
-
return [SYMBOLS[c], c]
|
131
|
+
return token(SYMBOLS[c], c).tap { traverse(1) }
|
101
132
|
when "\r"
|
102
133
|
n = @str[@index + 1]
|
103
134
|
if n == "\n"
|
104
|
-
|
105
|
-
|
135
|
+
return token(:NEWLINE, "#{c}#{n}").tap do
|
136
|
+
traverse(2)
|
137
|
+
new_line
|
138
|
+
end
|
106
139
|
else
|
107
|
-
|
108
|
-
|
140
|
+
return token(:NEWLINE, c).tap do
|
141
|
+
traverse(1)
|
142
|
+
new_line
|
143
|
+
end
|
109
144
|
end
|
110
145
|
when *NEWLINES
|
111
|
-
|
112
|
-
|
146
|
+
return token(:NEWLINE, c).tap do
|
147
|
+
traverse(1)
|
148
|
+
new_line
|
149
|
+
end
|
113
150
|
when "/"
|
114
151
|
if @str[@index + 1] == '/'
|
115
152
|
self.context = :single_line_comment
|
116
|
-
|
153
|
+
traverse(2)
|
117
154
|
elsif @str[@index + 1] == '*'
|
118
155
|
self.context = :multi_line_comment
|
119
156
|
@comment_nesting = 1
|
120
|
-
|
157
|
+
traverse(2)
|
121
158
|
elsif @str[@index + 1] == '-'
|
122
|
-
|
123
|
-
return [:SLASHDASH, '/-']
|
159
|
+
return token(:SLASHDASH, '/-').tap { traverse(2) }
|
124
160
|
else
|
125
161
|
self.context = :ident
|
126
162
|
@buffer = c
|
127
|
-
|
163
|
+
traverse(1)
|
128
164
|
end
|
129
165
|
when *WHITEPACE
|
130
166
|
self.context = :whitespace
|
131
167
|
@buffer = c
|
132
|
-
|
168
|
+
traverse(1)
|
133
169
|
when nil
|
134
|
-
return [false,
|
170
|
+
return [false, token(:EOF, :EOF)[1]] if @done
|
135
171
|
@done = true
|
136
|
-
return
|
172
|
+
return token(:EOF, :EOF)
|
137
173
|
when INITIAL_IDENTIFIER_CHARS
|
138
174
|
self.context = :ident
|
139
175
|
@buffer = c
|
140
|
-
|
176
|
+
traverse(1)
|
141
177
|
else
|
142
|
-
|
178
|
+
raise_error "Unexpected character #{c.inspect}"
|
143
179
|
end
|
144
180
|
when :ident
|
145
181
|
case c
|
146
182
|
when IDENTIFIER_CHARS
|
147
|
-
|
183
|
+
traverse(1)
|
148
184
|
@buffer += c
|
149
185
|
else
|
150
186
|
case @buffer
|
151
|
-
when 'true' then return
|
152
|
-
when 'false' then return
|
153
|
-
when 'null' then return
|
154
|
-
else return
|
187
|
+
when 'true' then return token(:TRUE, true)
|
188
|
+
when 'false' then return token(:FALSE, false)
|
189
|
+
when 'null' then return token(:NULL, nil)
|
190
|
+
else return token(:IDENT, @buffer)
|
155
191
|
end
|
156
192
|
end
|
157
193
|
when :string
|
@@ -159,18 +195,17 @@ module KDL
|
|
159
195
|
when '\\'
|
160
196
|
@buffer += c
|
161
197
|
@buffer += @str[@index + 1]
|
162
|
-
|
198
|
+
traverse(2)
|
163
199
|
when '"'
|
164
|
-
@
|
165
|
-
return [:STRING, convert_escapes(@buffer)]
|
200
|
+
return token(:STRING, convert_escapes(@buffer)).tap { traverse(1) }
|
166
201
|
when nil
|
167
|
-
|
202
|
+
raise_error "Unterminated string literal"
|
168
203
|
else
|
169
204
|
@buffer += c
|
170
|
-
|
205
|
+
traverse(1)
|
171
206
|
end
|
172
207
|
when :rawstring
|
173
|
-
|
208
|
+
raise_error "Unterminated rawstring literal" if c.nil?
|
174
209
|
|
175
210
|
if c == '"'
|
176
211
|
h = 0
|
@@ -178,17 +213,16 @@ module KDL
|
|
178
213
|
h += 1
|
179
214
|
end
|
180
215
|
if h == @rawstring_hashes
|
181
|
-
@
|
182
|
-
return [:RAWSTRING, @buffer]
|
216
|
+
return token(:RAWSTRING, @buffer).tap { traverse(1 + h) }
|
183
217
|
end
|
184
218
|
end
|
185
219
|
|
186
220
|
@buffer += c
|
187
|
-
|
221
|
+
traverse(1)
|
188
222
|
when :decimal
|
189
223
|
case c
|
190
224
|
when /[0-9.\-+_eE]/
|
191
|
-
|
225
|
+
traverse(1)
|
192
226
|
@buffer += c
|
193
227
|
else
|
194
228
|
return parse_decimal(@buffer)
|
@@ -196,7 +230,7 @@ module KDL
|
|
196
230
|
when :hexadecimal
|
197
231
|
case c
|
198
232
|
when /[0-9a-fA-F_]/
|
199
|
-
|
233
|
+
traverse(1)
|
200
234
|
@buffer += c
|
201
235
|
else
|
202
236
|
return parse_hexadecimal(@buffer)
|
@@ -204,7 +238,7 @@ module KDL
|
|
204
238
|
when :octal
|
205
239
|
case c
|
206
240
|
when /[0-7_]/
|
207
|
-
|
241
|
+
traverse(1)
|
208
242
|
@buffer += c
|
209
243
|
else
|
210
244
|
return parse_octal(@buffer)
|
@@ -212,7 +246,7 @@ module KDL
|
|
212
246
|
when :binary
|
213
247
|
case c
|
214
248
|
when /[01_]/
|
215
|
-
|
249
|
+
traverse(1)
|
216
250
|
@buffer += c
|
217
251
|
else
|
218
252
|
return parse_binary(@buffer)
|
@@ -220,51 +254,74 @@ module KDL
|
|
220
254
|
when :single_line_comment
|
221
255
|
if NEWLINES.include?(c) || c == "\r"
|
222
256
|
self.context = nil
|
257
|
+
@column_at_start = @column
|
223
258
|
next
|
224
259
|
elsif c.nil?
|
225
260
|
@done = true
|
226
|
-
return
|
261
|
+
return token(:EOF, :EOF)
|
227
262
|
else
|
228
|
-
|
263
|
+
traverse(1)
|
229
264
|
end
|
230
265
|
when :multi_line_comment
|
231
266
|
if c == '/' && @str[@index + 1] == '*'
|
232
267
|
@comment_nesting += 1
|
233
|
-
|
268
|
+
traverse(2)
|
234
269
|
elsif c == '*' && @str[@index + 1] == '/'
|
235
270
|
@comment_nesting -= 1
|
236
|
-
|
271
|
+
traverse(2)
|
237
272
|
if @comment_nesting == 0
|
238
273
|
revert_context
|
239
274
|
end
|
240
275
|
else
|
241
|
-
|
276
|
+
traverse(1)
|
242
277
|
end
|
243
278
|
when :whitespace
|
244
279
|
if WHITEPACE.include?(c)
|
245
|
-
|
280
|
+
traverse(1)
|
246
281
|
@buffer += c
|
247
282
|
elsif c == "\\"
|
248
283
|
t = Tokenizer.new(@str, @index + 1)
|
249
284
|
la = t.next_token[0]
|
250
285
|
if la == :NEWLINE
|
251
286
|
@index = t.index
|
287
|
+
new_line
|
252
288
|
elsif (la == :WS && (lan = t.next_token[0]) == :NEWLINE)
|
253
289
|
@index = t.index
|
290
|
+
new_line
|
254
291
|
else
|
255
|
-
|
292
|
+
raise_error "Unexpected '\\'"
|
256
293
|
end
|
257
294
|
elsif c == "/" && @str[@index + 1] == '*'
|
258
295
|
self.context = :multi_line_comment
|
259
296
|
@comment_nesting = 1
|
260
|
-
|
297
|
+
traverse(2)
|
261
298
|
else
|
262
|
-
return
|
299
|
+
return token(:WS, @buffer)
|
263
300
|
end
|
264
301
|
end
|
265
302
|
end
|
266
303
|
end
|
267
304
|
|
305
|
+
private
|
306
|
+
|
307
|
+
def token(type, value)
|
308
|
+
[type, Token.new(type, value, @line_at_start, @column_at_start)]
|
309
|
+
end
|
310
|
+
|
311
|
+
def traverse(n = 1)
|
312
|
+
@column += n
|
313
|
+
@index += n
|
314
|
+
end
|
315
|
+
|
316
|
+
def raise_error(message)
|
317
|
+
raise Error.new(message, @line, @column)
|
318
|
+
end
|
319
|
+
|
320
|
+
def new_line
|
321
|
+
@column = 1
|
322
|
+
@line += 1
|
323
|
+
end
|
324
|
+
|
268
325
|
def context=(val)
|
269
326
|
@previous_context = @context
|
270
327
|
@context = val
|
@@ -275,23 +332,21 @@ module KDL
|
|
275
332
|
@previous_context = nil
|
276
333
|
end
|
277
334
|
|
278
|
-
private
|
279
|
-
|
280
335
|
def parse_decimal(s)
|
281
|
-
return
|
282
|
-
|
336
|
+
return token(:FLOAT, Float(munch_underscores(s))) if s =~ /[.eE]/
|
337
|
+
token(:INTEGER, Integer(munch_underscores(s), 10))
|
283
338
|
end
|
284
339
|
|
285
340
|
def parse_hexadecimal(s)
|
286
|
-
|
341
|
+
token(:INTEGER, Integer(munch_underscores(s), 16))
|
287
342
|
end
|
288
343
|
|
289
344
|
def parse_octal(s)
|
290
|
-
|
345
|
+
token(:INTEGER, Integer(munch_underscores(s), 8))
|
291
346
|
end
|
292
347
|
|
293
348
|
def parse_binary(s)
|
294
|
-
|
349
|
+
token(:INTEGER, Integer(munch_underscores(s), 2))
|
295
350
|
end
|
296
351
|
|
297
352
|
def munch_underscores(s)
|
@@ -308,12 +363,13 @@ module KDL
|
|
308
363
|
when '\"' then "\""
|
309
364
|
when '\b' then "\b"
|
310
365
|
when '\f' then "\f"
|
311
|
-
|
366
|
+
when '\/' then "/"
|
367
|
+
else raise_error "Unexpected escape #{m.inspect}"
|
312
368
|
end
|
313
369
|
end.gsub(/\\u\{[0-9a-fA-F]{0,6}\}/) do |m|
|
314
370
|
i = Integer(m[3..-2], 16)
|
315
371
|
if i < 0 || i > 0x10FFFF
|
316
|
-
|
372
|
+
raise_error "Invalid code point #{u}"
|
317
373
|
end
|
318
374
|
i.chr(Encoding::UTF_8)
|
319
375
|
end
|
data/lib/kdl/version.rb
CHANGED
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: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: racc
|
@@ -33,7 +33,6 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- ".github/workflows/ruby.yml"
|
35
35
|
- ".gitignore"
|
36
|
-
- ".travis.yml"
|
37
36
|
- CODE_OF_CONDUCT.md
|
38
37
|
- Gemfile
|
39
38
|
- LICENSE.txt
|