1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[repr(u16)]
10#[allow(clippy::upper_case_acronyms)]
11pub enum SyntaxKind {
12 Whitespace,
18 Comment,
20 DocComment,
22 Newline,
24 LineContinuation,
26
27 Indent,
30 Dedent,
31 Eof,
32 Unknown,
34
35 Int,
37 Float,
38 Str,
40 StringName,
42 NodePath,
44 GetNode,
46 UniqueNode,
48 Ident,
49
50 AndKw,
55 AsKw,
56 AssertKw,
57 AwaitKw,
58 BreakKw,
59 BreakpointKw,
60 ClassKw,
61 ClassNameKw,
62 ConstKw,
63 ContinueKw,
64 ElifKw,
65 ElseKw,
66 EnumKw,
67 ExtendsKw,
68 FalseKw,
69 ForKw,
70 FuncKw,
71 IfKw,
72 InKw,
73 IsKw,
74 MatchKw,
75 NamespaceKw,
76 NotKw,
77 NullKw,
78 OrKw,
79 PassKw,
80 PreloadKw,
81 ReturnKw,
82 SelfKw,
83 SignalKw,
84 StaticKw,
85 SuperKw,
86 TraitKw,
87 TrueKw,
88 VarKw,
89 VoidKw,
90 WhenKw,
91 WhileKw,
92 YieldKw,
93
94 Plus,
96 Minus,
97 Star,
98 StarStar,
99 Slash,
100 Percent,
101 Eq,
102 PlusEq,
103 MinusEq,
104 StarEq,
105 StarStarEq,
106 SlashEq,
107 PercentEq,
108 AmpEq,
109 PipeEq,
110 CaretEq,
111 ShlEq,
112 ShrEq,
113 EqEq,
114 Bang,
115 BangEq,
116 Lt,
117 LtEq,
118 Gt,
119 GtEq,
120 Amp,
121 AmpAmp,
122 Pipe,
123 PipePipe,
124 Caret,
125 Tilde,
126 Shl,
127 Shr,
128 Arrow,
129 ColonEq,
130 Colon,
131 Semicolon,
132 Comma,
133 Dot,
134 DotDot,
135 Ellipsis,
137 At,
138 Dollar,
139 LParen,
140 RParen,
141 LBracket,
142 RBracket,
143 LBrace,
144 RBrace,
145
146 SourceFile,
149
150 Annotation,
152 ClassNameDecl,
153 ExtendsDecl,
154 SignalDecl,
155 EnumDecl,
156 EnumBody,
157 EnumVariant,
158 ConstDecl,
159 VarDecl,
160 FuncDecl,
161 ClassDecl,
162
163 ParamList,
165 Param,
166 ArgList,
167 TypeHint,
168 ReturnType,
169 Initializer,
170 Accessors,
172 Setter,
173 Getter,
174 Block,
175
176 ExprStmt,
178 AssignStmt,
179 IfStmt,
180 ElifClause,
181 ElseClause,
182 WhileStmt,
183 ForStmt,
184 MatchStmt,
185 MatchArm,
186 MatchGuard,
187 ReturnStmt,
188 PassStmt,
189 BreakStmt,
190 ContinueStmt,
191 BreakpointStmt,
192 AssertStmt,
193
194 BinaryExpr,
196 UnaryExpr,
197 TernaryExpr,
198 CastExpr,
199 AwaitExpr,
200 CallExpr,
201 SubscriptExpr,
202 AttributeExpr,
204 ParenExpr,
205 ArrayExpr,
206 DictExpr,
207 DictEntry,
208 LambdaExpr,
209 PreloadExpr,
210 NameRef,
212 Literal,
213
214 Error,
217}
218
219impl SyntaxKind {
220 pub const FIRST_NODE: SyntaxKind = SyntaxKind::SourceFile;
222
223 const FIRST_KEYWORD: SyntaxKind = SyntaxKind::AndKw;
224 const LAST_KEYWORD: SyntaxKind = SyntaxKind::YieldKw;
225
226 #[must_use]
228 pub fn is_keyword(self) -> bool {
229 self >= Self::FIRST_KEYWORD && self <= Self::LAST_KEYWORD
230 }
231
232 #[must_use]
237 pub fn is_ident_like(self) -> bool {
238 self == Self::Ident || self.is_keyword()
239 }
240
241 #[must_use]
256 pub fn is_name(self) -> bool {
257 matches!(self, Self::Ident | Self::MatchKw | Self::WhenKw)
258 }
259
260 #[must_use]
262 pub fn is_token(self) -> bool {
263 self < Self::FIRST_NODE
264 }
265
266 #[must_use]
268 pub fn is_node(self) -> bool {
269 !self.is_token()
270 }
271
272 #[must_use]
277 pub fn is_trivia(self) -> bool {
278 matches!(
279 self,
280 Self::Whitespace
281 | Self::Comment
282 | Self::DocComment
283 | Self::Newline
284 | Self::LineContinuation
285 )
286 }
287
288 #[must_use]
290 pub fn is_comment(self) -> bool {
291 matches!(self, Self::Comment | Self::DocComment)
292 }
293
294 #[must_use]
296 pub fn is_literal(self) -> bool {
297 matches!(
298 self,
299 Self::Int
300 | Self::Float
301 | Self::Str
302 | Self::StringName
303 | Self::NodePath
304 | Self::TrueKw
305 | Self::FalseKw
306 | Self::NullKw
307 )
308 }
309
310 #[must_use]
312 pub fn from_keyword(text: &str) -> Option<Self> {
313 Some(match text {
314 "and" => Self::AndKw,
315 "as" => Self::AsKw,
316 "assert" => Self::AssertKw,
317 "await" => Self::AwaitKw,
318 "break" => Self::BreakKw,
319 "breakpoint" => Self::BreakpointKw,
320 "class" => Self::ClassKw,
321 "class_name" => Self::ClassNameKw,
322 "const" => Self::ConstKw,
323 "continue" => Self::ContinueKw,
324 "elif" => Self::ElifKw,
325 "else" => Self::ElseKw,
326 "enum" => Self::EnumKw,
327 "extends" => Self::ExtendsKw,
328 "false" => Self::FalseKw,
329 "for" => Self::ForKw,
330 "func" => Self::FuncKw,
331 "if" => Self::IfKw,
332 "in" => Self::InKw,
333 "is" => Self::IsKw,
334 "match" => Self::MatchKw,
335 "namespace" => Self::NamespaceKw,
336 "not" => Self::NotKw,
337 "null" => Self::NullKw,
338 "or" => Self::OrKw,
339 "pass" => Self::PassKw,
340 "preload" => Self::PreloadKw,
341 "return" => Self::ReturnKw,
342 "self" => Self::SelfKw,
343 "signal" => Self::SignalKw,
344 "static" => Self::StaticKw,
345 "super" => Self::SuperKw,
346 "trait" => Self::TraitKw,
347 "true" => Self::TrueKw,
348 "var" => Self::VarKw,
349 "void" => Self::VoidKw,
350 "when" => Self::WhenKw,
351 "while" => Self::WhileKw,
352 "yield" => Self::YieldKw,
353 _ => return None,
354 })
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361
362 #[test]
363 fn token_and_node_partition() {
364 assert!(SyntaxKind::Whitespace.is_token());
365 assert!(SyntaxKind::RBrace.is_token());
366 assert!(SyntaxKind::SourceFile.is_node());
367 assert!(SyntaxKind::Error.is_node());
368 assert!(!SyntaxKind::SourceFile.is_token());
369 }
370
371 #[test]
372 fn indent_is_structural_not_trivia() {
373 assert!(SyntaxKind::Whitespace.is_trivia());
374 assert!(SyntaxKind::Comment.is_trivia());
375 assert!(!SyntaxKind::Indent.is_trivia());
376 assert!(!SyntaxKind::Dedent.is_trivia());
377 }
378
379 #[test]
380 fn keywords_round_trip() {
381 assert_eq!(SyntaxKind::from_keyword("func"), Some(SyntaxKind::FuncKw));
382 assert_eq!(
383 SyntaxKind::from_keyword("class_name"),
384 Some(SyntaxKind::ClassNameKw)
385 );
386 assert_eq!(SyntaxKind::from_keyword("classname"), None);
387 assert_eq!(SyntaxKind::from_keyword("Func"), None);
388 assert_eq!(SyntaxKind::from_keyword("position"), None);
389 }
390}