1use winnow::stream::Offset as _;
2use winnow::stream::Stream as _;
3use winnow::stream::TokenSlice;
4
5use super::EventReceiver;
6use crate::ErrorSink;
7use crate::Expected;
8use crate::ParseError;
9#[cfg(feature = "debug")]
10use crate::debug::DebugErrorSink;
11#[cfg(feature = "debug")]
12use crate::debug::DebugEventReceiver;
13use crate::decoder::Encoding;
14use crate::lexer::Token;
15use crate::lexer::TokenKind;
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 current_token = loop {
631 let Some(current_token) = tokens.next_token() else {
632 let previous_span = tokens
633 .previous_tokens()
634 .find(|t| {
635 !matches!(
636 t.kind(),
637 TokenKind::Whitespace
638 | TokenKind::Comment
639 | TokenKind::Newline
640 | TokenKind::Eof
641 )
642 })
643 .map(|t| t.span())
644 .unwrap_or_default();
645 error.report_error(
646 ParseError::new("missing value")
647 .with_context(previous_span)
648 .with_expected(&[Expected::Description("value")])
649 .with_unexpected(previous_span.after()),
650 );
651 return;
652 };
653 if current_token.kind() != TokenKind::Equals {
654 break current_token;
655 }
656 error.report_error(
657 ParseError::new("extra `=`")
658 .with_context(current_token.span())
659 .with_expected(&[])
660 .with_unexpected(current_token.span()),
661 );
662 receiver.error(current_token.span(), error);
663 };
664
665 match current_token.kind() {
666 TokenKind::Comment
667 | TokenKind::Comma
668 | TokenKind::Newline
669 | TokenKind::Eof
670 | TokenKind::Whitespace => {
671 let fake_key = current_token.span().before();
672 let encoding = None;
673 receiver.scalar(fake_key, encoding, error);
674 seek(tokens, -1);
675 }
676 TokenKind::Equals => unreachable!(),
678 TokenKind::LeftCurlyBracket => {
679 on_inline_table_open(tokens, current_token, receiver, error);
680 }
681 TokenKind::RightCurlyBracket => {
682 error.report_error(
683 ParseError::new("missing inline table opening")
684 .with_context(current_token.span())
685 .with_expected(&[Expected::Literal("{")])
686 .with_unexpected(current_token.span().before()),
687 );
688
689 let _ = receiver.inline_table_open(current_token.span().before(), error);
690 receiver.inline_table_close(current_token.span(), error);
691 }
692 TokenKind::LeftSquareBracket => {
693 on_array_open(tokens, current_token, receiver, error);
694 }
695 TokenKind::RightSquareBracket => {
696 error.report_error(
697 ParseError::new("missing array opening")
698 .with_context(current_token.span())
699 .with_expected(&[Expected::Literal("[")])
700 .with_unexpected(current_token.span().before()),
701 );
702
703 let _ = receiver.array_open(current_token.span().before(), error);
704 receiver.array_close(current_token.span(), error);
705 }
706 TokenKind::LiteralString
707 | TokenKind::BasicString
708 | TokenKind::MlLiteralString
709 | TokenKind::MlBasicString
710 | TokenKind::Dot
711 | TokenKind::Atom => {
712 on_scalar(tokens, current_token, receiver, error);
713 }
714 }
715}
716
717fn on_scalar(
723 tokens: &mut Stream<'_>,
724 scalar: &Token,
725 receiver: &mut dyn EventReceiver,
726 error: &mut dyn ErrorSink,
727) {
728 let mut span = scalar.span();
729 let encoding = match scalar.kind() {
730 TokenKind::Comment
731 | TokenKind::Comma
732 | TokenKind::Newline
733 | TokenKind::Eof
734 | TokenKind::Whitespace
735 | TokenKind::Equals
736 | TokenKind::LeftCurlyBracket
737 | TokenKind::RightCurlyBracket
738 | TokenKind::LeftSquareBracket
739 | TokenKind::RightSquareBracket => {
740 unreachable!()
741 }
742 TokenKind::LiteralString => Some(Encoding::LiteralString),
743 TokenKind::BasicString => Some(Encoding::BasicString),
744 TokenKind::MlLiteralString => Some(Encoding::MlLiteralString),
745 TokenKind::MlBasicString => Some(Encoding::MlBasicString),
746 TokenKind::Dot | TokenKind::Atom => {
747 while let Some(next_token) = tokens.first() {
748 match next_token.kind() {
749 TokenKind::Comment
750 | TokenKind::Comma
751 | TokenKind::Newline
752 | TokenKind::Eof
753 | TokenKind::Equals
754 | TokenKind::LeftCurlyBracket
755 | TokenKind::RightCurlyBracket
756 | TokenKind::LeftSquareBracket
757 | TokenKind::RightSquareBracket
758 | TokenKind::LiteralString
759 | TokenKind::BasicString
760 | TokenKind::MlLiteralString
761 | TokenKind::MlBasicString => {
762 break;
763 }
764 TokenKind::Whitespace => {
765 if let Some(second) = tokens.get(1) {
766 if second.kind() == TokenKind::Atom {
767 span = span.append(second.span());
768 let _ = tokens.next_slice(2);
769 continue;
770 }
771 }
772 break;
773 }
774 TokenKind::Dot | TokenKind::Atom => {
775 span = span.append(next_token.span());
776 let _ = tokens.next_token();
777 }
778 }
779 }
780 None
781 }
782 };
783 receiver.scalar(span, encoding, error);
784}
785
786fn on_array_open(
797 tokens: &mut Stream<'_>,
798 array_open: &Token,
799 receiver: &mut dyn EventReceiver,
800 error: &mut dyn ErrorSink,
801) {
802 if !receiver.array_open(array_open.span(), error) {
803 ignore_to_value_close(tokens, TokenKind::RightSquareBracket, receiver, error);
804 return;
805 }
806
807 enum State {
808 NeedsValue,
809 NeedsComma,
810 }
811
812 let mut state = State::NeedsValue;
813 while let Some(current_token) = tokens.next_token() {
814 match current_token.kind() {
815 TokenKind::Comment => {
816 on_comment(tokens, current_token, receiver, error);
817 }
818 TokenKind::Whitespace => {
819 receiver.whitespace(current_token.span(), error);
820 }
821 TokenKind::Newline => {
822 receiver.newline(current_token.span(), error);
823 }
824 TokenKind::Eof => {
825 break;
826 }
827 TokenKind::Comma => match state {
828 State::NeedsValue => {
829 error.report_error(
830 ParseError::new("extra comma in array")
831 .with_context(array_open.span())
832 .with_expected(&[Expected::Description("value")])
833 .with_unexpected(current_token.span()),
834 );
835 receiver.error(current_token.span(), error);
836 }
837 State::NeedsComma => {
838 receiver.value_sep(current_token.span(), error);
839
840 state = State::NeedsValue;
841 }
842 },
843 TokenKind::Equals => {
844 error.report_error(
845 ParseError::new("unexpected `=` in array")
846 .with_context(array_open.span())
847 .with_expected(&[Expected::Description("value"), Expected::Literal("]")])
848 .with_unexpected(current_token.span()),
849 );
850 receiver.error(current_token.span(), error);
851 }
852 TokenKind::LeftCurlyBracket => {
853 if !matches!(state, State::NeedsValue) {
854 error.report_error(
855 ParseError::new("missing comma between array elements")
856 .with_context(array_open.span())
857 .with_expected(&[Expected::Literal(",")])
858 .with_unexpected(current_token.span().before()),
859 );
860 receiver.value_sep(current_token.span().before(), error);
861 }
862
863 on_inline_table_open(tokens, current_token, receiver, error);
864
865 state = State::NeedsComma;
866 }
867 TokenKind::RightCurlyBracket => {
868 if !matches!(state, State::NeedsValue) {
869 error.report_error(
870 ParseError::new("missing comma between array elements")
871 .with_context(array_open.span())
872 .with_expected(&[Expected::Literal(",")])
873 .with_unexpected(current_token.span().before()),
874 );
875 receiver.value_sep(current_token.span().before(), error);
876 }
877
878 error.report_error(
879 ParseError::new("missing inline table opening")
880 .with_context(current_token.span())
881 .with_expected(&[Expected::Literal("{")])
882 .with_unexpected(current_token.span().before()),
883 );
884
885 let _ = receiver.inline_table_open(current_token.span().before(), error);
886 receiver.inline_table_close(current_token.span(), error);
887
888 state = State::NeedsComma;
889 }
890 TokenKind::LeftSquareBracket => {
891 if !matches!(state, State::NeedsValue) {
892 error.report_error(
893 ParseError::new("missing comma between array elements")
894 .with_context(array_open.span())
895 .with_expected(&[Expected::Literal(",")])
896 .with_unexpected(current_token.span().before()),
897 );
898 receiver.value_sep(current_token.span().before(), error);
899 }
900
901 on_array_open(tokens, current_token, receiver, error);
902
903 state = State::NeedsComma;
904 }
905 TokenKind::RightSquareBracket => {
906 receiver.array_close(current_token.span(), error);
907
908 return;
909 }
910 TokenKind::LiteralString
911 | TokenKind::BasicString
912 | TokenKind::MlLiteralString
913 | TokenKind::MlBasicString
914 | TokenKind::Dot
915 | TokenKind::Atom => {
916 if !matches!(state, State::NeedsValue) {
917 error.report_error(
918 ParseError::new("missing comma between array elements")
919 .with_context(array_open.span())
920 .with_expected(&[Expected::Literal(",")])
921 .with_unexpected(current_token.span().before()),
922 );
923 receiver.value_sep(current_token.span().before(), error);
924 }
925
926 on_scalar(tokens, current_token, receiver, error);
927
928 state = State::NeedsComma;
929 }
930 }
931 }
932
933 let previous_span = tokens
934 .previous_tokens()
935 .find(|t| {
936 !matches!(
937 t.kind(),
938 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
939 )
940 })
941 .map(|t| t.span())
942 .unwrap_or_default();
943 error.report_error(
944 ParseError::new("unclosed array")
945 .with_context(array_open.span())
946 .with_expected(&[Expected::Literal("]")])
947 .with_unexpected(previous_span.after()),
948 );
949 receiver.array_close(previous_span.after(), error);
950}
951
952fn on_inline_table_open(
963 tokens: &mut Stream<'_>,
964 inline_table_open: &Token,
965 receiver: &mut dyn EventReceiver,
966 error: &mut dyn ErrorSink,
967) {
968 if !receiver.inline_table_open(inline_table_open.span(), error) {
969 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
970 return;
971 }
972
973 #[allow(clippy::enum_variant_names)]
974 #[derive(Debug)]
975 enum State {
976 NeedsKey,
977 NeedsEquals,
978 NeedsValue,
979 NeedsComma,
980 }
981
982 impl State {
983 fn expected(&self) -> &'static [Expected] {
984 match self {
985 Self::NeedsKey => &[Expected::Description("key")],
986 Self::NeedsEquals => &[Expected::Literal("=")],
987 Self::NeedsValue => &[Expected::Description("value")],
988 Self::NeedsComma => &[Expected::Literal(",")],
989 }
990 }
991 }
992
993 let mut state = State::NeedsKey;
994 while let Some(current_token) = tokens.next_token() {
995 match current_token.kind() {
996 TokenKind::Comment => {
997 on_comment(tokens, current_token, receiver, error);
998 }
999 TokenKind::Whitespace => {
1000 receiver.whitespace(current_token.span(), error);
1001 }
1002 TokenKind::Newline => {
1003 receiver.newline(current_token.span(), error);
1004 }
1005 TokenKind::Eof => {
1006 break;
1007 }
1008 TokenKind::Comma => match state {
1009 State::NeedsKey | State::NeedsEquals | State::NeedsValue => {
1010 error.report_error(
1011 ParseError::new("extra comma in inline table")
1012 .with_context(inline_table_open.span())
1013 .with_expected(state.expected())
1014 .with_unexpected(current_token.span().before()),
1015 );
1016 receiver.error(current_token.span(), error);
1017 }
1018 State::NeedsComma => {
1019 receiver.value_sep(current_token.span(), error);
1020
1021 state = State::NeedsKey;
1022 }
1023 },
1024 TokenKind::Equals => match state {
1025 State::NeedsKey => {
1026 let fake_key = current_token.span().before();
1027 let encoding = None;
1028 receiver.simple_key(fake_key, encoding, error);
1029
1030 receiver.key_val_sep(current_token.span(), error);
1031
1032 state = State::NeedsValue;
1033 }
1034 State::NeedsEquals => {
1035 receiver.key_val_sep(current_token.span(), error);
1036
1037 state = State::NeedsValue;
1038 }
1039 State::NeedsValue | State::NeedsComma => {
1040 error.report_error(
1041 ParseError::new("extra assignment between key-value pairs")
1042 .with_context(inline_table_open.span())
1043 .with_expected(state.expected())
1044 .with_unexpected(current_token.span().before()),
1045 );
1046 receiver.error(current_token.span(), error);
1047 }
1048 },
1049 TokenKind::LeftCurlyBracket => match state {
1050 State::NeedsKey | State::NeedsComma => {
1051 error.report_error(
1052 ParseError::new("missing key for inline table element")
1053 .with_context(inline_table_open.span())
1054 .with_expected(state.expected())
1055 .with_unexpected(current_token.span().before()),
1056 );
1057 receiver.error(current_token.span(), error);
1058 ignore_to_value_close(tokens, TokenKind::RightCurlyBracket, receiver, error);
1059 }
1060 State::NeedsEquals => {
1061 error.report_error(
1062 ParseError::new("missing assignment between key-value pairs")
1063 .with_context(inline_table_open.span())
1064 .with_expected(state.expected())
1065 .with_unexpected(current_token.span().before()),
1066 );
1067
1068 on_inline_table_open(tokens, current_token, receiver, error);
1069
1070 state = State::NeedsComma;
1071 }
1072 State::NeedsValue => {
1073 on_inline_table_open(tokens, current_token, receiver, error);
1074
1075 state = State::NeedsComma;
1076 }
1077 },
1078 TokenKind::RightCurlyBracket => {
1079 match state {
1080 State::NeedsKey => {}
1081 State::NeedsEquals => {
1082 receiver.key_val_sep(current_token.span().before(), error);
1083 receiver.scalar(
1084 current_token.span().before(),
1085 Some(Encoding::LiteralString),
1086 error,
1087 );
1088 }
1089 State::NeedsValue => {
1090 receiver.scalar(
1091 current_token.span().before(),
1092 Some(Encoding::LiteralString),
1093 error,
1094 );
1095 }
1096 State::NeedsComma => {}
1097 }
1098 receiver.inline_table_close(current_token.span(), error);
1099
1100 return;
1101 }
1102 TokenKind::LeftSquareBracket => match state {
1103 State::NeedsKey | State::NeedsComma => {
1104 error.report_error(
1105 ParseError::new("missing key for inline table element")
1106 .with_context(inline_table_open.span())
1107 .with_expected(state.expected())
1108 .with_unexpected(current_token.span().before()),
1109 );
1110 receiver.error(current_token.span(), error);
1111 ignore_to_value_close(tokens, TokenKind::RightSquareBracket, receiver, error);
1112 }
1113 State::NeedsEquals => {
1114 error.report_error(
1115 ParseError::new("missing assignment between key-value pairs")
1116 .with_context(inline_table_open.span())
1117 .with_expected(state.expected())
1118 .with_unexpected(current_token.span().before()),
1119 );
1120
1121 on_array_open(tokens, current_token, receiver, error);
1122
1123 state = State::NeedsComma;
1124 }
1125 State::NeedsValue => {
1126 on_array_open(tokens, current_token, receiver, error);
1127
1128 state = State::NeedsComma;
1129 }
1130 },
1131 TokenKind::RightSquareBracket => match state {
1132 State::NeedsKey | State::NeedsEquals | State::NeedsComma => {
1133 error.report_error(
1134 ParseError::new("invalid inline table element")
1135 .with_context(inline_table_open.span())
1136 .with_expected(state.expected())
1137 .with_unexpected(current_token.span().before()),
1138 );
1139 receiver.error(current_token.span(), error);
1140 }
1141 State::NeedsValue => {
1142 error.report_error(
1143 ParseError::new("missing array opening")
1144 .with_context(current_token.span())
1145 .with_expected(&[Expected::Literal("[")])
1146 .with_unexpected(current_token.span().before()),
1147 );
1148
1149 let _ = receiver.array_open(current_token.span().before(), error);
1150 receiver.array_close(current_token.span(), error);
1151
1152 state = State::NeedsComma;
1153 }
1154 },
1155 TokenKind::LiteralString
1156 | TokenKind::BasicString
1157 | TokenKind::MlLiteralString
1158 | TokenKind::MlBasicString
1159 | TokenKind::Dot
1160 | TokenKind::Atom => match state {
1161 State::NeedsKey => {
1162 if current_token.kind() == TokenKind::Dot {
1163 receiver.simple_key(
1164 current_token.span().before(),
1165 current_token.kind().encoding(),
1166 error,
1167 );
1168 seek(tokens, -1);
1169 opt_dot_keys(tokens, receiver, error);
1170 state = State::NeedsEquals;
1171 } else {
1172 receiver.simple_key(
1173 current_token.span(),
1174 current_token.kind().encoding(),
1175 error,
1176 );
1177 opt_dot_keys(tokens, receiver, error);
1178 state = State::NeedsEquals;
1179 }
1180 }
1181 State::NeedsEquals => {
1182 error.report_error(
1183 ParseError::new("missing assignment between key-value pairs")
1184 .with_context(inline_table_open.span())
1185 .with_expected(state.expected())
1186 .with_unexpected(current_token.span().before()),
1187 );
1188
1189 on_scalar(tokens, current_token, receiver, error);
1190
1191 state = State::NeedsComma;
1192 }
1193 State::NeedsValue => {
1194 on_scalar(tokens, current_token, receiver, error);
1195
1196 state = State::NeedsComma;
1197 }
1198 State::NeedsComma => {
1199 error.report_error(
1200 ParseError::new("missing comma between key-value pairs")
1201 .with_context(inline_table_open.span())
1202 .with_expected(state.expected())
1203 .with_unexpected(current_token.span().before()),
1204 );
1205
1206 if current_token.kind() == TokenKind::Dot {
1207 receiver.simple_key(
1208 current_token.span().before(),
1209 current_token.kind().encoding(),
1210 error,
1211 );
1212 seek(tokens, -1);
1213 opt_dot_keys(tokens, receiver, error);
1214 state = State::NeedsEquals;
1215 } else {
1216 receiver.simple_key(
1217 current_token.span(),
1218 current_token.kind().encoding(),
1219 error,
1220 );
1221 opt_dot_keys(tokens, receiver, error);
1222 state = State::NeedsEquals;
1223 }
1224 }
1225 },
1226 }
1227 }
1228
1229 let previous_span = tokens
1230 .previous_tokens()
1231 .find(|t| {
1232 !matches!(
1233 t.kind(),
1234 TokenKind::Whitespace | TokenKind::Comment | TokenKind::Newline | TokenKind::Eof
1235 )
1236 })
1237 .map(|t| t.span())
1238 .unwrap_or_default();
1239 match state {
1240 State::NeedsKey => {}
1241 State::NeedsEquals => {
1242 receiver.key_val_sep(previous_span.after(), error);
1243 receiver.scalar(previous_span.after(), Some(Encoding::LiteralString), error);
1244 }
1245 State::NeedsValue => {
1246 receiver.scalar(previous_span.after(), Some(Encoding::LiteralString), error);
1247 }
1248 State::NeedsComma => {}
1249 }
1250 error.report_error(
1251 ParseError::new("unclosed inline table")
1252 .with_context(inline_table_open.span())
1253 .with_expected(&[Expected::Literal("}")])
1254 .with_unexpected(previous_span.after()),
1255 );
1256 receiver.inline_table_close(previous_span.after(), error);
1257}
1258
1259fn opt_whitespace(
1265 tokens: &mut Stream<'_>,
1266 receiver: &mut dyn EventReceiver,
1267 error: &mut dyn ErrorSink,
1268) {
1269 if let Some(ws_token) = next_token_if(tokens, |k| matches!(k, TokenKind::Whitespace)) {
1270 receiver.whitespace(ws_token.span(), error);
1271 }
1272}
1273
1274fn ws_comment_newline(
1299 tokens: &mut Stream<'_>,
1300 receiver: &mut dyn EventReceiver,
1301 error: &mut dyn ErrorSink,
1302) {
1303 let mut first = None;
1304 while let Some(current_token) = tokens.next_token() {
1305 let first = first.get_or_insert(current_token.span());
1306 match current_token.kind() {
1307 TokenKind::Dot
1308 | TokenKind::Equals
1309 | TokenKind::Comma
1310 | TokenKind::LeftSquareBracket
1311 | TokenKind::RightSquareBracket
1312 | TokenKind::LeftCurlyBracket
1313 | TokenKind::RightCurlyBracket
1314 | TokenKind::LiteralString
1315 | TokenKind::BasicString
1316 | TokenKind::MlLiteralString
1317 | TokenKind::MlBasicString
1318 | TokenKind::Atom => {
1319 let context = first.append(current_token.span());
1320 error.report_error(
1321 ParseError::new("unexpected key or value")
1322 .with_context(context)
1323 .with_expected(&[Expected::Literal("\n"), Expected::Literal("#")])
1324 .with_unexpected(current_token.span().before()),
1325 );
1326
1327 receiver.error(current_token.span(), error);
1328 ignore_to_newline(tokens, receiver, error);
1329 break;
1330 }
1331 TokenKind::Comment => {
1332 on_comment(tokens, current_token, receiver, error);
1333 break;
1334 }
1335 TokenKind::Whitespace => {
1336 receiver.whitespace(current_token.span(), error);
1337 continue;
1338 }
1339 TokenKind::Newline => {
1340 receiver.newline(current_token.span(), error);
1341 break;
1342 }
1343 TokenKind::Eof => {
1344 break;
1345 }
1346 }
1347 }
1348}
1349
1350fn on_comment(
1352 tokens: &mut Stream<'_>,
1353 comment_token: &Token,
1354 receiver: &mut dyn EventReceiver,
1355 error: &mut dyn ErrorSink,
1356) {
1357 receiver.comment(comment_token.span(), error);
1358
1359 let Some(current_token) = tokens.next_token() else {
1360 return;
1361 };
1362 match current_token.kind() {
1363 TokenKind::Dot
1364 | TokenKind::Equals
1365 | TokenKind::Comma
1366 | TokenKind::LeftSquareBracket
1367 | TokenKind::RightSquareBracket
1368 | TokenKind::LeftCurlyBracket
1369 | TokenKind::RightCurlyBracket
1370 | TokenKind::Whitespace
1371 | TokenKind::Comment
1372 | TokenKind::LiteralString
1373 | TokenKind::BasicString
1374 | TokenKind::MlLiteralString
1375 | TokenKind::MlBasicString
1376 | TokenKind::Atom => {
1377 let context = comment_token.span().append(current_token.span());
1378 error.report_error(
1379 ParseError::new("unexpected content between comment and newline")
1380 .with_context(context)
1381 .with_expected(&[Expected::Literal("\n")])
1382 .with_unexpected(current_token.span().before()),
1383 );
1384
1385 receiver.error(current_token.span(), error);
1386 ignore_to_newline(tokens, receiver, error);
1387 }
1388 TokenKind::Newline => {
1389 receiver.newline(current_token.span(), error);
1390 }
1391 TokenKind::Eof => {}
1392 }
1393}
1394
1395fn eof(tokens: &mut Stream<'_>, receiver: &mut dyn EventReceiver, error: &mut dyn ErrorSink) {
1396 let Some(current_token) = tokens.next_token() else {
1397 return;
1398 };
1399
1400 match current_token.kind() {
1401 TokenKind::Dot
1402 | TokenKind::Equals
1403 | TokenKind::Comma
1404 | TokenKind::LeftSquareBracket
1405 | TokenKind::RightSquareBracket
1406 | TokenKind::LeftCurlyBracket
1407 | TokenKind::RightCurlyBracket
1408 | TokenKind::LiteralString
1409 | TokenKind::BasicString
1410 | TokenKind::MlLiteralString
1411 | TokenKind::MlBasicString
1412 | TokenKind::Atom
1413 | TokenKind::Comment
1414 | TokenKind::Whitespace
1415 | TokenKind::Newline => {
1416 error.report_error(
1417 ParseError::new("unexpected content")
1418 .with_context(current_token.span())
1419 .with_expected(&[])
1420 .with_unexpected(current_token.span().before()),
1421 );
1422
1423 receiver.error(current_token.span(), error);
1424 while let Some(current_token) = tokens.next_token() {
1425 if current_token.kind() == TokenKind::Eof {
1426 continue;
1427 }
1428 receiver.error(current_token.span(), error);
1429 }
1430 }
1431 TokenKind::Eof => {}
1432 }
1433}
1434
1435#[cold]
1437fn ignore_to_newline(
1438 tokens: &mut Stream<'_>,
1439 receiver: &mut dyn EventReceiver,
1440 error: &mut dyn ErrorSink,
1441) {
1442 while let Some(current_token) = tokens.next_token() {
1443 match current_token.kind() {
1444 TokenKind::Dot
1445 | TokenKind::Equals
1446 | TokenKind::Comma
1447 | TokenKind::LeftSquareBracket
1448 | TokenKind::RightSquareBracket
1449 | TokenKind::LeftCurlyBracket
1450 | TokenKind::RightCurlyBracket
1451 | TokenKind::LiteralString
1452 | TokenKind::BasicString
1453 | TokenKind::MlLiteralString
1454 | TokenKind::MlBasicString
1455 | TokenKind::Atom => {
1456 receiver.error(current_token.span(), error);
1457 }
1458 TokenKind::Comment => {
1459 on_comment(tokens, current_token, receiver, error);
1460 break;
1461 }
1462 TokenKind::Whitespace => {
1463 receiver.whitespace(current_token.span(), error);
1464 }
1465 TokenKind::Newline => {
1466 receiver.newline(current_token.span(), error);
1467 break;
1468 }
1469 TokenKind::Eof => {
1470 break;
1471 }
1472 }
1473 }
1474}
1475
1476#[cold]
1480fn ignore_to_value_close(
1481 tokens: &mut Stream<'_>,
1482 closing_kind: TokenKind,
1483 receiver: &mut dyn EventReceiver,
1484 error: &mut dyn ErrorSink,
1485) {
1486 let mut array_count: usize = 0;
1487 let mut inline_table_count: usize = 0;
1488 while let Some(current_token) = tokens.next_token() {
1489 match current_token.kind() {
1490 TokenKind::Dot
1491 | TokenKind::Equals
1492 | TokenKind::Comma
1493 | TokenKind::LiteralString
1494 | TokenKind::BasicString
1495 | TokenKind::MlLiteralString
1496 | TokenKind::MlBasicString
1497 | TokenKind::Atom => {
1498 receiver.error(current_token.span(), error);
1499 }
1500 TokenKind::Comment => {
1501 on_comment(tokens, current_token, receiver, error);
1502 }
1503 TokenKind::Whitespace => {
1504 receiver.whitespace(current_token.span(), error);
1505 }
1506 TokenKind::Newline => {
1507 receiver.newline(current_token.span(), error);
1508 }
1509 TokenKind::LeftSquareBracket => {
1510 receiver.error(current_token.span(), error);
1511 array_count += 1;
1512 }
1513 TokenKind::RightSquareBracket => {
1514 if array_count == 0 && current_token.kind() == closing_kind {
1515 receiver.array_close(current_token.span(), error);
1516 break;
1517 } else {
1518 receiver.error(current_token.span(), error);
1519 array_count = array_count.saturating_sub(1);
1520 }
1521 }
1522 TokenKind::LeftCurlyBracket => {
1523 receiver.error(current_token.span(), error);
1524 inline_table_count += 1;
1525 }
1526 TokenKind::RightCurlyBracket => {
1527 if inline_table_count == 0 && current_token.kind() == closing_kind {
1528 receiver.inline_table_close(current_token.span(), error);
1529 break;
1530 } else {
1531 receiver.error(current_token.span(), error);
1532 inline_table_count = inline_table_count.saturating_sub(1);
1533 }
1534 }
1535 TokenKind::Eof => {
1536 break;
1537 }
1538 }
1539 }
1540}
1541
1542#[cold]
1543fn on_missing_key(
1544 tokens: &mut Stream<'_>,
1545 token: &Token,
1546 invalid_description: &'static str,
1547 receiver: &mut dyn EventReceiver,
1548 error: &mut dyn ErrorSink,
1549) {
1550 error.report_error(
1551 ParseError::new(invalid_description)
1552 .with_context(token.span())
1553 .with_expected(&[Expected::Description("key")])
1554 .with_unexpected(token.span().before()),
1555 );
1556
1557 if token.kind() == TokenKind::Eof {
1558 } else if token.kind() == TokenKind::Newline {
1559 receiver.newline(token.span(), error);
1560 } else if token.kind() == TokenKind::Comment {
1561 on_comment(tokens, token, receiver, error);
1562 } else {
1563 receiver.error(token.span(), error);
1564 }
1565}
1566
1567#[cold]
1568fn on_missing_expression_key(
1569 tokens: &mut Stream<'_>,
1570 token: &Token,
1571 receiver: &mut dyn EventReceiver,
1572 error: &mut dyn ErrorSink,
1573) {
1574 error.report_error(
1575 ParseError::new("invalid key-value pair")
1576 .with_context(token.span())
1577 .with_expected(&[Expected::Description("key")])
1578 .with_unexpected(token.span().before()),
1579 );
1580
1581 receiver.error(token.span(), error);
1582 ignore_to_newline(tokens, receiver, error);
1583}
1584
1585#[cold]
1586fn on_missing_std_table(
1587 tokens: &mut Stream<'_>,
1588 token: &Token,
1589 receiver: &mut dyn EventReceiver,
1590 error: &mut dyn ErrorSink,
1591) {
1592 error.report_error(
1593 ParseError::new("missing table open")
1594 .with_context(token.span())
1595 .with_expected(&[Expected::Literal("[")])
1596 .with_unexpected(token.span().before()),
1597 );
1598
1599 receiver.error(token.span(), error);
1600 ignore_to_newline(tokens, receiver, error);
1601}
1602
1603fn next_token_if<'i, F: Fn(TokenKind) -> bool>(
1604 tokens: &mut Stream<'i>,
1605 pred: F,
1606) -> Option<&'i Token> {
1607 match tokens.first() {
1608 Some(next) if pred(next.kind()) => tokens.next_token(),
1609 _ => None,
1610 }
1611}
1612
1613fn seek(stream: &mut Stream<'_>, offset: isize) {
1614 let current = stream.checkpoint();
1615 stream.reset_to_start();
1616 let start = stream.checkpoint();
1617 let old_offset = current.offset_from(&start);
1618 let new_offset = (old_offset as isize).saturating_add(offset) as usize;
1619 if new_offset < stream.eof_offset() {
1620 #[cfg(feature = "unsafe")] unsafe {
1622 stream.next_slice_unchecked(new_offset)
1623 };
1624 #[cfg(not(feature = "unsafe"))]
1625 stream.next_slice(new_offset);
1626 } else {
1627 stream.finish();
1628 }
1629}
1630
1631const UNQUOTED_STRING: &str = "unquoted string";