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 /// `export`
223 KW_EXPORT,
224 /// `as`
225 KW_AS,
226 /// `self`
227 KW_SELF,
228 /// `Self`
229 KW_SELF_UPPER,
230 /// `assert`
231 KW_ASSERT,
232 /// `assert_eq`
233 KW_ASSERT_EQ,
234 /// `assert_neq`
235 KW_ASSERT_NEQ,
236
237 // ==========================================================================
238 // Punctuation - Delimiters
239 // ==========================================================================
240 /// `(`
241 L_PAREN,
242 /// `)`
243 R_PAREN,
244 /// `[`
245 L_BRACKET,
246 /// `]`
247 R_BRACKET,
248 /// `{`
249 L_BRACE,
250 /// `}`
251 R_BRACE,
252
253 // ==========================================================================
254 // Punctuation - Separators
255 // ==========================================================================
256 /// `,`
257 COMMA,
258 /// `.`
259 DOT,
260 /// `..`
261 DOT_DOT,
262 /// `..=`
263 DOT_DOT_EQ,
264 /// `;`
265 SEMICOLON,
266 /// `:`
267 COLON,
268 /// `::`
269 COLON_COLON,
270 /// `?`
271 QUESTION,
272 /// `->`
273 ARROW,
274 /// `=>`
275 FAT_ARROW,
276 /// `_`
277 UNDERSCORE,
278 /// `@`
279 AT,
280
281 // ==========================================================================
282 // Operators - Assignment
283 // ==========================================================================
284 /// `=`
285 EQ,
286 /// `+=`
287 PLUS_EQ,
288 /// `-=`
289 MINUS_EQ,
290 /// `*=`
291 STAR_EQ,
292 /// `/=`
293 SLASH_EQ,
294 /// `%=`
295 PERCENT_EQ,
296 /// `**=`
297 STAR2_EQ,
298 /// `&&=`
299 AMP2_EQ,
300 /// `||=`
301 PIPE2_EQ,
302 /// `&=`
303 AMP_EQ,
304 /// `|=`
305 PIPE_EQ,
306 /// `^=`
307 CARET_EQ,
308 /// `<<=`
309 SHL_EQ,
310 /// `>>=`
311 SHR_EQ,
312
313 // ==========================================================================
314 // Operators - Arithmetic
315 // ==========================================================================
316 /// `+`
317 PLUS,
318 /// `-`
319 MINUS,
320 /// `*`
321 STAR,
322 /// `/`
323 SLASH,
324 /// `%`
325 PERCENT,
326 /// `**`
327 STAR2,
328
329 // ==========================================================================
330 // Operators - Comparison
331 // ==========================================================================
332 /// `==`
333 EQ2,
334 /// `!=`
335 BANG_EQ,
336 /// `<`
337 LT,
338 /// `<=`
339 LT_EQ,
340 /// `>`
341 GT,
342 /// `>=`
343 GT_EQ,
344
345 // ==========================================================================
346 // Operators - Logical
347 // ==========================================================================
348 /// `&&`
349 AMP2,
350 /// `||`
351 PIPE2,
352 /// `!`
353 BANG,
354
355 // ==========================================================================
356 // Operators - Bitwise
357 // ==========================================================================
358 /// `&`
359 AMP,
360 /// `|`
361 PIPE,
362 /// `^`
363 CARET,
364 /// `<<`
365 SHL,
366 /// `>>`
367 SHR,
368
369 // ==========================================================================
370 // Composite Nodes - Top Level
371 // ==========================================================================
372 /// Root node of the syntax tree.
373 ROOT,
374 /// Program declaration: `program foo.aleo { ... }`
375 PROGRAM_DECL,
376 /// Import statement: `import foo.aleo;`
377 IMPORT,
378 /// Main file contents.
379 MAIN_CONTENTS,
380 /// Module file contents.
381 MODULE_CONTENTS,
382
383 // ==========================================================================
384 // Composite Nodes - Declarations
385 // ==========================================================================
386 /// Function definition.
387 FUNCTION_DEF,
388 /// Final function definition: `final fn ...`
389 FINAL_FN_DEF,
390 /// View function definition: `view fn ...`. Read-only V15 entry point.
391 VIEW_FN_DEF,
392 /// Constructor definition.
393 CONSTRUCTOR_DEF,
394 /// Struct definition.
395 STRUCT_DEF,
396 /// Record definition.
397 RECORD_DEF,
398 /// Struct member declaration.
399 STRUCT_MEMBER,
400 /// Public struct member: `public name: TypeKind`
401 STRUCT_MEMBER_PUBLIC,
402 /// Private struct member: `private name: TypeKind`
403 STRUCT_MEMBER_PRIVATE,
404 /// Constant struct member: `constant name: TypeKind`
405 STRUCT_MEMBER_CONSTANT,
406 /// Mapping definition.
407 MAPPING_DEF,
408 /// Storage definition.
409 STORAGE_DEF,
410 /// Global constant definition.
411 GLOBAL_CONST,
412 /// Interface declaration.
413 INTERFACE_DEF,
414 /// Function prototype (in interface).
415 FN_PROTOTYPE_DEF,
416 /// Record prototype (in interface).
417 RECORD_PROTOTYPE_DEF,
418
419 // ==========================================================================
420 // Composite Nodes - Function Parts
421 // ==========================================================================
422 /// Annotation: `@foo`
423 ANNOTATION,
424 /// Annotation key-value pair: `key = "value"`
425 ANNOTATION_PAIR,
426 /// Parameter in a function signature.
427 PARAM,
428 /// Public parameter: `public name: TypeKind`
429 PARAM_PUBLIC,
430 /// Private parameter: `private name: TypeKind`
431 PARAM_PRIVATE,
432 /// Constant parameter: `constant name: TypeKind`
433 PARAM_CONSTANT,
434 /// Parameter list: `(a: u32, b: u32)`
435 PARAM_LIST,
436 /// Function output type.
437 RETURN_TYPE,
438 /// Const generic parameter.
439 CONST_PARAM,
440 /// Const generic parameter list.
441 CONST_PARAM_LIST,
442 /// Const generic argument list.
443 CONST_ARG_LIST,
444 /// Visibility-annotated return type for `_dynamic_call` (e.g. `public u64`).
445 DYNAMIC_CALL_RETURN_TYPE,
446 /// Array length expression wrapper in `[T; N]`.
447 ARRAY_LENGTH,
448
449 // ==========================================================================
450 // Composite Nodes - Statements
451 // ==========================================================================
452 /// Let statement: `let x = ...;`
453 LET_STMT,
454 /// Const statement: `const x = ...;`
455 CONST_STMT,
456 /// Return statement: `return ...;`
457 RETURN_STMT,
458 /// Expression statement: `foo();`
459 EXPR_STMT,
460 /// Assignment statement: `x = ...;`
461 ASSIGN_STMT,
462 /// Compound assignment statement: `x += ...;`, `x -= ...;`, etc.
463 COMPOUND_ASSIGN_STMT,
464 /// If statement: `if ... { } else { }`
465 IF_STMT,
466 /// For loop: `for i in 0..10 { }`
467 FOR_STMT,
468 /// Inclusive for loop: `for i in 0..=10 { }`
469 FOR_INCLUSIVE_STMT,
470 /// Block: `{ ... }`
471 BLOCK,
472 /// Assert statement: `assert(...);`
473 ASSERT_STMT,
474 /// Assert equals statement: `assert_eq(...);`
475 ASSERT_EQ_STMT,
476 /// Assert not equals statement: `assert_neq(...);`
477 ASSERT_NEQ_STMT,
478
479 // ==========================================================================
480 // Composite Nodes - Patterns
481 // ==========================================================================
482 /// Identifier pattern: `x`
483 IDENT_PATTERN,
484 /// Tuple pattern: `(a, b, c)`
485 TUPLE_PATTERN,
486 /// Wildcard pattern: `_`
487 WILDCARD_PATTERN,
488
489 // ==========================================================================
490 // Composite Nodes - Expressions
491 // ==========================================================================
492 /// Binary expression: `a + b`
493 BINARY_EXPR,
494 /// Unary expression: `!a`, `-a`
495 UNARY_EXPR,
496 /// Function call: `foo(a, b)`
497 CALL_EXPR,
498 /// Method call: `a.foo(b)`
499 METHOD_CALL_EXPR,
500 /// Member access: `a.b`
501 FIELD_EXPR,
502 /// Array/tuple index: `a[0]`
503 INDEX_EXPR,
504 /// Cast expression: `a as u32`
505 CAST_EXPR,
506 /// Ternary expression: `a ? b : c`
507 TERNARY_EXPR,
508 /// Array literal: `[1, 2, 3]`
509 ARRAY_EXPR,
510 /// Tuple literal: `(1, 2, 3)`
511 TUPLE_EXPR,
512 /// Struct literal: `Foo { a: 1, b: 2 }`
513 STRUCT_EXPR,
514 /// Struct locator literal: `program.aleo::TypeKind { a: 1, b: 2 }`
515 STRUCT_LOCATOR_EXPR,
516 /// Struct field initializer: `a: 1`
517 STRUCT_FIELD_INIT,
518 /// Struct field shorthand: `{ x }` (equivalent to `{ x: x }`)
519 STRUCT_FIELD_SHORTHAND,
520 /// Struct update base: `..other` in `Foo { a: 1, ..other }`
521 STRUCT_BASE_UPDATE,
522 /// Path expression: `foo::bar`
523 PATH_EXPR,
524 /// Path locator expression: `program.aleo::function`
525 PATH_LOCATOR_EXPR,
526 /// Program reference expression: `name.aleo` (without `::TypeKind` suffix).
527 PROGRAM_REF_EXPR,
528 /// Self expression: `self`
529 SELF_EXPR,
530 /// `Self` expression.
531 SELF_UPPER_EXPR,
532 /// Block keyword expression: `block`
533 BLOCK_KW_EXPR,
534 /// Network keyword expression: `network`
535 NETWORK_KW_EXPR,
536 /// Parenthesized expression: `(a + b)`
537 PAREN_EXPR,
538 /// Field literal: `42field`
539 LITERAL_FIELD,
540 /// Group literal: `42group`
541 LITERAL_GROUP,
542 /// Scalar literal: `42scalar`
543 LITERAL_SCALAR,
544 /// Integer literal: `42u32`, `42` (unsuffixed)
545 LITERAL_INT,
546 /// String literal: `"hello"`
547 LITERAL_STRING,
548 /// Address literal: `aleo1...`
549 LITERAL_ADDRESS,
550 /// Boolean literal: `true`, `false`
551 LITERAL_BOOL,
552 /// None literal: `none`
553 LITERAL_NONE,
554 /// Identifier literal: `'foo'`
555 LITERAL_IDENT,
556 /// Repeat expression: `[0u8; 32]`
557 REPEAT_EXPR,
558 /// Async expression: `async foo()`
559 FINAL_EXPR,
560 /// Tuple access: `a.0`
561 TUPLE_ACCESS_EXPR,
562 /// Dynamic interface access. Covers three surface forms:
563 /// - function call: `Interface @ (target) :: func(args)`
564 /// - storage/vector op: `Interface @ (target) :: member.op(args)`
565 /// - singleton bare read: `Interface @ (target) :: storage`
566 DYNAMIC_OP_EXPR,
567
568 // ==========================================================================
569 // Composite Nodes - Types
570 // ==========================================================================
571 /// Named/path type: `Foo`, `foo::Bar`
572 TYPE_PATH,
573 /// Primitive type: `u32`, `bool`, `field`, etc.
574 TYPE_PRIMITIVE,
575 /// Locator type: `program.aleo::TypeKind`
576 TYPE_LOCATOR,
577 /// Array type: `[u32; 10]`
578 TYPE_ARRAY,
579 /// Vector type: `[u32]`
580 TYPE_VECTOR,
581 /// Tuple type: `(u32, u32)`
582 TYPE_TUPLE,
583 /// Optional type: `u32?` (Future feature)
584 TYPE_OPTIONAL,
585 /// Final type: `Final<Foo>`
586 TYPE_FINAL,
587 /// Mapping type in storage.
588 TYPE_MAPPING,
589 /// Dynamic record type: `dyn record`
590 TYPE_DYN_RECORD,
591 /// Parent list: `Foo + Bar`
592 PARENT_LIST,
593
594 // Sentinel for bounds checking (must be last)
595 #[doc(hidden)]
596 __LAST,
597}
598
599impl SyntaxKind {
600 /// Check if this is a trivia token (whitespace or comment).
601 pub fn is_trivia(self) -> bool {
602 matches!(self, WHITESPACE | LINEBREAK | COMMENT_LINE | COMMENT_BLOCK)
603 }
604
605 /// Check if this is a keyword.
606 pub fn is_keyword(self) -> bool {
607 matches!(
608 self,
609 KW_TRUE
610 | KW_FALSE
611 | KW_NONE
612 | KW_ADDRESS
613 | KW_BOOL
614 | KW_FIELD
615 | KW_GROUP
616 | KW_SCALAR
617 | KW_SIGNATURE
618 | KW_STRING
619 | KW_RECORD
620 | KW_DYN
621 | KW_IDENTIFIER
622 | KW_FINAL_UPPER
623 | KW_I8
624 | KW_I16
625 | KW_I32
626 | KW_I64
627 | KW_I128
628 | KW_U8
629 | KW_U16
630 | KW_U32
631 | KW_U64
632 | KW_U128
633 | KW_IF
634 | KW_ELSE
635 | KW_FOR
636 | KW_IN
637 | KW_RETURN
638 | KW_LET
639 | KW_CONST
640 | KW_CONSTANT
641 | KW_FN
642 | KW_FINAL
643 | KW_VIEW
644 | KW_FN_UPPER
645 | KW_STRUCT
646 | KW_CONSTRUCTOR
647 | KW_INTERFACE
648 | KW_PROGRAM
649 | KW_IMPORT
650 | KW_MAPPING
651 | KW_STORAGE
652 | KW_NETWORK
653 | KW_ALEO
654 | KW_SCRIPT
655 | KW_BLOCK
656 | KW_PUBLIC
657 | KW_PRIVATE
658 | KW_EXPORT
659 | KW_AS
660 | KW_SELF
661 | KW_SELF_UPPER
662 | KW_ASSERT
663 | KW_ASSERT_EQ
664 | KW_ASSERT_NEQ
665 )
666 }
667
668 /// Check if this is a type keyword.
669 pub fn is_type_keyword(self) -> bool {
670 matches!(
671 self,
672 KW_ADDRESS
673 | KW_BOOL
674 | KW_FIELD
675 | KW_GROUP
676 | KW_SCALAR
677 | KW_SIGNATURE
678 | KW_STRING
679 | KW_DYN
680 | KW_IDENTIFIER
681 | KW_FINAL_UPPER
682 | KW_I8
683 | KW_I16
684 | KW_I32
685 | KW_I64
686 | KW_I128
687 | KW_U8
688 | KW_U16
689 | KW_U32
690 | KW_U64
691 | KW_U128
692 )
693 }
694
695 /// Check if this is a literal token.
696 pub fn is_literal(self) -> bool {
697 matches!(self, INTEGER | STRING | ADDRESS_LIT | IDENT_LIT | KW_TRUE | KW_FALSE | KW_NONE)
698 }
699
700 /// Check if this is a literal node kind.
701 pub fn is_literal_node(self) -> bool {
702 matches!(
703 self,
704 LITERAL_FIELD
705 | LITERAL_GROUP
706 | LITERAL_SCALAR
707 | LITERAL_INT
708 | LITERAL_STRING
709 | LITERAL_ADDRESS
710 | LITERAL_BOOL
711 | LITERAL_NONE
712 | LITERAL_IDENT
713 )
714 }
715
716 /// Check if this is a type node kind.
717 pub fn is_type(self) -> bool {
718 matches!(
719 self,
720 TYPE_PRIMITIVE
721 | TYPE_LOCATOR
722 | TYPE_PATH
723 | TYPE_ARRAY
724 | TYPE_VECTOR
725 | TYPE_TUPLE
726 | TYPE_OPTIONAL
727 | TYPE_FINAL
728 | TYPE_MAPPING
729 | TYPE_DYN_RECORD
730 )
731 }
732
733 /// Check if this is an expression node kind.
734 pub fn is_expression(self) -> bool {
735 self.is_literal_node()
736 || matches!(
737 self,
738 BINARY_EXPR
739 | UNARY_EXPR
740 | CALL_EXPR
741 | METHOD_CALL_EXPR
742 | FIELD_EXPR
743 | TUPLE_ACCESS_EXPR
744 | INDEX_EXPR
745 | CAST_EXPR
746 | TERNARY_EXPR
747 | ARRAY_EXPR
748 | REPEAT_EXPR
749 | TUPLE_EXPR
750 | STRUCT_EXPR
751 | STRUCT_LOCATOR_EXPR
752 | PATH_EXPR
753 | PATH_LOCATOR_EXPR
754 | PROGRAM_REF_EXPR
755 | SELF_EXPR
756 | SELF_UPPER_EXPR
757 | BLOCK_KW_EXPR
758 | NETWORK_KW_EXPR
759 | PAREN_EXPR
760 | FINAL_EXPR
761 | DYNAMIC_OP_EXPR
762 )
763 }
764
765 /// Check if this is a statement node kind.
766 pub fn is_statement(self) -> bool {
767 matches!(
768 self,
769 LET_STMT
770 | CONST_STMT
771 | RETURN_STMT
772 | EXPR_STMT
773 | ASSIGN_STMT
774 | COMPOUND_ASSIGN_STMT
775 | IF_STMT
776 | FOR_STMT
777 | FOR_INCLUSIVE_STMT
778 | BLOCK
779 | ASSERT_STMT
780 | ASSERT_EQ_STMT
781 | ASSERT_NEQ_STMT
782 )
783 }
784
785 /// Check if this is a punctuation token.
786 pub fn is_punctuation(self) -> bool {
787 matches!(
788 self,
789 L_PAREN
790 | R_PAREN
791 | L_BRACKET
792 | R_BRACKET
793 | L_BRACE
794 | R_BRACE
795 | COMMA
796 | DOT
797 | DOT_DOT
798 | DOT_DOT_EQ
799 | SEMICOLON
800 | COLON
801 | COLON_COLON
802 | QUESTION
803 | ARROW
804 | FAT_ARROW
805 | UNDERSCORE
806 | AT
807 )
808 }
809
810 /// Check if this is an operator token.
811 pub fn is_operator(self) -> bool {
812 matches!(
813 self,
814 EQ | PLUS_EQ
815 | MINUS_EQ
816 | STAR_EQ
817 | SLASH_EQ
818 | PERCENT_EQ
819 | STAR2_EQ
820 | AMP2_EQ
821 | PIPE2_EQ
822 | AMP_EQ
823 | PIPE_EQ
824 | CARET_EQ
825 | SHL_EQ
826 | SHR_EQ
827 | PLUS
828 | MINUS
829 | STAR
830 | SLASH
831 | PERCENT
832 | STAR2
833 | EQ2
834 | BANG_EQ
835 | LT
836 | LT_EQ
837 | GT
838 | GT_EQ
839 | AMP2
840 | PIPE2
841 | BANG
842 | AMP
843 | PIPE
844 | CARET
845 | SHL
846 | SHR
847 )
848 }
849
850 /// Returns a user-friendly name for this token kind, suitable for error messages.
851 pub fn user_friendly_name(self) -> &'static str {
852 match self {
853 // Special
854 ERROR => "an error",
855 EOF => "end of file",
856
857 // Trivia
858 WHITESPACE | LINEBREAK => "whitespace",
859 COMMENT_LINE | COMMENT_BLOCK => "a comment",
860
861 // Literals
862 INTEGER => "an integer literal",
863 STRING => "a static string",
864 ADDRESS_LIT => "an address literal",
865 IDENT_LIT => "an identifier literal",
866
867 // Identifiers
868 IDENT => "an identifier",
869
870 // Boolean literals
871 KW_TRUE => "'true'",
872 KW_FALSE => "'false'",
873 KW_NONE => "'none'",
874
875 // Type keywords
876 KW_ADDRESS => "'address'",
877 KW_BOOL => "'bool'",
878 KW_FIELD => "'field'",
879 KW_GROUP => "'group'",
880 KW_SCALAR => "'scalar'",
881 KW_SIGNATURE => "'signature'",
882 KW_STRING => "'string'",
883 KW_RECORD => "'record'",
884 KW_DYN => "'dyn'",
885 KW_IDENTIFIER => "'identifier'",
886 KW_FINAL_UPPER => "'Final'",
887 KW_I8 => "'i8'",
888 KW_I16 => "'i16'",
889 KW_I32 => "'i32'",
890 KW_I64 => "'i64'",
891 KW_I128 => "'i128'",
892 KW_U8 => "'u8'",
893 KW_U16 => "'u16'",
894 KW_U32 => "'u32'",
895 KW_U64 => "'u64'",
896 KW_U128 => "'u128'",
897
898 // Control flow keywords
899 KW_IF => "'if'",
900 KW_ELSE => "'else'",
901 KW_FOR => "'for'",
902 KW_IN => "'in'",
903 KW_RETURN => "'return'",
904
905 // Declaration keywords
906 KW_LET => "'let'",
907 KW_CONST => "'const'",
908 KW_CONSTANT => "'constant'",
909 KW_FINAL => "'final'",
910 KW_VIEW => "'view'",
911 KW_FN => "'fn'",
912 KW_FN_UPPER => "'Fn'",
913 KW_STRUCT => "'struct'",
914 KW_CONSTRUCTOR => "'constructor'",
915 KW_INTERFACE => "'interface'",
916
917 // Program structure keywords
918 KW_PROGRAM => "'program'",
919 KW_IMPORT => "'import'",
920 KW_MAPPING => "'mapping'",
921 KW_STORAGE => "'storage'",
922 KW_NETWORK => "'network'",
923 KW_ALEO => "'aleo'",
924 KW_SCRIPT => "'script'",
925 KW_BLOCK => "'block'",
926
927 // Visibility and assertion keywords
928 KW_PUBLIC => "'public'",
929 KW_PRIVATE => "'private'",
930 KW_EXPORT => "'export'",
931 KW_AS => "'as'",
932 KW_SELF => "'self'",
933 KW_SELF_UPPER => "'Self'",
934 KW_ASSERT => "'assert'",
935 KW_ASSERT_EQ => "'assert_eq'",
936 KW_ASSERT_NEQ => "'assert_neq'",
937
938 // Delimiters
939 L_PAREN => "'('",
940 R_PAREN => "')'",
941 L_BRACKET => "'['",
942 R_BRACKET => "']'",
943 L_BRACE => "'{'",
944 R_BRACE => "'}'",
945
946 // Separators
947 COMMA => "','",
948 DOT => "'.'",
949 DOT_DOT => "'..'",
950 DOT_DOT_EQ => "'..='",
951 SEMICOLON => "';'",
952 COLON => "':'",
953 COLON_COLON => "'::'",
954 QUESTION => "'?'",
955 ARROW => "'->'",
956 FAT_ARROW => "'=>'",
957 UNDERSCORE => "'_'",
958 AT => "'@'",
959
960 // Assignment operators
961 EQ => "'='",
962 PLUS_EQ => "'+='",
963 MINUS_EQ => "'-='",
964 STAR_EQ => "'*='",
965 SLASH_EQ => "'/='",
966 PERCENT_EQ => "'%='",
967 STAR2_EQ => "'**='",
968 AMP2_EQ => "'&&='",
969 PIPE2_EQ => "'||='",
970 AMP_EQ => "'&='",
971 PIPE_EQ => "'|='",
972 CARET_EQ => "'^='",
973 SHL_EQ => "'<<='",
974 SHR_EQ => "'>>='",
975
976 // Arithmetic operators
977 PLUS => "'+'",
978 MINUS => "'-'",
979 STAR => "'*'",
980 SLASH => "'/'",
981 PERCENT => "'%'",
982 STAR2 => "'**'",
983
984 // Comparison operators
985 EQ2 => "'=='",
986 BANG_EQ => "'!='",
987 LT => "'<'",
988 LT_EQ => "'<='",
989 GT => "'>'",
990 GT_EQ => "'>='",
991
992 // Logical operators
993 AMP2 => "'&&'",
994 PIPE2 => "'||'",
995 BANG => "'!'",
996
997 // Bitwise operators
998 AMP => "'&'",
999 PIPE => "'|'",
1000 CARET => "'^'",
1001 SHL => "'<<'",
1002 SHR => "'>>'",
1003
1004 // Composite nodes - these shouldn't appear in "expected" messages typically
1005 _ => "a token",
1006 }
1007 }
1008}
1009
1010impl From<SyntaxKind> for rowan::SyntaxKind {
1011 fn from(kind: SyntaxKind) -> Self {
1012 Self(kind as u16)
1013 }
1014}
1015
1016/// Convert a raw rowan SyntaxKind to our SyntaxKind.
1017///
1018/// # Panics
1019/// Panics if the raw value is out of range.
1020pub fn syntax_kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
1021 SYNTAX_KIND_TABLE.get(raw.0 as usize).copied().unwrap_or_else(|| panic!("invalid SyntaxKind: {}", raw.0))
1022}
1023
1024#[cfg(test)]
1025mod tests {
1026 use super::*;
1027
1028 #[test]
1029 fn syntax_kind_table_is_correct() {
1030 // Verify that the table matches the enum discriminants
1031 for (i, &kind) in SYNTAX_KIND_TABLE.iter().enumerate() {
1032 assert_eq!(
1033 kind as u16, i as u16,
1034 "SYNTAX_KIND_TABLE[{i}] = {:?} has discriminant {}, expected {i}",
1035 kind, kind as u16
1036 );
1037 }
1038 }
1039
1040 #[test]
1041 fn syntax_kind_roundtrip() {
1042 // Test that we can convert to rowan::SyntaxKind and back
1043 for &kind in SYNTAX_KIND_TABLE.iter() {
1044 if kind == __LAST {
1045 continue;
1046 }
1047 let raw: rowan::SyntaxKind = kind.into();
1048 let back = syntax_kind_from_raw(raw);
1049 assert_eq!(kind, back);
1050 }
1051 }
1052
1053 #[test]
1054 fn is_trivia() {
1055 assert!(WHITESPACE.is_trivia());
1056 assert!(LINEBREAK.is_trivia());
1057 assert!(COMMENT_LINE.is_trivia());
1058 assert!(COMMENT_BLOCK.is_trivia());
1059 assert!(!IDENT.is_trivia());
1060 assert!(!KW_LET.is_trivia());
1061 }
1062
1063 #[test]
1064 fn is_keyword() {
1065 assert!(KW_LET.is_keyword());
1066 assert!(KW_FN.is_keyword());
1067 assert!(KW_TRUE.is_keyword());
1068 assert!(!IDENT.is_keyword());
1069 assert!(!PLUS.is_keyword());
1070 }
1071
1072 #[test]
1073 fn is_literal() {
1074 assert!(INTEGER.is_literal());
1075 assert!(STRING.is_literal());
1076 assert!(ADDRESS_LIT.is_literal());
1077 assert!(KW_TRUE.is_literal());
1078 assert!(KW_FALSE.is_literal());
1079 assert!(KW_NONE.is_literal());
1080 assert!(!IDENT.is_literal());
1081 }
1082}