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]
243 pub fn is_token(self) -> bool {
244 self < Self::FIRST_NODE
245 }
246
247 #[must_use]
249 pub fn is_node(self) -> bool {
250 !self.is_token()
251 }
252
253 #[must_use]
258 pub fn is_trivia(self) -> bool {
259 matches!(
260 self,
261 Self::Whitespace
262 | Self::Comment
263 | Self::DocComment
264 | Self::Newline
265 | Self::LineContinuation
266 )
267 }
268
269 #[must_use]
271 pub fn is_comment(self) -> bool {
272 matches!(self, Self::Comment | Self::DocComment)
273 }
274
275 #[must_use]
277 pub fn is_literal(self) -> bool {
278 matches!(
279 self,
280 Self::Int
281 | Self::Float
282 | Self::Str
283 | Self::StringName
284 | Self::NodePath
285 | Self::TrueKw
286 | Self::FalseKw
287 | Self::NullKw
288 )
289 }
290
291 #[must_use]
293 pub fn from_keyword(text: &str) -> Option<Self> {
294 Some(match text {
295 "and" => Self::AndKw,
296 "as" => Self::AsKw,
297 "assert" => Self::AssertKw,
298 "await" => Self::AwaitKw,
299 "break" => Self::BreakKw,
300 "breakpoint" => Self::BreakpointKw,
301 "class" => Self::ClassKw,
302 "class_name" => Self::ClassNameKw,
303 "const" => Self::ConstKw,
304 "continue" => Self::ContinueKw,
305 "elif" => Self::ElifKw,
306 "else" => Self::ElseKw,
307 "enum" => Self::EnumKw,
308 "extends" => Self::ExtendsKw,
309 "false" => Self::FalseKw,
310 "for" => Self::ForKw,
311 "func" => Self::FuncKw,
312 "if" => Self::IfKw,
313 "in" => Self::InKw,
314 "is" => Self::IsKw,
315 "match" => Self::MatchKw,
316 "namespace" => Self::NamespaceKw,
317 "not" => Self::NotKw,
318 "null" => Self::NullKw,
319 "or" => Self::OrKw,
320 "pass" => Self::PassKw,
321 "preload" => Self::PreloadKw,
322 "return" => Self::ReturnKw,
323 "self" => Self::SelfKw,
324 "signal" => Self::SignalKw,
325 "static" => Self::StaticKw,
326 "super" => Self::SuperKw,
327 "trait" => Self::TraitKw,
328 "true" => Self::TrueKw,
329 "var" => Self::VarKw,
330 "void" => Self::VoidKw,
331 "when" => Self::WhenKw,
332 "while" => Self::WhileKw,
333 "yield" => Self::YieldKw,
334 _ => return None,
335 })
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn token_and_node_partition() {
345 assert!(SyntaxKind::Whitespace.is_token());
346 assert!(SyntaxKind::RBrace.is_token());
347 assert!(SyntaxKind::SourceFile.is_node());
348 assert!(SyntaxKind::Error.is_node());
349 assert!(!SyntaxKind::SourceFile.is_token());
350 }
351
352 #[test]
353 fn indent_is_structural_not_trivia() {
354 assert!(SyntaxKind::Whitespace.is_trivia());
355 assert!(SyntaxKind::Comment.is_trivia());
356 assert!(!SyntaxKind::Indent.is_trivia());
357 assert!(!SyntaxKind::Dedent.is_trivia());
358 }
359
360 #[test]
361 fn keywords_round_trip() {
362 assert_eq!(SyntaxKind::from_keyword("func"), Some(SyntaxKind::FuncKw));
363 assert_eq!(
364 SyntaxKind::from_keyword("class_name"),
365 Some(SyntaxKind::ClassNameKw)
366 );
367 assert_eq!(SyntaxKind::from_keyword("classname"), None);
368 assert_eq!(SyntaxKind::from_keyword("Func"), None);
369 assert_eq!(SyntaxKind::from_keyword("position"), None);
370 }
371}