ridl_syntax/syntax_kind.rs
1//! Token and node kinds shared by the lexer ([`crate::lexer`]) and the grammar.
2
3/// The kinds of syntax tokens and nodes the family grammar produces.
4///
5/// The token variants are the full family token set the lexer recognises
6/// (typl reference §1.4 and §2). The node variants
7/// are the typl grammar's node inventory — one variant per rule
8/// in `family.ungram`, plus [`ErrorNode`](SyntaxKind::ErrorNode) for recovery.
9/// [`RidlLanguage`] maps between this enum and rowan's raw kind through the
10/// `#[repr(u16)]` discriminants, so the node variants stay grouped at the end
11/// with [`ErrorNode`](SyntaxKind::ErrorNode) last — that is the range the
12/// `kind_from_raw` assertion below guards.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[repr(u16)]
15pub enum SyntaxKind {
16 // Tokens — the full family lexer (typl reference §1.4, §2).
17 //
18 // Keywords the typl profile uses (typl reference §1.4). Each used keyword
19 // maps to a distinct variant; every family-registry word the typl profile
20 // does not use maps to `ReservedWord` instead.
21 PackageKw,
22 ImportKw,
23 AsKw,
24 InternalKw,
25 TypeKw,
26 ConstKw,
27 StructKw,
28 EnumKw,
29 EnumsetKw,
30 UnionKw,
31 BooleanKw,
32 IntegerKw,
33 FloatKw,
34 StringKw,
35 BytesKw,
36 TrueKw,
37 FalseKw,
38 StepKw,
39 MatchKw,
40 ReservedKw,
41 ErrorKw,
42 // Contextual: lexes as `Ident`; the parser remaps it when `enum` or
43 // `enumset` follows (typl reference §1.4).
44 OpenKw,
45 // Keywords the ridl profile activates beyond typl's set (ridl reference
46 // §2.3): the interaction and container words plus the expr-core pair.
47 // Under `Profile::Typl` these words still lex to `ReservedWord`.
48 InterfaceKw,
49 ServiceKw,
50 SignalKw,
51 EventKw,
52 CommandKw,
53 QueryKw,
54 FixedKw,
55 RequireKw,
56 EnsureKw,
57 // Keywords the rsdl profile activates beyond typl's set (rsdl reference
58 // §2). Under `Profile::Typl` and `Profile::Ridl` these words still lex to
59 // `ReservedWord`.
60 SystemKw,
61 ComponentKw,
62 DistributionKw,
63 DeploymentKw,
64 MachineKw,
65 OffersKw,
66 RequiresKw,
67 ForKw,
68 /// A family-registry word that the active profile does not use (typl
69 /// reference §1.4). Reserved in every profile, never a valid identifier.
70 ReservedWord,
71 // Names and literals.
72 Ident,
73 IntNumber,
74 FloatNumber,
75 String,
76 Regex,
77 Duration,
78 // Punctuation.
79 Colon,
80 Eq,
81 LBracket,
82 RBracket,
83 LBrace,
84 RBrace,
85 LParen,
86 RParen,
87 DotDot,
88 Dot,
89 Slash,
90 Comma,
91 Question,
92 Semicolon,
93 At,
94 Pipe,
95 Percent,
96 Minus,
97 // Expression operators (ridl reference §13, general form expr core).
98 // Family tokens like `Duration`: the lexer recognises them under every
99 // profile; the typl grammar simply never accepts them.
100 Lt,
101 Le,
102 Gt,
103 Ge,
104 EqEq,
105 Neq,
106 AmpAmp,
107 PipePipe,
108 Bang,
109 Plus,
110 Star,
111 // Trivia and the catch-all for unrecognised input.
112 Whitespace,
113 LineComment,
114 BlockComment,
115 DocComment,
116 Error,
117 // Nodes — the typl grammar's node inventory (`family.ungram`).
118 // The full parser produces them; until it lands, the
119 // generated typed AST casts over trees built directly in tests.
120 SourceFile,
121 PackageDecl,
122 Import,
123 TypeDef,
124 ConstDef,
125 StructDef,
126 FieldDef,
127 ReservedEntry,
128 EnumDef,
129 EnumValue,
130 EnumSetDef,
131 EnumSetBit,
132 UnionDef,
133 UnionArm,
134 TupleType,
135 TupleField,
136 ArrayType,
137 MapType,
138 OptionalType,
139 PathType,
140 PrimitiveType,
141 UnitExpr,
142 Constraint,
143 Bound,
144 Name,
145 QualifiedName,
146 Literal,
147 InitValue,
148 // Nodes of the ridl interaction grammar (`family.ungram`,
149 // ridl reference Appendix C, ADR-0008 decisions 1 and 2).
150 InterfaceDef,
151 SignalDef,
152 EventDef,
153 CommandDef,
154 QueryDef,
155 FixedDef,
156 Param,
157 ParamList,
158 ReturnType,
159 StreamType,
160 FallibleType,
161 Timing,
162 TimingRange,
163 AttrBlock,
164 // Nodes of the attribute and guaranteed-subset expression grammar
165 // (`family.ungram`, general form §4.2, expr-core
166 // specification §3.1).
167 Attribute,
168 AttrValue,
169 BinaryExpr,
170 PrefixExpr,
171 MemberExpr,
172 PathExpr,
173 ParenExpr,
174 LiteralExpr,
175 // Nodes of the ridl service grammar (`family.ungram`, ridl reference §14.5). `service_def` is not in
176 // Appendix C.
177 ServiceDef,
178 DottedName,
179 // Nodes of the rsdl grammar (`family.ungram` — rsdl reference §3, §4,
180 // Appendix B).
181 SystemDef,
182 ComponentDef,
183 ComponentLine,
184 DistributionDef,
185 DeploymentDef,
186 MachineDef,
187 MemberLine,
188 Reference,
189 /// A recovery node: error recovery wraps the tokens it skips in one of
190 /// these, so broken input still produces a lossless tree. It is the one
191 /// node kind with no rule in `family.ungram`, and the last variant — the
192 /// `kind_from_raw` assertion below guards the range up to it.
193 ErrorNode,
194}
195
196impl SyntaxKind {
197 /// Whitespace and comments — tokens that carry no grammatical meaning but
198 /// must stay in the tree for losslessness. Doc comments are trivia too: the
199 /// grammar reads them from the trivia preceding a definition.
200 pub fn is_trivia(self) -> bool {
201 matches!(
202 self,
203 SyntaxKind::Whitespace
204 | SyntaxKind::LineComment
205 | SyntaxKind::BlockComment
206 | SyntaxKind::DocComment
207 )
208 }
209}
210
211impl From<SyntaxKind> for rowan::SyntaxKind {
212 fn from(kind: SyntaxKind) -> Self {
213 Self(kind as u16)
214 }
215}
216
217/// The rowan [`Language`](rowan::Language) instance for the RIDL family. It
218/// binds rowan's raw `u16` kinds to [`SyntaxKind`] through the enum's
219/// `#[repr(u16)]` discriminants.
220#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
221pub enum RidlLanguage {}
222
223impl rowan::Language for RidlLanguage {
224 type Kind = SyntaxKind;
225
226 fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
227 assert!(
228 raw.0 <= SyntaxKind::ErrorNode as u16,
229 "raw kind {} is out of range for SyntaxKind",
230 raw.0,
231 );
232 // SAFETY: SyntaxKind is `#[repr(u16)]` with contiguous discriminants
233 // from 0 up to and including `ErrorNode`. The assertion above proves
234 // `raw.0` names one of them, so the transmute produces a valid variant.
235 unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
236 }
237
238 fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
239 kind.into()
240 }
241}
242
243/// A node in the red (cursor) tree over [`RidlLanguage`].
244pub type SyntaxNode = rowan::SyntaxNode<RidlLanguage>;
245/// A token in the red (cursor) tree over [`RidlLanguage`].
246pub type SyntaxToken = rowan::SyntaxToken<RidlLanguage>;