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