@@ -9,6 +9,11 @@ import toml.util
9
9
import toml.token
10
10
import toml.scanner
11
11
12
+ pub const (
13
+ all_formatting = [token.Kind.whitespace, .tab, .nl]
14
+ space_formatting = [token.Kind.whitespace, .tab]
15
+ )
16
+
12
17
// Parser contains the necessary fields for keeping the state of the parsing process.
13
18
pub struct Parser {
14
19
pub :
@@ -127,7 +132,8 @@ fn (mut p Parser) check(check_token token.Kind) ? {
127
132
}
128
133
}
129
134
130
- // check_one_of returns true if the current token's `Kind` is equal that of `expected_token`.
135
+ // check_one_of forwards the parser to the next token if the current
136
+ // token's `Kind` can be found in `tokens`. Otherwise it returns an error.
131
137
fn (mut p Parser) check_one_of (tokens []token.Kind) ? {
132
138
if p.tok.kind in tokens {
133
139
p.next () ?
@@ -137,6 +143,45 @@ fn (mut p Parser) check_one_of(tokens []token.Kind) ? {
137
143
}
138
144
}
139
145
146
+ // ignore_while forwards the parser to the next token as long as the current
147
+ // token's `Kind` can be found in `tokens`. This is helpful for ignoring
148
+ // a stream of formatting tokens.
149
+ fn (mut p Parser) ignore_while (tokens []token.Kind) {
150
+ if p.tok.kind in tokens {
151
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'ignoring "$p.tok.kind " ...' )
152
+ p.next () or { return }
153
+ p.ignore_while (tokens)
154
+ }
155
+ }
156
+
157
+ // ignore_while_peek forwards the parser to the next token as long as `peek_tok`
158
+ // token's `Kind` can be found in `tokens`. This is helpful for ignoring
159
+ // a stream of formatting tokens.
160
+ // In contrast to `ignore_while`, `ignore_while_peek` compares on `peek_tok` this is
161
+ // sometimes necessary since not all parser calls forward using the `next()` call.
162
+ fn (mut p Parser) ignore_while_peek (tokens []token.Kind) {
163
+ for p.peek_tok.kind in tokens {
164
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'eating "$p.tok.kind " ...' )
165
+ p.next () or { return }
166
+ }
167
+ }
168
+
169
+ // peek_over peeks ahead from token starting at `i` skipping over
170
+ // any `token.Kind`s found in `tokens`. `peek_over` returns the next token *not*
171
+ // found in `tokens`.
172
+ fn (mut p Parser) peek_over (i int , tokens []token.Kind) ? token.Token {
173
+ mut peek_tok := p.peek_tok
174
+
175
+ // Peek ahead as far as we can from token at `i` while the peeked
176
+ // token is found in `tokens`.
177
+ mut peek_i := i
178
+ for peek_tok.kind in tokens {
179
+ peek_tok = p.peek (peek_i) ?
180
+ peek_i++
181
+ }
182
+ return peek_tok
183
+ }
184
+
140
185
// is_at returns true if the token kind is equal to `expected_token`.
141
186
fn (mut p Parser) is_at (expected_token token.Kind) bool {
142
187
return p.tok.kind == expected_token
@@ -251,12 +296,15 @@ pub fn (mut p Parser) find_in_table(mut table map[string]ast.Value, key string)
251
296
pub fn (mut p Parser) sub_key () ? string {
252
297
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing nested key...' )
253
298
key := p.key () ?
299
+ p.ignore_while_peek (parser.space_formatting)
254
300
mut text := key.str ()
255
301
for p.peek_tok.kind == .period {
256
302
p.next () ? // .
257
303
p.check (.period) ?
304
+ p.ignore_while (parser.space_formatting)
258
305
next_key := p.key () ?
259
306
text + = '.' + next_key.text
307
+ p.ignore_while_peek (parser.space_formatting)
260
308
}
261
309
p.next () ?
262
310
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsed nested key `$text ` now at "$p.tok.kind " "$p.tok.lit "' )
@@ -282,23 +330,22 @@ pub fn (mut p Parser) root_table() ? {
282
330
p.ast_root.comments << c
283
331
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'skipping comment "$c.text "' )
284
332
}
285
- // .whitespace, .tab, .nl {
286
- // util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping "$p.tok.kind "$p.tok.lit"')
287
- // }
333
+ .whitespace, .tab, .nl, .cr {
334
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'skipping formatting "$p.tok.kind " "$p.tok.lit "' )
335
+ continue
336
+ }
288
337
.bare, .quoted, .boolean, .number, .underscore { // NOTE .boolean allows for use of "true" and "false" as table keys
289
- if p.peek_tok.kind == .assign
290
- || (p.tok.kind == .number && p.peek_tok.kind == .minus) {
291
- key , val := p.key_value () ?
338
+ mut peek_tok := p.peek_tok
292
339
293
- t := p.find_table () ?
294
- unsafe {
295
- util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'setting "$key.str ()" = $val.to_json () in table ${ptr_str(t)} ' )
296
- t[key.str ()] = val
297
- }
298
- } else if p.peek_tok.kind == .period {
299
- subkey := p.sub_key () ?
340
+ // Peek forward as far as we can skipping over space formatting tokens.
341
+ peek_tok = p.peek_over (1 , parser.space_formatting) ?
300
342
343
+ if peek_tok.kind == .period {
344
+ p.ignore_while (parser.space_formatting)
345
+ subkey := p.sub_key () ?
346
+ p.ignore_while (parser.space_formatting)
301
347
p.check (.assign) ?
348
+ p.ignore_while (parser.space_formatting)
302
349
val := p.value () ?
303
350
304
351
sub_table , key := p.sub_table_key (subkey)
@@ -309,19 +356,32 @@ pub fn (mut p Parser) root_table() ? {
309
356
t[key] = val
310
357
}
311
358
} else {
312
- return error (@MOD + '.' + @STRUCT + '.' + @FN +
313
- ' dead end at "$p.tok.kind " "$p.tok.lit "' )
359
+ p.ignore_while (parser.space_formatting)
360
+ key , val := p.key_value () ?
361
+
362
+ t := p.find_table () ?
363
+ unsafe {
364
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'setting "$key.str ()" = $val.to_json () in table ${ptr_str(t)} ' )
365
+ t[key.str ()] = val
366
+ }
314
367
}
315
368
}
316
369
.lsbr {
317
370
p.check (.lsbr) ? // '[' bracket
371
+ p.ignore_while (parser.space_formatting)
372
+
373
+ mut peek_tok := p.peek_tok
374
+ // Peek forward as far as we can skipping over space formatting tokens.
375
+ peek_tok = p.peek_over (1 , parser.space_formatting) ?
318
376
319
377
if p.tok.kind == .lsbr {
320
378
p.array_of_tables (mut & p.root_map) ?
321
379
p.skip_next = true // skip calling p.next() in coming iteration
322
- util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'leaving double bracket at "$p.tok.kind "$p.tok.lit ". NEXT is "$p.peek_tok.kind "$p.peek_tok.lit "' )
323
- } else if p.peek_tok.kind == .period {
380
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'leaving double bracket at "$p.tok.kind " "$p.tok.lit ". NEXT is "$p.peek_tok.kind "$p.peek_tok.lit "' )
381
+ } else if peek_tok.kind == .period {
382
+ p.ignore_while (parser.space_formatting)
324
383
p.root_map_key = p.sub_key () ?
384
+ p.ignore_while (parser.space_formatting)
325
385
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'setting root map key to `$p.root_map_key ` at "$p.tok.kind " "$p.tok.lit "' )
326
386
p.expect (.rsbr) ?
327
387
} else {
@@ -359,17 +419,25 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ? {
359
419
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing token "$p.tok.kind "' )
360
420
361
421
if previous_token_was_value {
422
+ p.ignore_while (parser.space_formatting)
362
423
if p.tok.kind != .rcbr {
363
424
p.expect (.comma) ?
364
425
}
365
426
previous_token_was_value = false
366
427
}
367
428
368
429
match p.tok.kind {
369
- // .whitespace, .tab, .nl {
370
- // util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping "$p.tok.kind "$p.tok.lit"')
371
- // }
430
+ .whitespace, .tab {
431
+ /*
432
+ if !p.scanner.config.tokenize_formatting {
433
+ util.printdbg(@MOD + '.' + @STRUCT + '.' + @FN, 'skipping "$p.tok.kind" "$p.tok.lit"')
434
+ continue
435
+ }*/
436
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'skipping formatting "$p.tok.kind " "$p.tok.lit "' )
437
+ continue
438
+ }
372
439
.comma {
440
+ p.ignore_while_peek (parser.space_formatting)
373
441
if p.peek_tok.kind == .rcbr {
374
442
p.next () ? // Forward to the peek_tok
375
443
return error (@MOD + '.' + @STRUCT + '.' + @FN +
@@ -388,13 +456,16 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ? {
388
456
return
389
457
}
390
458
.bare, .quoted, .boolean, .number, .underscore {
391
- if p.peek_tok.kind == .assign {
392
- key , val := p.key_value () ?
393
- util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'inserting @5 "$key.str ()" = $val.to_json () into ${ptr_str(tbl)} ' )
394
- tbl[key.str ()] = val
395
- } else if p.peek_tok.kind == .period {
459
+ mut peek_tok := p.peek_tok
460
+ // Peek forward as far as we can skipping over space formatting tokens.
461
+ peek_tok = p.peek_over (1 , parser.space_formatting) ?
462
+
463
+ if peek_tok.kind == .period {
464
+ p.ignore_while (parser.space_formatting)
396
465
subkey := p.sub_key () ?
466
+ p.ignore_while (parser.space_formatting)
397
467
p.check (.assign) ?
468
+ p.ignore_while (parser.space_formatting)
398
469
val := p.value () ?
399
470
400
471
sub_table , key := p.sub_table_key (subkey)
@@ -405,8 +476,10 @@ pub fn (mut p Parser) inline_table(mut tbl map[string]ast.Value) ? {
405
476
t[key] = val
406
477
}
407
478
} else {
408
- return error (@MOD + '.' + @STRUCT + '.' + @FN +
409
- ' dead end at "$p.tok.kind " "$p.tok.lit "' )
479
+ p.ignore_while (parser.space_formatting)
480
+ key , val := p.key_value () ?
481
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'inserting @5 "$key.str ()" = $val.to_json () into ${ptr_str(tbl)} ' )
482
+ tbl[key.str ()] = val
410
483
}
411
484
previous_token_was_value = true
412
485
}
@@ -438,6 +511,8 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ? {
438
511
p.check (.rsbr) ?
439
512
p.check (.rsbr) ?
440
513
514
+ p.ignore_while (parser.all_formatting)
515
+
441
516
key_str := key.str ()
442
517
unsafe {
443
518
if key_str in table.keys () {
@@ -448,15 +523,15 @@ pub fn (mut p Parser) array_of_tables(mut table map[string]ast.Value) ? {
448
523
{
449
524
if val is []ast.Value {
450
525
arr := & (table[key_str] as []ast.Value)
451
- arr << p.double_bracket_array () ?
526
+ arr << p.array_of_tables_contents () ?
452
527
table[key_str] = arr
453
528
} else {
454
529
return error (@MOD + '.' + @STRUCT + '.' + @FN +
455
530
' table[$key_str ] is not an array. (excerpt): "...${p.excerpt()} ..."' )
456
531
}
457
532
}
458
533
} else {
459
- table[key_str] = p.double_bracket_array () ?
534
+ table[key_str] = p.array_of_tables_contents () ?
460
535
}
461
536
}
462
537
p.last_aot = key_str
@@ -475,6 +550,7 @@ pub fn (mut p Parser) double_array_of_tables(mut table map[string]ast.Value) ? {
475
550
next_key := p.key () ?
476
551
key_str + = '.' + next_key.text
477
552
}
553
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsed nested key `$key_str ` now at "$p.tok.kind " "$p.tok.lit "' )
478
554
479
555
p.next () ?
480
556
p.check (.rsbr) ?
@@ -501,7 +577,10 @@ pub fn (mut p Parser) double_array_of_tables(mut table map[string]ast.Value) ? {
501
577
}
502
578
503
579
mut t_arr := & (table[p.last_aot] as []ast.Value)
504
- mut t_map := t_arr[p.last_aot_index]
580
+ mut t_map := ast.Value (map [string ]ast.Value{})
581
+ if t_arr.len > 0 {
582
+ t_map = t_arr[p.last_aot_index]
583
+ }
505
584
mut t := & (t_map as map [string ]ast.Value)
506
585
507
586
if last in t.keys () {
@@ -512,29 +591,51 @@ pub fn (mut p Parser) double_array_of_tables(mut table map[string]ast.Value) ? {
512
591
{
513
592
if val is []ast.Value {
514
593
arr := & (val as []ast.Value)
515
- arr << p.double_bracket_array () ?
594
+ arr << p.array_of_tables_contents () ?
516
595
t[last] = arr
517
596
} else {
518
597
return error (@MOD + '.' + @STRUCT + '.' + @FN +
519
598
' t[$last ] is not an array. (excerpt): "...${p.excerpt()} ..."' )
520
599
}
521
600
}
522
601
} else {
523
- t[last] = p.double_bracket_array () ?
602
+ t[last] = p.array_of_tables_contents () ?
603
+ }
604
+ if t_arr.len == 0 {
605
+ t_arr << t
606
+ p.last_aot_index = 0
524
607
}
525
608
}
526
609
}
527
610
528
611
// array parses next tokens into an array of `ast.Value`s.
529
- pub fn (mut p Parser) double_bracket_array () ? []ast.Value {
530
- mut arr := []ast.Value{}
531
- for p.tok.kind in [.bare, .quoted, .boolean, .number] && p.peek_tok.kind == .assign {
532
- mut tbl := map [string ]ast.Value{}
533
- key , val := p.key_value () ?
534
- tbl[key.str ()] = val
535
- arr << tbl
612
+ pub fn (mut p Parser) array_of_tables_contents () ? []ast.Value {
613
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing array of tables contents from "$p.tok.kind " "$p.tok.lit "' )
614
+ mut tbl := map [string ]ast.Value{}
615
+ for p.tok.kind in [.bare, .quoted, .boolean, .number] {
616
+ if p.peek_tok.kind == .period {
617
+ subkey := p.sub_key () ?
618
+ p.check (.assign) ?
619
+ val := p.value () ?
620
+
621
+ sub_table , key := p.sub_table_key (subkey)
622
+
623
+ mut t := p.find_in_table (mut tbl, sub_table) ?
624
+ unsafe {
625
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'inserting @6 "$key " = $val.to_json () into ${ptr_str(t)} ' )
626
+ t[key] = val
627
+ }
628
+ } else {
629
+ key , val := p.key_value () ?
630
+ tbl[key.str ()] = val
631
+ }
536
632
p.next () ?
633
+ p.ignore_while (parser.all_formatting)
537
634
}
635
+ mut arr := []ast.Value{}
636
+ arr << tbl
637
+ util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing array of tables ${arr.str().replace(' \n',
638
+ ' ')}. leaving at "$p.tok.kind " "$p.tok.lit "' )
538
639
return arr
539
640
}
540
641
@@ -549,6 +650,7 @@ pub fn (mut p Parser) array() ?[]ast.Value {
549
650
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing token "$p.tok.kind " "$p.tok.lit "' )
550
651
551
652
if previous_token_was_value {
653
+ p.ignore_while (parser.all_formatting)
552
654
if p.tok.kind != .rsbr && p.tok.kind != .hash {
553
655
p.expect (.comma) ?
554
656
}
@@ -581,6 +683,7 @@ pub fn (mut p Parser) array() ?[]ast.Value {
581
683
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'skipping comment "$c.text "' )
582
684
}
583
685
.lcbr {
686
+ p.ignore_while (parser.space_formatting)
584
687
mut t := map [string ]ast.Value{}
585
688
p.inline_table (mut t) ?
586
689
arr << ast.Value (t)
@@ -680,7 +783,9 @@ pub fn (mut p Parser) key_value() ?(ast.Key, ast.Value) {
680
783
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsing key value pair...' )
681
784
key := p.key () ?
682
785
p.next () ?
786
+ p.ignore_while (parser.space_formatting)
683
787
p.check (.assign) ? // Assignment operator
788
+ p.ignore_while (parser.space_formatting)
684
789
value := p.value () ?
685
790
util.printdbg (@MOD + '.' + @STRUCT + '.' + @FN, 'parsed key value pair. "$key " = $value.to_json ()' )
686
791
return key, value
@@ -711,6 +816,7 @@ pub fn (mut p Parser) value() ?ast.Value {
711
816
ast.Value (p.array () ? )
712
817
}
713
818
.lcbr {
819
+ p.ignore_while (parser.space_formatting)
714
820
mut t := map [string ]ast.Value{}
715
821
p.inline_table (mut t) ?
716
822
// table[key_str] = ast.Value(t)
0 commit comments