Skip to main content

saphyr_parser/
parser.rs

1//! Home to the YAML Parser.
2//!
3//! The parser takes input from the [`crate::scanner::Scanner`], performs final checks for YAML
4//! compliance, and emits a stream of YAML events. This stream can for instance be used to create
5//! YAML objects.
6
7use crate::{
8    BufferedInput, Marker,
9    input::{Input, str::StrInput},
10    scanner::{ScalarStyle, ScanError, Scanner, Span, Token, TokenType},
11};
12
13use alloc::{
14    borrow::Cow,
15    collections::BTreeMap,
16    string::{String, ToString},
17    vec::Vec,
18};
19use core::fmt::Display;
20
21#[derive(Clone, Copy, PartialEq, Debug, Eq)]
22enum State {
23    StreamStart,
24    ImplicitDocumentStart,
25    DocumentStart,
26    DocumentContent,
27    DocumentEnd,
28    BlockNode,
29    BlockSequenceFirstEntry,
30    BlockSequenceEntry,
31    IndentlessSequenceEntry,
32    BlockMappingFirstKey,
33    BlockMappingKey,
34    BlockMappingValue,
35    FlowSequenceFirstEntry,
36    FlowSequenceEntry,
37    FlowSequenceEntryMappingKey,
38    FlowSequenceEntryMappingValue,
39    FlowSequenceEntryMappingEnd(Marker),
40    FlowMappingFirstKey,
41    FlowMappingKey,
42    FlowMappingValue,
43    FlowMappingEmptyValue,
44    End,
45}
46
47/// An event generated by the YAML parser.
48///
49/// Events are used in the low-level event-based API (push parser). The API entrypoint is the
50/// [`EventReceiver`] trait.
51#[derive(Clone, PartialEq, Debug, Eq)]
52pub enum Event<'input> {
53    /// Reserved for internal use.
54    Nothing,
55    /// Event generated at the very beginning of parsing.
56    StreamStart,
57    /// Last event that will be generated by the parser. Signals EOF.
58    StreamEnd,
59    /// The start of a YAML document.
60    ///
61    /// When the boolean is `true`, it is an explicit document start
62    /// directive (`---`).
63    ///
64    /// When the boolean is `false`, it is an implicit document start
65    /// (without `---`).
66    DocumentStart(bool),
67    /// The YAML end document directive (`...`).
68    DocumentEnd,
69    /// A YAML Alias.
70    Alias(
71        /// The anchor ID the alias refers to.
72        usize,
73    ),
74    /// Value, style, `anchor_id`, tag
75    Scalar(
76        Cow<'input, str>,
77        ScalarStyle,
78        usize,
79        Option<Cow<'input, Tag>>,
80    ),
81    /// The start of a YAML sequence (array).
82    SequenceStart(
83        /// The anchor ID of the start of the sequence.
84        usize,
85        /// An optional tag
86        Option<Cow<'input, Tag>>,
87    ),
88    /// The end of a YAML sequence (array).
89    SequenceEnd,
90    /// The start of a YAML mapping (object, hash).
91    MappingStart(
92        /// The anchor ID of the start of the mapping.
93        usize,
94        /// An optional tag
95        Option<Cow<'input, Tag>>,
96    ),
97    /// The end of a YAML mapping (object, hash).
98    MappingEnd,
99}
100
101/// A YAML tag.
102#[derive(Clone, PartialEq, Debug, Eq, Ord, PartialOrd, Hash)]
103pub struct Tag {
104    /// Handle of the tag (`!` included).
105    pub handle: String,
106    /// The suffix of the tag.
107    pub suffix: String,
108}
109
110impl Tag {
111    /// Returns whether the tag is a YAML tag from the core schema (`!!str`, `!!int`, ...).
112    ///
113    /// The YAML specification specifies [a list of
114    /// tags](https://yaml.org/spec/1.2.2/#103-core-schema) for the Core Schema. This function
115    /// checks whether _the handle_ (but not the suffix) is the handle for the YAML Core Schema.
116    ///
117    /// # Return
118    /// Returns `true` if the handle is `tag:yaml.org,2002`, `false` otherwise.
119    #[must_use]
120    pub fn is_yaml_core_schema(&self) -> bool {
121        self.handle == "tag:yaml.org,2002:"
122    }
123}
124
125impl Display for Tag {
126    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
127        if self.handle == "!" {
128            write!(f, "!{}", self.suffix)
129        } else {
130            write!(f, "{}!{}", self.handle, self.suffix)
131        }
132    }
133}
134
135impl<'input> Event<'input> {
136    /// Create an empty scalar.
137    fn empty_scalar() -> Self {
138        Event::Scalar(Cow::default(), ScalarStyle::Plain, 0, None)
139    }
140
141    /// Create an empty scalar with the given anchor.
142    fn empty_scalar_with_anchor(anchor: usize, tag: Option<Cow<'input, Tag>>) -> Self {
143        Event::Scalar(Cow::default(), ScalarStyle::Plain, anchor, tag)
144    }
145}
146
147/// A YAML parser.
148#[derive(Debug)]
149pub struct Parser<'input, T: Input> {
150    /// The underlying scanner from which we pull tokens.
151    scanner: Scanner<'input, T>,
152    /// The stack of _previous_ states we were in.
153    ///
154    /// States are pushed in the context of subobjects to this stack. The top-most element is the
155    /// state in which to come back to when exiting the current state.
156    states: Vec<State>,
157    /// The state in which we currently are.
158    state: State,
159    /// The next token from the scanner.
160    token: Option<Token<'input>>,
161    /// The next YAML event to emit.
162    current: Option<(Event<'input>, Span)>,
163    /// Anchors that have been encountered in the YAML document.
164    anchors: BTreeMap<Cow<'input, str>, usize>,
165    /// Next ID available for an anchor.
166    ///
167    /// Every anchor is given a unique ID. We use an incrementing ID and this is both the ID to
168    /// return for the next anchor and the count of anchor IDs emitted.
169    anchor_id_count: usize,
170    /// The tag directives (`%TAG`) the parser has encountered.
171    ///
172    /// Key is the handle, and value is the prefix.
173    tags: BTreeMap<String, String>,
174    /// Whether we have emitted [`Event::StreamEnd`].
175    ///
176    /// Emitted means that it has been returned from [`Self::next`]. If it is stored in
177    /// [`Self::token`], this is set to `false`.
178    stream_end_emitted: bool,
179    /// Make tags global across all documents.
180    keep_tags: bool,
181}
182
183impl<T: Input + Clone> Clone for Parser<'_, T> {
184    fn clone(&self) -> Self {
185        Self {
186            scanner: self.scanner.clone(),
187            states: self.states.clone(),
188            state: self.state,
189            token: self.token.clone(),
190            current: self.current.clone(),
191            anchors: self.anchors.clone(),
192            anchor_id_count: self.anchor_id_count,
193            tags: self.tags.clone(),
194            stream_end_emitted: self.stream_end_emitted,
195            keep_tags: self.keep_tags,
196        }
197    }
198}
199
200/// Trait to be implemented in order to use the low-level parsing API.
201///
202/// The low-level parsing API is event-based (a push parser), calling [`EventReceiver::on_event`]
203/// for each YAML [`Event`] that occurs.
204/// The [`EventReceiver`] trait only receives events. In order to receive both events and their
205/// location in the source, use [`SpannedEventReceiver`]. Note that [`EventReceiver`]s implement
206/// [`SpannedEventReceiver`] automatically.
207///
208/// # Event hierarchy
209/// The event stream starts with an [`Event::StreamStart`] event followed by an
210/// [`Event::DocumentStart`] event. If the YAML document starts with a mapping (an object), an
211/// [`Event::MappingStart`] event is emitted. If it starts with a sequence (an array), an
212/// [`Event::SequenceStart`] event is emitted. Otherwise, an [`Event::Scalar`] event is emitted.
213///
214/// In a mapping, key-values are sent as consecutive events. The first event after an
215/// [`Event::MappingStart`] will be the key, and following its value. If the mapping contains no
216/// sub-mapping or sub-sequence, then even events (starting from 0) will always be keys and odd
217/// ones will always be values. The mapping ends when an [`Event::MappingEnd`] event is received.
218///
219/// In a sequence, values are sent consecutively until the [`Event::SequenceEnd`] event.
220///
221/// If a value is a sub-mapping or a sub-sequence, an [`Event::MappingStart`] or
222/// [`Event::SequenceStart`] event will be sent respectively. Following events until the associated
223/// [`Event::MappingStart`] or [`Event::SequenceEnd`] (beware of nested mappings or sequences) will
224/// be part of the value and not another key-value pair or element in the sequence.
225///
226/// For instance, the following yaml:
227/// ```yaml
228/// a: b
229/// c:
230///   d: e
231/// f:
232///   - g
233///   - h
234/// ```
235/// will emit (indented and commented for lisibility):
236/// ```text
237/// StreamStart, DocumentStart, MappingStart,
238///   Scalar("a", ..), Scalar("b", ..)
239///   Scalar("c", ..), MappingStart, Scalar("d", ..), Scalar("e", ..), MappingEnd,
240///   Scalar("f", ..), SequenceStart, Scalar("g", ..), Scalar("h", ..), SequenceEnd,
241/// MappingEnd, DocumentEnd, StreamEnd
242/// ```
243///
244/// # Example
245/// ```
246/// # use saphyr_parser::{Event, EventReceiver, Parser};
247/// #
248/// /// Sink of events. Collects them into an array.
249/// struct EventSink<'input> {
250///     events: Vec<Event<'input>>,
251/// }
252///
253/// /// Implement `on_event`, pushing into `self.events`.
254/// impl<'input> EventReceiver<'input> for EventSink<'input> {
255///     fn on_event(&mut self, ev: Event<'input>) {
256///         self.events.push(ev);
257///     }
258/// }
259///
260/// /// Load events from a yaml string.
261/// fn str_to_events(yaml: &str) -> Vec<Event<'_>> {
262///     let mut sink = EventSink { events: Vec::new() };
263///     let mut parser = Parser::new_from_str(yaml);
264///     // Load events using our sink as the receiver.
265///     parser.load(&mut sink, true).unwrap();
266///     sink.events
267/// }
268/// ```
269pub trait EventReceiver<'input> {
270    /// Handler called for each YAML event that is emitted by the parser.
271    fn on_event(&mut self, ev: Event<'input>);
272}
273
274/// Trait to be implemented for using the low-level parsing API.
275///
276/// Functionally similar to [`EventReceiver`], but receives a [`Span`] as well as the event.
277pub trait SpannedEventReceiver<'input> {
278    /// Handler called for each event that occurs.
279    fn on_event(&mut self, ev: Event<'input>, span: Span);
280}
281
282impl<'input, R: EventReceiver<'input>> SpannedEventReceiver<'input> for R {
283    fn on_event(&mut self, ev: Event<'input>, _span: Span) {
284        self.on_event(ev);
285    }
286}
287
288/// A convenience alias for a `Result` of a parser event.
289pub type ParseResult<'input> = Result<(Event<'input>, Span), ScanError>;
290
291impl<'input> Parser<'input, StrInput<'input>> {
292    /// Create a new instance of a parser from a &str.
293    #[must_use]
294    pub fn new_from_str(value: &'input str) -> Self {
295        debug_print!("\x1B[;31m>>>>>>>>>> New parser from str\x1B[;0m");
296        Parser::new(StrInput::new(value))
297    }
298}
299
300impl<'input, T> Parser<'input, BufferedInput<T>>
301where
302    T: Iterator<Item = char> + 'input,
303{
304    /// Create a new instance of a parser from an iterator of `char`s.
305    #[must_use]
306    pub fn new_from_iter(iter: T) -> Self {
307        debug_print!("\x1B[;31m>>>>>>>>>> New parser from iter\x1B[;0m");
308        Parser::new(BufferedInput::new(iter))
309    }
310}
311
312impl<'input, T: Input> Parser<'input, T> {
313    /// Create a new instance of a parser from the given input of characters.
314    pub fn new(src: T) -> Self {
315        Parser {
316            scanner: Scanner::new(src),
317            states: Vec::new(),
318            state: State::StreamStart,
319            token: None,
320            current: None,
321
322            anchors: BTreeMap::new(),
323            // valid anchor_id starts from 1
324            anchor_id_count: 1,
325            tags: BTreeMap::new(),
326            stream_end_emitted: false,
327            keep_tags: false,
328        }
329    }
330
331    /// Whether to keep tags across multiple documents when parsing.
332    ///
333    /// This behavior is non-standard as per the YAML specification but can be encountered in the
334    /// wild. This boolean allows enabling this non-standard extension. This would result in the
335    /// parser accepting input from [test
336    /// QLJ7](https://github.com/yaml/yaml-test-suite/blob/ccfa74e56afb53da960847ff6e6976c0a0825709/src/QLJ7.yaml)
337    /// of the yaml-test-suite:
338    ///
339    /// ```yaml
340    /// %TAG !prefix! tag:example.com,2011:
341    /// --- !prefix!A
342    /// a: b
343    /// --- !prefix!B
344    /// c: d
345    /// --- !prefix!C
346    /// e: f
347    /// ```
348    ///
349    /// With `keep_tags` set to `false`, the above YAML is rejected. As per the specification, tags
350    /// only apply to the document immediately following them. This would error on `!prefix!B`.
351    ///
352    /// With `keep_tags` set to `true`, the above YAML is accepted by the parser.
353    #[must_use]
354    pub fn keep_tags(mut self, value: bool) -> Self {
355        self.keep_tags = value;
356        self
357    }
358
359    /// Try to load the next event and return it, but do not consuming it from `self`.
360    ///
361    /// Any subsequent call to [`Parser::peek`] will return the same value, until a call to
362    /// [`Iterator::next`] or [`Parser::load`].
363    ///
364    /// # Errors
365    /// Returns `ScanError` when loading the next event fails.
366    pub fn peek(&mut self) -> Option<Result<&(Event<'input>, Span), ScanError>> {
367        if let Some(ref x) = self.current {
368            Some(Ok(x))
369        } else {
370            if self.stream_end_emitted {
371                return None;
372            }
373            match self.next_event_impl() {
374                Ok(token) => self.current = Some(token),
375                Err(e) => return Some(Err(e)),
376            }
377            self.current.as_ref().map(Ok)
378        }
379    }
380
381    /// Try to load the next event and return it, consuming it from `self`.
382    ///
383    /// # Errors
384    /// Returns `ScanError` when loading the next event fails.
385    pub fn next_event(&mut self) -> Option<ParseResult<'input>> {
386        if self.stream_end_emitted {
387            return None;
388        }
389
390        let tok = self.next_event_impl();
391        if matches!(tok, Ok((Event::StreamEnd, _))) {
392            self.stream_end_emitted = true;
393        }
394        Some(tok)
395    }
396
397    /// Implementation function for [`Self::next_event`] without the `Option`.
398    ///
399    /// [`Self::next_event`] should conform to the expectations of an [`Iterator`] and return an
400    /// option. This burdens the parser code. This function is used internally when an option is
401    /// undesirable.
402    fn next_event_impl<'a>(&mut self) -> ParseResult<'a>
403    where
404        'input: 'a,
405    {
406        match self.current.take() {
407            None => self.parse(),
408            Some(v) => Ok(v),
409        }
410    }
411
412    /// Peek at the next token from the scanner.
413    fn peek_token(&mut self) -> Result<&Token<'_>, ScanError> {
414        match self.token {
415            None => {
416                self.token = Some(self.scan_next_token()?);
417                Ok(self.token.as_ref().unwrap())
418            }
419            Some(ref tok) => Ok(tok),
420        }
421    }
422
423    /// Extract and return the next token from the scanner.
424    ///
425    /// This function does _not_ make use of `self.token`.
426    fn scan_next_token(&mut self) -> Result<Token<'input>, ScanError> {
427        let token = self.scanner.next();
428        match token {
429            None => match self.scanner.get_error() {
430                None => Err(ScanError::new_str(self.scanner.mark(), "unexpected eof")),
431                Some(e) => Err(e),
432            },
433            Some(tok) => Ok(tok),
434        }
435    }
436
437    fn fetch_token<'a>(&mut self) -> Token<'a>
438    where
439        'input: 'a,
440    {
441        self.token
442            .take()
443            .expect("fetch_token needs to be preceded by peek_token")
444    }
445
446    /// Skip the next token from the scanner.
447    fn skip(&mut self) {
448        self.token = None;
449    }
450    /// Pops the top-most state and make it the current state.
451    fn pop_state(&mut self) {
452        self.state = self.states.pop().unwrap();
453    }
454    /// Push a new state atop the state stack.
455    fn push_state(&mut self, state: State) {
456        self.states.push(state);
457    }
458
459    fn parse<'a>(&mut self) -> ParseResult<'a>
460    where
461        'input: 'a,
462    {
463        if self.state == State::End {
464            return Ok((Event::StreamEnd, Span::empty(self.scanner.mark())));
465        }
466        let (ev, mark) = self.state_machine()?;
467        Ok((ev, mark))
468    }
469
470    /// Load the YAML from the stream in `self`, pushing events into `recv`.
471    ///
472    /// The contents of the stream are parsed and the corresponding events are sent into the
473    /// recveiver. For detailed explanations about how events work, see [`EventReceiver`].
474    ///
475    /// If `multi` is set to `true`, the parser will allow parsing of multiple YAML documents
476    /// inside the stream.
477    ///
478    /// Note that any [`EventReceiver`] is also a [`SpannedEventReceiver`], so implementing the
479    /// former is enough to call this function.
480    /// # Errors
481    /// Returns `ScanError` when loading fails.
482    pub fn load<R: SpannedEventReceiver<'input>>(
483        &mut self,
484        recv: &mut R,
485        multi: bool,
486    ) -> Result<(), ScanError> {
487        if !self.scanner.stream_started() {
488            let (ev, span) = self.next_event_impl()?;
489            if ev != Event::StreamStart {
490                return Err(ScanError::new_str(
491                    span.start,
492                    "did not find expected <stream-start>",
493                ));
494            }
495            recv.on_event(ev, span);
496        }
497
498        if self.scanner.stream_ended() {
499            // XXX has parsed?
500            recv.on_event(Event::StreamEnd, Span::empty(self.scanner.mark()));
501            return Ok(());
502        }
503        loop {
504            let (ev, span) = self.next_event_impl()?;
505            if ev == Event::StreamEnd {
506                recv.on_event(ev, span);
507                return Ok(());
508            }
509            // clear anchors before a new document
510            self.anchors.clear();
511            self.load_document(ev, span, recv)?;
512            if !multi {
513                break;
514            }
515        }
516        Ok(())
517    }
518
519    fn load_document<R: SpannedEventReceiver<'input>>(
520        &mut self,
521        first_ev: Event<'input>,
522        span: Span,
523        recv: &mut R,
524    ) -> Result<(), ScanError> {
525        if !matches!(first_ev, Event::DocumentStart(_)) {
526            return Err(ScanError::new_str(
527                span.start,
528                "did not find expected <document-start>",
529            ));
530        }
531        recv.on_event(first_ev, span);
532
533        let (ev, span) = self.next_event_impl()?;
534        self.load_node(ev, span, recv)?;
535
536        // DOCUMENT-END is expected.
537        let (ev, mark) = self.next_event_impl()?;
538        assert_eq!(ev, Event::DocumentEnd);
539        recv.on_event(ev, mark);
540
541        Ok(())
542    }
543
544    fn load_node<R: SpannedEventReceiver<'input>>(
545        &mut self,
546        first_ev: Event<'input>,
547        span: Span,
548        recv: &mut R,
549    ) -> Result<(), ScanError> {
550        match first_ev {
551            Event::Alias(..) | Event::Scalar(..) => {
552                recv.on_event(first_ev, span);
553                Ok(())
554            }
555            Event::SequenceStart(..) => {
556                recv.on_event(first_ev, span);
557                self.load_sequence(recv)
558            }
559            Event::MappingStart(..) => {
560                recv.on_event(first_ev, span);
561                self.load_mapping(recv)
562            }
563            _ => {
564                #[cfg(feature = "debug_prints")]
565                std::println!("UNREACHABLE EVENT: {first_ev:?}");
566                unreachable!();
567            }
568        }
569    }
570
571    fn load_mapping<R: SpannedEventReceiver<'input>>(
572        &mut self,
573        recv: &mut R,
574    ) -> Result<(), ScanError> {
575        let (mut key_ev, mut key_mark) = self.next_event_impl()?;
576        while key_ev != Event::MappingEnd {
577            // key
578            self.load_node(key_ev, key_mark, recv)?;
579
580            // value
581            let (ev, mark) = self.next_event_impl()?;
582            self.load_node(ev, mark, recv)?;
583
584            // next event
585            let (ev, mark) = self.next_event_impl()?;
586            key_ev = ev;
587            key_mark = mark;
588        }
589        recv.on_event(key_ev, key_mark);
590        Ok(())
591    }
592
593    fn load_sequence<R: SpannedEventReceiver<'input>>(
594        &mut self,
595        recv: &mut R,
596    ) -> Result<(), ScanError> {
597        let (mut ev, mut mark) = self.next_event_impl()?;
598        while ev != Event::SequenceEnd {
599            self.load_node(ev, mark, recv)?;
600
601            // next event
602            let (next_ev, next_mark) = self.next_event_impl()?;
603            ev = next_ev;
604            mark = next_mark;
605        }
606        recv.on_event(ev, mark);
607        Ok(())
608    }
609
610    fn state_machine<'a>(&mut self) -> ParseResult<'a>
611    where
612        'input: 'a,
613    {
614        // let next_tok = self.peek_token().cloned()?;
615        // println!("cur_state {:?}, next tok: {:?}", self.state, next_tok);
616        debug_print!("\n\x1B[;33mParser state: {:?} \x1B[;0m", self.state);
617
618        match self.state {
619            State::StreamStart => self.stream_start(),
620
621            State::ImplicitDocumentStart => self.document_start(true),
622            State::DocumentStart => self.document_start(false),
623            State::DocumentContent => self.document_content(),
624            State::DocumentEnd => self.document_end(),
625
626            State::BlockNode => self.parse_node(true, false),
627            // State::BlockNodeOrIndentlessSequence => self.parse_node(true, true),
628            // State::FlowNode => self.parse_node(false, false),
629            State::BlockMappingFirstKey => self.block_mapping_key(true),
630            State::BlockMappingKey => self.block_mapping_key(false),
631            State::BlockMappingValue => self.block_mapping_value(),
632
633            State::BlockSequenceFirstEntry => self.block_sequence_entry(true),
634            State::BlockSequenceEntry => self.block_sequence_entry(false),
635
636            State::FlowSequenceFirstEntry => self.flow_sequence_entry(true),
637            State::FlowSequenceEntry => self.flow_sequence_entry(false),
638
639            State::FlowMappingFirstKey => self.flow_mapping_key(true),
640            State::FlowMappingKey => self.flow_mapping_key(false),
641            State::FlowMappingValue => self.flow_mapping_value(false),
642
643            State::IndentlessSequenceEntry => self.indentless_sequence_entry(),
644
645            State::FlowSequenceEntryMappingKey => self.flow_sequence_entry_mapping_key(),
646            State::FlowSequenceEntryMappingValue => self.flow_sequence_entry_mapping_value(),
647            State::FlowSequenceEntryMappingEnd(mark) => self.flow_sequence_entry_mapping_end(mark),
648            State::FlowMappingEmptyValue => self.flow_mapping_value(true),
649
650            /* impossible */
651            State::End => unreachable!(),
652        }
653    }
654
655    fn stream_start<'a>(&mut self) -> ParseResult<'a>
656    where
657        'input: 'a,
658    {
659        match *self.peek_token()? {
660            Token(span, TokenType::StreamStart(_)) => {
661                self.state = State::ImplicitDocumentStart;
662                self.skip();
663                Ok((Event::StreamStart, span))
664            }
665            Token(span, _) => Err(ScanError::new_str(
666                span.start,
667                "did not find expected <stream-start>",
668            )),
669        }
670    }
671
672    fn document_start<'a>(&mut self, implicit: bool) -> ParseResult<'a>
673    where
674        'input: 'a,
675    {
676        while let TokenType::DocumentEnd = self.peek_token()?.1 {
677            self.skip();
678        }
679
680        match *self.peek_token()? {
681            Token(span, TokenType::StreamEnd) => {
682                self.state = State::End;
683                self.skip();
684                Ok((Event::StreamEnd, span))
685            }
686            Token(
687                _,
688                TokenType::VersionDirective(..)
689                | TokenType::TagDirective(..)
690                | TokenType::ReservedDirective(..)
691                | TokenType::DocumentStart,
692            ) => {
693                // explicit document
694                self.explicit_document_start()
695            }
696            Token(span, _) if implicit => {
697                self.parser_process_directives()?;
698                self.push_state(State::DocumentEnd);
699                self.state = State::BlockNode;
700                Ok((Event::DocumentStart(false), span))
701            }
702            _ => {
703                // explicit document
704                self.explicit_document_start()
705            }
706        }
707    }
708
709    fn parser_process_directives(&mut self) -> Result<(), ScanError> {
710        let mut version_directive_received = false;
711        loop {
712            let mut tags = BTreeMap::new();
713            match self.peek_token()? {
714                Token(span, TokenType::VersionDirective(_, _)) => {
715                    // XXX parsing with warning according to spec
716                    //if major != 1 || minor > 2 {
717                    //    return Err(ScanError::new_str(tok.0,
718                    //        "found incompatible YAML document"));
719                    //}
720                    if version_directive_received {
721                        return Err(ScanError::new_str(
722                            span.start,
723                            "duplicate version directive",
724                        ));
725                    }
726                    version_directive_received = true;
727                }
728                Token(mark, TokenType::TagDirective(handle, prefix)) => {
729                    if tags.contains_key(&**handle) {
730                        return Err(ScanError::new_str(
731                            mark.start,
732                            "the TAG directive must only be given at most once per handle in the same document",
733                        ));
734                    }
735                    tags.insert(handle.to_string(), prefix.to_string());
736                }
737                Token(_, TokenType::ReservedDirective(_, _)) => {
738                    // Reserved directives are ignored
739                }
740                _ => break,
741            }
742            self.tags = tags;
743            self.skip();
744        }
745        Ok(())
746    }
747
748    fn explicit_document_start<'a>(&mut self) -> ParseResult<'a>
749    where
750        'input: 'a,
751    {
752        self.parser_process_directives()?;
753        match *self.peek_token()? {
754            Token(mark, TokenType::DocumentStart) => {
755                self.push_state(State::DocumentEnd);
756                self.state = State::DocumentContent;
757                self.skip();
758                Ok((Event::DocumentStart(true), mark))
759            }
760            Token(span, _) => Err(ScanError::new_str(
761                span.start,
762                "did not find expected <document start>",
763            )),
764        }
765    }
766
767    fn document_content<'a>(&mut self) -> ParseResult<'a>
768    where
769        'input: 'a,
770    {
771        match *self.peek_token()? {
772            Token(
773                mark,
774                TokenType::VersionDirective(..)
775                | TokenType::TagDirective(..)
776                | TokenType::ReservedDirective(..)
777                | TokenType::DocumentStart
778                | TokenType::DocumentEnd
779                | TokenType::StreamEnd,
780            ) => {
781                self.pop_state();
782                // empty scalar
783                Ok((Event::empty_scalar(), mark))
784            }
785            _ => self.parse_node(true, false),
786        }
787    }
788
789    fn document_end<'a>(&mut self) -> ParseResult<'a>
790    where
791        'input: 'a,
792    {
793        let mut explicit_end = false;
794        let span: Span = match *self.peek_token()? {
795            Token(span, TokenType::DocumentEnd) => {
796                explicit_end = true;
797                self.skip();
798                span
799            }
800            Token(span, _) => span,
801        };
802
803        if !self.keep_tags {
804            self.tags.clear();
805        }
806        if explicit_end {
807            self.state = State::ImplicitDocumentStart;
808        } else {
809            if let Token(
810                span,
811                TokenType::VersionDirective(..)
812                | TokenType::TagDirective(..)
813                | TokenType::ReservedDirective(..),
814            ) = *self.peek_token()?
815            {
816                return Err(ScanError::new_str(
817                    span.start,
818                    "missing explicit document end marker before directive",
819                ));
820            }
821            self.state = State::DocumentStart;
822        }
823
824        Ok((Event::DocumentEnd, span))
825    }
826
827    fn register_anchor(&mut self, name: Cow<'input, str>, _: &Span) -> usize {
828        // anchors can be overridden/reused
829        // if self.anchors.contains_key(name) {
830        //     return Err(ScanError::new_str(*mark,
831        //         "while parsing anchor, found duplicated anchor"));
832        // }
833        let new_id = self.anchor_id_count;
834        self.anchor_id_count += 1;
835        self.anchors.insert(name, new_id);
836        new_id
837    }
838
839    fn parse_node<'a>(&mut self, block: bool, indentless_sequence: bool) -> ParseResult<'a>
840    where
841        'input: 'a,
842    {
843        let mut anchor_id = 0;
844        let mut tag = None;
845        match *self.peek_token()? {
846            Token(_, TokenType::Alias(_)) => {
847                self.pop_state();
848                if let Token(span, TokenType::Alias(name)) = self.fetch_token() {
849                    match self.anchors.get(&*name) {
850                        None => {
851                            return Err(ScanError::new_str(
852                                span.start,
853                                "while parsing node, found unknown anchor",
854                            ));
855                        }
856                        Some(id) => return Ok((Event::Alias(*id), span)),
857                    }
858                }
859                unreachable!()
860            }
861            Token(_, TokenType::Anchor(_)) => {
862                if let Token(span, TokenType::Anchor(name)) = self.fetch_token() {
863                    anchor_id = self.register_anchor(name, &span);
864                    if let TokenType::Tag(..) = self.peek_token()?.1 {
865                        if let TokenType::Tag(handle, suffix) = self.fetch_token().1 {
866                            tag = Some(self.resolve_tag(span, &handle, suffix)?);
867                        } else {
868                            unreachable!()
869                        }
870                    }
871                } else {
872                    unreachable!()
873                }
874            }
875            Token(mark, TokenType::Tag(..)) => {
876                if let TokenType::Tag(handle, suffix) = self.fetch_token().1 {
877                    tag = Some(self.resolve_tag(mark, &handle, suffix)?);
878                    if let TokenType::Anchor(_) = &self.peek_token()?.1 {
879                        if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() {
880                            anchor_id = self.register_anchor(name, &mark);
881                        } else {
882                            unreachable!()
883                        }
884                    }
885                } else {
886                    unreachable!()
887                }
888            }
889            _ => {}
890        }
891        match *self.peek_token()? {
892            Token(mark, TokenType::BlockEntry) if indentless_sequence => {
893                self.state = State::IndentlessSequenceEntry;
894                Ok((Event::SequenceStart(anchor_id, tag), mark))
895            }
896            Token(_, TokenType::Scalar(..)) => {
897                self.pop_state();
898                if let Token(mark, TokenType::Scalar(style, v)) = self.fetch_token() {
899                    Ok((Event::Scalar(v, style, anchor_id, tag), mark))
900                } else {
901                    unreachable!()
902                }
903            }
904            Token(mark, TokenType::FlowSequenceStart) => {
905                self.state = State::FlowSequenceFirstEntry;
906                Ok((Event::SequenceStart(anchor_id, tag), mark))
907            }
908            Token(mark, TokenType::FlowMappingStart) => {
909                self.state = State::FlowMappingFirstKey;
910                Ok((Event::MappingStart(anchor_id, tag), mark))
911            }
912            Token(mark, TokenType::BlockSequenceStart) if block => {
913                self.state = State::BlockSequenceFirstEntry;
914                Ok((Event::SequenceStart(anchor_id, tag), mark))
915            }
916            Token(mark, TokenType::BlockMappingStart) if block => {
917                self.state = State::BlockMappingFirstKey;
918                Ok((Event::MappingStart(anchor_id, tag), mark))
919            }
920            // ex 7.2, an empty scalar can follow a secondary tag
921            Token(mark, _) if tag.is_some() || anchor_id > 0 => {
922                self.pop_state();
923                Ok((Event::empty_scalar_with_anchor(anchor_id, tag), mark))
924            }
925            Token(span, _) => Err(ScanError::new_str(
926                span.start,
927                "while parsing a node, did not find expected node content",
928            )),
929        }
930    }
931
932    fn block_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
933    where
934        'input: 'a,
935    {
936        // skip BlockMappingStart
937        if first {
938            let _ = self.peek_token()?;
939            //self.marks.push(tok.0);
940            self.skip();
941        }
942        match *self.peek_token()? {
943            Token(_, TokenType::Key) => {
944                self.skip();
945                if let Token(mark, TokenType::Key | TokenType::Value | TokenType::BlockEnd) =
946                    *self.peek_token()?
947                {
948                    self.state = State::BlockMappingValue;
949                    // empty scalar
950                    Ok((Event::empty_scalar(), mark))
951                } else {
952                    self.push_state(State::BlockMappingValue);
953                    self.parse_node(true, true)
954                }
955            }
956            // XXX(chenyh): libyaml failed to parse spec 1.2, ex8.18
957            Token(mark, TokenType::Value) => {
958                self.state = State::BlockMappingValue;
959                Ok((Event::empty_scalar(), mark))
960            }
961            Token(mark, TokenType::BlockEnd) => {
962                self.pop_state();
963                self.skip();
964                Ok((Event::MappingEnd, mark))
965            }
966            Token(span, _) => Err(ScanError::new_str(
967                span.start,
968                "while parsing a block mapping, did not find expected key",
969            )),
970        }
971    }
972
973    fn block_mapping_value<'a>(&mut self) -> ParseResult<'a>
974    where
975        'input: 'a,
976    {
977        match *self.peek_token()? {
978            Token(mark, TokenType::Value) => {
979                self.skip();
980                if let Token(_, TokenType::Key | TokenType::Value | TokenType::BlockEnd) =
981                    *self.peek_token()?
982                {
983                    self.state = State::BlockMappingKey;
984                    // empty scalar
985                    Ok((Event::empty_scalar(), mark))
986                } else {
987                    self.push_state(State::BlockMappingKey);
988                    self.parse_node(true, true)
989                }
990            }
991            Token(mark, _) => {
992                self.state = State::BlockMappingKey;
993                // empty scalar
994                Ok((Event::empty_scalar(), mark))
995            }
996        }
997    }
998
999    fn flow_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
1000    where
1001        'input: 'a,
1002    {
1003        if first {
1004            let _ = self.peek_token()?;
1005            self.skip();
1006        }
1007        let span: Span = {
1008            match *self.peek_token()? {
1009                Token(mark, TokenType::FlowMappingEnd) => mark,
1010                Token(mark, _) => {
1011                    if !first {
1012                        match *self.peek_token()? {
1013                            Token(_, TokenType::FlowEntry) => self.skip(),
1014                            Token(span, _) => {
1015                                return Err(ScanError::new_str(
1016                                    span.start,
1017                                    "while parsing a flow mapping, did not find expected ',' or '}'",
1018                                ));
1019                            }
1020                        }
1021                    }
1022
1023                    match *self.peek_token()? {
1024                        Token(_, TokenType::Key) => {
1025                            self.skip();
1026                            if let Token(
1027                                mark,
1028                                TokenType::Value | TokenType::FlowEntry | TokenType::FlowMappingEnd,
1029                            ) = *self.peek_token()?
1030                            {
1031                                self.state = State::FlowMappingValue;
1032                                return Ok((Event::empty_scalar(), mark));
1033                            }
1034                            self.push_state(State::FlowMappingValue);
1035                            return self.parse_node(false, false);
1036                        }
1037                        Token(marker, TokenType::Value) => {
1038                            self.state = State::FlowMappingValue;
1039                            return Ok((Event::empty_scalar(), marker));
1040                        }
1041                        Token(_, TokenType::FlowMappingEnd) => (),
1042                        _ => {
1043                            self.push_state(State::FlowMappingEmptyValue);
1044                            return self.parse_node(false, false);
1045                        }
1046                    }
1047
1048                    mark
1049                }
1050            }
1051        };
1052
1053        self.pop_state();
1054        self.skip();
1055        Ok((Event::MappingEnd, span))
1056    }
1057
1058    fn flow_mapping_value<'a>(&mut self, empty: bool) -> ParseResult<'a>
1059    where
1060        'input: 'a,
1061    {
1062        let span: Span = {
1063            if empty {
1064                let Token(mark, _) = *self.peek_token()?;
1065                self.state = State::FlowMappingKey;
1066                return Ok((Event::empty_scalar(), mark));
1067            }
1068            match *self.peek_token()? {
1069                Token(span, TokenType::Value) => {
1070                    self.skip();
1071                    match self.peek_token()?.1 {
1072                        TokenType::FlowEntry | TokenType::FlowMappingEnd => {}
1073                        _ => {
1074                            self.push_state(State::FlowMappingKey);
1075                            return self.parse_node(false, false);
1076                        }
1077                    }
1078                    span
1079                }
1080                Token(marker, _) => marker,
1081            }
1082        };
1083
1084        self.state = State::FlowMappingKey;
1085        Ok((Event::empty_scalar(), span))
1086    }
1087
1088    fn flow_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
1089    where
1090        'input: 'a,
1091    {
1092        // skip FlowMappingStart
1093        if first {
1094            let _ = self.peek_token()?;
1095            //self.marks.push(tok.0);
1096            self.skip();
1097        }
1098        match *self.peek_token()? {
1099            Token(mark, TokenType::FlowSequenceEnd) => {
1100                self.pop_state();
1101                self.skip();
1102                return Ok((Event::SequenceEnd, mark));
1103            }
1104            Token(_, TokenType::FlowEntry) if !first => {
1105                self.skip();
1106            }
1107            Token(span, _) if !first => {
1108                return Err(ScanError::new_str(
1109                    span.start,
1110                    "while parsing a flow sequence, expected ',' or ']'",
1111                ));
1112            }
1113            _ => { /* next */ }
1114        }
1115        match *self.peek_token()? {
1116            Token(mark, TokenType::FlowSequenceEnd) => {
1117                self.pop_state();
1118                self.skip();
1119                Ok((Event::SequenceEnd, mark))
1120            }
1121            Token(mark, TokenType::Key) => {
1122                self.state = State::FlowSequenceEntryMappingKey;
1123                self.skip();
1124                Ok((Event::MappingStart(0, None), mark))
1125            }
1126            _ => {
1127                self.push_state(State::FlowSequenceEntry);
1128                self.parse_node(false, false)
1129            }
1130        }
1131    }
1132
1133    fn indentless_sequence_entry<'a>(&mut self) -> ParseResult<'a>
1134    where
1135        'input: 'a,
1136    {
1137        match *self.peek_token()? {
1138            Token(mark, TokenType::BlockEntry) => {
1139                self.skip();
1140                if let Token(
1141                    _,
1142                    TokenType::BlockEntry | TokenType::Key | TokenType::Value | TokenType::BlockEnd,
1143                ) = *self.peek_token()?
1144                {
1145                    self.state = State::IndentlessSequenceEntry;
1146                    Ok((Event::empty_scalar(), mark))
1147                } else {
1148                    self.push_state(State::IndentlessSequenceEntry);
1149                    self.parse_node(true, false)
1150                }
1151            }
1152            Token(mark, _) => {
1153                self.pop_state();
1154                Ok((Event::SequenceEnd, mark))
1155            }
1156        }
1157    }
1158
1159    fn block_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
1160    where
1161        'input: 'a,
1162    {
1163        // BLOCK-SEQUENCE-START
1164        if first {
1165            let _ = self.peek_token()?;
1166            //self.marks.push(tok.0);
1167            self.skip();
1168        }
1169        match *self.peek_token()? {
1170            Token(mark, TokenType::BlockEnd) => {
1171                self.pop_state();
1172                self.skip();
1173                Ok((Event::SequenceEnd, mark))
1174            }
1175            Token(mark, TokenType::BlockEntry) => {
1176                self.skip();
1177                if let Token(_, TokenType::BlockEntry | TokenType::BlockEnd) = *self.peek_token()? {
1178                    self.state = State::BlockSequenceEntry;
1179                    Ok((Event::empty_scalar(), mark))
1180                } else {
1181                    self.push_state(State::BlockSequenceEntry);
1182                    self.parse_node(true, false)
1183                }
1184            }
1185            Token(span, _) => Err(ScanError::new_str(
1186                span.start,
1187                "while parsing a block collection, did not find expected '-' indicator",
1188            )),
1189        }
1190    }
1191
1192    fn flow_sequence_entry_mapping_key<'a>(&mut self) -> ParseResult<'a>
1193    where
1194        'input: 'a,
1195    {
1196        if let Token(mark, TokenType::Value | TokenType::FlowEntry | TokenType::FlowSequenceEnd) =
1197            *self.peek_token()?
1198        {
1199            self.skip();
1200            self.state = State::FlowSequenceEntryMappingValue;
1201            Ok((Event::empty_scalar(), mark))
1202        } else {
1203            self.push_state(State::FlowSequenceEntryMappingValue);
1204            self.parse_node(false, false)
1205        }
1206    }
1207
1208    fn flow_sequence_entry_mapping_value<'a>(&mut self) -> ParseResult<'a>
1209    where
1210        'input: 'a,
1211    {
1212        match *self.peek_token()? {
1213            Token(_, TokenType::Value) => {
1214                self.skip();
1215                self.state = State::FlowSequenceEntryMappingValue;
1216                let Token(span, ref tok) = *self.peek_token()?;
1217                if matches!(tok, TokenType::FlowEntry | TokenType::FlowSequenceEnd) {
1218                    self.state = State::FlowSequenceEntryMappingEnd(span.end);
1219                    Ok((Event::empty_scalar(), span))
1220                } else {
1221                    self.push_state(State::FlowSequenceEntryMappingEnd(span.end));
1222                    self.parse_node(false, false)
1223                }
1224            }
1225            Token(mark, _) => {
1226                self.state = State::FlowSequenceEntryMappingEnd(mark.end);
1227                Ok((Event::empty_scalar(), mark))
1228            }
1229        }
1230    }
1231
1232    #[allow(clippy::unnecessary_wraps)]
1233    fn flow_sequence_entry_mapping_end<'a>(&mut self, mark: Marker) -> ParseResult<'a>
1234    where
1235        'input: 'a,
1236    {
1237        self.state = State::FlowSequenceEntry;
1238        Ok((Event::MappingEnd, Span::empty(mark)))
1239    }
1240
1241    /// Resolve a tag from the handle and the suffix.
1242    fn resolve_tag(
1243        &self,
1244        span: Span,
1245        handle: &str,
1246        suffix: String,
1247    ) -> Result<Cow<'input, Tag>, ScanError> {
1248        let tag = if handle == "!!" {
1249            // "!!" is a shorthand for "tag:yaml.org,2002:". However, that default can be
1250            // overridden.
1251            Tag {
1252                handle: self
1253                    .tags
1254                    .get("!!")
1255                    .map_or_else(|| "tag:yaml.org,2002:".to_string(), ToString::to_string),
1256                suffix,
1257            }
1258        } else if handle.is_empty() && suffix == "!" {
1259            // "!" introduces a local tag. Local tags may have their prefix overridden.
1260            match self.tags.get("") {
1261                Some(prefix) => Tag {
1262                    handle: prefix.clone(),
1263                    suffix,
1264                },
1265                None => Tag {
1266                    handle: String::new(),
1267                    suffix,
1268                },
1269            }
1270        } else {
1271            // Lookup handle in our tag directives.
1272            let prefix = self.tags.get(handle);
1273            if let Some(prefix) = prefix {
1274                Tag {
1275                    handle: prefix.clone(),
1276                    suffix,
1277                }
1278            } else {
1279                // Otherwise, it may be a local handle. With a local handle, the handle is set to
1280                // "!" and the suffix to whatever follows it ("!foo" -> ("!", "foo")).
1281                // If the handle is of the form "!foo!", this cannot be a local handle and we need
1282                // to error.
1283                if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
1284                    return Err(ScanError::new_str(span.start, "the handle wasn't declared"));
1285                }
1286                Tag {
1287                    handle: handle.to_string(),
1288                    suffix,
1289                }
1290            }
1291        };
1292        Ok(Cow::Owned(tag))
1293    }
1294}
1295
1296impl<'input, T: Input> Iterator for Parser<'input, T> {
1297    type Item = Result<(Event<'input>, Span), ScanError>;
1298
1299    fn next(&mut self) -> Option<Self::Item> {
1300        self.next_event()
1301    }
1302}
1303
1304#[cfg(test)]
1305mod test {
1306    use super::{Event, Parser};
1307
1308    #[test]
1309    fn test_peek_eq_parse() {
1310        let s = "
1311a0 bb: val
1312a1: &x
1313    b1: 4
1314    b2: d
1315a2: 4
1316a3: [1, 2, 3]
1317a4:
1318    - [a1, a2]
1319    - 2
1320a5: *x
1321";
1322        let mut p = Parser::new_from_str(s);
1323        loop {
1324            let event_peek = p.peek().unwrap().unwrap().clone();
1325            let event = p.next_event().unwrap().unwrap();
1326            assert_eq!(event, event_peek);
1327            if event.0 == Event::StreamEnd {
1328                break;
1329            }
1330        }
1331    }
1332
1333    #[test]
1334    fn test_keep_tags_across_multiple_documents() {
1335        let text = r#"
1336%YAML 1.1
1337%TAG !t! tag:test,2024:
1338--- !t!1 &1
1339foo: "bar"
1340--- !t!2 &2
1341baz: "qux"
1342"#;
1343        for x in Parser::new_from_str(text).keep_tags(true) {
1344            let x = x.unwrap();
1345            if let Event::MappingStart(_, tag) = x.0 {
1346                let tag = tag.unwrap();
1347                assert_eq!(tag.handle, "tag:test,2024:");
1348            }
1349        }
1350
1351        for x in Parser::new_from_str(text).keep_tags(false) {
1352            if x.is_err() {
1353                // Test successful
1354                return;
1355            }
1356        }
1357        panic!("Test failed, did not encounter error")
1358    }
1359}