1#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
9#[repr(u16)]
10pub enum SyntaxKind {
11 WHITESPACE = 0,
13 NEWLINE,
14 COMMENT, BLOCK_COMMENT, IDENT, QUOTED_IDENT, STRING, DOLLAR_STRING, FILE_URI, INT_NUMBER,
24 FLOAT_NUMBER,
25 VARIABLE, PLACEHOLDER, L_PAREN, R_PAREN, L_BRACKET, R_BRACKET, L_BRACE, R_BRACE, COMMA, DOT, SEMICOLON, COLON, COLON2, ASSIGN, EQ, NEQ, LT, LTE, NULL_SAFE_EQ, GT, GTE, PLUS, MINUS, STAR, SLASH, PERCENT, CONCAT, PIPE, PIPE_GT, FLOW_PIPE, ARROW, FAT_ARROW, AMP, CARET, TILDE, AT, DOLLAR, QUESTION, BANG, #[doc(hidden)]
74 __KW_START,
75 SELECT_KW,
76 FROM_KW,
77 WHERE_KW,
78 GROUP_KW,
79 BY_KW,
80 HAVING_KW,
81 ORDER_KW,
82 LIMIT_KW,
83 OFFSET_KW,
84 FETCH_KW,
85 TOP_KW,
86 AS_KW,
87 AND_KW,
88 OR_KW,
89 NOT_KW,
90 NULL_KW,
91 IS_KW,
92 IN_KW,
93 LIKE_KW,
94 ILIKE_KW,
95 RLIKE_KW,
96 REGEXP_KW,
97 BETWEEN_KW,
98 CASE_KW,
99 WHEN_KW,
100 THEN_KW,
101 ELSE_KW,
102 END_KW,
103 JOIN_KW,
104 INNER_KW,
105 LEFT_KW,
106 RIGHT_KW,
107 FULL_KW,
108 OUTER_KW,
109 CROSS_KW,
110 LATERAL_KW,
111 NATURAL_KW,
112 ON_KW,
113 USING_KW,
114 WITH_KW,
115 RECURSIVE_KW,
116 UNION_KW,
117 ALL_KW,
118 ANY_KW,
119 EXCEPT_KW,
120 INTERSECT_KW,
121 MINUS_KW,
122 DISTINCT_KW,
123 QUALIFY_KW,
124 OVER_KW,
125 PARTITION_KW,
126 WINDOW_KW,
127 ROWS_KW,
128 RANGE_KW,
129 UNBOUNDED_KW,
130 PRECEDING_KW,
131 FOLLOWING_KW,
132 CURRENT_KW,
133 ROW_KW,
134 ASC_KW,
135 DESC_KW,
136 NULLS_KW,
137 FIRST_KW,
138 LAST_KW,
139 TRUE_KW,
140 FALSE_KW,
141 CAST_KW,
142 TRY_CAST_KW,
143 EXISTS_KW,
144 VALUES_KW,
145 PIVOT_KW,
146 UNPIVOT_KW,
147 SAMPLE_KW,
148 TABLESAMPLE_KW,
149 CREATE_KW,
150 REPLACE_KW,
151 IF_KW,
152 TABLE_KW,
153 VIEW_KW,
154 TEMPORARY_KW,
155 TEMP_KW,
156 TRANSIENT_KW,
157 VOLATILE_KW,
158 SECURE_KW,
159 INSERT_KW,
160 INTO_KW,
161 UPDATE_KW,
162 DELETE_KW,
163 MERGE_KW,
164 SET_KW,
165 FLATTEN_KW,
166 CONNECT_KW,
167 START_KW,
168 PRIOR_KW,
169 LANGUAGE_KW,
170 JAVASCRIPT_KW,
171 PYTHON_KW,
172 JAVA_KW,
173 SCALA_KW,
174 SQL_KW,
175 BEGIN_KW,
176 DECLARE_KW,
177 LET_KW,
178 RETURN_KW,
179 CALL_KW,
180 PROCEDURE_KW,
181 FUNCTION_KW,
182 RETURNS_KW,
183 TASK_KW,
184 WAREHOUSE_KW,
185 SCHEDULE_KW,
186 AFTER_KW,
187 COPY_KW,
188 GRANTS_KW,
189 HANDLER_KW,
190 PACKAGES_KW,
191 IMPORTS_KW,
192 RUNTIME_VERSION_KW,
193 EXECUTE_KW,
194 OWNER_KW,
195 CALLER_KW,
196 STRICT_KW,
197 CALLED_KW,
198 INPUT_KW,
199 OUTPUT_KW,
200 OUT_KW,
201 MATCHED_KW,
202 DROP_KW,
203 ALTER_KW,
204 WITHIN_KW,
205 FOR_KW,
206 IMMEDIATE_KW,
207 OVERWRITE_KW,
208 GRANT_KW,
209 REVOKE_KW,
210 USE_KW,
211 SHOW_KW,
212 DESCRIBE_KW,
213 TRUNCATE_KW,
214 COMMIT_KW,
215 ROLLBACK_KW,
216 UNDROP_KW,
217 ELSEIF_KW,
218 WHILE_KW,
219 LOOP_KW,
220 REPEAT_KW,
221 UNTIL_KW,
222 DO_KW,
223 EXCEPTION_KW,
224 CURSOR_KW,
225 RESULTSET_KW,
226 #[doc(hidden)]
227 __KW_END,
228
229 SOURCE_FILE,
231 ERROR,
232 EOF,
233 CONTEXTUAL_KEYWORD,
239 SELECT_STMT,
241 EXPR_STMT,
242 SELECT_LIST,
244 SELECT_ITEM,
245 FROM_CLAUSE,
246 WHERE_CLAUSE,
247 TABLE_REF,
248 LATERAL_VIEW,
249 TIME_TRAVEL,
250 SAMPLE_CLAUSE,
251 AS_OF_TRAVEL,
252 ARG_LIST,
253 TYPE_NAME,
254 NAME,
255 NAME_REF,
256 LITERAL,
258 STAR_EXPR,
259 PAREN_EXPR,
260 PREFIX_EXPR,
261 BIN_EXPR,
262 CALL_EXPR,
263 INDEX_EXPR,
264 CAST_EXPR,
265 BIND_MARKER,
266 INTERVAL_LITERAL,
267 ARRAY_LITERAL,
268 OBJECT_LITERAL,
269 OBJECT_FIELD,
270 WITH_QUERY,
272 WITH_CLAUSE,
273 CTE,
274 COLUMN_LIST,
275 SET_OP,
276 SUBQUERY,
277 GROUP_BY_CLAUSE,
279 HAVING_CLAUSE,
280 QUALIFY_CLAUSE,
281 ORDER_BY_CLAUSE,
282 DISTRIBUTE_BY_CLAUSE,
283 SORT_BY_CLAUSE,
284 CLUSTER_BY_CLAUSE,
285 ORDER_BY_ITEM,
286 LIMIT_CLAUSE,
287 OFFSET_CLAUSE,
288 JOIN,
289 IS_EXPR,
291 IN_EXPR,
292 BETWEEN_EXPR,
293 EXISTS_EXPR,
294 EXPR_LIST,
295 WINDOW_EXPR,
297 WINDOW_SPEC,
298 PARTITION_BY_CLAUSE,
299 WINDOW_FRAME,
300 CASE_EXPR,
302 CASE_WHEN,
303 JSON_ACCESS,
304 LAMBDA_EXPR,
305 LAMBDA_PARAMS,
306 VALUES_CLAUSE,
307 VALUES_ROW,
308 INSERT_STMT,
310 UPDATE_STMT,
311 DELETE_STMT,
312 MERGE_STMT,
313 SET_CLAUSE,
314 ASSIGNMENT,
315 MERGE_WHEN,
316 CREATE_STMT,
318 DROP_STMT,
319 ALTER_STMT,
320 GRANT_STMT,
321 REVOKE_STMT,
322 CALL_STMT,
323 USE_STMT,
324 SHOW_STMT,
325 DESCRIBE_STMT,
326 TRUNCATE_STMT,
327 COMMENT_STMT,
328 TRANSACTION_STMT,
329 UNDROP_STMT,
330 BLOCK_STMT,
332 DECLARE_SECTION,
333 DECLARE_ITEM,
334 STMT_LIST,
335 EXCEPTION_SECTION,
336 EXCEPTION_WHEN,
337 LET_STMT,
338 ASSIGN_STMT,
339 RETURN_STMT,
340 IF_STMT,
341 LOOP_STMT,
342 CASE_STMT,
344 CASE_STMT_WHEN,
346 SCRIPT_STMT,
347 COLUMN_DEF_LIST,
348 COLUMN_DEF,
349 ROUTINE_RETURNS_CLAUSE,
351 ROUTINE_LANGUAGE_CLAUSE,
353 WITHIN_GROUP,
355 PIVOT_CLAUSE,
356 NAMED_ARG,
357 MATCH_RECOGNIZE,
358 MEASURES_CLAUSE,
360 ROW_MATCH_CLAUSE,
361 AFTER_MATCH_CLAUSE,
362 PATTERN_CLAUSE,
363 PATTERN_BODY,
364 SUBSET_CLAUSE,
365 DEFINE_CLAUSE,
366 DEFINE_ITEM,
367 START_WITH_CLAUSE,
369 CONNECT_BY_CLAUSE,
370 FLOW_STMT,
372 SET_STMT,
374 EXECUTE_STMT,
375 GROUPING_SETS,
376 COPY_STMT,
378 STAGE_FILE_STMT,
380 COPY_LOCATION,
381 COPY_OPTION,
382 STAGE_REF,
384 INTO_CLAUSE,
386 INSERT_WHEN,
387 OBJECT_PROPERTY, STREAM_SOURCE, TASK_AFTER, SEMANTIC_VIEW_CLAUSE, SEMANTIC_VIEW_ITEM, PRIV_LIST, GRANT_TARGET, GRANTEE, ALTER_ACTION,
402
403 VACUUM_STMT, OPTIMIZE_STMT, ZORDER_CLAUSE, CACHE_STMT, UNCACHE_STMT, REFRESH_STMT, DESCRIBE_HISTORY_STMT, RESTORE_STMT, ANALYZE_STMT, MSCK_REPAIR_STMT, #[doc(hidden)]
417 __LAST,
418}
419
420impl SyntaxKind {
421 #[inline]
423 pub const fn to_u16(self) -> u16 {
424 self as u16
425 }
426
427 #[inline]
433 pub fn from_u16(raw: u16) -> SyntaxKind {
434 assert!(
435 raw <= SyntaxKind::__LAST as u16,
436 "SyntaxKind out of range: {raw}"
437 );
438 unsafe { std::mem::transmute::<u16, SyntaxKind>(raw) }
441 }
442
443 #[inline]
445 pub const fn is_trivia(self) -> bool {
446 matches!(
447 self,
448 SyntaxKind::WHITESPACE
449 | SyntaxKind::NEWLINE
450 | SyntaxKind::COMMENT
451 | SyntaxKind::BLOCK_COMMENT
452 )
453 }
454
455 #[inline]
457 pub const fn is_comment(self) -> bool {
458 matches!(self, SyntaxKind::COMMENT | SyntaxKind::BLOCK_COMMENT)
459 }
460
461 #[inline]
463 pub fn is_keyword(self) -> bool {
464 let v = self as u16;
465 v > SyntaxKind::__KW_START as u16 && v < SyntaxKind::__KW_END as u16
466 }
467
468 pub fn describe(self) -> &'static str {
475 use SyntaxKind::*;
476 match self {
477 IDENT => "an identifier",
479 QUOTED_IDENT => "a quoted identifier",
480 STRING => "a string literal",
481 DOLLAR_STRING => "a dollar-quoted string",
482 FILE_URI => "a file URI",
483 INT_NUMBER => "an integer literal",
484 FLOAT_NUMBER => "a number literal",
485 VARIABLE => "a variable",
486 PLACEHOLDER => "a template placeholder",
487 L_PAREN => "'('",
489 R_PAREN => "')'",
490 L_BRACKET => "'['",
491 R_BRACKET => "']'",
492 L_BRACE => "'{'",
493 R_BRACE => "'}'",
494 COMMA => "','",
495 DOT => "'.'",
496 SEMICOLON => "';'",
497 COLON => "':'",
498 COLON2 => "'::'",
499 ASSIGN => "':='",
500 EQ => "'='",
501 NEQ => "'<>'",
502 LT => "'<'",
503 LTE => "'<='",
504 NULL_SAFE_EQ => "'<=>'",
505 GT => "'>'",
506 GTE => "'>='",
507 PLUS => "'+'",
508 MINUS => "'-'",
509 STAR => "'*'",
510 SLASH => "'/'",
511 PERCENT => "'%'",
512 CONCAT => "'||'",
513 PIPE => "'|'",
514 PIPE_GT => "'|>'",
515 FLOW_PIPE => "'->>'",
516 ARROW => "'->'",
517 FAT_ARROW => "'=>'",
518 AMP => "'&'",
519 CARET => "'^'",
520 TILDE => "'~'",
521 AT => "'@'",
522 DOLLAR => "'$'",
523 QUESTION => "'?'",
524 BANG => "'!'",
525 WHITESPACE => "whitespace",
527 NEWLINE => "a newline",
528 COMMENT => "a comment",
529 BLOCK_COMMENT => "a block comment",
530 EOF => "end of input",
531 CONTEXTUAL_KEYWORD => "a keyword",
532 kind if kind.is_keyword() => kind.keyword_word(),
534 _ => "input",
536 }
537 }
538
539 fn keyword_word(self) -> &'static str {
542 macro_rules! kw {
543 ($($variant:ident => $word:literal,)*) => {
544 match self {
545 $(SyntaxKind::$variant => $word,)*
546 _ => "",
547 }
548 };
549 }
550 kw! {
551 SELECT_KW => "SELECT", FROM_KW => "FROM", WHERE_KW => "WHERE", GROUP_KW => "GROUP",
552 BY_KW => "BY", HAVING_KW => "HAVING", ORDER_KW => "ORDER", LIMIT_KW => "LIMIT",
553 OFFSET_KW => "OFFSET", FETCH_KW => "FETCH", TOP_KW => "TOP", AS_KW => "AS",
554 AND_KW => "AND", OR_KW => "OR", NOT_KW => "NOT", NULL_KW => "NULL", IS_KW => "IS",
555 IN_KW => "IN", LIKE_KW => "LIKE", ILIKE_KW => "ILIKE", RLIKE_KW => "RLIKE",
556 REGEXP_KW => "REGEXP", BETWEEN_KW => "BETWEEN", CASE_KW => "CASE", WHEN_KW => "WHEN",
557 THEN_KW => "THEN", ELSE_KW => "ELSE", END_KW => "END", JOIN_KW => "JOIN",
558 INNER_KW => "INNER", LEFT_KW => "LEFT", RIGHT_KW => "RIGHT", FULL_KW => "FULL",
559 OUTER_KW => "OUTER", CROSS_KW => "CROSS", LATERAL_KW => "LATERAL",
560 NATURAL_KW => "NATURAL", ON_KW => "ON", USING_KW => "USING", WITH_KW => "WITH",
561 RECURSIVE_KW => "RECURSIVE", UNION_KW => "UNION", ALL_KW => "ALL", ANY_KW => "ANY",
562 EXCEPT_KW => "EXCEPT", INTERSECT_KW => "INTERSECT", MINUS_KW => "MINUS",
563 DISTINCT_KW => "DISTINCT", QUALIFY_KW => "QUALIFY", OVER_KW => "OVER",
564 PARTITION_KW => "PARTITION", WINDOW_KW => "WINDOW", ROWS_KW => "ROWS",
565 RANGE_KW => "RANGE", UNBOUNDED_KW => "UNBOUNDED", PRECEDING_KW => "PRECEDING",
566 FOLLOWING_KW => "FOLLOWING", CURRENT_KW => "CURRENT", ROW_KW => "ROW", ASC_KW => "ASC",
567 DESC_KW => "DESC", NULLS_KW => "NULLS", FIRST_KW => "FIRST", LAST_KW => "LAST",
568 TRUE_KW => "TRUE", FALSE_KW => "FALSE", CAST_KW => "CAST", TRY_CAST_KW => "TRY_CAST",
569 EXISTS_KW => "EXISTS", VALUES_KW => "VALUES", PIVOT_KW => "PIVOT",
570 UNPIVOT_KW => "UNPIVOT", SAMPLE_KW => "SAMPLE", TABLESAMPLE_KW => "TABLESAMPLE",
571 CREATE_KW => "CREATE", REPLACE_KW => "REPLACE", IF_KW => "IF", TABLE_KW => "TABLE",
572 VIEW_KW => "VIEW", TEMPORARY_KW => "TEMPORARY", TEMP_KW => "TEMP",
573 TRANSIENT_KW => "TRANSIENT", VOLATILE_KW => "VOLATILE", SECURE_KW => "SECURE",
574 INSERT_KW => "INSERT", INTO_KW => "INTO", UPDATE_KW => "UPDATE", DELETE_KW => "DELETE",
575 MERGE_KW => "MERGE", SET_KW => "SET", FLATTEN_KW => "FLATTEN", CONNECT_KW => "CONNECT",
576 START_KW => "START", PRIOR_KW => "PRIOR", LANGUAGE_KW => "LANGUAGE",
577 JAVASCRIPT_KW => "JAVASCRIPT", PYTHON_KW => "PYTHON", JAVA_KW => "JAVA",
578 SCALA_KW => "SCALA", SQL_KW => "SQL", BEGIN_KW => "BEGIN", DECLARE_KW => "DECLARE",
579 LET_KW => "LET", RETURN_KW => "RETURN", CALL_KW => "CALL", PROCEDURE_KW => "PROCEDURE",
580 FUNCTION_KW => "FUNCTION", RETURNS_KW => "RETURNS", TASK_KW => "TASK",
581 WAREHOUSE_KW => "WAREHOUSE", SCHEDULE_KW => "SCHEDULE", AFTER_KW => "AFTER",
582 COPY_KW => "COPY", GRANTS_KW => "GRANTS", HANDLER_KW => "HANDLER",
583 PACKAGES_KW => "PACKAGES", IMPORTS_KW => "IMPORTS",
584 RUNTIME_VERSION_KW => "RUNTIME_VERSION", EXECUTE_KW => "EXECUTE", OWNER_KW => "OWNER",
585 CALLER_KW => "CALLER", STRICT_KW => "STRICT", CALLED_KW => "CALLED",
586 INPUT_KW => "INPUT", OUTPUT_KW => "OUTPUT", OUT_KW => "OUT", MATCHED_KW => "MATCHED",
587 DROP_KW => "DROP", ALTER_KW => "ALTER", WITHIN_KW => "WITHIN", FOR_KW => "FOR",
588 IMMEDIATE_KW => "IMMEDIATE", OVERWRITE_KW => "OVERWRITE", GRANT_KW => "GRANT",
589 REVOKE_KW => "REVOKE", USE_KW => "USE", SHOW_KW => "SHOW", DESCRIBE_KW => "DESCRIBE",
590 TRUNCATE_KW => "TRUNCATE", COMMIT_KW => "COMMIT", ROLLBACK_KW => "ROLLBACK",
591 UNDROP_KW => "UNDROP", ELSEIF_KW => "ELSEIF", WHILE_KW => "WHILE", LOOP_KW => "LOOP",
592 REPEAT_KW => "REPEAT", UNTIL_KW => "UNTIL", DO_KW => "DO", EXCEPTION_KW => "EXCEPTION",
593 CURSOR_KW => "CURSOR", RESULTSET_KW => "RESULTSET",
594 }
595 }
596}
597
598#[cfg(test)]
599mod tests {
600 use super::SyntaxKind;
601
602 #[test]
603 fn keyword_and_trivia_predicates() {
604 assert!(SyntaxKind::SELECT_KW.is_keyword());
605 assert!(SyntaxKind::QUALIFY_KW.is_keyword());
606 assert!(!SyntaxKind::IDENT.is_keyword());
607 assert!(!SyntaxKind::PIPE_GT.is_keyword());
608 assert!(SyntaxKind::WHITESPACE.is_trivia());
609 assert!(SyntaxKind::BLOCK_COMMENT.is_trivia());
610 assert!(SyntaxKind::COMMENT.is_comment());
611 assert!(!SyntaxKind::IDENT.is_trivia());
612 }
613
614 #[test]
615 fn u16_roundtrip_is_total() {
616 for raw in 0..=SyntaxKind::__LAST.to_u16() {
618 let kind = SyntaxKind::from_u16(raw);
619 assert_eq!(kind.to_u16(), raw);
620 }
621 }
622
623 #[test]
624 #[should_panic]
625 fn from_u16_out_of_range_panics() {
626 let _ = SyntaxKind::from_u16(u16::MAX);
627 }
628
629 #[test]
630 fn describe_is_human_readable() {
631 assert_eq!(SyntaxKind::INTO_KW.describe(), "INTO");
632 assert_eq!(SyntaxKind::SELECT_KW.describe(), "SELECT");
633 assert_eq!(SyntaxKind::L_PAREN.describe(), "'('");
634 assert_eq!(SyntaxKind::FAT_ARROW.describe(), "'=>'");
635 assert_eq!(SyntaxKind::IDENT.describe(), "an identifier");
636 assert_eq!(SyntaxKind::STRING.describe(), "a string literal");
637 assert_eq!(SyntaxKind::FILE_URI.describe(), "a file URI");
638 assert_eq!(SyntaxKind::EOF.describe(), "end of input");
639 }
640
641 #[test]
642 fn unsupported_but_lexed_tokens_are_documented() {
643 for (kind, text) in [
647 (SyntaxKind::PIPE_GT, "'|>'"),
648 (SyntaxKind::L_BRACE, "'{'"),
649 (SyntaxKind::QUESTION, "'?'"),
650 (SyntaxKind::NULL_SAFE_EQ, "'<=>'"),
651 (SyntaxKind::BANG, "'!'"),
652 (SyntaxKind::AMP, "'&'"),
653 (SyntaxKind::CARET, "'^'"),
654 ] {
655 assert_eq!(kind.describe(), text);
656 assert!(!kind.is_keyword(), "{kind:?} must not be reserved grammar");
657 }
658 }
659
660 #[test]
661 fn describe_covers_every_keyword() {
662 for raw in (SyntaxKind::__KW_START as u16 + 1)..(SyntaxKind::__KW_END as u16) {
665 let kind = SyntaxKind::from_u16(raw);
666 assert!(kind.is_keyword());
667 assert!(
668 !kind.describe().is_empty(),
669 "{kind:?} has no describe() text"
670 );
671 }
672 }
673}