rlsp_yaml_parser/event.rs
1// SPDX-License-Identifier: MIT
2
3//! High-level parse events produced by the streaming parser.
4//!
5//! The public entry point is [`crate::parse_events`], which returns an
6//! iterator of <code>Result<([Event], [crate::pos::Span]), [crate::error::Error]></code>.
7//!
8//! Each event carries a [`crate::pos::Span`] covering the input bytes that
9//! contributed to it. For zero-width synthetic events (e.g. `StreamStart`
10//! at the very beginning of input), the span has equal `start` and `end`.
11//!
12
13use std::borrow::Cow;
14
15/// Block scalar chomping mode per YAML 1.2 §8.1.1.2.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum Chomp {
18 /// `-` — trailing newlines stripped.
19 Strip,
20 /// (default, no indicator) — single trailing newline kept.
21 Clip,
22 /// `+` — all trailing newlines kept.
23 Keep,
24}
25
26/// The style (block or flow) of a collection (sequence or mapping).
27///
28/// Currently only `Block` is produced; `Flow` will be used when flow sequences
29/// (`[a, b]`) and flow mappings (`{a: b}`) are implemented in Task 14.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum CollectionStyle {
32 /// A block-style collection using indentation and `-`/`:` indicators.
33 Block,
34 /// A flow-style collection using `[]` or `{}` delimiters (Task 14).
35 Flow,
36}
37
38/// The style in which a scalar value was written in the source.
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum ScalarStyle {
41 /// An unquoted plain scalar (YAML 1.2 §7.3.3).
42 Plain,
43 /// A `'single-quoted'` scalar (YAML 1.2 §7.3.2).
44 SingleQuoted,
45 /// A `"double-quoted"` scalar (YAML 1.2 §7.3.1).
46 DoubleQuoted,
47 /// A `|` literal block scalar (YAML 1.2 §8.1.2).
48 Literal(Chomp),
49 /// A `>` folded block scalar (YAML 1.2 §8.1.3).
50 ///
51 /// Line folding is applied to the collected content: a single line break
52 /// between two equally-indented non-blank lines becomes a space; N blank
53 /// lines between non-blank lines produce N newlines; more-indented lines
54 /// preserve their relative leading whitespace and the line break before
55 /// them is kept as `\n` rather than folded to a space. Callers must not
56 /// treat the value as whitespace-safe — more-indented lines can inject
57 /// arbitrary leading spaces into the parsed value.
58 Folded(Chomp),
59}
60
61/// A high-level YAML parse event.
62#[derive(Debug, Clone, PartialEq, Eq)]
63pub enum Event<'input> {
64 /// The YAML stream has started.
65 ///
66 /// Always the first event in any parse. The associated span is a
67 /// zero-width span at [`crate::pos::Pos::ORIGIN`].
68 StreamStart,
69 /// The YAML stream has ended.
70 ///
71 /// Always the last event in any parse. The associated span is a
72 /// zero-width span at the position immediately after the last byte of
73 /// input.
74 StreamEnd,
75 /// A YAML comment (YAML 1.2 §6.6).
76 ///
77 /// `text` is the comment body — the content of the line after the `#`
78 /// character, with the `#` itself excluded. Leading whitespace after `#`
79 /// is preserved (e.g. `# hello` → text `" hello"`; `#nospace` → text
80 /// `"nospace"`). The associated span covers from the `#` character
81 /// through the last byte of comment text (the newline is not included).
82 ///
83 /// One `Comment` event is emitted per physical line.
84 Comment {
85 /// Comment body (everything after the `#`, excluding the newline).
86 text: &'input str,
87 },
88 /// An alias node (`*name`) that references a previously anchored node.
89 ///
90 /// The associated span covers the entire `*name` token (from `*` through
91 /// the last character of the name). Resolution of the alias to its
92 /// anchored node is the loader's responsibility (Task 20) — the parser
93 /// emits this event without expansion.
94 Alias {
95 /// The anchor name being referenced (e.g. `"foo"` for `*foo`).
96 /// Borrowed directly from input — no allocation.
97 name: &'input str,
98 },
99 /// A document has started.
100 ///
101 /// `explicit` is `true` when the document was introduced with `---`.
102 /// `false` for bare documents (no marker).
103 DocumentStart {
104 /// Whether the document was introduced with `---`.
105 explicit: bool,
106 /// Version from the `%YAML` directive preceding this document, if any.
107 ///
108 /// `Some((1, 2))` for `%YAML 1.2`, `None` when no `%YAML` directive was present.
109 version: Option<(u8, u8)>,
110 /// Tag handle/prefix pairs from `%TAG` directives preceding this document.
111 ///
112 /// Each entry is `(handle, prefix)` — e.g. `("!foo!", "tag:example.com,2026:")`.
113 /// Empty when no `%TAG` directives were present.
114 tag_directives: Vec<(String, String)>,
115 },
116 /// A document has ended.
117 ///
118 /// `explicit` is `true` when the document was closed with `...`.
119 /// `false` for implicitly-ended documents.
120 DocumentEnd {
121 /// Whether the document was closed with `...`.
122 explicit: bool,
123 },
124 /// A block or flow sequence has started.
125 ///
126 /// Followed by zero or more node events (scalars or nested collections),
127 /// then a matching [`Event::SequenceEnd`].
128 SequenceStart {
129 /// The anchor name, if any (e.g. `&foo`).
130 anchor: Option<&'input str>,
131 /// The resolved tag, if any (e.g. `"tag:yaml.org,2002:seq"` for `!!seq`).
132 ///
133 /// Verbatim tags (`!<URI>`) borrow from input. Shorthand tags resolved
134 /// via `%TAG` directives or the built-in `!!` default produce owned strings.
135 tag: Option<Cow<'input, str>>,
136 /// Whether this is a block (`-` indicator) or flow (`[...]`) sequence.
137 style: CollectionStyle,
138 },
139 /// A sequence has ended.
140 ///
141 /// Matches the most recent [`Event::SequenceStart`] on the event stack.
142 SequenceEnd,
143 /// A block or flow mapping has started.
144 ///
145 /// Followed by alternating key/value node events (scalars or nested
146 /// collections), then a matching [`Event::MappingEnd`].
147 MappingStart {
148 /// The anchor name, if any (e.g. `&foo`).
149 anchor: Option<&'input str>,
150 /// The resolved tag, if any (e.g. `"tag:yaml.org,2002:map"` for `!!map`).
151 ///
152 /// See [`SequenceStart::tag`] for resolution semantics.
153 tag: Option<Cow<'input, str>>,
154 /// Whether this is a block (indentation-based) or flow (`{...}`) mapping.
155 style: CollectionStyle,
156 },
157 /// A mapping has ended.
158 ///
159 /// Matches the most recent [`Event::MappingStart`] on the event stack.
160 MappingEnd,
161 /// A scalar value.
162 ///
163 /// `value` borrows from input when no transformation is required (the
164 /// vast majority of plain scalars). It owns when line folding produces
165 /// a string that doesn't exist contiguously in the input.
166 Scalar {
167 /// The scalar's decoded value.
168 value: Cow<'input, str>,
169 /// The style in which the scalar appeared in the source.
170 style: ScalarStyle,
171 /// The anchor name, if any (e.g. `&foo`).
172 anchor: Option<&'input str>,
173 /// The resolved tag, if any (e.g. `"tag:yaml.org,2002:str"` for `!!str`).
174 ///
175 /// See [`SequenceStart::tag`] for resolution semantics.
176 tag: Option<Cow<'input, str>>,
177 },
178}