Skip to main content

yaml_rt_core/
syntax.rs

1use crate::semantic::SemanticStore;
2use crate::{NodeId, Parser, Source, Span, YamlError};
3
4/// Lossless syntax node produced by the CST parser.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Node {
7    /// Node classification.
8    pub(crate) kind: NodeKind,
9    /// Original source span for this node.
10    pub(crate) span: Span,
11    pub(crate) parent: u32,
12    pub(crate) first_child: u32,
13    pub(crate) last_child: u32,
14    pub(crate) next_sibling: u32,
15}
16
17pub(crate) const NO_NODE: u32 = u32::MAX;
18
19impl Node {
20    /// Returns this node's syntax classification.
21    #[must_use]
22    pub const fn kind(&self) -> NodeKind {
23        self.kind
24    }
25
26    /// Returns this node's original source span.
27    #[must_use]
28    pub const fn span(&self) -> Span {
29        self.span
30    }
31
32    /// Returns this node's parent, when it is not the stream root.
33    #[must_use]
34    pub const fn parent(&self) -> Option<NodeId> {
35        node_link(self.parent)
36    }
37}
38
39/// Iterator over a node's children in source order.
40#[derive(Debug, Clone)]
41pub struct Children<'doc> {
42    nodes: &'doc [Node],
43    next: u32,
44}
45
46impl<'doc> Children<'doc> {
47    pub(crate) fn new(nodes: &'doc [Node], parent: NodeId) -> Self {
48        let next = nodes
49            .get(parent.as_usize())
50            .map_or(NO_NODE, |node| node.first_child);
51        Self { nodes, next }
52    }
53}
54
55impl Iterator for Children<'_> {
56    type Item = NodeId;
57
58    fn next(&mut self) -> Option<Self::Item> {
59        let id = node_link(self.next)?;
60        self.next = self.nodes[id.as_usize()].next_sibling;
61        Some(id)
62    }
63}
64
65pub(crate) const fn node_link(link: u32) -> Option<NodeId> {
66    if link == NO_NODE {
67        None
68    } else {
69        Some(NodeId(link))
70    }
71}
72
73/// Node kinds emitted by the CST parser.
74#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
75pub enum NodeKind {
76    /// Complete YAML stream.
77    Stream,
78    /// Content document inside a stream.
79    Document,
80    /// Explicit document start or end marker.
81    DocumentMarker,
82    /// YAML directive line.
83    Directive,
84    /// Block mapping collection.
85    BlockMapping,
86    /// One mapping entry line.
87    MappingEntry,
88    /// Block sequence collection.
89    BlockSequence,
90    /// One block or flow sequence item wrapper.
91    SequenceEntry,
92    /// Single-line flow sequence collection.
93    FlowSequence,
94    /// Single-line flow mapping collection.
95    FlowMapping,
96    /// Literal block scalar collection.
97    LiteralScalar,
98    /// Folded block scalar collection.
99    FoldedScalar,
100    /// Scalar syntax span.
101    Scalar,
102}
103
104/// Semantic YAML event produced by the parser.
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct YamlEvent {
107    /// Event classification.
108    pub kind: YamlEventKind,
109    /// Source span associated with this event.
110    pub span: Span,
111    /// CST node that originated this semantic event, when applicable.
112    pub(crate) cst: Option<NodeId>,
113    pub(crate) content_indent: Option<u32>,
114}
115
116/// YAML collection spelling.
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
118pub enum CollectionStyle {
119    /// Block collection syntax.
120    Block,
121    /// Flow collection syntax.
122    Flow,
123}
124
125/// YAML scalar spelling.
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum YamlScalarStyle {
128    /// Plain scalar syntax.
129    Plain,
130    /// Single-quoted scalar syntax.
131    SingleQuoted,
132    /// Double-quoted scalar syntax.
133    DoubleQuoted,
134    /// Literal block scalar syntax.
135    Literal,
136    /// Folded block scalar syntax.
137    Folded,
138}
139
140/// Semantic YAML event kinds.
141#[derive(Debug, Clone, PartialEq, Eq)]
142pub enum YamlEventKind {
143    /// Start of a YAML stream.
144    StreamStart,
145    /// End of a YAML stream.
146    StreamEnd,
147    /// Start of a YAML document.
148    DocumentStart {
149        /// Whether the source used an explicit `---` marker.
150        explicit: bool,
151    },
152    /// End of a YAML document.
153    DocumentEnd {
154        /// Whether the source used an explicit `...` marker.
155        explicit: bool,
156    },
157    /// Start of a sequence node.
158    SequenceStart {
159        /// Sequence spelling style.
160        style: CollectionStyle,
161        /// Explicit tag, when present.
162        tag: Option<String>,
163        /// Explicit anchor, when present.
164        anchor: Option<String>,
165    },
166    /// End of a sequence node.
167    SequenceEnd,
168    /// Start of a mapping node.
169    MappingStart {
170        /// Mapping spelling style.
171        style: CollectionStyle,
172        /// Explicit tag, when present.
173        tag: Option<String>,
174        /// Explicit anchor, when present.
175        anchor: Option<String>,
176    },
177    /// End of a mapping node.
178    MappingEnd,
179    /// Scalar node with decoded content.
180    Scalar {
181        /// Scalar spelling style.
182        style: YamlScalarStyle,
183        /// Decoded scalar value.
184        value: String,
185        /// Explicit tag, when present.
186        tag: Option<String>,
187        /// Explicit anchor, when present.
188        anchor: Option<String>,
189    },
190    /// Alias node.
191    Alias {
192        /// Alias name without the leading `*`.
193        name: String,
194    },
195}
196
197/// Parses a source buffer into a lossless CST node arena.
198///
199/// # Errors
200///
201/// Returns an error when the source contains YAML syntax the parser cannot
202/// accept or when parser events cannot be produced from the CST.
203pub fn parse_cst(source: &Source) -> Result<Vec<Node>, YamlError> {
204    Parser::new(source).parse().map(|parsed| parsed.nodes)
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub(crate) struct ParsedYaml {
209    pub(crate) nodes: Vec<Node>,
210    pub(crate) semantics: SemanticStore,
211}