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