kdl 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27d22aaf844ad47e14321925d2ef8d3346b0960fe5d284ca191fb25231571d2c
4
- data.tar.gz: c22e4025f6ed2f42654e899123f46a46f195ce7b14d002b2c240d6b24222871a
3
+ metadata.gz: dfb8d87e0f543090b994347f56085b076d82ce8050f52e49e112a2e723aafc09
4
+ data.tar.gz: 33443ec26405e8cd235275ab262378d2afc6bfebf4bf186a22580d6c62d8db07
5
5
  SHA512:
6
- metadata.gz: a810a2fbd5c1d3336e89bff3a59af3e93aa9d1c1fc80c37e5f02e93d9b96bec0a6cf6ad448b8c6d624d380dee65a5c99290c4352edb3acca5b673a4728c8aa45
7
- data.tar.gz: b1af0ff7997fac32d3d4640866b788cf884cfac8ca342e6de02296c59f5ef58b4d230d0a67be17cc687c98dd6ad15f0f21b729c2dbcd27f3ffadf2d5169f70ee
6
+ metadata.gz: '0396991421855a4b2c9b40263a50b255c8ab78b493604254437a6fe2cae9a05d8ac967c6fa19893e8712f210d5e882d6f98338331d56fa2b80e01c24c33b980e'
7
+ data.tar.gz: 9a3af62eae607011f76a1b154cf4604afd9d6cb38dacdaccc28f735720b8caec9789d6d75766904d395a4969a44b903e890363b7df17533349b8d8c2186a790e
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # KDL
2
2
 
