1use winnow::stream::Offset as _;
2use winnow::stream::Stream as _;
3use winnow::stream::TokenSlice;
4
5use super::EventReceiver;
6#[cfg(feature = "debug")]
7use crate::debug::DebugErrorSink;
8#[cfg(feature = "debug")]
9use crate::debug::DebugEventReceiver;
10use crate::decoder::Encoding;
11use crate::lexer::Token;
12use crate::lexer::TokenKind;
13use crate::ErrorSink;
14use crate::Expected;
15use crate::ParseError;
16
17pub fn parse_document(
19 tokens: &[Token],
20 receiver: &mut dyn EventReceiver,
21 error: &mut dyn ErrorSink,
22) {
23 let mut tokens = TokenSlice::new(tokens);
24 #[cfg(feature = "debug")]
25 let mut receiver = DebugEventReceiver::new(receiver);
26 #[cfg(feature = "debug")]
27 let receiver = &mut receiver;
28 #[cfg(feature = "debug")]
29 let mut error = DebugErrorSink::new(error);
30 #[cfg(feature = "debug")]
31 let error = &mut error;
32 document(&mut tokens, receiver, error);
33 eof(&mut tokens, receiver, error);
34}
35
36pub fn parse_key(tokens: &[Token], receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
38 let mut tokens = TokenSlice::new(tokens);
39 #[cfg(feature = "debug")]
40 let mut receiver = DebugEventReceiver::new(receiver);
41 #[cfg(feature = "debug")]
42 let receiver = &mut receiver;
43 #[cfg(feature = "debug")]
44 let mut error = DebugErrorSink::new(error);
45 #[cfg(feature = "debug")]
46 let error = &mut error;
47 key(&mut tokens, "invalid key", receiver, error);
48 eof(&mut tokens, receiver, error);
49}
50
51pub fn parse_simple_key(
53 tokens: &[Token],
54 receiver: &mut dyn EventReceiver,
55 error: &mut dyn ErrorSink,
56) {
57 let mut tokens = TokenSlice::new(tokens);
58 #[cfg(feature = "debug")]
59 let mut receiver = DebugEventReceiver::new(receiver);
60 #[cfg(feature = "debug")]
61 let receiver = &mut receiver;
62 #[cfg(feature = "debug")]
63 let mut error = DebugErrorSink::new(error);
64 #[cfg(feature = "debug")]
65 let error = &mut error;
66 simple_key(&mut tokens, "invalid key", receiver, error);
67 eof(&mut tokens, receiver, error);
68}
69
70pub fn parse_value(tokens: &[Token], receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
72 let mut tokens = TokenSlice::new(tokens);
73 #[cfg(feature = "debug")]
74 let mut receiver = DebugEventReceiver::new(receiver);
75 #[cfg(feature = "debug")]
76 let receiver = &mut receiver;
77 #[cfg(feature = "debug")]
78 let mut error = DebugErrorSink::new(error);
79 #[cfg(feature = "debug")]
80 let error = &mut error;
81 value(&mut tokens, receiver, error);
82 eof(&mut tokens, receiver, error);
83}
84
85type Stream<'i> = TokenSlice<'i, Token>;
86
87fn document(tokens: &mut Stream<'_>, receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
147 while let Some(current_token) = tokens.next_token() {
148 match current_token.kind() {
149 TokenKind::LeftSquareBracket => on_table(tokens, current_token, receiver, error),
150 TokenKind::RightSquareBracket => {
151 on_missing_std_table(tokens, current_token, receiver, error);
152 }
153 TokenKind::LiteralString => on_expression_key(
154 tokens,
155 current_token,
156 Some(Encoding::LiteralString),
157 receiver,
158 error,
159 ),
160 TokenKind::BasicString => on_expression_key(
161 tokens,
162 current_token,
163 Some(Encoding::BasicString),
164 receiver,
165 error,
166 ),
167 TokenKind::MlLiteralString => on_expression_key(
168 tokens,
169 current_token,
170 Some(Encoding::MlLiteralString),
171 receiver,
172 error,
173 ),
174 TokenKind::MlBasicString => on_expression_key(
175 tokens,
176 current_token,
177 Some(Encoding::MlBasicString),
178 receiver,
179 error,
180 ),
181 TokenKind::Atom => on_expression_key(tokens, current_token, None, receiver, error),
182 TokenKind::Equals => {
183 let fake_key = current_token.span().before();
184 let encoding = None;
185 receiver.simple_key(fake_key, encoding, error);
186 on_expression_key_val_sep(tokens, current_token, receiver, error);
187 }
188 TokenKind::Dot => {
189 on_expression_dot(tokens, current_token, receiver, error);
190 }
191 TokenKind::Comma | TokenKind::RightCurlyBracket | TokenKind::LeftCurlyBracket => {
192 on_missing_expression_key(tokens, current_token, receiver, error);
193 }
194 TokenKind::Whitespace => receiver.whitespace(current_token.span(), error),
195 TokenKind::Newline => receiver.newline(current_token.span(), error),
196 TokenKind::Comment => on_comment(tokens, current_token, receiver, error),
197 TokenKind::Eof => {
198 break;
199 }
200 }
201 }
202}
203
204fn on_table(
222 tokens: &mut Stream<'_>,
223 open_token: &Token,
224 receiver: &mut dyn EventReceiver,
225 error: &mut dyn ErrorSink,
226) {
227 let is_array_table = if let Some(second_open_token) =
228 next_token_if(tokens, |k| matches!(k, TokenKind::LeftSquareBracket))
229 {
230 let span = open_token.span().append(second_open_token.span());
231 receiver.array_table_open(span, error);
232 true
233 } else {
234 let span = open_token.span();
235 receiver.std_table_open(span, error);
236 false
237 };
238
239 opt_whitespace(tokens, receiver, error);
240
241 let valid_key = key(tokens, "invalid table", receiver, error);
242
243 opt_whitespace(tokens, receiver, error);
244
245 let mut success = false;
246 if let Some(close_token) = next_token_if(tokens, |k| matches!(k, TokenKind::RightSquareBracket))
247 {
248 if is_array_table {
249 if let Some(second_close_token) =
250 next_token_if(tokens, |k| matches!(k, TokenKind::RightSquareBracket))
251 {
252 let span = close_token.span().append(second_close_token.span());
253 receiver.array_table_close(span, error);
254 success = true;
255 } else {
256 let context = open_token.span().append(close_token.span());
257 error.report_error(
258 ParseError::new("unclosed array table")
259 .with_context(context)
260 .with_expected(&[Expected::Literal("]")])
261 .with_unexpected(close_token.span().after()),
262 );
263 }
264 } else {
265 receiver.std_table_close(close_token.span(), error);
266 success = true;
267 }
268 } else if valid_key {
269 let last_key_token = tokens
270 .previous_tokens()
271 .find(|t| t.kind() != TokenKind::Whitespace)
272 .unwrap_or(open_token);
273 let context = open_token.span().append(last_key_token.span());
274 if is_array_table {
275 error.report_error(
276 ParseError::new("unclosed array table")
277 .with_context(context)
278 .with_expected(&[Expected::Literal("]]")])
279 .with_unexpected(last_key_token.span().after()),
280 );
281 } else {
282 error.report_error(
283 ParseError::new("unclosed table")
284 .with_context(context)
285 .with_expected(&[Expected::Literal("]")])
286 .with_unexpected(last_key_token.span().after()),
287 );
288 }
289 }
290
291 if success {
292 ws_comment_newline(tokens, receiver, error);
293 } else {
294 ignore_to_newline(tokens, receiver, error);
295 }
296}
297
298fn key(
315 tokens: &mut Stream<'_>,
316 invalid_description: &'static str,
317 receiver: &mut dyn EventReceiver,
318 error: &mut dyn ErrorSink,
319) -> bool {
320 while let Some(current_token) = tokens.next_token() {
321 let encoding = match current_token.kind() {
322 TokenKind::RightSquareBracket
323 | TokenKind::Comment
324 | TokenKind::Equals
325 | TokenKind::Comma
326 | TokenKind::LeftSquareBracket
327 | TokenKind::LeftCurlyBracket
328 | TokenKind::RightCurlyBracket
329 | TokenKind::Newline
330 | TokenKind::Eof => {
331 let fake_key = current_token.span().before();
332 let encoding = None;
333 receiver.simple_key(fake_key, encoding, error);
334 seek(tokens, -1);
335 return false;
336 }
337 TokenKind::Whitespace => {
338 receiver.whitespace(current_token.span(), error);
339 continue;
340 }
341 TokenKind::Dot => {
342 let fake_key = current_token.span().before();
343 let encoding = None;
344 receiver.simple_key(fake_key, encoding, error);
345 receiver.key_sep(current_token.span(), error);
346 continue;
347 }
348 TokenKind::LiteralString => Some(Encoding::LiteralString),
349 TokenKind::BasicString => Some(Encoding::BasicString),
350 TokenKind::MlLiteralString => Some(Encoding::MlLiteralString),
351 TokenKind::MlBasicString => Some(Encoding::MlBasicString),
352 TokenKind::Atom => None,
353 };
354 receiver.simple_key(current_token.span(), encoding, error);
355 return opt_dot_keys(tokens, receiver, error);
356 }
357
358 let previous_span = tokens
359 .previous_tokens()
360 .find(|t| {
361 !matches!(
362 t.kind(),
363 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
364 )
365 })
366 .map(|t| t.span())
367 .unwrap_or_default();
368 error.report_error(
369 ParseError::new(invalid_description)
370 .with_context(previous_span)
371 .with_expected(&[Expected::Description("key")])
372 .with_unexpected(previous_span.after()),
373 );
374 false
375}
376
377fn on_expression_key<'i>(
389 tokens: &mut Stream<'i>,
390 key_token: &'i Token,
391 encoding: Option<Encoding>,
392 receiver: &mut dyn EventReceiver,
393 error: &mut dyn ErrorSink,
394) {
395 receiver.simple_key(key_token.span(), encoding, error);
396 opt_dot_keys(tokens, receiver, error);
397
398 opt_whitespace(tokens, receiver, error);
399
400 let Some(eq_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Equals)) else {
401 if let Some(peek_token) = tokens.first() {
402 let span = peek_token.span().before();
403 error.report_error(
404 ParseError::new("key with no value")
405 .with_context(span)
406 .with_expected(&[Expected::Literal("=")])
407 .with_unexpected(span),
408 );
409 }
410 ignore_to_newline(tokens, receiver, error);
411 return;
412 };
413 on_expression_key_val_sep(tokens, eq_token, receiver, error);
414}
415
416fn on_expression_dot<'i>(
417 tokens: &mut Stream<'i>,
418 dot_token: &'i Token,
419 receiver: &mut dyn EventReceiver,
420 error: &mut dyn ErrorSink,
421) {
422 receiver.simple_key(dot_token.span().before(), None, error);
423 seek(tokens, -1);
424 opt_dot_keys(tokens, receiver, error);
425
426 opt_whitespace(tokens, receiver, error);
427
428 let Some(eq_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Equals)) else {
429 if let Some(peek_token) = tokens.first() {
430 let span = peek_token.span().before();
431 error.report_error(
432 ParseError::new("missing value for key")
433 .with_context(span)
434 .with_expected(&[Expected::Literal("=")])
435 .with_unexpected(span),
436 );
437 }
438 ignore_to_newline(tokens, receiver, error);
439 return;
440 };
441 on_expression_key_val_sep(tokens, eq_token, receiver, error);
442}
443
444fn on_expression_key_val_sep<'i>(
445 tokens: &mut Stream<'i>,
446 eq_token: &'i Token,
447 receiver: &mut dyn EventReceiver,
448 error: &mut dyn ErrorSink,
449) {
450 receiver.key_val_sep(eq_token.span(), error);
451
452 opt_whitespace(tokens, receiver, error);
453
454 value(tokens, receiver, error);
455
456 ws_comment_newline(tokens, receiver, error);
457}
458
459fn simple_key(
471 tokens: &mut Stream<'_>,
472 invalid_description: &'static str,
473 receiver: &mut dyn EventReceiver,
474 error: &mut dyn ErrorSink,
475) {
476 let Some(current_token) = tokens.next_token() else {
477 let previous_span = tokens
478 .previous_tokens()
479 .find(|t| {
480 !matches!(
481 t.kind(),
482 TokenKind::Whitespace
483 | TokenKind::Comment
484 | TokenKind::Newline
485 | TokenKind::Eof
486 )
487 })
488 .map(|t| t.span())
489 .unwrap_or_default();
490 error.report_error(
491 ParseError::new(invalid_description)
492 .with_context(previous_span)
493 .with_expected(&[Expected::Description("key")])
494 .with_unexpected(previous_span.after()),
495 );
496 return;
497 };
498
499 const EXPECTED_KEYS: [Expected; 3] = [
500 Expected::Description(Encoding::LiteralString.description()),
501 Expected::Description(Encoding::BasicString.description()),
502 Expected::Description(UNQUOTED_STRING),
503 ];
504
505 let kind = match current_token.kind() {
506 TokenKind::Dot
507 | TokenKind::RightSquareBracket
508 | TokenKind::Comment
509 | TokenKind::Equals
510 | TokenKind::Comma
511 | TokenKind::LeftSquareBracket
512 | TokenKind::LeftCurlyBracket
513 | TokenKind::RightCurlyBracket
514 | TokenKind::Newline
515 | TokenKind::Eof
516 | TokenKind::Whitespace => {
517 on_missing_key(tokens, current_token, invalid_description, receiver, error);
518 return;
519 }
520 TokenKind::LiteralString => Some(Encoding::LiteralString),
521 TokenKind::BasicString => Some(Encoding::BasicString),
522 TokenKind::MlLiteralString => {
523 error.report_error(
524 ParseError::new(invalid_description)
525 .with_context(current_token.span())
526 .with_expected(&EXPECTED_KEYS)
527 .with_unexpected(current_token.span()),
528 );
529 Some(Encoding::MlLiteralString)
530 }
531 TokenKind::MlBasicString => {
532 error.report_error(
533 ParseError::new(invalid_description)
534 .with_context(current_token.span())
535 .with_expected(&EXPECTED_KEYS)
536 .with_unexpected(current_token.span()),
537 );
538 Some(Encoding::MlBasicString)
539 }
540 TokenKind::Atom => None,
541 };
542 receiver.simple_key(current_token.span(), kind, error);
543}
544
545fn opt_dot_keys(
564 tokens: &mut Stream<'_>,
565 receiver: &mut dyn EventReceiver,
566 error: &mut dyn ErrorSink,
567) -> bool {
568 opt_whitespace(tokens, receiver, error);
569
570 let mut success = true;
571 'dot: while let Some(dot_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Dot)) {
572 receiver.key_sep(dot_token.span(), error);
573
574 while let Some(current_token) = tokens.next_token() {
575 let kind = match current_token.kind() {
576 TokenKind::Equals
577 | TokenKind::Comma
578 | TokenKind::LeftSquareBracket
579 | TokenKind::RightSquareBracket
580 | TokenKind::LeftCurlyBracket
581 | TokenKind::RightCurlyBracket
582 | TokenKind::Comment
583 | TokenKind::Newline
584 | TokenKind::Eof => {
585 let fake_key = current_token.span().before();
586 let encoding = None;
587 receiver.simple_key(fake_key, encoding, error);
588 seek(tokens, -1);
589
590 success = false;
591 break 'dot;
592 }
593 TokenKind::Whitespace => {
594 receiver.whitespace(current_token.span(), error);
595 continue;
596 }
597 TokenKind::Dot => {
598 let fake_key = current_token.span().before();
599 let encoding = None;
600 receiver.simple_key(fake_key, encoding, error);
601 receiver.key_sep(current_token.span(), error);
602 continue;
603 }
604 TokenKind::LiteralString => Some(Encoding::LiteralString),
605 TokenKind::BasicString => Some(Encoding::BasicString),
606 TokenKind::MlLiteralString => Some(Encoding::MlLiteralString),
607 TokenKind::MlBasicString => Some(Encoding::MlBasicString),
608 TokenKind::Atom => None,
609 };
610 receiver.simple_key(current_token.span(), kind, error);
611 opt_whitespace(tokens, receiver, error);
612 continue 'dot;
613 }
614
615 let fake_key = dot_token.span().after();
616 let encoding = None;
617 receiver.simple_key(fake_key, encoding, error);
618 }
619
620 success
621}
622
623fn value(tokens: &mut Stream<'_>, receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
629 let Some(current_token) = tokens.next_token() else {
630 let previous_span = tokens
631 .previous_tokens()
632 .find(|t| {
633 !matches!(
634 t.kind(),
635 TokenKind::Whitespace
636 | TokenKind::Comment
637 | TokenKind::Newline
638 | TokenKind::Eof
639 )
640 })
641 .map(|t| t.span())
642 .unwrap_or_default();
643 error.report_error(
644 ParseError::new("missing value")
645 .with_context(previous_span)
646 .with_expected(&[Expected::Description("value")])
647 .with_unexpected(previous_span.after()),
648 );
649 return;
650 };
651
652 match current_token.kind() {
653 TokenKind::Comment
654 | TokenKind::Comma
655 | TokenKind::Newline
656 | TokenKind::Eof
657 | TokenKind::Whitespace => {
658 let fake_key = current_token.span().before();
659 let encoding = None;
660 receiver.scalar(fake_key, encoding, error);
661 seek(tokens, -1);
662 }
663 TokenKind::Equals => {
664 error.report_error(
665 ParseError::new("extra `=`")
666 .with_context(current_token.span())
667 .with_expected(&[])
668 .with_unexpected(current_token.span()),
669 );
670 receiver.error(current_token.span(), error);
671 value(tokens, receiver, error);
672 }
673 TokenKind::LeftCurlyBracket => {
674 on_inline_table_open(tokens, current_token, receiver, error);
675 }
676 TokenKind::RightCurlyBracket => {
677 error.report_error(
678 ParseError::new("missing inline table opening")
679 .with_context(current_token.span())
680 .with_expected(&[Expected::Literal("{")])
681 .with_unexpected(current_token.span().before()),
682 );
683
684 let _ = receiver.inline_table_open(current_token.span().before(), error);
685 receiver.inline_table_close(current_token.span(), error);
686 }
687 TokenKind::LeftSquareBracket => {
688 on_array_open(tokens, current_token, receiver, error);
689 }
690 TokenKind::RightSquareBracket => {
691 error.report_error(
692 ParseError::new("missing array opening")
693 .with_context(current_token.span())
694 .with_expected(&[Expected::Literal("[")])
695 .with_unexpected(current_token.span().before()),
696 );
697
698 let _ = receiver.array_open(current_token.span().before(), error);
699 receiver.array_close(current_token.span(), error);
700 }
701 TokenKind::LiteralString
702 | TokenKind::BasicString
703 | TokenKind::MlLiteralString
704 | TokenKind::MlBasicString
705 | TokenKind::Dot
706 | TokenKind::Atom => {
707 on_scalar(tokens, current_token, receiver, error);
708 }
709 }
710}
711
712fn on_scalar(
718 tokens: &mut Stream<'_>,
719 scalar: &Token,
720 receiver: &mut dyn EventReceiver,
721 error: &mut dyn ErrorSink,
722) {
723 let mut span = scalar.span();
724 let encoding = match scalar.kind() {
725 TokenKind::Comment
726 | TokenKind::Comma
727 | TokenKind::Newline
728 | TokenKind::Eof
729 | TokenKind::Whitespace
730 | TokenKind::Equals
731 | TokenKind::LeftCurlyBracket
732 | TokenKind::RightCurlyBracket
733 | TokenKind::LeftSquareBracket
734 | TokenKind::RightSquareBracket => {
735 unreachable!()
736 }
737 TokenKind::LiteralString => Some(Encoding::LiteralString),
738 TokenKind::BasicString => Some(Encoding::BasicString),
739 TokenKind::MlLiteralString => Some(Encoding::MlLiteralString),
740 TokenKind::MlBasicString => Some(Encoding::MlBasicString),
741 TokenKind::Dot | TokenKind::Atom => {
742 while let Some(next_token) = tokens.first() {
743 match next_token.kind() {
744 TokenKind::Comment
745 | TokenKind::Comma
746 | TokenKind::Newline
747 | TokenKind::Eof
748 | TokenKind::Equals
749 | TokenKind::LeftCurlyBracket
750 | TokenKind::RightCurlyBracket
751 | TokenKind::LeftSquareBracket
752 | TokenKind::RightSquareBracket
753 | TokenKind::LiteralString
754 | TokenKind::BasicString
755 | TokenKind::MlLiteralString
756 | TokenKind::MlBasicString => {
757 break;
758 }
759 TokenKind::Whitespace => {
760 if let Some(second) = tokens.get(1) {
761 if second.kind() == TokenKind::Atom {
762 span = span.append(second.span());
763 let _ = tokens.next_slice(2);
764 continue;
765 }
766 }
767 break;
768 }
769 TokenKind::Dot | TokenKind::Atom => {
770 span = span.append(next_token.span());
771 let _ = tokens.next_token();
772 }
773 }
774 }
775 None
776 }
777 };
778 receiver.scalar(span, encoding, error);
779}
780
781fn on_array_open(
792 tokens: &mut Stream<'_>,
793 array_open: &Token,
794 receiver: &mut dyn EventReceiver,
795 error: &mut dyn ErrorSink,
796) {
797 if !receiver.array_open(array_open.span(), error) {
798 ignore_to_value_close(tokens, TokenKind::RightSquareBracket, receiver, error);
799 return;
800 }
801
802 enum State {
803 NeedsValue,
804 NeedsComma,
805 }
806
807 let mut state = State::NeedsValue;
808 while let Some(current_token) = tokens.next_token() {
809 match current_token.kind() {
810 TokenKind::Comment => {
811 on_comment(tokens, current_token, receiver, error);
812 }
813 TokenKind::Whitespace => {
814 receiver.whitespace(current_token.span(), error);
815 }
816 TokenKind::Newline => {
817 receiver.newline(current_token.span(), error);
818 }
819 TokenKind::Eof => {
820 break;
821 }
822 TokenKind::Comma => match state {
823 State::NeedsValue => {
824 error.report_error(
825 ParseError::new("extra comma in array")
826 .with_context(array_open.span())
827 .with_expected(&[Expected::Description("value")])
828 .with_unexpected(current_token.span()),
829 );
830 receiver.error(current_token.span(), error);
831 }
832 State::NeedsComma => {
833 receiver.value_sep(current_token.span(), error);
834
835 state = State::NeedsValue;
836 }
837 },
838 TokenKind::Equals => {
839 error.report_error(
840 ParseError::new("unexpected `=` in array")
841 .with_context(array_open.span())
842 .with_expected(&[Expected::Description("value"), Expected::Literal("]")])
843 .with_unexpected(current_token.span()),
844 );
845 receiver.error(current_token.span(), error);
846 }
847 TokenKind::LeftCurlyBracket => {
848 if !matches!(state, State::NeedsValue) {
849 error.report_error(
850 ParseError::new("missing comma between array elements")
851 .with_context(array_open.span())
852 .with_expected(&[Expected::Literal(",")])
853 .with_unexpected(current_token.span().before()),
854 );
855 receiver.value_sep(current_token.span().before(), error);
856 }
857
858 on_inline_table_open(tokens, current_token, receiver, error);
859
860 state = State::NeedsComma;
861 }
862 TokenKind::RightCurlyBracket => {
863 if !matches!(state, State::NeedsValue) {
864 error.report_error(
865 ParseError::new("missing comma between array elements")
866 .with_context(array_open.span())
867 .with_expected(&[Expected::Literal(",")])
868 .with_unexpected(current_token.span().before()),
869 );
870 receiver.value_sep(current_token.span().before(), error);
871 }
872
873 error.report_error(
874 ParseError::new("missing inline table opening")
875 .with_context(current_token.span())
876 .with_expected(&[Expected::Literal("{")])
877 .with_unexpected(current_token.span().before()),
878 );
879
880 let _ = receiver.inline_table_open(current_token.span().before(), error);
881 receiver.inline_table_close(current_token.span(), error);
882
883 state = State::NeedsComma;
884 }
885 TokenKind::LeftSquareBracket => {
886 if !matches!(state, State::NeedsValue) {
887 error.report_error(
888 ParseError::new("missing comma between array elements")
889 .with_context(array_open.span())
890 .with_expected(&[Expected::Literal(",")])
891 .with_unexpected(current_token.span().before()),
892 );
893 receiver.value_sep(current_token.span().before(), error);
894 }
895
896 on_array_open(tokens, current_token, receiver, error);
897
898 state = State::NeedsComma;
899 }
900 TokenKind::RightSquareBracket => {
901 receiver.array_close(current_token.span(), error);
902
903 return;
904 }
905 TokenKind::LiteralString
906 | TokenKind::BasicString
907 | TokenKind::MlLiteralString
908 | TokenKind::MlBasicString
909 | TokenKind::Dot
910 | TokenKind::Atom => {
911 if !matches!(state, State::NeedsValue) {
912 error.report_error(
913 ParseError::new("missing comma between array elements")
914 .with_context(array_open.span())
915 .with_expected(&[Expected::Literal(",")])
916 .with_unexpected(current_token.span().before()),
917 );
918 receiver.value_sep(current_token.span().before(), error);
919 }
920
921 on_scalar(tokens, current_token, receiver, error);
922
923 state = State::NeedsComma;
924 }
925 }
926 }
927
928 let previous_span = tokens
929 .previous_tokens()
930 .find(|t| {
931 !matches!(
932 t.kind(),
933 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
934 )
935 })
936 .map(|t| t.span())
937 .unwrap_or_default();
938 error.report_error(
939 ParseError::new("unclosed array")
940 .with_context(array_open.span())
941 .with_expected(&[Expected::Literal("]")])
942 .with_unexpected(previous_span.after()),
943 );
944 receiver.array_close(previous_span.after(), error);
945}
946
947fn on_inline_table_open(
958 tokens: &mut Stream<'_>,
959 inline_table_open: &Token,
960 receiver: &mut dyn EventReceiver,
961 error: &mut dyn ErrorSink,
962) {
963 if !receiver.inline_table_open(inline_table_open.span(), error) {
964 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
965 return;
966 }
967
968 #[allow(clippy::enum_variant_names)]
969 #[derive(Debug)]
970 enum State {
971 NeedsKey,
972 NeedsEquals,
973 NeedsValue,
974 NeedsComma,
975 }
976
977 impl State {
978 fn expected(&self) -> &'static [Expected] {
979 match self {
980 Self::NeedsKey => &[Expected::Description("key")],
981 Self::NeedsEquals => &[Expected::Literal("=")],
982 Self::NeedsValue => &[Expected::Description("value")],
983 Self::NeedsComma => &[Expected::Literal(",")],
984 }
985 }
986 }
987
988 let mut state = State::NeedsKey;
989 while let Some(current_token) = tokens.next_token() {
990 match current_token.kind() {
991 TokenKind::Comment => {
992 on_comment(tokens, current_token, receiver, error);
993 }
994 TokenKind::Whitespace => {
995 receiver.whitespace(current_token.span(), error);
996 }
997 TokenKind::Newline => {
998 receiver.newline(current_token.span(), error);
999 }
1000 TokenKind::Eof => {
1001 break;
1002 }
1003 TokenKind::Comma => match state {
1004 State::NeedsKey | State::NeedsEquals | State::NeedsValue => {
1005 error.report_error(
1006 ParseError::new("extra comma in inline table")
1007 .with_context(inline_table_open.span())
1008 .with_expected(state.expected())
1009 .with_unexpected(current_token.span().before()),
1010 );
1011 receiver.error(current_token.span(), error);
1012 }
1013 State::NeedsComma => {
1014 receiver.value_sep(current_token.span(), error);
1015
1016 state = State::NeedsKey;
1017 }
1018 },
1019 TokenKind::Equals => match state {
1020 State::NeedsKey => {
1021 let fake_key = current_token.span().before();
1022 let encoding = None;
1023 receiver.simple_key(fake_key, encoding, error);
1024
1025 receiver.key_val_sep(current_token.span(), error);
1026
1027 state = State::NeedsValue;
1028 }
1029 State::NeedsEquals => {
1030 receiver.key_val_sep(current_token.span(), error);
1031
1032 state = State::NeedsValue;
1033 }
1034 State::NeedsValue | State::NeedsComma => {
1035 error.report_error(
1036 ParseError::new("extra assignment between key-value pairs")
1037 .with_context(inline_table_open.span())
1038 .with_expected(state.expected())
1039 .with_unexpected(current_token.span().before()),
1040 );
1041 receiver.error(current_token.span(), error);
1042 }
1043 },
1044 TokenKind::LeftCurlyBracket => match state {
1045 State::NeedsKey | State::NeedsComma => {
1046 error.report_error(
1047 ParseError::new("missing key for inline table element")
1048 .with_context(inline_table_open.span())
1049 .with_expected(state.expected())
1050 .with_unexpected(current_token.span().before()),
1051 );
1052 receiver.error(current_token.span(), error);
1053 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
1054 }
1055 State::NeedsEquals => {
1056 error.report_error(
1057 ParseError::new("missing assignment between key-value pairs")
1058 .with_context(inline_table_open.span())
1059 .with_expected(state.expected())
1060 .with_unexpected(current_token.span().before()),
1061 );
1062
1063 on_inline_table_open(tokens, current_token, receiver, error);
1064
1065 state = State::NeedsComma;
1066 }
1067 State::NeedsValue => {
1068 on_inline_table_open(tokens, current_token, receiver, error);
1069
1070 state = State::NeedsComma;
1071 }
1072 },
1073 TokenKind::RightCurlyBracket => {
1074 match state {
1075 State::NeedsKey => {}
1076 State::NeedsEquals => {
1077 receiver.key_val_sep(current_token.span().before(), error);
1078 receiver.scalar(
1079 current_token.span().before(),
1080 Some(Encoding::LiteralString),
1081 error,
1082 );
1083 }
1084 State::NeedsValue => {
1085 receiver.scalar(
1086 current_token.span().before(),
1087 Some(Encoding::LiteralString),
1088 error,
1089 );
1090 }
1091 State::NeedsComma => {}
1092 }
1093 receiver.inline_table_close(current_token.span(), error);
1094
1095 return;
1096 }
1097 TokenKind::LeftSquareBracket => match state {
1098 State::NeedsKey | State::NeedsComma => {
1099 error.report_error(
1100 ParseError::new("missing key for inline table element")
1101 .with_context(inline_table_open.span())
1102 .with_expected(state.expected())
1103 .with_unexpected(current_token.span().before()),
1104 );
1105 receiver.error(current_token.span(), error);
1106 ignore_to_value_close(tokens, TokenKind::RightSquareBracket, receiver, error);
1107 }
1108 State::NeedsEquals => {
1109 error.report_error(
1110 ParseError::new("missing assignment between key-value pairs")
1111 .with_context(inline_table_open.span())
1112 .with_expected(state.expected())
1113 .with_unexpected(current_token.span().before()),
1114 );
1115
1116 on_array_open(tokens, current_token, receiver, error);
1117
1118 state = State::NeedsComma;
1119 }
1120 State::NeedsValue => {
1121 on_array_open(tokens, current_token, receiver, error);
1122
1123 state = State::NeedsComma;
1124 }
1125 },
1126 TokenKind::RightSquareBracket => match state {
1127 State::NeedsKey | State::NeedsEquals | State::NeedsComma => {
1128 error.report_error(
1129 ParseError::new("invalid inline table element")
1130 .with_context(inline_table_open.span())
1131 .with_expected(state.expected())
1132 .with_unexpected(current_token.span().before()),
1133 );
1134 receiver.error(current_token.span(), error);
1135 }
1136 State::NeedsValue => {
1137 error.report_error(
1138 ParseError::new("missing array opening")
1139 .with_context(current_token.span())
1140 .with_expected(&[Expected::Literal("[")])
1141 .with_unexpected(current_token.span().before()),
1142 );
1143
1144 let _ = receiver.array_open(current_token.span().before(), error);
1145 receiver.array_close(current_token.span(), error);
1146
1147 state = State::NeedsComma;
1148 }
1149 },
1150 TokenKind::LiteralString
1151 | TokenKind::BasicString
1152 | TokenKind::MlLiteralString
1153 | TokenKind::MlBasicString
1154 | TokenKind::Dot
1155 | TokenKind::Atom => match state {
1156 State::NeedsKey => {
1157 if current_token.kind() == TokenKind::Dot {
1158 receiver.simple_key(
1159 current_token.span().before(),
1160 current_token.kind().encoding(),
1161 error,
1162 );
1163 seek(tokens, -1);
1164 opt_dot_keys(tokens, receiver, error);
1165 state = State::NeedsEquals;
1166 } else {
1167 receiver.simple_key(
1168 current_token.span(),
1169 current_token.kind().encoding(),
1170 error,
1171 );
1172 opt_dot_keys(tokens, receiver, error);
1173 state = State::NeedsEquals;
1174 }
1175 }
1176 State::NeedsEquals => {
1177 error.report_error(
1178 ParseError::new("missing assignment between key-value pairs")
1179 .with_context(inline_table_open.span())
1180 .with_expected(state.expected())
1181 .with_unexpected(current_token.span().before()),
1182 );
1183
1184 on_scalar(tokens, current_token, receiver, error);
1185
1186 state = State::NeedsComma;
1187 }
1188 State::NeedsValue => {
1189 on_scalar(tokens, current_token, receiver, error);
1190
1191 state = State::NeedsComma;
1192 }
1193 State::NeedsComma => {
1194 error.report_error(
1195 ParseError::new("missing comma between key-value pairs")
1196 .with_context(inline_table_open.span())
1197 .with_expected(state.expected())
1198 .with_unexpected(current_token.span().before()),
1199 );
1200
1201 if current_token.kind() == TokenKind::Dot {
1202 receiver.simple_key(
1203 current_token.span().before(),
1204 current_token.kind().encoding(),
1205 error,
1206 );
1207 seek(tokens, -1);
1208 opt_dot_keys(tokens, receiver, error);
1209 state = State::NeedsEquals;
1210 } else {
1211 receiver.simple_key(
1212 current_token.span(),
1213 current_token.kind().encoding(),
1214 error,
1215 );
1216 opt_dot_keys(tokens, receiver, error);
1217 state = State::NeedsEquals;
1218 }
1219 }
1220 },
1221 }
1222 }
1223
1224 let previous_span = tokens
1225 .previous_tokens()
1226 .find(|t| {
1227 !matches!(
1228 t.kind(),
1229 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
1230 )
1231 })
1232 .map(|t| t.span())
1233 .unwrap_or_default();
1234 match state {
1235 State::NeedsKey => {}
1236 State::NeedsEquals => {
1237 receiver.key_val_sep(previous_span.after(), error);
1238 receiver.scalar(previous_span.after(), Some(Encoding::LiteralString), error);
1239 }
1240 State::NeedsValue => {
1241 receiver.scalar(previous_span.after(), Some(Encoding::LiteralString), error);
1242 }
1243 State::NeedsComma => {}
1244 }
1245 error.report_error(
1246 ParseError::new("unclosed inline table")
1247 .with_context(inline_table_open.span())
1248 .with_expected(&[Expected::Literal("}")])
1249 .with_unexpected(previous_span.after()),
1250 );
1251 receiver.inline_table_close(previous_span.after(), error);
1252}
1253
1254fn opt_whitespace(
1260 tokens: &mut Stream<'_>,
1261 receiver: &mut dyn EventReceiver,
1262 error: &mut dyn ErrorSink,
1263) {
1264 if let Some(ws_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Whitespace)) {
1265 receiver.whitespace(ws_token.span(), error);
1266 }
1267}
1268
1269fn ws_comment_newline(
1294 tokens: &mut Stream<'_>,
1295 receiver: &mut dyn EventReceiver,
1296 error: &mut dyn ErrorSink,
1297) {
1298 let mut first = None;
1299 while let Some(current_token) = tokens.next_token() {
1300 let first = first.get_or_insert(current_token.span());
1301 match current_token.kind() {
1302 TokenKind::Dot
1303 | TokenKind::Equals
1304 | TokenKind::Comma
1305 | TokenKind::LeftSquareBracket
1306 | TokenKind::RightSquareBracket
1307 | TokenKind::LeftCurlyBracket
1308 | TokenKind::RightCurlyBracket
1309 | TokenKind::LiteralString
1310 | TokenKind::BasicString
1311 | TokenKind::MlLiteralString
1312 | TokenKind::MlBasicString
1313 | TokenKind::Atom => {
1314 let context = first.append(current_token.span());
1315 error.report_error(
1316 ParseError::new("unexpected key or value")
1317 .with_context(context)
1318 .with_expected(&[Expected::Literal("\n"), Expected::Literal("#")])
1319 .with_unexpected(current_token.span().before()),
1320 );
1321
1322 receiver.error(current_token.span(), error);
1323 ignore_to_newline(tokens, receiver, error);
1324 break;
1325 }
1326 TokenKind::Comment => {
1327 on_comment(tokens, current_token, receiver, error);
1328 break;
1329 }
1330 TokenKind::Whitespace => {
1331 receiver.whitespace(current_token.span(), error);
1332 continue;
1333 }
1334 TokenKind::Newline => {
1335 receiver.newline(current_token.span(), error);
1336 break;
1337 }
1338 TokenKind::Eof => {
1339 break;
1340 }
1341 }
1342 }
1343}
1344
1345fn on_comment(
1347 tokens: &mut Stream<'_>,
1348 comment_token: &Token,
1349 receiver: &mut dyn EventReceiver,
1350 error: &mut dyn ErrorSink,
1351) {
1352 receiver.comment(comment_token.span(), error);
1353
1354 let Some(current_token) = tokens.next_token() else {
1355 return;
1356 };
1357 match current_token.kind() {
1358 TokenKind::Dot
1359 | TokenKind::Equals
1360 | TokenKind::Comma
1361 | TokenKind::LeftSquareBracket
1362 | TokenKind::RightSquareBracket
1363 | TokenKind::LeftCurlyBracket
1364 | TokenKind::RightCurlyBracket
1365 | TokenKind::Whitespace
1366 | TokenKind::Comment
1367 | TokenKind::LiteralString
1368 | TokenKind::BasicString
1369 | TokenKind::MlLiteralString
1370 | TokenKind::MlBasicString
1371 | TokenKind::Atom => {
1372 let context = comment_token.span().append(current_token.span());
1373 error.report_error(
1374 ParseError::new("unexpected content between comment and newline")
1375 .with_context(context)
1376 .with_expected(&[Expected::Literal("\n")])
1377 .with_unexpected(current_token.span().before()),
1378 );
1379
1380 receiver.error(current_token.span(), error);
1381 ignore_to_newline(tokens, receiver, error);
1382 }
1383 TokenKind::Newline => {
1384 receiver.newline(current_token.span(), error);
1385 }
1386 TokenKind::Eof => {}
1387 }
1388}
1389
1390fn eof(tokens: &mut Stream<'_>, receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
1391 let Some(current_token) = tokens.next_token() else {
1392 return;
1393 };
1394
1395 match current_token.kind() {
1396 TokenKind::Dot
1397 | TokenKind::Equals
1398 | TokenKind::Comma
1399 | TokenKind::LeftSquareBracket
1400 | TokenKind::RightSquareBracket
1401 | TokenKind::LeftCurlyBracket
1402 | TokenKind::RightCurlyBracket
1403 | TokenKind::LiteralString
1404 | TokenKind::BasicString
1405 | TokenKind::MlLiteralString
1406 | TokenKind::MlBasicString
1407 | TokenKind::Atom
1408 | TokenKind::Comment
1409 | TokenKind::Whitespace
1410 | TokenKind::Newline => {
1411 error.report_error(
1412 ParseError::new("unexpected content")
1413 .with_context(current_token.span())
1414 .with_expected(&[])
1415 .with_unexpected(current_token.span().before()),
1416 );
1417
1418 receiver.error(current_token.span(), error);
1419 while let Some(current_token) = tokens.next_token() {
1420 if current_token.kind() == TokenKind::Eof {
1421 continue;
1422 }
1423 receiver.error(current_token.span(), error);
1424 }
1425 }
1426 TokenKind::Eof => {}
1427 }
1428}
1429
1430#[cold]
1432fn ignore_to_newline(
1433 tokens: &mut Stream<'_>,
1434 receiver: &mut dyn EventReceiver,
1435 error: &mut dyn ErrorSink,
1436) {
1437 while let Some(current_token) = tokens.next_token() {
1438 match current_token.kind() {
1439 TokenKind::Dot
1440 | TokenKind::Equals
1441 | TokenKind::Comma
1442 | TokenKind::LeftSquareBracket
1443 | TokenKind::RightSquareBracket
1444 | TokenKind::LeftCurlyBracket
1445 | TokenKind::RightCurlyBracket
1446 | TokenKind::LiteralString
1447 | TokenKind::BasicString
1448 | TokenKind::MlLiteralString
1449 | TokenKind::MlBasicString
1450 | TokenKind::Atom => {
1451 receiver.error(current_token.span(), error);
1452 }
1453 TokenKind::Comment => {
1454 on_comment(tokens, current_token, receiver, error);
1455 break;
1456 }
1457 TokenKind::Whitespace => {
1458 receiver.whitespace(current_token.span(), error);
1459 }
1460 TokenKind::Newline => {
1461 receiver.newline(current_token.span(), error);
1462 break;
1463 }
1464 TokenKind::Eof => {
1465 break;
1466 }
1467 }
1468 }
1469}
1470
1471#[cold]
1475fn ignore_to_value_close(
1476 tokens: &mut Stream<'_>,
1477 closing_kind: TokenKind,
1478 receiver: &mut dyn EventReceiver,
1479 error: &mut dyn ErrorSink,
1480) {
1481 let mut array_count: usize = 0;
1482 let mut inline_table_count: usize = 0;
1483 while let Some(current_token) = tokens.next_token() {
1484 match current_token.kind() {
1485 TokenKind::Dot
1486 | TokenKind::Equals
1487 | TokenKind::Comma
1488 | TokenKind::LiteralString
1489 | TokenKind::BasicString
1490 | TokenKind::MlLiteralString
1491 | TokenKind::MlBasicString
1492 | TokenKind::Atom => {
1493 receiver.error(current_token.span(), error);
1494 }
1495 TokenKind::Comment => {
1496 on_comment(tokens, current_token, receiver, error);
1497 }
1498 TokenKind::Whitespace => {
1499 receiver.whitespace(current_token.span(), error);
1500 }
1501 TokenKind::Newline => {
1502 receiver.newline(current_token.span(), error);
1503 }
1504 TokenKind::LeftSquareBracket => {
1505 receiver.error(current_token.span(), error);
1506 array_count += 1;
1507 }
1508 TokenKind::RightSquareBracket => {
1509 if array_count == 0 && current_token.kind() == closing_kind {
1510 receiver.array_close(current_token.span(), error);
1511 break;
1512 } else {
1513 receiver.error(current_token.span(), error);
1514 array_count = array_count.saturating_sub(1);
1515 }
1516 }
1517 TokenKind::LeftCurlyBracket => {
1518 receiver.error(current_token.span(), error);
1519 inline_table_count += 1;
1520 }
1521 TokenKind::RightCurlyBracket => {
1522 if inline_table_count == 0 && current_token.kind() == closing_kind {
1523 receiver.inline_table_close(current_token.span(), error);
1524 break;
1525 } else {
1526 receiver.error(current_token.span(), error);
1527 inline_table_count = inline_table_count.saturating_sub(1);
1528 }
1529 }
1530 TokenKind::Eof => {
1531 break;
1532 }
1533 }
1534 }
1535}
1536
1537#[cold]
1538fn on_missing_key(
1539 tokens: &mut Stream<'_>,
1540 token: &Token,
1541 invalid_description: &'static str,
1542 receiver: &mut dyn EventReceiver,
1543 error: &mut dyn ErrorSink,
1544) {
1545 error.report_error(
1546 ParseError::new(invalid_description)
1547 .with_context(token.span())
1548 .with_expected(&[Expected::Description("key")])
1549 .with_unexpected(token.span().before()),
1550 );
1551
1552 if token.kind() == TokenKind::Eof {
1553 } else if token.kind() == TokenKind::Newline {
1554 receiver.newline(token.span(), error);
1555 } else if token.kind() == TokenKind::Comment {
1556 on_comment(tokens, token, receiver, error);
1557 } else {
1558 receiver.error(token.span(), error);
1559 }
1560}
1561
1562#[cold]
1563fn on_missing_expression_key(
1564 tokens: &mut Stream<'_>,
1565 token: &Token,
1566 receiver: &mut dyn EventReceiver,
1567 error: &mut dyn ErrorSink,
1568) {
1569 error.report_error(
1570 ParseError::new("invalid key-value pair")
1571 .with_context(token.span())
1572 .with_expected(&[Expected::Description("key")])
1573 .with_unexpected(token.span().before()),
1574 );
1575
1576 receiver.error(token.span(), error);
1577 ignore_to_newline(tokens, receiver, error);
1578}
1579
1580#[cold]
1581fn on_missing_std_table(
1582 tokens: &mut Stream<'_>,
1583 token: &Token,
1584 receiver: &mut dyn EventReceiver,
1585 error: &mut dyn ErrorSink,
1586) {
1587 error.report_error(
1588 ParseError::new("missing table open")
1589 .with_context(token.span())
1590 .with_expected(&[Expected::Literal("[")])
1591 .with_unexpected(token.span().before()),
1592 );
1593
1594 receiver.error(token.span(), error);
1595 ignore_to_newline(tokens, receiver, error);
1596}
1597
1598fn next_token_if<'i, F: Fn(TokenKind) -> bool>(
1599 tokens: &mut Stream<'i>,
1600 pred: F,
1601) -> Option<&'i Token> {
1602 match tokens.first() {
1603 Some(next) if pred(next.kind()) => tokens.next_token(),
1604 _ => None,
1605 }
1606}
1607
1608fn seek(stream: &mut Stream<'_>, offset: isize) {
1609 let current = stream.checkpoint();
1610 stream.reset_to_start();
1611 let start = stream.checkpoint();
1612 let old_offset = current.offset_from(&start);
1613 let new_offset = (old_offset as isize).saturating_add(offset) as usize;
1614 if new_offset < stream.eof_offset() {
1615 #[cfg(feature = "unsafe")] unsafe {
1617 stream.next_slice_unchecked(new_offset)
1618 };
1619 #[cfg(not(feature = "unsafe"))]
1620 stream.next_slice(new_offset);
1621 } else {
1622 stream.finish();
1623 }
1624}
1625
1626const UNQUOTED_STRING: &str = "unquoted string";