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}