Skip to content

Commit b7d2198

Browse files
authored
Merge pull request #726 from hattya/toml-0.4
Text.TOML: comply with v0.4.0
2 parents 6df5def + 4f988e2 commit b7d2198

File tree

3 files changed

+236
-167
lines changed

3 files changed

+236
-167
lines changed

autoload/vital/__vital__/Text/TOML.vim

Lines changed: 77 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ endfunction
2626
"
2727
" private api
2828
"
29-
" work around: '[^\r\n]*' doesn't work well in old-vim, but "[^\r\n]*" works well
30-
let s:skip_pattern = '\C^\%(\_s\+\|' . "#[^\r\n]*" . '\)'
31-
let s:table_name_pattern = '\%([^ [:tab:]#.[\]=]\+\)'
32-
let s:table_key_pattern = s:table_name_pattern
29+
let s:skip_pattern = '\C^\%(\%(\s\|\r\?\n\)\+\|#[^\r\n]*\)'
30+
let s:bare_key_pattern = '\%([A-Za-z0-9_-]\+\)'
3331

3432
function! s:_skip(input) abort
35-
while s:_match(a:input, '\%(\_s\|#\)')
33+
while s:_match(a:input, '\%(\s\|\r\?\n\|#\)')
3634
let a:input.p = matchend(a:input.text, s:skip_pattern, a:input.p)
3735
endwhile
3836
endfunction
@@ -68,14 +66,10 @@ function! s:_eof(input) abort
6866
endfunction
6967

7068
function! s:_error(input) abort
71-
let buf = []
72-
let offset = 0
73-
while (a:input.p + offset) < a:input.length && a:input.text[a:input.p + offset] !~# "[\r\n]"
74-
let buf += [a:input.text[a:input.p + offset]]
75-
let offset += 1
76-
endwhile
69+
let s = matchstr(a:input.text, s:regex_prefix . '.\{-}\ze\%(\r\?\n\|$\)', a:input.p)
70+
let s = substitute(s, '\r', '\\r', 'g')
7771

78-
throw printf("vital: Text.TOML: Illegal toml format at `%s'.", join(buf, ''))
72+
throw printf("vital: Text.TOML: Illegal toml format at `%s'.", s)
7973
endfunction
8074

8175
function! s:_parse(input) abort
@@ -84,25 +78,16 @@ function! s:_parse(input) abort
8478
call s:_skip(a:input)
8579
while !s:_eof(a:input)
8680
if s:_match(a:input, '[^ [:tab:]#.[\]]')
87-
let key = s:_key(a:input)
81+
let keys = s:_keys(a:input, '=')
8882
call s:_equals(a:input)
8983
let value = s:_value(a:input)
90-
91-
call s:_put_dict(data, key, value)
92-
93-
unlet value
84+
call s:_put_dict(data, keys, value)
9485
elseif s:_match(a:input, '\[\[')
95-
let [key, value] = s:_array_of_tables(a:input)
96-
97-
call s:_put_array(data, key, value)
98-
99-
unlet value
86+
let [keys, value] = s:_array_of_tables(a:input)
87+
call s:_put_array(data, keys, value)
10088
elseif s:_match(a:input, '\[')
101-
let [key, value] = s:_table(a:input)
102-
103-
call s:_put_dict(data, key, value)
104-
105-
unlet value
89+
let [keys, value] = s:_table(a:input)
90+
call s:_put_dict(data, keys, value)
10691
else
10792
call s:_error(a:input)
10893
endif
@@ -112,14 +97,26 @@ function! s:_parse(input) abort
11297
return data
11398
endfunction
11499

115-
function! s:_key(input) abort
116-
let s = s:_consume(a:input, s:table_key_pattern)
117-
return s
100+
function! s:_keys(input, end) abort
101+
let keys = []
102+
while !s:_eof(a:input) && !s:_match(a:input, a:end)
103+
call s:_skip(a:input)
104+
if s:_match(a:input, '"')
105+
let key = s:_basic_string(a:input)
106+
else
107+
let key = s:_consume(a:input, s:bare_key_pattern)
108+
endif
109+
let keys += [key]
110+
call s:_consume(a:input, '\.\?')
111+
endwhile
112+
if empty(keys)
113+
return s:_error(a:input)
114+
endif
115+
return keys
118116
endfunction
119117

120118
function! s:_equals(input) abort
121-
call s:_consume(a:input, '=')
122-
return '='
119+
return s:_consume(a:input, '=')
123120
endfunction
124121

