noyalib/cst/syntax.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2026 Noyalib. All rights reserved.
3
4//! Syntax-kind tags for green-tree nodes and tokens.
5//!
6//! Mirrors the design doc's enumeration. Token (leaf) kinds are
7//! ordered before composite (non-leaf) kinds in the variant list to
8//! make the leaf-vs-composite distinction visible at a glance.
9
10/// Kind of a green-tree node or token.
11///
12/// Token kinds describe leaves whose `text` slice is the source
13/// substring they came from. Composite kinds describe parent nodes
14/// whose `text` is the concatenation of their descendants.
15///
16/// # Examples
17///
18/// ```
19/// use noyalib::cst::SyntaxKind;
20/// assert!(SyntaxKind::PlainScalar.is_token());
21/// assert!(!SyntaxKind::Document.is_token());
22/// ```
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24#[non_exhaustive]
25pub enum SyntaxKind {
26 // ── trivia (leaves) ─────────────────────────────────────────
27 /// Run of inline blanks (spaces and tabs) between tokens.
28 Whitespace,
29 /// A single line break (`\n` or `\r\n`).
30 Newline,
31 /// A `# …` comment up to the next line break.
32 Comment,
33 /// A UTF-8 byte-order mark consumed at stream start.
34 Bom,
35 /// A `%YAML` / `%TAG` / reserved directive line, *including* the
36 /// leading `%` and excluding the terminating line break.
37 Directive,
38
39 // ── structural punctuation (leaves) ─────────────────────────
40 /// `-` block-sequence indicator.
41 DashIndicator,
42 /// `?` explicit-key indicator.
43 QuestionIndicator,
44 /// `:` value indicator.
45 ColonIndicator,
46 /// `,` flow-entry indicator.
47 Comma,
48 /// `[` flow-sequence open.
49 OpenBracket,
50 /// `]` flow-sequence close.
51 CloseBracket,
52 /// `{` flow-mapping open.
53 OpenBrace,
54 /// `}` flow-mapping close.
55 CloseBrace,
56 /// `&name` anchor mark — leaf includes the `&`.
57 AnchorMark,
58 /// `*name` alias mark — leaf includes the `*`.
59 AliasMark,
60 /// `!tag` tag mark — leaf includes the `!` and any handle / suffix.
61 TagMark,
62 /// `---` document-start indicator.
63 DocStart,
64 /// `...` document-end indicator.
65 DocEnd,
66
67 // ── scalar leaves ───────────────────────────────────────────
68 /// A plain (unquoted) scalar.
69 PlainScalar,
70 /// A `'…'` single-quoted scalar.
71 SingleQuotedScalar,
72 /// A `"…"` double-quoted scalar.
73 DoubleQuotedScalar,
74 /// A `|…` literal block scalar (header + content).
75 LiteralScalar,
76 /// A `>…` folded block scalar (header + content).
77 FoldedScalar,
78
79 // ── composite (non-leaf) kinds ──────────────────────────────
80 /// The whole stream — root of the green tree returned by
81 /// [`crate::cst::parse_document`] and [`crate::cst::parse_stream`].
82 Stream,
83 /// A single YAML document inside the stream.
84 Document,
85 /// A block-style mapping. Children are [`Self::MappingEntry`]
86 /// nodes (or trivia) in source order.
87 BlockMapping,
88 /// A block-style sequence. Children are [`Self::SequenceItem`]
89 /// nodes (or trivia) in source order.
90 BlockSequence,
91 /// A `{ … }` flow mapping. Children are the brace tokens, the
92 /// entries' tokens, and inter-token trivia. Flow content is
93 /// kept flat — flow entries are not subdivided into
94 /// [`Self::MappingEntry`] composites.
95 FlowMapping,
96 /// A `[ … ]` flow sequence. Flow content is kept flat — see
97 /// [`Self::FlowMapping`].
98 FlowSequence,
99 /// A single key/value entry of a [`Self::BlockMapping`]. Holds
100 /// the (optional) `?` indicator, the key tokens, the `:`
101 /// indicator, the value tokens (which may themselves be a nested
102 /// block / flow collection), and any inline trailing trivia.
103 MappingEntry,
104 /// A single item of a [`Self::BlockSequence`], including the `-`
105 /// indicator and the value tokens (or a nested collection).
106 SequenceItem,
107}
108
109impl SyntaxKind {
110 /// `true` for leaves whose `text` is a verbatim source slice;
111 /// `false` for composite parent nodes.
112 ///
113 /// # Examples
114 ///
115 /// ```
116 /// use noyalib::cst::SyntaxKind;
117 /// assert!(SyntaxKind::Whitespace.is_token());
118 /// assert!(!SyntaxKind::Stream.is_token());
119 /// assert!(!SyntaxKind::BlockMapping.is_token());
120 /// ```
121 #[must_use]
122 pub const fn is_token(self) -> bool {
123 !matches!(
124 self,
125 Self::Stream
126 | Self::Document
127 | Self::BlockMapping
128 | Self::BlockSequence
129 | Self::FlowMapping
130 | Self::FlowSequence
131 | Self::MappingEntry
132 | Self::SequenceItem
133 )
134 }
135}