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