125122
function! s:_value(input) abort
@@ -135,11 +132,13 @@ function! s:_value(input) abort
135132
return s:_literal(a:input)
136133
elseif s:_match(a:input, '\[')
137134
return s:_array(a:input)
135+
elseif s:_match(a:input, '{')
136+
return s:_inline_table(a:input)
138137
elseif s:_match(a:input, '\%(true\|false\)')
139138
return s:_boolean(a:input)
140139
elseif s:_match(a:input, '\d\{4}-')
141140
return s:_datetime(a:input)
142-
elseif s:_match(a:input, '[+-]\?\%(\d\+\.\d\|\d\+\%(\.\d\+\)\?[eE]\)')
141+
elseif s:_match(a:input, '[+-]\?\d\+\%(_\d\+\)*\%(\.\d\+\%(_\d\+\)*\|\%(\.\d\+\%(_\d\+\)*\)\?[eE]\)')
143142
return s:_float(a:input)
144143
else
145144
return s:_integer(a:input)
@@ -158,8 +157,8 @@ endfunction
158157
function! s:_multiline_basic_string(input) abort
159158
let s = s:_consume(a:input, '"\{3}\%(\\.\|\_.\)\{-}"\{3}')
160159
let s = s[3 : -4]
161-
let s = substitute(s, "^\n", '', '')
162-
let s = substitute(s, '\\' . "\n" . '\_s*', '', 'g')
160+
let s = substitute(s, '^\r\?\n', '', '')
161+
let s = substitute(s, '\\\%(\s\|\r\?\n\)*', '', 'g')
163162
return s:_unescape(s)
164163
endfunction
165164

@@ -171,36 +170,25 @@ endfunction
171170
function! s:_multiline_literal(input) abort
172171
let s = s:_consume(a:input, "'\\{3}.\\{-}'\\{3}")
173172
let s = s[3 : -4]
174-
let s = substitute(s, "^\n", '', '')
173+
let s = substitute(s, '^\r\?\n', '', '')
175174
return s
176175
endfunction
177176

178177
"
179178
" Integer
180179
"
181180
function! s:_integer(input) abort
182-
let s = s:_consume(a:input, '[+-]\?\d\+')
181+
let s = s:_consume(a:input, '[+-]\?\d\+\%(_\d\+\)*')
182+
let s = substitute(s, '_', '', 'g')
183183
return str2nr(s)
184184
endfunction
185185

186186
"
187187
" Float
188188
"
189189
function! s:_float(input) abort
190-
if s:_match(a:input, '[+-]\?[0-9.]\+[eE][+-]\?\d\+')
191-
return s:_exponent(a:input)
192-
else
193-
return s:_fractional(a:input)
194-
endif
195-
endfunction
196-
197-
function! s:_fractional(input) abort
198-
let s = s:_consume(a:input, '[+-]\?[0-9.]\+')
199-
return str2float(s)
200-
endfunction
201-
202-
function! s:_exponent(input) abort
203-
let s = s:_consume(a:input, '[+-]\?[0-9.]\+[eE][+-]\?\d\+')
190+
let s = s:_consume(a:input, '[+-]\?[0-9._]\+\%([eE][+-]\?\d\+\%(_\d\+\)*\)\?')
191+
let s = substitute(s, '_', '', 'g')
204192
return str2float(s)
205193
endfunction
206194

@@ -241,40 +229,54 @@ endfunction
241229
"
242230
function! s:_table(input) abort
243231
let tbl = {}
244-
let name = s:_consume(a:input, '\[\s*' . s:table_name_pattern . '\%(\s*\.\s*' . s:table_name_pattern . '\)*\s*\]')
245-
let name = name[1 : -2]
232+
call s:_consume(a:input, '\[')
233+
let name = s:_keys(a:input, '\]')
234+
call s:_consume(a:input, '\]')
246235
call s:_skip(a:input)
247236
" while !s:_eof(a:input) && !s:_match(a:input, '\[\{1,2}[a-zA-Z0-9.]\+\]\{1,2}')
248237
while !s:_eof(a:input) && !s:_match(a:input, '\[')
249-
let key = s:_key(a:input)
238+
let keys = s:_keys(a:input, '=')
250239
call s:_equals(a:input)
251240
let value = s:_value(a:input)
252-
253-
let tbl[key] = value
254-
255-
unlet value
241+
call s:_put_dict(tbl, keys, value)
256242
call s:_skip(a:input)
257243
endwhile
258244
return [name, tbl]
259245
endfunction
260246

