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 | TokenType::ByteOrderMark = 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        let mut tags = BTreeMap::new();
712        loop {
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.skip();
743        }
744        self.tags.extend(tags);
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, TokenType::ByteOrderMark) => Err(ScanError::new_str(
761                span.start,
762                "a byte order mark must not appear inside a document",
763            )),
764            Token(span, _) => Err(ScanError::new_str(
765                span.start,
766                "did not find expected <document start>",
767            )),
768        }
769    }
770
771    fn document_content<'a>(&mut self) -> ParseResult<'a>
772    where
773        'input: 'a,
774    {
775        match *self.peek_token()? {
776            Token(
777                mark,
778                TokenType::VersionDirective(..)
779                | TokenType::TagDirective(..)
780                | TokenType::ReservedDirective(..)
781                | TokenType::DocumentStart
782                | TokenType::DocumentEnd
783                | TokenType::ByteOrderMark
784                | TokenType::StreamEnd,
785            ) => {
786                self.pop_state();
787                // empty scalar
788                Ok((Event::empty_scalar(), mark))
789            }
790            _ => self.parse_node(true, false),
791        }
792    }
793
794    fn document_end<'a>(&mut self) -> ParseResult<'a>
795    where
796        'input: 'a,
797    {
798        // A byte order mark ends the document, and only more byte order marks, comments, or
799        // document markers may follow it (see 9.2. Streams). Anything else is rejected when the
800        // next document starts anyway, but checking here points the error at the byte order mark.
801        if let Token(span, TokenType::ByteOrderMark) = *self.peek_token()? {
802            while let TokenType::ByteOrderMark = self.peek_token()?.1 {
803                self.skip();
804            }
805
806            match self.peek_token()?.1 {
807                TokenType::DocumentStart | TokenType::DocumentEnd | TokenType::StreamEnd => {}
808                _ => {
809                    return Err(ScanError::new_str(
810                        span.start,
811                        "a byte order mark must not appear inside a document",
812                    ));
813                }
814            }
815        }
816
817        let mut explicit_end = false;
818        let span: Span = match *self.peek_token()? {
819            Token(span, TokenType::DocumentEnd) => {
820                explicit_end = true;
821                self.skip();
822                span
823            }
824            Token(span, _) => span,
825        };
826
827        if !self.keep_tags {
828            self.tags.clear();
829        }
830        if explicit_end {
831            self.state = State::ImplicitDocumentStart;
832        } else {
833            if let Token(
834                span,
835                TokenType::VersionDirective(..)
836                | TokenType::TagDirective(..)
837                | TokenType::ReservedDirective(..),
838            ) = *self.peek_token()?
839            {
840                return Err(ScanError::new_str(
841                    span.start,
842                    "missing explicit document end marker before directive",
843                ));
844            }
845            self.state = State::DocumentStart;
846        }
847
848        Ok((Event::DocumentEnd, span))
849    }
850
851    fn register_anchor(&mut self, name: Cow<'input, str>, _: &Span) -> usize {
852        // anchors can be overridden/reused
853        // if self.anchors.contains_key(name) {
854        //     return Err(ScanError::new_str(*mark,
855        //         "while parsing anchor, found duplicated anchor"));
856        // }
857        let new_id = self.anchor_id_count;
858        self.anchor_id_count += 1;
859        self.anchors.insert(name, new_id);
860        new_id
861    }
862
863    fn parse_node<'a>(&mut self, block: bool, indentless_sequence: bool) -> ParseResult<'a>
864    where
865        'input: 'a,
866    {
867        let mut anchor_id = 0;
868        let mut tag = None;
869        let start_mark = self.peek_token()?.0.start;
870        let mut end_mark = start_mark;
871        match *self.peek_token()? {
872            Token(_, TokenType::Alias(_)) => {
873                self.pop_state();
874                if let Token(span, TokenType::Alias(name)) = self.fetch_token() {
875                    match self.anchors.get(&*name) {
876                        None => {
877                            return Err(ScanError::new_str(
878                                span.start,
879                                "while parsing node, found unknown anchor",
880                            ));
881                        }
882                        Some(id) => return Ok((Event::Alias(*id), span)),
883                    }
884                }
885                unreachable!()
886            }
887            Token(_, TokenType::Anchor(_)) => {
888                if let Token(span, TokenType::Anchor(name)) = self.fetch_token() {
889                    anchor_id = self.register_anchor(name, &span);
890                    end_mark = span.end;
891                    if let TokenType::Tag(..) = self.peek_token()?.1 {
892                        if let Token(mark, TokenType::Tag(handle, suffix)) = self.fetch_token() {
893                            tag = Some(self.resolve_tag(span, &handle, suffix)?);
894                            end_mark = mark.end;
895                        } else {
896                            unreachable!()
897                        }
898                    }
899                } else {
900                    unreachable!()
901                }
902            }
903            Token(mark, TokenType::Tag(..)) => {
904                if let TokenType::Tag(handle, suffix) = self.fetch_token().1 {
905                    tag = Some(self.resolve_tag(mark, &handle, suffix)?);
906                    end_mark = mark.end;
907                    if let TokenType::Anchor(_) = &self.peek_token()?.1 {
908                        if let Token(mark, TokenType::Anchor(name)) = self.fetch_token() {
909                            anchor_id = self.register_anchor(name, &mark);
910                            end_mark = mark.end;
911                        } else {
912                            unreachable!()
913                        }
914                    }
915                } else {
916                    unreachable!()
917                }
918            }
919            _ => {}
920        }
921        let (event, end_mark) = match *self.peek_token()? {
922            Token(mark, TokenType::BlockEntry) if indentless_sequence => {
923                self.state = State::IndentlessSequenceEntry;
924                (Event::SequenceStart(anchor_id, tag), mark.end)
925            }
926            Token(_, TokenType::Scalar(..)) => {
927                self.pop_state();
928                if let Token(mark, TokenType::Scalar(style, v)) = self.fetch_token() {
929                    (Event::Scalar(v, style, anchor_id, tag), mark.end)
930                } else {
931                    unreachable!()
932                }
933            }
934            Token(mark, TokenType::FlowSequenceStart) => {
935                self.state = State::FlowSequenceFirstEntry;
936                (Event::SequenceStart(anchor_id, tag), mark.end)
937            }
938            Token(mark, TokenType::FlowMappingStart) => {
939                self.state = State::FlowMappingFirstKey;
940                (Event::MappingStart(anchor_id, tag), mark.end)
941            }
942            Token(mark, TokenType::BlockSequenceStart) if block => {
943                self.state = State::BlockSequenceFirstEntry;
944                (Event::SequenceStart(anchor_id, tag), mark.end)
945            }
946            Token(mark, TokenType::BlockMappingStart) if block => {
947                self.state = State::BlockMappingFirstKey;
948                (Event::MappingStart(anchor_id, tag), mark.end)
949            }
950            // ex 7.2, an empty scalar can follow a secondary tag
951            Token(..) if tag.is_some() || anchor_id > 0 => {
952                self.pop_state();
953                (Event::empty_scalar_with_anchor(anchor_id, tag), end_mark)
954            }
955            Token(span, _) => {
956                return Err(ScanError::new_str(
957                    span.start,
958                    "while parsing a node, did not find expected node content",
959                ));
960            }
961        };
962        Ok((event, Span::new(start_mark, end_mark)))
963    }
964
965    fn block_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
966    where
967        'input: 'a,
968    {
969        // skip BlockMappingStart
970        if first {
971            let _ = self.peek_token()?;
972            //self.marks.push(tok.0);
973            self.skip();
974        }
975        match *self.peek_token()? {
976            Token(_, TokenType::Key) => {
977                self.skip();
978                if let Token(mark, TokenType::Key | TokenType::Value | TokenType::BlockEnd) =
979                    *self.peek_token()?
980                {
981                    self.state = State::BlockMappingValue;
982                    // empty scalar
983                    Ok((Event::empty_scalar(), mark))
984                } else {
985                    self.push_state(State::BlockMappingValue);
986                    self.parse_node(true, true)
987                }
988            }
989            // XXX(chenyh): libyaml failed to parse spec 1.2, ex8.18
990            Token(mark, TokenType::Value) => {
991                self.state = State::BlockMappingValue;
992                Ok((Event::empty_scalar(), mark))
993            }
994            Token(mark, TokenType::BlockEnd) => {
995                self.pop_state();
996                self.skip();
997                Ok((Event::MappingEnd, mark))
998            }
999            Token(span, _) => Err(ScanError::new_str(
1000                span.start,
1001                "while parsing a block mapping, did not find expected key",
1002            )),
1003        }
1004    }
1005
1006    fn block_mapping_value<'a>(&mut self) -> ParseResult<'a>
1007    where
1008        'input: 'a,
1009    {
1010        match *self.peek_token()? {
1011            Token(mark, TokenType::Value) => {
1012                self.skip();
1013                if let Token(_, TokenType::Key | TokenType::Value | TokenType::BlockEnd) =
1014                    *self.peek_token()?
1015                {
1016                    self.state = State::BlockMappingKey;
1017                    // empty scalar
1018                    Ok((Event::empty_scalar(), mark))
1019                } else {
1020                    self.push_state(State::BlockMappingKey);
1021                    self.parse_node(true, true)
1022                }
1023            }
1024            Token(mark, _) => {
1025                self.state = State::BlockMappingKey;
1026                // empty scalar
1027                Ok((Event::empty_scalar(), mark))
1028            }
1029        }
1030    }
1031
1032    fn flow_mapping_key<'a>(&mut self, first: bool) -> ParseResult<'a>
1033    where
1034        'input: 'a,
1035    {
1036        if first {
1037            let _ = self.peek_token()?;
1038            self.skip();
1039        }
1040        let span: Span = {
1041            match *self.peek_token()? {
1042                Token(mark, TokenType::FlowMappingEnd) => mark,
1043                Token(mark, _) => {
1044                    if !first {
1045                        match *self.peek_token()? {
1046                            Token(_, TokenType::FlowEntry) => self.skip(),
1047                            Token(span, _) => {
1048                                return Err(ScanError::new_str(
1049                                    span.start,
1050                                    "while parsing a flow mapping, did not find expected ',' or '}'",
1051                                ));
1052                            }
1053                        }
1054                    }
1055
1056                    match *self.peek_token()? {
1057                        Token(_, TokenType::Key) => {
1058                            self.skip();
1059                            if let Token(
1060                                mark,
1061                                TokenType::Value | TokenType::FlowEntry | TokenType::FlowMappingEnd,
1062                            ) = *self.peek_token()?
1063                            {
1064                                self.state = State::FlowMappingValue;
1065                                return Ok((Event::empty_scalar(), mark));
1066                            }
1067                            self.push_state(State::FlowMappingValue);
1068                            return self.parse_node(false, false);
1069                        }
1070                        Token(marker, TokenType::Value) => {
1071                            self.state = State::FlowMappingValue;
1072                            return Ok((Event::empty_scalar(), marker));
1073                        }
1074                        Token(_, TokenType::FlowMappingEnd) => (),
1075                        _ => {
1076                            self.push_state(State::FlowMappingEmptyValue);
1077                            return self.parse_node(false, false);
1078                        }
1079                    }
1080
1081                    mark
1082                }
1083            }
1084        };
1085
1086        self.pop_state();
1087        self.skip();
1088        Ok((Event::MappingEnd, span))
1089    }
1090
1091    fn flow_mapping_value<'a>(&mut self, empty: bool) -> ParseResult<'a>
1092    where
1093        'input: 'a,
1094    {
1095        let span: Span = {
1096            if empty {
1097                let Token(mark, _) = *self.peek_token()?;
1098                self.state = State::FlowMappingKey;
1099                return Ok((Event::empty_scalar(), mark));
1100            }
1101            match *self.peek_token()? {
1102                Token(span, TokenType::Value) => {
1103                    self.skip();
1104                    match self.peek_token()?.1 {
1105                        TokenType::FlowEntry | TokenType::FlowMappingEnd => {}
1106                        _ => {
1107                            self.push_state(State::FlowMappingKey);
1108                            return self.parse_node(false, false);
1109                        }
1110                    }
1111                    span
1112                }
1113                Token(marker, _) => marker,
1114            }
1115        };
1116
1117        self.state = State::FlowMappingKey;
1118        Ok((Event::empty_scalar(), span))
1119    }
1120
1121    fn flow_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
1122    where
1123        'input: 'a,
1124    {
1125        // skip FlowMappingStart
1126        if first {
1127            let _ = self.peek_token()?;
1128            //self.marks.push(tok.0);
1129            self.skip();
1130        }
1131        match *self.peek_token()? {
1132            Token(mark, TokenType::FlowSequenceEnd) => {
1133                self.pop_state();
1134                self.skip();
1135                return Ok((Event::SequenceEnd, mark));
1136            }
1137            Token(_, TokenType::FlowEntry) if !first => {
1138                self.skip();
1139            }
1140            Token(span, _) if !first => {
1141                return Err(ScanError::new_str(
1142                    span.start,
1143                    "while parsing a flow sequence, expected ',' or ']'",
1144                ));
1145            }
1146            _ => { /* next */ }
1147        }
1148        match *self.peek_token()? {
1149            Token(mark, TokenType::FlowSequenceEnd) => {
1150                self.pop_state();
1151                self.skip();
1152                Ok((Event::SequenceEnd, mark))
1153            }
1154            Token(mark, TokenType::Key) => {
1155                self.state = State::FlowSequenceEntryMappingKey;
1156                self.skip();
1157                Ok((Event::MappingStart(0, None), mark))
1158            }
1159            _ => {
1160                self.push_state(State::FlowSequenceEntry);
1161                self.parse_node(false, false)
1162            }
1163        }
1164    }
1165
1166    fn indentless_sequence_entry<'a>(&mut self) -> ParseResult<'a>
1167    where
1168        'input: 'a,
1169    {
1170        match *self.peek_token()? {
1171            Token(mark, TokenType::BlockEntry) => {
1172                self.skip();
1173                if let Token(
1174                    _,
1175                    TokenType::BlockEntry | TokenType::Key | TokenType::Value | TokenType::BlockEnd,
1176                ) = *self.peek_token()?
1177                {
1178                    self.state = State::IndentlessSequenceEntry;
1179                    Ok((Event::empty_scalar(), mark))
1180                } else {
1181                    self.push_state(State::IndentlessSequenceEntry);
1182                    self.parse_node(true, false)
1183                }
1184            }
1185            Token(mark, _) => {
1186                self.pop_state();
1187                Ok((Event::SequenceEnd, mark))
1188            }
1189        }
1190    }
1191
1192    fn block_sequence_entry<'a>(&mut self, first: bool) -> ParseResult<'a>
1193    where
1194        'input: 'a,
1195    {
1196        // BLOCK-SEQUENCE-START
1197        if first {
1198            let _ = self.peek_token()?;
1199            //self.marks.push(tok.0);
1200            self.skip();
1201        }
1202        match *self.peek_token()? {
1203            Token(mark, TokenType::BlockEnd) => {
1204                self.pop_state();
1205                self.skip();
1206                Ok((Event::SequenceEnd, mark))
1207            }
1208            Token(mark, TokenType::BlockEntry) => {
1209                self.skip();
1210                if let Token(_, TokenType::BlockEntry | TokenType::BlockEnd) = *self.peek_token()? {
1211                    self.state = State::BlockSequenceEntry;
1212                    Ok((Event::empty_scalar(), mark))
1213                } else {
1214                    self.push_state(State::BlockSequenceEntry);
1215                    self.parse_node(true, false)
1216                }
1217            }
1218            Token(span, _) => Err(ScanError::new_str(
1219                span.start,
1220                "while parsing a block collection, did not find expected '-' indicator",
1221            )),
1222        }
1223    }
1224
1225    fn flow_sequence_entry_mapping_key<'a>(&mut self) -> ParseResult<'a>
1226    where
1227        'input: 'a,
1228    {
1229        if let Token(mark, TokenType::Value | TokenType::FlowEntry | TokenType::FlowSequenceEnd) =
1230            *self.peek_token()?
1231        {
1232            self.skip();
1233            self.state = State::FlowSequenceEntryMappingValue;
1234            Ok((Event::empty_scalar(), mark))
1235        } else {
1236            self.push_state(State::FlowSequenceEntryMappingValue);
1237            self.parse_node(false, false)
1238        }
1239    }
1240
1241    fn flow_sequence_entry_mapping_value<'a>(&mut self) -> ParseResult<'a>
1242    where
1243        'input: 'a,
1244    {
1245        match *self.peek_token()? {
1246            Token(_, TokenType::Value) => {
1247                self.skip();
1248                self.state = State::FlowSequenceEntryMappingValue;
1249                let Token(span, ref tok) = *self.peek_token()?;
1250                if matches!(tok, TokenType::FlowEntry | TokenType::FlowSequenceEnd) {
1251                    self.state = State::FlowSequenceEntryMappingEnd(span.end);
1252                    Ok((Event::empty_scalar(), span))
1253                } else {
1254                    self.push_state(State::FlowSequenceEntryMappingEnd(span.end));
1255                    self.parse_node(false, false)
1256                }
1257            }
1258            Token(mark, _) => {
1259                self.state = State::FlowSequenceEntryMappingEnd(mark.end);
1260                Ok((Event::empty_scalar(), mark))
1261            }
1262        }
1263    }
1264
1265    #[allow(clippy::unnecessary_wraps)]
1266    fn flow_sequence_entry_mapping_end<'a>(&mut self, mark: Marker) -> ParseResult<'a>
1267    where
1268        'input: 'a,
1269    {
1270        self.state = State::FlowSequenceEntry;
1271        Ok((Event::MappingEnd, Span::empty(mark)))
1272    }
1273
1274    /// Resolve a tag from the handle and the suffix.
1275    fn resolve_tag(
1276        &self,
1277        span: Span,
1278        handle: &str,
1279        suffix: String,
1280    ) -> Result<Cow<'input, Tag>, ScanError> {
1281        let tag = if handle == "!!" {
1282            // "!!" is a shorthand for "tag:yaml.org,2002:". However, that default can be
1283            // overridden.
1284            Tag {
1285                handle: self
1286                    .tags
1287                    .get("!!")
1288                    .map_or_else(|| "tag:yaml.org,2002:".to_string(), ToString::to_string),
1289                suffix,
1290            }
1291        } else if handle.is_empty() && suffix == "!" {
1292            // "!" introduces a local tag. Local tags may have their prefix overridden.
1293            match self.tags.get("") {
1294                Some(prefix) => Tag {
1295                    handle: prefix.clone(),
1296                    suffix,
1297                },
1298                None => Tag {
1299                    handle: String::new(),
1300                    suffix,
1301                },
1302            }
1303        } else {
1304            // Lookup handle in our tag directives.
1305            let prefix = self.tags.get(handle);
1306            if let Some(prefix) = prefix {
1307                Tag {
1308                    handle: prefix.clone(),
1309                    suffix,
1310                }
1311            } else {
1312                // Otherwise, it may be a local handle. With a local handle, the handle is set to
1313                // "!" and the suffix to whatever follows it ("!foo" -> ("!", "foo")).
1314                // If the handle is of the form "!foo!", this cannot be a local handle and we need
1315                // to error.
1316                if handle.len() >= 2 && handle.starts_with('!') && handle.ends_with('!') {
1317                    return Err(ScanError::new_str(span.start, "the handle wasn't declared"));
1318                }
1319                Tag {
1320                    handle: handle.to_string(),
1321                    suffix,
1322                }
1323            }
1324        };
1325        Ok(Cow::Owned(tag))
1326    }
1327}
1328
1329impl<'input, T: Input> Iterator for Parser<'input, T> {
1330    type Item = Result<(Event<'input>, Span), ScanError>;
1331
1332    fn next(&mut self) -> Option<Self::Item> {
1333        self.next_event()
1334    }
1335}
1336
1337#[cfg(test)]
1338mod test {
1339    use super::{Event, Parser};
1340
1341    #[test]
1342    fn test_peek_eq_parse() {
1343        let s = "
1344a0 bb: val
1345a1: &x
1346    b1: 4
1347    b2: d
1348a2: 4
1349a3: [1, 2, 3]
1350a4:
1351    - [a1, a2]
1352    - 2
1353a5: *x
1354";
1355        let mut p = Parser::new_from_str(s);
1356        loop {
1357            let event_peek = p.peek().unwrap().unwrap().clone();
1358            let event = p.next_event().unwrap().unwrap();
1359            assert_eq!(event, event_peek);
1360            if event.0 == Event::StreamEnd {
1361                break;
1362            }
1363        }
1364    }
1365
1366    #[test]
1367    fn test_keep_tags_across_multiple_documents() {
1368        let text = r#"
1369%YAML 1.1
1370%TAG !t! tag:test,2024:
1371--- !t!1 &1
1372foo: "bar"
1373--- !t!2 &2
1374baz: "qux"
1375"#;
1376        for x in Parser::new_from_str(text).keep_tags(true) {
1377            let x = x.unwrap();
1378            if let Event::MappingStart(_, tag) = x.0 {
1379                let tag = tag.unwrap();
1380                assert_eq!(tag.handle, "tag:test,2024:");
1381            }
1382        }
1383
1384        for x in Parser::new_from_str(text).keep_tags(false) {
1385            if x.is_err() {
1386                // Test successful
1387                return;
1388            }
1389        }
1390        panic!("Test failed, did not encounter error")
1391    }
1392}