1use alloc::vec::Vec;
15use core::fmt;
16
17use mf2_model::{Diagnostic, Diagnostics, Parsed, Span};
18
19#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
21#[repr(u8)]
22#[non_exhaustive]
23pub enum SyntaxKind {
24 SimpleMessage,
27 ComplexMessage,
29 InputDeclaration,
31 LocalDeclaration,
33 QuotedPattern,
35 Pattern,
37 Matcher,
39 Variant,
41 Expression,
43 MarkupOpen,
45 MarkupStandalone,
47 MarkupClose,
49 Function,
51 Option,
53 Attribute,
55 Variable,
57 Identifier,
59 QuotedLiteral,
61
62 Text,
65 Escape,
67 LiteralText,
69 UnquotedLiteral,
71 Name,
73 Star,
75 KwInput,
77 KwLocal,
79 KwMatch,
81 LBrace,
83 RBrace,
85 LBrace2,
87 RBrace2,
89 Pipe,
91 Dollar,
93 Colon,
95 Hash,
97 Slash,
99 At,
101 Equals,
103 Trivia,
105 Error,
107}
108
109impl SyntaxKind {
110 pub fn is_token(self) -> bool {
112 (self as u8) >= (SyntaxKind::Text as u8)
113 }
114
115 pub fn is_node(self) -> bool {
117 !self.is_token()
118 }
119
120 pub(crate) fn is_semantic_token(self) -> bool {
123 matches!(
124 self,
125 SyntaxKind::Text
126 | SyntaxKind::Escape
127 | SyntaxKind::LiteralText
128 | SyntaxKind::UnquotedLiteral
129 | SyntaxKind::Name
130 | SyntaxKind::Star
131 )
132 }
133
134 pub fn is_markup(self) -> bool {
136 matches!(
137 self,
138 SyntaxKind::MarkupOpen | SyntaxKind::MarkupStandalone | SyntaxKind::MarkupClose
139 )
140 }
141}
142
143#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
145pub struct Node {
146 pub(crate) start: u32,
147 pub(crate) end: u32,
148 pub(crate) last: u32,
150 pub(crate) kind: SyntaxKind,
151}
152
153impl Node {
154 pub fn kind(&self) -> SyntaxKind {
156 self.kind
157 }
158
159 pub fn span(&self) -> Span {
161 Span {
162 start: self.start,
163 end: self.end,
164 }
165 }
166
167 pub(crate) fn range(&self) -> core::ops::Range<usize> {
168 self.start as usize..self.end as usize
169 }
170}
171
172#[derive(Clone, Copy, Debug)]
174pub struct CstRef<'a, 'src> {
175 pub(crate) src: &'src str,
176 pub(crate) nodes: &'a [Node],
177 pub(crate) diagnostics: &'a [Diagnostic],
178}
179
180impl<'a, 'src> CstRef<'a, 'src> {
181 pub fn source(&self) -> &'src str {
183 self.src
184 }
185
186 pub fn root(&self) -> Option<SyntaxNode<'a, 'src>> {
189 (!self.nodes.is_empty()).then_some(SyntaxNode {
190 src: self.src,
191 nodes: self.nodes,
192 index: 0,
193 })
194 }
195
196 pub fn nodes(&self) -> &'a [Node] {
198 self.nodes
199 }
200
201 pub fn diagnostics(&self) -> &'a [Diagnostic] {
203 self.diagnostics
204 }
205
206 pub fn has_errors(&self) -> bool {
208 !self.diagnostics.is_empty()
209 }
210
211 pub fn tokens(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
213 let (src, nodes) = (self.src, self.nodes);
214 nodes
215 .iter()
216 .enumerate()
217 .filter(|(_, n)| n.kind.is_token())
218 .map(move |(i, _)| SyntaxNode {
219 src,
220 nodes,
221 index: u32::try_from(i).unwrap_or(u32::MAX),
224 })
225 }
226
227 pub fn to_model(&self) -> Parsed<'src> {
230 if self.has_errors() || self.nodes.is_empty() {
231 return Parsed {
232 message: None,
233 diagnostics: Diagnostics::from(self.diagnostics.to_vec()),
234 };
235 }
236 crate::model_from_arena(self.src, self.nodes)
237 }
238}
239
240impl fmt::Display for CstRef<'_, '_> {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 for t in self.tokens() {
244 f.write_str(t.text())?;
245 }
246 Ok(())
247 }
248}
249
250#[derive(Clone, Debug)]
252pub struct Cst<'src> {
253 pub(crate) src: &'src str,
254 pub(crate) nodes: Vec<Node>,
255 pub(crate) diagnostics: Vec<Diagnostic>,
256}
257
258impl<'src> Cst<'src> {
259 pub fn view(&self) -> CstRef<'_, 'src> {
261 CstRef {
262 src: self.src,
263 nodes: &self.nodes,
264 diagnostics: &self.diagnostics,
265 }
266 }
267
268 pub fn source(&self) -> &'src str {
270 self.src
271 }
272
273 pub fn root(&self) -> Option<SyntaxNode<'_, 'src>> {
275 self.view().root()
276 }
277
278 pub fn diagnostics(&self) -> &[Diagnostic] {
280 &self.diagnostics
281 }
282
283 pub fn has_errors(&self) -> bool {
285 !self.diagnostics.is_empty()
286 }
287
288 pub fn to_model(&self) -> Parsed<'src> {
290 self.view().to_model()
291 }
292}
293
294impl fmt::Display for Cst<'_> {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 fmt::Display::fmt(&self.view(), f)
297 }
298}
299
300#[derive(Clone, Copy, Debug)]
302pub struct SyntaxNode<'a, 'src> {
303 src: &'src str,
304 nodes: &'a [Node],
305 index: u32,
306}
307
308impl<'a, 'src> SyntaxNode<'a, 'src> {
309 fn node(&self) -> Node {
310 self.nodes[self.index as usize]
311 }
312
313 pub fn index(&self) -> usize {
315 self.index as usize
316 }
317
318 pub fn kind(&self) -> SyntaxKind {
320 self.node().kind
321 }
322
323 pub fn span(&self) -> Span {
325 self.node().span()
326 }
327
328 pub fn text(&self) -> &'src str {
330 self.src.get(self.node().range()).unwrap_or("")
331 }
332
333 pub fn is_token(&self) -> bool {
335 self.kind().is_token()
336 }
337
338 pub fn children(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
340 let (src, nodes) = (self.src, self.nodes);
341 let end = self.node().last;
342 let mut next = self.index + 1;
343 core::iter::from_fn(move || {
344 if next >= end {
345 return None;
346 }
347 let index = next;
348 next = nodes.get(index as usize).map_or(end, |n| n.last);
349 Some(SyntaxNode { src, nodes, index })
350 })
351 }
352
353 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode<'a, 'src>> + use<'a, 'src> {
355 let (src, nodes) = (self.src, self.nodes);
356 (self.index + 1..self.node().last).map(move |index| SyntaxNode { src, nodes, index })
357 }
358}