3
- [![Actions Status](https://github.com/jellymann/kdl-rb/workflows/Ruby/badge.svg)](https://github.com/jellymann/kdl-rb\/actions)
3
+ [![Actions Status](https://github.com/jellymann/kdl-rb/workflows/Ruby/badge.svg)](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
 
@@ -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
 
@@ -1,6 +1,32 @@
1
1
  module KDL
2
2
  class Tokenizer
3
- class Error < StandardError; end
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
- @index += 1
78
+ traverse(1)
49
79
  when 'r'
50
80
  if @str[@index + 1] == '"'
51
81
  self.context = :rawstring
52
- @index += 2
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
- @index += 1
102
+ traverse(1)
73
103
  when /[0-9\-+]/
74
104
  n = @str[@index + 1]
75
105
  if c == '0' && n =~ /[box]/
76
- @index += 2
106
+ traverse(2)
77
107
  @buffer = ''
78
108
  self.context = case n
79
- when 'b' then :binary
80
- when 'o' then :octal
81
- when 'x' then :hexadecimal
82
- end
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
- @index += 1
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
- raise Error, "Unexpected '\\'"
128
+ raise_error "Unexpected '\\'"
97
129
  end
98
130
  when *SYMBOLS.keys
99
- @index += 1
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
- @index += 2
105
- return [:NEWLINE, "#{c}#{n}"]
135
+ return token(:NEWLINE, "#{c}#{n}").tap do
136
+ traverse(2)
137
+ new_line
138
+ end
106
139
  else
107
- @index += 1
108
- return [:NEWLINE, c]
140
+ return token(:NEWLINE, c).tap do
141
+ traverse(1)
142
+ new_line
143
+ end
109
144
  end
110
145
  when *NEWLINES
111
- @index += 1
112
- return [:NEWLINE, c]
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
- @index += 2
153
+ traverse(2)
117
154
  elsif @str[@index + 1] == '*'
118
155
  self.context = :multi_line_comment
119
156
  @comment_nesting = 1
120
- @index += 2
157
+ traverse(2)
121
158
  elsif @str[@index + 1] == '-'
122
- @index += 2
123
- return [:SLASHDASH, '/-']
159
+ return token(:SLASHDASH, '/-').tap { traverse(2) }
124
160
  else
125
161
  self.context = :ident
126
162
  @buffer = c
127
- @index += 1
163
+ traverse(1)
128
164
  end
129
165
  when *WHITEPACE
130
166
  self.context = :whitespace
131
167
  @buffer = c
132
- @index += 1
168
+ traverse(1)
133
169
  when nil
134
- return [false, false] if @done
170
+ return [false, token(:EOF, :EOF)[1]] if @done
135
171
  @done = true
136
- return [:EOF, '']
172
+ return token(:EOF, :EOF)
137
173
  when INITIAL_IDENTIFIER_CHARS
138
174
  self.context = :ident
139
175
  @buffer = c
140
- @index += 1
176
+ traverse(1)
141
177
  else
142
- raise Error, "Unexpected character #{c.inspect}"
178
+ raise_error "Unexpected character #{c.inspect}"
143
179
  end
144
180
  when :ident
145
181
  case c
146
182
  when IDENTIFIER_CHARS
147
- @index += 1
183
+ traverse(1)
148
184
  @buffer += c
149
185
  else
150
186
  case @buffer
151
- when 'true' then return [:TRUE, true]
152
- when 'false' then return [:FALSE, false]
153
- when 'null' then return [:NULL, nil]
154
- else return [:IDENT, @buffer]
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
- @index += 2
198
+ traverse(2)
163
199
  when '"'
164
- @index += 1
165
- return [:STRING, convert_escapes(@buffer)]
200
+ return token(:STRING, convert_escapes(@buffer)).tap { traverse(1) }
166
201
  when nil
167
- raise Error, "Unterminated string literal"
202
+ raise_error "Unterminated string literal"
168
203
  else
169
204
  @buffer += c
170
- @index += 1
205
+ traverse(1)
171
206
  end
172
207
  when :rawstring
173
- raise Error, "Unterminated rawstring literal" if c.nil?
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
- @index += 1 + h
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
- @index += 1
221
+ traverse(1)
188
222
  when :decimal
189
223
  case c
190
224
  when /[0-9.\-+_eE]/
191
- @index += 1
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
- @index += 1
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
- @index += 1
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
- @index += 1
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 [:EOF, '']
261
+ return token(:EOF, :EOF)
227
262
  else
228
- @index += 1
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
- @index += 2
268
+ traverse(2)
234
269
  elsif c == '*' && @str[@index + 1] == '/'
235
270
  @comment_nesting -= 1
236
- @index += 2
271
+ traverse(2)
237
272
  if @comment_nesting == 0
238
273
  revert_context
239
274
  end
240
275
  else
241
- @index += 1
276
+ traverse(1)
242
277
  end
243
278
  when :whitespace
244
279
  if WHITEPACE.include?(c)
245
- @index += 1
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
- raise Error, "Unexpected '\\'"
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
- @index += 2
297
+ traverse(2)
261
298
  else
262
- return [:WS, @buffer]
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 [:FLOAT, Float(munch_underscores(s))] if s =~ /[.eE]/
282
- [:INTEGER, Integer(munch_underscores(s), 10)]
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
- [:INTEGER, Integer(munch_underscores(s), 16)]
341
+ token(:INTEGER, Integer(munch_underscores(s), 16))
287
342
  end
288
343
 
289
344
  def parse_octal(s)
290
- [:INTEGER, Integer(munch_underscores(s), 8)]
345
+ token(:INTEGER, Integer(munch_underscores(s), 8))
291
346
  end
292
347
 
293
348
  def parse_binary(s)
294
- [:INTEGER, Integer(munch_underscores(s), 2)]
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
- else raise Error, "Unexpected escape #{m.inspect}"
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
- raise Error, "Invalid code point #{u}"
372
+ raise_error "Invalid code point #{u}"
317
373
  end
318
374
  i.chr(Encoding::UTF_8)
319
375
  end
@@ -1,3 +1,3 @@
1
1
  module KDL
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  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: 0.1.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: 2020-12-27 00:00:00.000000000 Z
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
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- before_install: gem install bundler -v 2.1.2