leo_parser_rowan/syntax_kind.rs
1// Copyright (C) 2019-2026 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17//! Syntax kind definitions for the rowan-based Leo parser.
18//!
19//! This module defines a flat `SyntaxKind` enum containing all token and node
20//! types used in the Leo syntax tree. The enum is `#[repr(u16)]` for
21//! compatibility with rowan's internal representation.
22
23// Re-export the variants to make the `SyntaxKind` helper method implementations
24// a bit less noisey.
25use SyntaxKind::*;
26
27/// Macro to define SyntaxKind enum and its lookup table in one place.
28/// This ensures they can never get out of sync.
29macro_rules! define_syntax_kinds {
30 (
31 $(
32 $(#[$attr:meta])*
33 $variant:ident $(= $value:expr)?
34 ),* $(,)?
35 ) => {
36 /// All syntax kinds for Leo tokens and nodes.
37 ///
38 /// This enum is intentionally flat (not nested) to satisfy rowan's requirement
39 /// for a `#[repr(u16)]` type. Categories are indicated by comments and helper
40 /// methods like `is_trivia()` and `is_keyword()`.
41 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
42 #[repr(u16)]
43 #[allow(non_camel_case_types)]
44 pub enum SyntaxKind {
45 $(
46 $(#[$attr])*
47 $variant $(= $value)?
48 ),*
49 }
50
51 /// Lookup table for converting raw u16 values back to SyntaxKind.
52 /// This is auto-generated by the define_syntax_kinds! macro.
53 const SYNTAX_KIND_TABLE: &[SyntaxKind] = &[
54 $(SyntaxKind::$variant),*
55 ];
56 };
57}
58
59define_syntax_kinds! {
60 // ==========================================================================
61 // Special
62 // ==========================================================================
63 /// Error node for wrapping parse errors and invalid tokens.
64 ERROR = 0,
65 /// End of file marker.
66 EOF,
67
68 // ==========================================================================
69 // Trivia (whitespace and comments)
70 // ==========================================================================
71 /// Horizontal whitespace: spaces, tabs, form feeds.
72 WHITESPACE,
73 /// Line breaks: \n or \r\n.
74 LINEBREAK,
75 /// Line comment: // ...
76 COMMENT_LINE,
77 /// Block comment: /* ... */
78 COMMENT_BLOCK,
79
80 // ==========================================================================
81 // Literals
82 // ==========================================================================
83 /// Integer literal: 123, 0xFF, 0b101, 0o77
84 INTEGER,
85 /// String literal: "..."
86 STRING,
87 /// Address literal: aleo1...
88 ADDRESS_LIT,
89 /// Identifier literal: 'foo'
90 IDENT_LIT,
91
92 // ==========================================================================
93 // Identifiers
94 // ==========================================================================
95 /// Identifier: foo, Bar, _baz
96 /// Note: Complex identifiers (paths, program IDs, locators) are deferred
97 /// to Phase 2. The lexer produces simple IDENT tokens; the parser handles
98 /// disambiguation of foo::bar, foo.aleo, foo.aleo::bar patterns.
99 IDENT,
100
101 // ==========================================================================
102 // Keywords - Literals
103 // ==========================================================================
104 /// `true`
105 KW_TRUE,
106 /// `false`
107 KW_FALSE,
108 /// `none`
109 KW_NONE,
110
111 // ==========================================================================
112 // Keywords - Types
113 // ==========================================================================
114 /// `address`
115 KW_ADDRESS,
116 /// `bool`
117 KW_BOOL,
118 /// `field`
119 KW_FIELD,
120 /// `group`
121 KW_GROUP,
122 /// `scalar`
123 KW_SCALAR,
124 /// `signature`
125 KW_SIGNATURE,
126 /// `string`
127 KW_STRING,
128 /// `record`
129 KW_RECORD,
130 /// `dyn`
131 KW_DYN,
132 /// `identifier`
133 KW_IDENTIFIER,
134 /// `Final`
135 KW_FINAL_UPPER,
136 /// `i8`
137 KW_I8,
138 /// `i16`
139 KW_I16,
140 /// `i32`
141 KW_I32,
142 /// `i64`
143 KW_I64,
144 /// `i128`
145 KW_I128,
146 /// `u8`
147 KW_U8,
148 /// `u16`
149 KW_U16,
150 /// `u32`
151 KW_U32,
152 /// `u64`
153 KW_U64,
154 /// `u128`
155 KW_U128,
156
157 // ==========================================================================
158 // Keywords - Control Flow
159 // ==========================================================================
160 /// `if`
161 KW_IF,
162 /// `else`
163 KW_ELSE,
164 /// `for`
165 KW_FOR,
166 /// `in`
167 KW_IN,
168 /// `return`
169 KW_RETURN,
170
171 // ==========================================================================
172 // Keywords - Declarations
173 // ==========================================================================
174 /// `let`
175 KW_LET,
176 /// `const`
177 KW_CONST,
178 /// `constant`
179 KW_CONSTANT,
180 /// `final`
181 KW_FINAL,
182 /// `view`
183 KW_VIEW,
184 /// `fn`
185 KW_FN,
186 /// `Fn`
187 KW_FN_UPPER,
188 /// `struct`
189 KW_STRUCT,
190 /// `constructor`
191 KW_CONSTRUCTOR,
192 /// `interface`
193 KW_INTERFACE,
194
195 // ==========================================================================
196 // Keywords - Program Structure
197 // ==========================================================================
198 /// `program`
199 KW_PROGRAM,
200 /// `import`
201 KW_IMPORT,
202 /// `mapping`
203 KW_MAPPING,
204 /// `storage`
205 KW_STORAGE,
206 /// `network`
207 KW_NETWORK,
208 /// `aleo`
209 KW_ALEO,
210 /// `script`
211 KW_SCRIPT,
212 /// `block`
213 KW_BLOCK,
214
215 // ==========================================================================
216 // Keywords - Visibility & Assertions
217 // ==========================================================================
218 /// `public`
219 KW_PUBLIC,
220 /// `private`
221 KW_PRIVATE,
222 /// `as`
223 KW_AS,
224 /// `self`
225 KW_SELF,
226 /// `assert`
227 KW_ASSERT,
228 /// `assert_eq`
229 KW_ASSERT_EQ,
230 /// `assert_neq`
231 KW_ASSERT_NEQ,
232
233 // ==========================================================================
234 // Punctuation - Delimiters
235 // ==========================================================================
236 /// `(`
237 L_PAREN,
238 /// `)`
239 R_PAREN,
240 /// `[`
241 L_BRACKET,
242 /// `]`
243 R_BRACKET,
244 /// `{`
245 L_BRACE,
246 /// `}`
247 R_BRACE,
248
249 // ==========================================================================
250 // Punctuation - Separators
251 // ==========================================================================
252 /// `,`
253 COMMA,
254 /// `.`
255 DOT,
256 /// `..`
257 DOT_DOT,
258 /// `..=`
259 DOT_DOT_EQ,
260 /// `;`
261 SEMICOLON,
262 /// `:`
263 COLON,
264 /// `::`
265 COLON_COLON,
266 /// `?`
267 QUESTION,
268 /// `->`
269 ARROW,
270 /// `=>`
271 FAT_ARROW,
272 /// `_`
273 UNDERSCORE,
274 /// `@`
275 AT,
276
277 // ==========================================================================
278 // Operators - Assignment
279 // ==========================================================================
280 /// `=`
281 EQ,
282 /// `+=`
283 PLUS_EQ,
284 /// `-=`
285 MINUS_EQ,
286 /// `*=`
287 STAR_EQ,
288 /// `/=`
289 SLASH_EQ,
290 /// `%=`
291 PERCENT_EQ,
292 /// `**=`
293 STAR2_EQ,
294 /// `&&=`
295 AMP2_EQ,
296 /// `||=`
297 PIPE2_EQ,
298 /// `&=`
299 AMP_EQ,
300 /// `|=`
301 PIPE_EQ,
302 /// `^=`
303 CARET_EQ,
304 /// `<<=`
305 SHL_EQ,
306 /// `>>=`
307 SHR_EQ,
308
309 // ==========================================================================
310 // Operators - Arithmetic
311 // ==========================================================================
312 /// `+`
313 PLUS,
314 /// `-`
315 MINUS,
316 /// `*`
317 STAR,
318 /// `/`
319 SLASH,
320 /// `%`
321 PERCENT,
322 /// `**`
323 STAR2,
324
325 // ==========================================================================
326 // Operators - Comparison
327 // ==========================================================================
328 /// `==`
329 EQ2,
330 /// `!=`
331 BANG_EQ,
332 /// `<`
333 LT,
334 /// `<=`
335 LT_EQ,
336 /// `>`
337 GT,
338 /// `>=`
339 GT_EQ,
340
341 // ==========================================================================
342 // Operators - Logical
343 // ==========================================================================
344 /// `&&`
345 AMP2,
346 /// `||`
347 PIPE2,
348 /// `!`
349 BANG,
350
351 // ==========================================================================
352 // Operators - Bitwise
353 // ==========================================================================
354 /// `&`
355 AMP,
356 /// `|`
357 PIPE,
358 /// `^`
359 CARET,
360 /// `<<`
361 SHL,
362 /// `>>`
363 SHR,
364
365 // ==========================================================================
366 // Composite Nodes - Top Level
367 // ==========================================================================
368 /// Root node of the syntax tree.
369 ROOT,
370 /// Program declaration: `program foo.aleo { ... }`
371 PROGRAM_DECL,
372 /// Import statement: `import foo.aleo;`
373 IMPORT,
374 /// Main file contents.
375 MAIN_CONTENTS,
376 /// Module file contents.
377 MODULE_CONTENTS,
378
379 // ==========================================================================
380 // Composite Nodes - Declarations
381 // ==========================================================================
382 /// Function definition.
383 FUNCTION_DEF,
384 /// Final function definition: `final fn ...`
385 FINAL_FN_DEF,
386 /// View function definition: `view fn ...`. Read-only V15 entry point.
387 VIEW_FN_DEF,
388 /// Constructor definition.
389 CONSTRUCTOR_DEF,
390 /// Struct definition.
391 STRUCT_DEF,
392 /// Record definition.
393 RECORD_DEF,
394 /// Struct member declaration.
395 STRUCT_MEMBER,
396 /// Public struct member: `public name: Type`
397 STRUCT_MEMBER_PUBLIC,
398 /// Private struct member: `private name: Type`
399 STRUCT_MEMBER_PRIVATE,
400 /// Constant struct member: `constant name: Type`
401 STRUCT_MEMBER_CONSTANT,
402 /// Mapping definition.
403 MAPPING_DEF,
404 /// Storage definition.
405 STORAGE_DEF,
406 /// Global constant definition.
407 GLOBAL_CONST,
408 /// Interface declaration.
409 INTERFACE_DEF,
410 /// Function prototype (in interface).
411 FN_PROTOTYPE_DEF,
412 /// Record prototype (in interface).
413 RECORD_PROTOTYPE_DEF,
414
415 // ==========================================================================
416 // Composite Nodes - Function Parts
417 // ==========================================================================
418 /// Annotation: `@foo`
419 ANNOTATION,
420 /// Annotation key-value pair: `key = "value"`
421 ANNOTATION_PAIR,
422 /// Parameter in a function signature.
423 PARAM,
424 /// Public parameter: `public name: Type`
425 PARAM_PUBLIC,
426 /// Private parameter: `private name: Type`
427 PARAM_PRIVATE,
428 /// Constant parameter: `constant name: Type`
429 PARAM_CONSTANT,
430 /// Parameter list: `(a: u32, b: u32)`
431 PARAM_LIST,
432 /// Function output type.
433 RETURN_TYPE,
434 /// Const generic parameter.
435 CONST_PARAM,
436 /// Const generic parameter list.
437 CONST_PARAM_LIST,
438 /// Const generic argument list.
439 CONST_ARG_LIST,
440 /// Visibility-annotated return type for `_dynamic_call` (e.g. `public u64`).
441 DYNAMIC_CALL_RETURN_TYPE,
442 /// Array length expression wrapper in `[T; N]`.
443 ARRAY_LENGTH,
444
445 // ==========================================================================
446 // Composite Nodes - Statements
447 // ==========================================================================
448 /// Let statement: `let x = ...;`
449 LET_STMT,
450 /// Const statement: `const x = ...;`
451 CONST_STMT,
452 /// Return statement: `return ...;`
453 RETURN_STMT,
454 /// Expression statement: `foo();`
455 EXPR_STMT,
456 /// Assignment statement: `x = ...;`
457 ASSIGN_STMT,
458 /// Compound assignment statement: `x += ...;`, `x -= ...;`, etc.
459 COMPOUND_ASSIGN_STMT,
460 /// If statement: `if ... { } else { }`
461 IF_STMT,
462 /// For loop: `for i in 0..10 { }`
463 FOR_STMT,
464 /// Inclusive for loop: `for i in 0..=10 { }`
465 FOR_INCLUSIVE_STMT,
466 /// Block: `{ ... }`
467 BLOCK,
468 /// Assert statement: `assert(...);`
469 ASSERT_STMT,
470 /// Assert equals statement: `assert_eq(...);`
471 ASSERT_EQ_STMT,
472 /// Assert not equals statement: `assert_neq(...);`
473 ASSERT_NEQ_STMT,
474
475 // ==========================================================================
476 // Composite Nodes - Patterns
477 // ==========================================================================
478 /// Identifier pattern: `x`
479 IDENT_PATTERN,
480 /// Tuple pattern: `(a, b, c)`
481 TUPLE_PATTERN,
482 /// Wildcard pattern: `_`
483 WILDCARD_PATTERN,
484
485 // ==========================================================================
486 // Composite Nodes - Expressions
487 // ==========================================================================
488 /// Binary expression: `a + b`
489 BINARY_EXPR,
490 /// Unary expression: `!a`, `-a`
491 UNARY_EXPR,
492 /// Function call: `foo(a, b)`
493 CALL_EXPR,
494 /// Method call: `a.foo(b)`
495 METHOD_CALL_EXPR,
496 /// Member access: `a.b`
497 FIELD_EXPR,
498 /// Array/tuple index: `a[0]`
499 INDEX_EXPR,
500 /// Cast expression: `a as u32`
501 CAST_EXPR,
502 /// Ternary expression: `a ? b : c`
503 TERNARY_EXPR,
504 /// Array literal: `[1, 2, 3]`
505 ARRAY_EXPR,
506 /// Tuple literal: `(1, 2, 3)`
507 TUPLE_EXPR,
508 /// Struct literal: `Foo { a: 1, b: 2 }`
509 STRUCT_EXPR,
510 /// Struct locator literal: `program.aleo::Type { a: 1, b: 2 }`
511 STRUCT_LOCATOR_EXPR,
512 /// Struct field initializer: `a: 1`
513 STRUCT_FIELD_INIT,
514 /// Struct field shorthand: `{ x }` (equivalent to `{ x: x }`)
515 STRUCT_FIELD_SHORTHAND,
516 /// Struct update base: `..other` in `Foo { a: 1, ..other }`
517 STRUCT_BASE_UPDATE,
518 /// Path expression: `foo::bar`
519 PATH_EXPR,
520 /// Path locator expression: `program.aleo::function`
521 PATH_LOCATOR_EXPR,
522 /// Program reference expression: `name.aleo` (without `::Type` suffix).
523 PROGRAM_REF_EXPR,
524 /// Self expression: `self`
525 SELF_EXPR,
526 /// Block keyword expression: `block`
527 BLOCK_KW_EXPR,
528 /// Network keyword expression: `network`
529 NETWORK_KW_EXPR,
530 /// Parenthesized expression: `(a + b)`
531 PAREN_EXPR,
532 /// Field literal: `42field`
533 LITERAL_FIELD,
534 /// Group literal: `42group`
535 LITERAL_GROUP,
536 /// Scalar literal: `42scalar`
537 LITERAL_SCALAR,
538 /// Integer literal: `42u32`, `42` (unsuffixed)
539 LITERAL_INT,
540 /// String literal: `"hello"`
541 LITERAL_STRING,
542 /// Address literal: `aleo1...`
543 LITERAL_ADDRESS,
544 /// Boolean literal: `true`, `false`
545 LITERAL_BOOL,
546 /// None literal: `none`
547 LITERAL_NONE,
548 /// Identifier literal: `'foo'`
549 LITERAL_IDENT,
550 /// Repeat expression: `[0u8; 32]`
551 REPEAT_EXPR,
552 /// Async expression: `async foo()`
553 FINAL_EXPR,
554 /// Tuple access: `a.0`
555 TUPLE_ACCESS_EXPR,
556 /// Dynamic interface access. Covers three surface forms:
557 /// - function call: `Interface @ (target) :: func(args)`
558 /// - storage/vector op: `Interface @ (target) :: member.op(args)`
559 /// - singleton bare read: `Interface @ (target) :: storage`
560 DYNAMIC_OP_EXPR,
561
562 // ==========================================================================
563 // Composite Nodes - Types
564 // ==========================================================================
565 /// Named/path type: `Foo`, `foo::Bar`
566 TYPE_PATH,
567 /// Primitive type: `u32`, `bool`, `field`, etc.
568 TYPE_PRIMITIVE,
569 /// Locator type: `program.aleo::Type`
570 TYPE_LOCATOR,
571 /// Array type: `[u32; 10]`
572 TYPE_ARRAY,
573 /// Vector type: `[u32]`
574 TYPE_VECTOR,
575 /// Tuple type: `(u32, u32)`
576 TYPE_TUPLE,
577 /// Optional type: `u32?` (Future feature)
578 TYPE_OPTIONAL,
579 /// Final type: `Final<Foo>`
580 TYPE_FINAL,
581 /// Mapping type in storage.
582 TYPE_MAPPING,
583 /// Dynamic record type: `dyn record`
584 TYPE_DYN_RECORD,
585 /// Parent list: `Foo + Bar`
586 PARENT_LIST,
587
588 // Sentinel for bounds checking (must be last)
589 #[doc(hidden)]
590 __LAST,
591}
592
593impl SyntaxKind {
594 /// Check if this is a trivia token (whitespace or comment).
595 pub fn is_trivia(self) -> bool {
596 matches!(self, WHITESPACE | LINEBREAK | COMMENT_LINE | COMMENT_BLOCK)
597 }
598
599 /// Check if this is a keyword.
600 pub fn is_keyword(self) -> bool {
601 matches!(
602 self,
603 KW_TRUE
604 | KW_FALSE
605 | KW_NONE
606 | KW_ADDRESS
607 | KW_BOOL
608 | KW_FIELD
609 | KW_GROUP
610 | KW_SCALAR
611 | KW_SIGNATURE
612 | KW_STRING
613 | KW_RECORD
614 | KW_DYN
615 | KW_IDENTIFIER
616 | KW_FINAL_UPPER
617 | KW_I8
618 | KW_I16
619 | KW_I32
620 | KW_I64
621 | KW_I128
622 | KW_U8
623 | KW_U16
624 | KW_U32
625 | KW_U64
626 | KW_U128
627 | KW_IF
628 | KW_ELSE
629 | KW_FOR
630 | KW_IN
631 | KW_RETURN
632 | KW_LET
633 | KW_CONST
634 | KW_CONSTANT
635 | KW_FN
636 | KW_FINAL
637 | KW_VIEW
638 | KW_FN_UPPER
639 | KW_STRUCT
640 | KW_CONSTRUCTOR
641 | KW_INTERFACE
642 | KW_PROGRAM
643 | KW_IMPORT
644 | KW_MAPPING
645 | KW_STORAGE
646 | KW_NETWORK
647 | KW_ALEO
648 | KW_SCRIPT
649 | KW_BLOCK
650 | KW_PUBLIC
651 | KW_PRIVATE
652 | KW_AS
653 | KW_SELF
654 | KW_ASSERT
655 | KW_ASSERT_EQ
656 | KW_ASSERT_NEQ
657 )
658 }
659
660 /// Check if this is a type keyword.
661 pub fn is_type_keyword(self) -> bool {
662 matches!(
663 self,
664 KW_ADDRESS
665 | KW_BOOL
666 | KW_FIELD
667 | KW_GROUP
668 | KW_SCALAR
669 | KW_SIGNATURE
670 | KW_STRING
671 | KW_DYN
672 | KW_IDENTIFIER
673 | KW_FINAL_UPPER
674 | KW_I8
675 | KW_I16
676 | KW_I32
677 | KW_I64
678 | KW_I128
679 | KW_U8
680 | KW_U16
681 | KW_U32
682 | KW_U64
683 | KW_U128
684 )
685 }
686
687 /// Check if this is a literal token.
688 pub fn is_literal(self) -> bool {
689 matches!(self, INTEGER | STRING | ADDRESS_LIT | IDENT_LIT | KW_TRUE | KW_FALSE | KW_NONE)
690 }
691
692 /// Check if this is a literal node kind.
693 pub fn is_literal_node(self) -> bool {
694 matches!(
695 self,
696 LITERAL_FIELD
697 | LITERAL_GROUP
698 | LITERAL_SCALAR
699 | LITERAL_INT
700 | LITERAL_STRING
701 | LITERAL_ADDRESS
702 | LITERAL_BOOL
703 | LITERAL_NONE
704 | LITERAL_IDENT
705 )
706 }
707
708 /// Check if this is a type node kind.
709 pub fn is_type(self) -> bool {
710 matches!(
711 self,
712 TYPE_PRIMITIVE
713 | TYPE_LOCATOR
714 | TYPE_PATH
715 | TYPE_ARRAY
716 | TYPE_VECTOR
717 | TYPE_TUPLE
718 | TYPE_OPTIONAL
719 | TYPE_FINAL
720 | TYPE_MAPPING
721 | TYPE_DYN_RECORD
722 )
723 }
724
725 /// Check if this is an expression node kind.
726 pub fn is_expression(self) -> bool {
727 self.is_literal_node()
728 || matches!(
729 self,
730 BINARY_EXPR
731 | UNARY_EXPR
732 | CALL_EXPR
733 | METHOD_CALL_EXPR
734 | FIELD_EXPR
735 | TUPLE_ACCESS_EXPR
736 | INDEX_EXPR
737 | CAST_EXPR
738 | TERNARY_EXPR
739 | ARRAY_EXPR
740 | REPEAT_EXPR
741 | TUPLE_EXPR
742 | STRUCT_EXPR
743 | STRUCT_LOCATOR_EXPR
744 | PATH_EXPR
745 | PATH_LOCATOR_EXPR
746 | PROGRAM_REF_EXPR
747 | SELF_EXPR
748 | BLOCK_KW_EXPR
749 | NETWORK_KW_EXPR
750 | PAREN_EXPR
751 | FINAL_EXPR
752 | DYNAMIC_OP_EXPR
753 )
754 }
755
756 /// Check if this is a statement node kind.
757 pub fn is_statement(self) -> bool {
758 matches!(
759 self,
760 LET_STMT
761 | CONST_STMT
762 | RETURN_STMT
763 | EXPR_STMT
764 | ASSIGN_STMT
765 | COMPOUND_ASSIGN_STMT
766 | IF_STMT
767 | FOR_STMT
768 | FOR_INCLUSIVE_STMT
769 | BLOCK
770 | ASSERT_STMT
771 | ASSERT_EQ_STMT
772 | ASSERT_NEQ_STMT
773 )
774 }
775
776 /// Check if this is a punctuation token.
777 pub fn is_punctuation(self) -> bool {
778 matches!(
779 self,
780 L_PAREN
781 | R_PAREN
782 | L_BRACKET
783 | R_BRACKET
784 | L_BRACE
785 | R_BRACE
786 | COMMA
787 | DOT
788 | DOT_DOT
789 | DOT_DOT_EQ
790 | SEMICOLON
791 | COLON
792 | COLON_COLON
793 | QUESTION
794 | ARROW
795 | FAT_ARROW
796 | UNDERSCORE
797 | AT
798 )
799 }
800
801 /// Check if this is an operator token.
802 pub fn is_operator(self) -> bool {
803 matches!(
804 self,
805 EQ | PLUS_EQ
806 | MINUS_EQ
807 | STAR_EQ
808 | SLASH_EQ
809 | PERCENT_EQ
810 | STAR2_EQ
811 | AMP2_EQ
812 | PIPE2_EQ
813 | AMP_EQ
814 | PIPE_EQ
815 | CARET_EQ
816 | SHL_EQ
817 | SHR_EQ
818 | PLUS
819 | MINUS
820 | STAR
821 | SLASH
822 | PERCENT
823 | STAR2
824 | EQ2
825 | BANG_EQ
826 | LT
827 | LT_EQ
828 | GT
829 | GT_EQ
830 | AMP2
831 | PIPE2
832 | BANG
833 | AMP
834 | PIPE
835 | CARET
836 | SHL
837 | SHR
838 )
839 }
840
841 /// Returns a user-friendly name for this token kind, suitable for error messages.
842 pub fn user_friendly_name(self) -> &'static str {
843 match self {
844 // Special
845 ERROR => "an error",
846 EOF => "end of file",
847
848 // Trivia
849 WHITESPACE | LINEBREAK => "whitespace",
850 COMMENT_LINE | COMMENT_BLOCK => "a comment",
851
852 // Literals
853 INTEGER => "an integer literal",
854 STRING => "a static string",
855 ADDRESS_LIT => "an address literal",
856 IDENT_LIT => "an identifier literal",
857
858 // Identifiers
859 IDENT => "an identifier",
860
861 // Boolean literals
862 KW_TRUE => "'true'",
863 KW_FALSE => "'false'",
864 KW_NONE => "'none'",
865
866 // Type keywords
867 KW_ADDRESS => "'address'",
868 KW_BOOL => "'bool'",
869 KW_FIELD => "'field'",
870 KW_GROUP => "'group'",
871 KW_SCALAR => "'scalar'",
872 KW_SIGNATURE => "'signature'",
873 KW_STRING => "'string'",
874 KW_RECORD => "'record'",
875 KW_DYN => "'dyn'",
876 KW_IDENTIFIER => "'identifier'",
877 KW_FINAL_UPPER => "'Final'",
878 KW_I8 => "'i8'",
879 KW_I16 => "'i16'",
880 KW_I32 => "'i32'",
881 KW_I64 => "'i64'",
882 KW_I128 => "'i128'",
883 KW_U8 => "'u8'",
884 KW_U16 => "'u16'",
885 KW_U32 => "'u32'",
886 KW_U64 => "'u64'",
887 KW_U128 => "'u128'",
888
889 // Control flow keywords
890 KW_IF => "'if'",
891 KW_ELSE => "'else'",
892 KW_FOR => "'for'",
893 KW_IN => "'in'",
894 KW_RETURN => "'return'",
895
896 // Declaration keywords
897 KW_LET => "'let'",
898 KW_CONST => "'const'",
899 KW_CONSTANT => "'constant'",
900 KW_FINAL => "'final'",
901 KW_VIEW => "'view'",
902 KW_FN => "'fn'",
903 KW_FN_UPPER => "'Fn'",
904 KW_STRUCT => "'struct'",
905 KW_CONSTRUCTOR => "'constructor'",
906 KW_INTERFACE => "'interface'",
907
908 // Program structure keywords
909 KW_PROGRAM => "'program'",
910 KW_IMPORT => "'import'",
911 KW_MAPPING => "'mapping'",
912 KW_STORAGE => "'storage'",
913 KW_NETWORK => "'network'",
914 KW_ALEO => "'aleo'",
915 KW_SCRIPT => "'script'",
916 KW_BLOCK => "'block'",
917
918 // Visibility and assertion keywords
919 KW_PUBLIC => "'public'",
920 KW_PRIVATE => "'private'",
921 KW_AS => "'as'",
922 KW_SELF => "'self'",
923 KW_ASSERT => "'assert'",
924 KW_ASSERT_EQ => "'assert_eq'",
925 KW_ASSERT_NEQ => "'assert_neq'",
926
927 // Delimiters
928 L_PAREN => "'('",
929 R_PAREN => "')'",
930 L_BRACKET => "'['",
931 R_BRACKET => "']'",
932 L_BRACE => "'{'",
933 R_BRACE => "'}'",
934
935 // Separators
936 COMMA => "','",
937 DOT => "'.'",
938 DOT_DOT => "'..'",
939 DOT_DOT_EQ => "'..='",
940 SEMICOLON => "';'",
941 COLON => "':'",
942 COLON_COLON => "'::'",
943 QUESTION => "'?'",
944 ARROW => "'->'",
945 FAT_ARROW => "'=>'",
946 UNDERSCORE => "'_'",
947 AT => "'@'",
948
949 // Assignment operators
950 EQ => "'='",
951 PLUS_EQ => "'+='",
952 MINUS_EQ => "'-='",
953 STAR_EQ => "'*='",
954 SLASH_EQ => "'/='",
955 PERCENT_EQ => "'%='",
956 STAR2_EQ => "'**='",
957 AMP2_EQ => "'&&='",
958 PIPE2_EQ => "'||='",
959 AMP_EQ => "'&='",
960 PIPE_EQ => "'|='",
961 CARET_EQ => "'^='",
962 SHL_EQ => "'<<='",
963 SHR_EQ => "'>>='",
964
965 // Arithmetic operators
966 PLUS => "'+'",
967 MINUS => "'-'",
968 STAR => "'*'",
969 SLASH => "'/'",
970 PERCENT => "'%'",
971 STAR2 => "'**'",
972
973 // Comparison operators
974 EQ2 => "'=='",
975 BANG_EQ => "'!='",
976 LT => "'<'",
977 LT_EQ => "'<='",
978 GT => "'>'",
979 GT_EQ => "'>='",
980
981 // Logical operators
982 AMP2 => "'&&'",
983 PIPE2 => "'||'",
984 BANG => "'!'",
985
986 // Bitwise operators
987 AMP => "'&'",
988 PIPE => "'|'",
989 CARET => "'^'",
990 SHL => "'<<'",
991 SHR => "'>>'",
992
993 // Composite nodes - these shouldn't appear in "expected" messages typically
994 _ => "a token",
995 }
996 }
997}
998
999impl From<SyntaxKind> for rowan::SyntaxKind {
1000 fn from(kind: SyntaxKind) -> Self {
1001 Self(kind as u16)
1002 }
1003}
1004
1005/// Convert a raw rowan SyntaxKind to our SyntaxKind.
1006///
1007/// # Panics
1008/// Panics if the raw value is out of range.
1009pub fn syntax_kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
1010 SYNTAX_KIND_TABLE.get(raw.0 as usize).copied().unwrap_or_else(|| panic!("invalid SyntaxKind: {}", raw.0))
1011}
1012
1013#[cfg(test)]
1014mod tests {
1015 use super::*;
1016
1017 #[test]
1018 fn syntax_kind_table_is_correct() {
1019 // Verify that the table matches the enum discriminants
1020 for (i, &kind) in SYNTAX_KIND_TABLE.iter().enumerate() {
1021 assert_eq!(
1022 kind as u16, i as u16,
1023 "SYNTAX_KIND_TABLE[{i}] = {:?} has discriminant {}, expected {i}",
1024 kind, kind as u16
1025 );
1026 }
1027 }
1028
1029 #[test]
1030 fn syntax_kind_roundtrip() {
1031 // Test that we can convert to rowan::SyntaxKind and back
1032 for &kind in SYNTAX_KIND_TABLE.iter() {
1033 if kind == __LAST {
1034 continue;
1035 }
1036 let raw: rowan::SyntaxKind = kind.into();
1037 let back = syntax_kind_from_raw(raw);
1038 assert_eq!(kind, back);
1039 }
1040 }
1041
1042 #[test]
1043 fn is_trivia() {
1044 assert!(WHITESPACE.is_trivia());
1045 assert!(LINEBREAK.is_trivia());
1046 assert!(COMMENT_LINE.is_trivia());
1047 assert!(COMMENT_BLOCK.is_trivia());
1048 assert!(!IDENT.is_trivia());
1049 assert!(!KW_LET.is_trivia());
1050 }
1051
1052 #[test]
1053 fn is_keyword() {
1054 assert!(KW_LET.is_keyword());
1055 assert!(KW_FN.is_keyword());
1056 assert!(KW_TRUE.is_keyword());
1057 assert!(!IDENT.is_keyword());
1058 assert!(!PLUS.is_keyword());
1059 }
1060
1061 #[test]
1062 fn is_literal() {
1063 assert!(INTEGER.is_literal());
1064 assert!(STRING.is_literal());
1065 assert!(ADDRESS_LIT.is_literal());
1066 assert!(KW_TRUE.is_literal());
1067 assert!(KW_FALSE.is_literal());
1068 assert!(KW_NONE.is_literal());
1069 assert!(!IDENT.is_literal());
1070 }
1071}