261247
"
262-
" Array of tables
248+
" Inline Table
249+
"
250+
function! s:_inline_table(input) abort
251+
let tbl = {}
252+
call s:_consume(a:input, '{')
253+
while !s:_eof(a:input) && !s:_match(a:input, '}')
254+
let keys = s:_keys(a:input, '=')
255+
call s:_equals(a:input)
256+
let value = s:_value(a:input)
257+
call s:_put_dict(tbl, keys, value)
258+
call s:_consume(a:input, ',\?')
259+
call s:_skip(a:input)
260+
endwhile
261+
call s:_consume(a:input, '}')
262+
return tbl
263+
endfunction
264+
265+
"
266+
" Array of Tables
263267
"
264268
function! s:_array_of_tables(input) abort
265269
let tbl = {}
266-
let name = s:_consume(a:input, '\[\[\s*' . s:table_name_pattern . '\%(\s*\.\s*' . s:table_name_pattern . '\)*\s*\]\]')
267-
let name = name[2 : -3]
270+
call s:_consume(a:input, '\[\[')
271+
let name = s:_keys(a:input, '\]\]')
272+
call s:_consume(a:input, '\]\]')
268273
call s:_skip(a:input)
269274
" while !s:_eof(a:input) && !s:_match(a:input, '\[\{1,2}[a-zA-Z0-9.]\+\]\{1,2}')
270275
while !s:_eof(a:input) && !s:_match(a:input, '\[')
271-
let key = s:_key(a:input)
276+
let keys = s:_keys(a:input, '=')
272277
call s:_equals(a:input)
273278
let value = s:_value(a:input)
274-
275-
let tbl[key] = value
276-
277-
unlet value
279+
call s:_put_dict(tbl, keys, value)
278280
call s:_skip(a:input)
279281
endwhile
280282
return [name, [tbl]]
@@ -288,7 +290,6 @@ function! s:_unescape(text) abort
288290
let text = substitute(text, '\\n', "\n", 'g')
289291
let text = substitute(text, '\\f', "\f", 'g')
290292
let text = substitute(text, '\\r', "\r", 'g')
291-
let text = substitute(text, '\\/', '/', 'g')
292293
let text = substitute(text, '\\\\', '\', 'g')
293294
let text = substitute(text, '\C\\u\(\x\{4}\)', '\=s:_nr2char("0x" . submatch(1))', 'g')
294295
let text = substitute(text, '\C\\U\(\x\{8}\)', '\=s:_nr2char("0x" . submatch(1))', 'g')
@@ -299,39 +300,35 @@ function! s:_nr2char(nr) abort
299300
return iconv(nr2char(a:nr), &encoding, 'utf8')
300301
endfunction
301302

302-
function! s:_put_dict(dict, key, value) abort
303-
let keys = split(a:key, '\.')
304-
303+
function! s:_put_dict(dict, keys, value) abort
305304
let ref = a:dict
306-
for key in keys[ : -2]
307-
if has_key(ref, key) && type(ref[key]) == type({})
305+
for key in a:keys[: -2]
306+
if has_key(ref, key) && type(ref[key]) == v:t_dict
308307
let ref = ref[key]
309-
elseif has_key(ref, key) && type(ref[key]) == type([])
308+
elseif has_key(ref, key) && type(ref[key]) == v:t_list
310309
let ref = ref[key][-1]
311310
else
312311
let ref[key] = {}
313312
let ref = ref[key]
314313
endif
315314
endfor
316315

317-
let ref[keys[-1]] = a:value
316+
let ref[a:keys[-1]] = a:value
318317
endfunction
319318

320-
function! s:_put_array(dict, key, value) abort
321-
let keys = split(a:key, '\.')
322-
319+
function! s:_put_array(dict, keys, value) abort
323320
let ref = a:dict
324-
for key in keys[ : -2]
321+
for key in a:keys[: -2]
325322
let ref[key] = get(ref, key, {})
326323

327-
if type(ref[key]) == type([])
324+
if type(ref[key]) == v:t_list
328325
let ref = ref[key][-1]
329326
else
330327
let ref = ref[key]
331328
endif
332329
endfor
333330

334-
let ref[keys[-1]] = get(ref, keys[-1], []) + a:value
331+
let ref[a:keys[-1]] = get(ref, a:keys[-1], []) + a:value
335332
endfunction
336333

337334
let &cpo = s:save_cpo

doc/vital/Text/TOML.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ INTERFACE |Vital.Text.TOML-interface|
1212
==============================================================================
1313
INTRODUCTION *Vital.Text.TOML-introduction*
1414

15-
*Vital.Text.TOML* is a TOML parser.
15+
*Vital.Text.TOML* is a TOML parser (v0.4.0 compliant).
1616

1717
See https://github.com/toml-lang/toml
1818

0 commit comments

Comments
 (0)