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 error.report_error(
821 ParseError::new("unclosed array")
822 .with_context(array_open.span())
823 .with_expected(&[Expected::Literal("]")])
824 .with_unexpected(current_token.span()),
825 );
826 receiver.array_close(current_token.span().before(), error);
827 return;
828 }
829 TokenKind::Comma => match state {
830 State::NeedsValue => {
831 error.report_error(
832 ParseError::new("extra comma in array")
833 .with_context(array_open.span())
834 .with_expected(&[Expected::Description("value")])
835 .with_unexpected(current_token.span()),
836 );
837 receiver.error(current_token.span(), error);
838 }
839 State::NeedsComma => {
840 receiver.value_sep(current_token.span(), error);
841
842 state = State::NeedsValue;
843 }
844 },
845 TokenKind::Equals => {
846 error.report_error(
847 ParseError::new("unexpected `=` in array")
848 .with_context(array_open.span())
849 .with_expected(&[Expected::Description("value"), Expected::Literal("]")])
850 .with_unexpected(current_token.span()),
851 );
852 receiver.error(current_token.span(), error);
853 }
854 TokenKind::LeftCurlyBracket => {
855 if !matches!(state, State::NeedsValue) {
856 error.report_error(
857 ParseError::new("missing comma between array elements")
858 .with_context(array_open.span())
859 .with_expected(&[Expected::Literal(",")])
860 .with_unexpected(current_token.span().before()),
861 );
862 receiver.value_sep(current_token.span().before(), error);
863 }
864
865 on_inline_table_open(tokens, current_token, receiver, error);
866
867 state = State::NeedsComma;
868 }
869 TokenKind::RightCurlyBracket => {
870 if !matches!(state, State::NeedsValue) {
871 error.report_error(
872 ParseError::new("missing comma between array elements")
873 .with_context(array_open.span())
874 .with_expected(&[Expected::Literal(",")])
875 .with_unexpected(current_token.span().before()),
876 );
877 receiver.value_sep(current_token.span().before(), error);
878 }
879
880 error.report_error(
881 ParseError::new("missing inline table opening")
882 .with_context(current_token.span())
883 .with_expected(&[Expected::Literal("{")])
884 .with_unexpected(current_token.span().before()),
885 );
886
887 let _ = receiver.inline_table_open(current_token.span().before(), error);
888 receiver.inline_table_close(current_token.span(), error);
889
890 state = State::NeedsComma;
891 }
892 TokenKind::LeftSquareBracket => {
893 if !matches!(state, State::NeedsValue) {
894 error.report_error(
895 ParseError::new("missing comma between array elements")
896 .with_context(array_open.span())
897 .with_expected(&[Expected::Literal(",")])
898 .with_unexpected(current_token.span().before()),
899 );
900 receiver.value_sep(current_token.span().before(), error);
901 }
902
903 on_array_open(tokens, current_token, receiver, error);
904
905 state = State::NeedsComma;
906 }
907 TokenKind::RightSquareBracket => {
908 receiver.array_close(current_token.span(), error);
909
910 return;
911 }
912 TokenKind::LiteralString
913 | TokenKind::BasicString
914 | TokenKind::MlLiteralString
915 | TokenKind::MlBasicString
916 | TokenKind::Dot
917 | TokenKind::Atom => {
918 if !matches!(state, State::NeedsValue) {
919 error.report_error(
920 ParseError::new("missing comma between array elements")
921 .with_context(array_open.span())
922 .with_expected(&[Expected::Literal(",")])
923 .with_unexpected(current_token.span().before()),
924 );
925 receiver.value_sep(current_token.span().before(), error);
926 }
927
928 on_scalar(tokens, current_token, receiver, error);
929
930 state = State::NeedsComma;
931 }
932 }
933 }
934
935 let previous_span = tokens
936 .previous_tokens()
937 .find(|t| {
938 !matches!(
939 t.kind(),
940 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
941 )
942 })
943 .map(|t| t.span())
944 .unwrap_or_default();
945 error.report_error(
946 ParseError::new("unclosed array")
947 .with_context(array_open.span())
948 .with_expected(&[Expected::Literal("]")])
949 .with_unexpected(previous_span.after()),
950 );
951 receiver.array_close(previous_span.after(), error);
952}
953
954fn on_inline_table_open(
965 tokens: &mut Stream<'_>,
966 inline_table_open: &Token,
967 receiver: &mut dyn EventReceiver,
968 error: &mut dyn ErrorSink,
969) {
970 if !receiver.inline_table_open(inline_table_open.span(), error) {
971 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
972 return;
973 }
974
975 #[allow(clippy::enum_variant_names)]
976 #[derive(Debug)]
977 enum State {
978 NeedsKey,
979 NeedsEquals,
980 NeedsValue,
981 NeedsComma,
982 }
983
984 impl State {
985 fn expected(&self) -> &'static [Expected] {
986 match self {
987 Self::NeedsKey => &[Expected::Description("key")],
988 Self::NeedsEquals => &[Expected::Literal("=")],
989 Self::NeedsValue => &[Expected::Description("value")],
990 Self::NeedsComma => &[Expected::Literal(",")],
991 }
992 }
993 }
994
995 let mut state = State::NeedsKey;
996 while let Some(current_token) = tokens.next_token() {
997 match current_token.kind() {
998 TokenKind::Comment => {
999 on_comment(tokens, current_token, receiver, error);
1000 }
1001 TokenKind::Whitespace => {
1002 receiver.whitespace(current_token.span(), error);
1003 }
1004 TokenKind::Newline => {
1005 receiver.newline(current_token.span(), error);
1006 }
1007 TokenKind::Eof => {
1008 error.report_error(
1009 ParseError::new("unclosed inline table")
1010 .with_context(inline_table_open.span())
1011 .with_expected(&[Expected::Literal("}")])
1012 .with_unexpected(current_token.span()),
1013 );
1014
1015 receiver.inline_table_close(current_token.span().before(), error);
1016 return;
1017 }
1018 TokenKind::Comma => match state {
1019 State::NeedsKey | State::NeedsEquals | State::NeedsValue => {
1020 error.report_error(
1021 ParseError::new("extra comma in inline table")
1022 .with_context(inline_table_open.span())
1023 .with_expected(state.expected())
1024 .with_unexpected(current_token.span().before()),
1025 );
1026 receiver.error(current_token.span(), error);
1027 }
1028 State::NeedsComma => {
1029 receiver.value_sep(current_token.span(), error);
1030
1031 state = State::NeedsKey;
1032 }
1033 },
1034 TokenKind::Equals => match state {
1035 State::NeedsKey => {
1036 let fake_key = current_token.span().before();
1037 let encoding = None;
1038 receiver.simple_key(fake_key, encoding, error);
1039
1040 receiver.key_val_sep(current_token.span(), error);
1041
1042 state = State::NeedsValue;
1043 }
1044 State::NeedsEquals => {
1045 receiver.key_val_sep(current_token.span(), error);
1046
1047 state = State::NeedsValue;
1048 }
1049 State::NeedsValue | State::NeedsComma => {
1050 error.report_error(
1051 ParseError::new("extra assignment between key-value pairs")
1052 .with_context(inline_table_open.span())
1053 .with_expected(state.expected())
1054 .with_unexpected(current_token.span().before()),
1055 );
1056 receiver.error(current_token.span(), error);
1057 }
1058 },
1059 TokenKind::LeftCurlyBracket => match state {
1060 State::NeedsKey | State::NeedsComma => {
1061 error.report_error(
1062 ParseError::new("missing key for inline table element")
1063 .with_context(inline_table_open.span())
1064 .with_expected(state.expected())
1065 .with_unexpected(current_token.span().before()),
1066 );
1067 receiver.error(current_token.span(), error);
1068 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
1069 }
1070 State::NeedsEquals => {
1071 error.report_error(
1072 ParseError::new("missing assignment between key-value pairs")
1073 .with_context(inline_table_open.span())
1074 .with_expected(state.expected())
1075 .with_unexpected(current_token.span().before()),
1076 );
1077
1078 on_inline_table_open(tokens, current_token, receiver, error);
1079
1080 state = State::NeedsComma;
1081 }
1082 State::NeedsValue => {
1083 on_inline_table_open(tokens, current_token, receiver, error);
1084
1085 state = State::NeedsComma;
1086 }
1087 },
1088 TokenKind::RightCurlyBracket => {
1089 receiver.inline_table_close(current_token.span(), error);
1090
1091 return;
1092 }
1093 TokenKind::LeftSquareBracket => match state {
1094 State::NeedsKey | State::NeedsComma => {
1095 error.report_error(
1096 ParseError::new("missing key for inline table element")
1097 .with_context(inline_table_open.span())
1098 .with_expected(state.expected())
1099 .with_unexpected(current_token.span().before()),
1100 );
1101 receiver.error(current_token.span(), error);
1102 ignore_to_value_close(tokens, TokenKind::RightSquareBracket, receiver, error);
1103 }
1104 State::NeedsEquals => {
1105 error.report_error(
1106 ParseError::new("missing assignment between key-value pairs")
1107 .with_context(inline_table_open.span())
1108 .with_expected(state.expected())
1109 .with_unexpected(current_token.span().before()),
1110 );
1111
1112 on_array_open(tokens, current_token, receiver, error);
1113
1114 state = State::NeedsComma;
1115 }
1116 State::NeedsValue => {
1117 on_array_open(tokens, current_token, receiver, error);
1118
1119 state = State::NeedsComma;
1120 }
1121 },
1122 TokenKind::RightSquareBracket => match state {
1123 State::NeedsKey | State::NeedsEquals | State::NeedsComma => {
1124 error.report_error(
1125 ParseError::new("invalid inline table element")
1126 .with_context(inline_table_open.span())
1127 .with_expected(state.expected())
1128 .with_unexpected(current_token.span().before()),
1129 );
1130 receiver.error(current_token.span(), error);
1131 }
1132 State::NeedsValue => {
1133 error.report_error(
1134 ParseError::new("missing array opening")
1135 .with_context(current_token.span())
1136 .with_expected(&[Expected::Literal("[")])
1137 .with_unexpected(current_token.span().before()),
1138 );
1139
1140 let _ = receiver.array_open(current_token.span().before(), error);
1141 receiver.array_close(current_token.span(), error);
1142
1143 state = State::NeedsComma;
1144 }
1145 },
1146 TokenKind::LiteralString
1147 | TokenKind::BasicString
1148 | TokenKind::MlLiteralString
1149 | TokenKind::MlBasicString
1150 | TokenKind::Dot
1151 | TokenKind::Atom => match state {
1152 State::NeedsKey => {
1153 if current_token.kind() == TokenKind::Dot {
1154 receiver.simple_key(
1155 current_token.span().before(),
1156 current_token.kind().encoding(),
1157 error,
1158 );
1159 seek(tokens, -1);
1160 opt_dot_keys(tokens, receiver, error);
1161 state = State::NeedsEquals;
1162 } else {
1163 receiver.simple_key(
1164 current_token.span(),
1165 current_token.kind().encoding(),
1166 error,
1167 );
1168 opt_dot_keys(tokens, receiver, error);
1169 state = State::NeedsEquals;
1170 }
1171 }
1172 State::NeedsEquals => {
1173 error.report_error(
1174 ParseError::new("missing assignment between key-value pairs")
1175 .with_context(inline_table_open.span())
1176 .with_expected(state.expected())
1177 .with_unexpected(current_token.span().before()),
1178 );
1179
1180 on_scalar(tokens, current_token, receiver, error);
1181
1182 state = State::NeedsComma;
1183 }
1184 State::NeedsValue => {
1185 on_scalar(tokens, current_token, receiver, error);
1186
1187 state = State::NeedsComma;
1188 }
1189 State::NeedsComma => {
1190 error.report_error(
1191 ParseError::new("missing comma between key-value pairs")
1192 .with_context(inline_table_open.span())
1193 .with_expected(state.expected())
1194 .with_unexpected(current_token.span().before()),
1195 );
1196
1197 if current_token.kind() == TokenKind::Dot {
1198 receiver.simple_key(
1199 current_token.span().before(),
1200 current_token.kind().encoding(),
1201 error,
1202 );
1203 seek(tokens, -1);
1204 opt_dot_keys(tokens, receiver, error);
1205 state = State::NeedsEquals;
1206 } else {
1207 receiver.simple_key(
1208 current_token.span(),
1209 current_token.kind().encoding(),
1210 error,
1211 );
1212 opt_dot_keys(tokens, receiver, error);
1213 state = State::NeedsEquals;
1214 }
1215 }
1216 },
1217 }
1218 }
1219
1220 let previous_span = tokens
1221 .previous_tokens()
1222 .find(|t| {
1223 !matches!(
1224 t.kind(),
1225 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
1226 )
1227 })
1228 .map(|t| t.span())
1229 .unwrap_or_default();
1230 error.report_error(
1231 ParseError::new("unclosed inline table")
1232 .with_context(inline_table_open.span())
1233 .with_expected(&[Expected::Literal("}")])
1234 .with_unexpected(previous_span.after()),
1235 );
1236 receiver.array_close(previous_span.after(), error);
1237}
1238
1239fn opt_whitespace(
1245 tokens: &mut Stream<'_>,
1246 receiver: &mut dyn EventReceiver,
1247 error: &mut dyn ErrorSink,
1248) {
1249 if let Some(ws_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Whitespace)) {
1250 receiver.whitespace(ws_token.span(), error);
1251 }
1252}
1253
1254fn ws_comment_newline(
1279 tokens: &mut Stream<'_>,
1280 receiver: &mut dyn EventReceiver,
1281 error: &mut dyn ErrorSink,
1282) {
1283 let mut first = None;
1284 while let Some(current_token) = tokens.next_token() {
1285 let first = first.get_or_insert(current_token.span());
1286 match current_token.kind() {
1287 TokenKind::Dot
1288 | TokenKind::Equals
1289 | TokenKind::Comma
1290 | TokenKind::LeftSquareBracket
1291 | TokenKind::RightSquareBracket
1292 | TokenKind::LeftCurlyBracket
1293 | TokenKind::RightCurlyBracket
1294 | TokenKind::LiteralString
1295 | TokenKind::BasicString
1296 | TokenKind::MlLiteralString
1297 | TokenKind::MlBasicString
1298 | TokenKind::Atom => {
1299 let context = first.append(current_token.span());
1300 error.report_error(
1301 ParseError::new("unexpected key or value")
1302 .with_context(context)
1303 .with_expected(&[Expected::Literal("\n"), Expected::Literal("#")])
1304 .with_unexpected(current_token.span().before()),
1305 );
1306
1307 receiver.error(current_token.span(), error);
1308 ignore_to_newline(tokens, receiver, error);
1309 break;
1310 }
1311 TokenKind::Comment => {
1312 on_comment(tokens, current_token, receiver, error);
1313 break;
1314 }
1315 TokenKind::Whitespace => {
1316 receiver.whitespace(current_token.span(), error);
1317 continue;
1318 }
1319 TokenKind::Newline => {
1320 receiver.newline(current_token.span(), error);
1321 break;
1322 }
1323 TokenKind::Eof => {
1324 break;
1325 }
1326 }
1327 }
1328}
1329
1330fn on_comment(
1332 tokens: &mut Stream<'_>,
1333 comment_token: &Token,
1334 receiver: &mut dyn EventReceiver,
1335 error: &mut dyn ErrorSink,
1336) {
1337 receiver.comment(comment_token.span(), error);
1338
1339 let Some(current_token) = tokens.next_token() else {
1340 return;
1341 };
1342 match current_token.kind() {
1343 TokenKind::Dot
1344 | TokenKind::Equals
1345 | TokenKind::Comma
1346 | TokenKind::LeftSquareBracket
1347 | TokenKind::RightSquareBracket
1348 | TokenKind::LeftCurlyBracket
1349 | TokenKind::RightCurlyBracket
1350 | TokenKind::Whitespace
1351 | TokenKind::Comment
1352 | TokenKind::LiteralString
1353 | TokenKind::BasicString
1354 | TokenKind::MlLiteralString
1355 | TokenKind::MlBasicString
1356 | TokenKind::Atom => {
1357 let context = comment_token.span().append(current_token.span());
1358 error.report_error(
1359 ParseError::new("unexpected content between comment and newline")
1360 .with_context(context)
1361 .with_expected(&[Expected::Literal("\n")])
1362 .with_unexpected(current_token.span().before()),
1363 );
1364
1365 receiver.error(current_token.span(), error);
1366 ignore_to_newline(tokens, receiver, error);
1367 }
1368 TokenKind::Newline => {
1369 receiver.newline(current_token.span(), error);
1370 }
1371 TokenKind::Eof => {}
1372 }
1373}
1374
1375fn eof(tokens: &mut Stream<'_>, receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
1376 let Some(current_token) = tokens.next_token() else {
1377 return;
1378 };
1379
1380 match current_token.kind() {
1381 TokenKind::Dot
1382 | TokenKind::Equals
1383 | TokenKind::Comma
1384 | TokenKind::LeftSquareBracket
1385 | TokenKind::RightSquareBracket
1386 | TokenKind::LeftCurlyBracket
1387 | TokenKind::RightCurlyBracket
1388 | TokenKind::LiteralString
1389 | TokenKind::BasicString
1390 | TokenKind::MlLiteralString
1391 | TokenKind::MlBasicString
1392 | TokenKind::Atom
1393 | TokenKind::Comment
1394 | TokenKind::Whitespace
1395 | TokenKind::Newline => {
1396 error.report_error(
1397 ParseError::new("unexpected content")
1398 .with_context(current_token.span())
1399 .with_expected(&[])
1400 .with_unexpected(current_token.span().before()),
1401 );
1402
1403 receiver.error(current_token.span(), error);
1404 while let Some(current_token) = tokens.next_token() {
1405 if current_token.kind() == TokenKind::Eof {
1406 continue;
1407 }
1408 receiver.error(current_token.span(), error);
1409 }
1410 }
1411 TokenKind::Eof => {}
1412 }
1413}
1414
1415#[cold]
1417fn ignore_to_newline(
1418 tokens: &mut Stream<'_>,
1419 receiver: &mut dyn EventReceiver,
1420 error: &mut dyn ErrorSink,
1421) {
1422 while let Some(current_token) = tokens.next_token() {
1423 match current_token.kind() {
1424 TokenKind::Dot
1425 | TokenKind::Equals
1426 | TokenKind::Comma
1427 | TokenKind::LeftSquareBracket
1428 | TokenKind::RightSquareBracket
1429 | TokenKind::LeftCurlyBracket
1430 | TokenKind::RightCurlyBracket
1431 | TokenKind::LiteralString
1432 | TokenKind::BasicString
1433 | TokenKind::MlLiteralString
1434 | TokenKind::MlBasicString
1435 | TokenKind::Atom => {
1436 receiver.error(current_token.span(), error);
1437 }
1438 TokenKind::Comment => {
1439 on_comment(tokens, current_token, receiver, error);
1440 break;
1441 }
1442 TokenKind::Whitespace => {
1443 receiver.whitespace(current_token.span(), error);
1444 }
1445 TokenKind::Newline => {
1446 receiver.newline(current_token.span(), error);
1447 break;
1448 }
1449 TokenKind::Eof => {
1450 break;
1451 }
1452 }
1453 }
1454}
1455
1456#[cold]
1460fn ignore_to_value_close(
1461 tokens: &mut Stream<'_>,
1462 closing_kind: TokenKind,
1463 receiver: &mut dyn EventReceiver,
1464 error: &mut dyn ErrorSink,
1465) {
1466 let mut array_count: usize = 0;
1467 let mut inline_table_count: usize = 0;
1468 while let Some(current_token) = tokens.next_token() {
1469 match current_token.kind() {
1470 TokenKind::Dot
1471 | TokenKind::Equals
1472 | TokenKind::Comma
1473 | TokenKind::LiteralString
1474 | TokenKind::BasicString
1475 | TokenKind::MlLiteralString
1476 | TokenKind::MlBasicString
1477 | TokenKind::Atom => {
1478 receiver.error(current_token.span(), error);
1479 }
1480 TokenKind::Comment => {
1481 on_comment(tokens, current_token, receiver, error);
1482 }
1483 TokenKind::Whitespace => {
1484 receiver.whitespace(current_token.span(), error);
1485 }
1486 TokenKind::Newline => {
1487 receiver.newline(current_token.span(), error);
1488 }
1489 TokenKind::LeftSquareBracket => {
1490 receiver.error(current_token.span(), error);
1491 array_count += 1;
1492 }
1493 TokenKind::RightSquareBracket => {
1494 if array_count == 0 && current_token.kind() == closing_kind {
1495 receiver.array_close(current_token.span(), error);
1496 break;
1497 } else {
1498 receiver.error(current_token.span(), error);
1499 array_count = array_count.saturating_sub(1);
1500 }
1501 }
1502 TokenKind::LeftCurlyBracket => {
1503 receiver.error(current_token.span(), error);
1504 inline_table_count += 1;
1505 }
1506 TokenKind::RightCurlyBracket => {
1507 if inline_table_count == 0 && current_token.kind() == closing_kind {
1508 receiver.inline_table_close(current_token.span(), error);
1509 break;
1510 } else {
1511 receiver.error(current_token.span(), error);
1512 inline_table_count = inline_table_count.saturating_sub(1);
1513 }
1514 }
1515 TokenKind::Eof => {
1516 break;
1517 }
1518 }
1519 }
1520}
1521
1522#[cold]
1523fn on_missing_key(
1524 tokens: &mut Stream<'_>,
1525 token: &Token,
1526 invalid_description: &'static str,
1527 receiver: &mut dyn EventReceiver,
1528 error: &mut dyn ErrorSink,
1529) {
1530 error.report_error(
1531 ParseError::new(invalid_description)
1532 .with_context(token.span())
1533 .with_expected(&[Expected::Description("key")])
1534 .with_unexpected(token.span().before()),
1535 );
1536
1537 if token.kind() == TokenKind::Eof {
1538 } else if token.kind() == TokenKind::Newline {
1539 receiver.newline(token.span(), error);
1540 } else if token.kind() == TokenKind::Comment {
1541 on_comment(tokens, token, receiver, error);
1542 } else {
1543 receiver.error(token.span(), error);
1544 }
1545}
1546
1547#[cold]
1548fn on_missing_expression_key(
1549 tokens: &mut Stream<'_>,
1550 token: &Token,
1551 receiver: &mut dyn EventReceiver,
1552 error: &mut dyn ErrorSink,
1553) {
1554 error.report_error(
1555 ParseError::new("invalid key-value pair")
1556 .with_context(token.span())
1557 .with_expected(&[Expected::Description("key")])
1558 .with_unexpected(token.span().before()),
1559 );
1560
1561 receiver.error(token.span(), error);
1562 ignore_to_newline(tokens, receiver, error);
1563}
1564
1565#[cold]
1566fn on_missing_std_table(
1567 tokens: &mut Stream<'_>,
1568 token: &Token,
1569 receiver: &mut dyn EventReceiver,
1570 error: &mut dyn ErrorSink,
1571) {
1572 error.report_error(
1573 ParseError::new("missing table open")
1574 .with_context(token.span())
1575 .with_expected(&[Expected::Literal("[")])
1576 .with_unexpected(token.span().before()),
1577 );
1578
1579 receiver.error(token.span(), error);
1580 ignore_to_newline(tokens, receiver, error);
1581}
1582
1583fn next_token_if<'i, F: Fn(TokenKind) -> bool>(
1584 tokens: &mut Stream<'i>,
1585 pred: F,
1586) -> Option<&'i Token> {
1587 match tokens.first() {
1588 Some(next) if pred(next.kind()) => tokens.next_token(),
1589 _ => None,
1590 }
1591}
1592
1593fn seek(stream: &mut Stream<'_>, offset: isize) {
1594 let current = stream.checkpoint();
1595 stream.reset_to_start();
1596 let start = stream.checkpoint();
1597 let old_offset = current.offset_from(&start);
1598 let new_offset = (old_offset as isize).saturating_add(offset) as usize;
1599 if new_offset < stream.eof_offset() {
1600 #[cfg(feature = "unsafe")] unsafe {
1602 stream.next_slice_unchecked(new_offset)
1603 };
1604 #[cfg(not(feature = "unsafe"))]
1605 stream.next_slice(new_offset);
1606 } else {
1607 stream.finish();
1608 }
1609}
1610
1611const UNQUOTED_STRING: &str = "unquoted string";