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 /// Path expression: `foo::bar`
517 PATH_EXPR,
518 /// Path locator expression: `program.aleo::function`
519 PATH_LOCATOR_EXPR,
520 /// Program reference expression: `name.aleo` (without `::Type` suffix).
521 PROGRAM_REF_EXPR,
522 /// Self expression: `self`
523 SELF_EXPR,
524 /// Block keyword expression: `block`
525 BLOCK_KW_EXPR,
526 /// Network keyword expression: `network`
527 NETWORK_KW_EXPR,
528 /// Parenthesized expression: `(a + b)`
529 PAREN_EXPR,
530 /// Field literal: `42field`
531 LITERAL_FIELD,
532 /// Group literal: `42group`
533 LITERAL_GROUP,
534 /// Scalar literal: `42scalar`
535 LITERAL_SCALAR,
536 /// Integer literal: `42u32`, `42` (unsuffixed)
537 LITERAL_INT,
538 /// String literal: `"hello"`
539 LITERAL_STRING,
540 /// Address literal: `aleo1...`
541 LITERAL_ADDRESS,
542 /// Boolean literal: `true`, `false`
543 LITERAL_BOOL,
544 /// None literal: `none`
545 LITERAL_NONE,
546 /// Identifier literal: `'foo'`
547 LITERAL_IDENT,
548 /// Repeat expression: `[0u8; 32]`
549 REPEAT_EXPR,
550 /// Async expression: `async foo()`
551 FINAL_EXPR,
552 /// Tuple access: `a.0`
553 TUPLE_ACCESS_EXPR,
554 /// Dynamic interface access. Covers three surface forms:
555 /// - function call: `Interface @ (target) :: func(args)`
556 /// - storage/vector op: `Interface @ (target) :: member.op(args)`
557 /// - singleton bare read: `Interface @ (target) :: storage`
558 DYNAMIC_OP_EXPR,
559
560 // ==========================================================================
561 // Composite Nodes - Types
562 // ==========================================================================
563 /// Named/path type: `Foo`, `foo::Bar`
564 TYPE_PATH,
565 /// Primitive type: `u32`, `bool`, `field`, etc.
566 TYPE_PRIMITIVE,
567 /// Locator type: `program.aleo::Type`
568 TYPE_LOCATOR,
569 /// Array type: `[u32; 10]`
570 TYPE_ARRAY,
571 /// Vector type: `[u32]`
572 TYPE_VECTOR,
573 /// Tuple type: `(u32, u32)`
574 TYPE_TUPLE,
575 /// Optional type: `u32?` (Future feature)
576 TYPE_OPTIONAL,
577 /// Final type: `Final<Foo>`
578 TYPE_FINAL,
579 /// Mapping type in storage.
580 TYPE_MAPPING,
581 /// Dynamic record type: `dyn record`
582 TYPE_DYN_RECORD,
583 /// Parent list: `Foo + Bar`
584 PARENT_LIST,
585
586 // Sentinel for bounds checking (must be last)
587 #[doc(hidden)]
588 __LAST,
589}
590
591impl SyntaxKind {
592 /// Check if this is a trivia token (whitespace or comment).
593 pub fn is_trivia(self) -> bool {
594 matches!(self, WHITESPACE | LINEBREAK | COMMENT_LINE | COMMENT_BLOCK)
595 }
596
597 /// Check if this is a keyword.
598 pub fn is_keyword(self) -> bool {
599 matches!(
600 self,
601 KW_TRUE
602 | KW_FALSE
603 | KW_NONE
604 | KW_ADDRESS
605 | KW_BOOL
606 | KW_FIELD
607 | KW_GROUP
608 | KW_SCALAR
609 | KW_SIGNATURE
610 | KW_STRING
611 | KW_RECORD
612 | KW_DYN
613 | KW_IDENTIFIER
614 | KW_FINAL_UPPER
615 | KW_I8
616 | KW_I16
617 | KW_I32
618 | KW_I64
619 | KW_I128
620 | KW_U8
621 | KW_U16
622 | KW_U32
623 | KW_U64
624 | KW_U128
625 | KW_IF
626 | KW_ELSE
627 | KW_FOR
628 | KW_IN
629 | KW_RETURN
630 | KW_LET
631 | KW_CONST
632 | KW_CONSTANT
633 | KW_FN
634 | KW_FINAL
635 | KW_VIEW
636 | KW_FN_UPPER
637 | KW_STRUCT
638 | KW_CONSTRUCTOR
639 | KW_INTERFACE
640 | KW_PROGRAM
641 | KW_IMPORT
642 | KW_MAPPING
643 | KW_STORAGE
644 | KW_NETWORK
645 | KW_ALEO
646 | KW_SCRIPT
647 | KW_BLOCK
648 | KW_PUBLIC
649 | KW_PRIVATE
650 | KW_AS
651 | KW_SELF
652 | KW_ASSERT
653 | KW_ASSERT_EQ
654 | KW_ASSERT_NEQ
655 )
656 }
657
658 /// Check if this is a type keyword.
659 pub fn is_type_keyword(self) -> bool {
660 matches!(
661 self,
662 KW_ADDRESS
663 | KW_BOOL
664 | KW_FIELD
665 | KW_GROUP
666 | KW_SCALAR
667 | KW_SIGNATURE
668 | KW_STRING
669 | KW_DYN
670 | KW_IDENTIFIER
671 | KW_FINAL_UPPER
672 | KW_I8
673 | KW_I16
674 | KW_I32
675 | KW_I64
676 | KW_I128
677 | KW_U8
678 | KW_U16
679 | KW_U32
680 | KW_U64
681 | KW_U128
682 )
683 }
684
685 /// Check if this is a literal token.
686 pub fn is_literal(self) -> bool {
687 matches!(self, INTEGER | STRING | ADDRESS_LIT | IDENT_LIT | KW_TRUE | KW_FALSE | KW_NONE)
688 }
689
690 /// Check if this is a literal node kind.
691 pub fn is_literal_node(self) -> bool {
692 matches!(
693 self,
694 LITERAL_FIELD
695 | LITERAL_GROUP
696 | LITERAL_SCALAR
697 | LITERAL_INT
698 | LITERAL_STRING
699 | LITERAL_ADDRESS
700 | LITERAL_BOOL
701 | LITERAL_NONE
702 | LITERAL_IDENT
703 )
704 }
705
706 /// Check if this is a type node kind.
707 pub fn is_type(self) -> bool {
708 matches!(
709 self,
710 TYPE_PRIMITIVE
711 | TYPE_LOCATOR
712 | TYPE_PATH
713 | TYPE_ARRAY
714 | TYPE_VECTOR
715 | TYPE_TUPLE
716 | TYPE_OPTIONAL
717 | TYPE_FINAL
718 | TYPE_MAPPING
719 | TYPE_DYN_RECORD
720 )
721 }
722
723 /// Check if this is an expression node kind.
724 pub fn is_expression(self) -> bool {
725 self.is_literal_node()
726 || matches!(
727 self,
728 BINARY_EXPR
729 | UNARY_EXPR
730 | CALL_EXPR
731 | METHOD_CALL_EXPR
732 | FIELD_EXPR
733 | TUPLE_ACCESS_EXPR
734 | INDEX_EXPR
735 | CAST_EXPR
736 | TERNARY_EXPR
737 | ARRAY_EXPR
738 | REPEAT_EXPR
739 | TUPLE_EXPR
740 | STRUCT_EXPR
741 | STRUCT_LOCATOR_EXPR
742 | PATH_EXPR
743 | PATH_LOCATOR_EXPR
744 | PROGRAM_REF_EXPR
745 | SELF_EXPR
746 | BLOCK_KW_EXPR
747 | NETWORK_KW_EXPR
748 | PAREN_EXPR
749 | FINAL_EXPR
750 | DYNAMIC_OP_EXPR
751 )
752 }
753
754 /// Check if this is a statement node kind.
755 pub fn is_statement(self) -> bool {
756 matches!(
757 self,
758 LET_STMT
759 | CONST_STMT
760 | RETURN_STMT
761 | EXPR_STMT
762 | ASSIGN_STMT
763 | COMPOUND_ASSIGN_STMT
764 | IF_STMT
765 | FOR_STMT
766 | FOR_INCLUSIVE_STMT
767 | BLOCK
768 | ASSERT_STMT
769 | ASSERT_EQ_STMT
770 | ASSERT_NEQ_STMT
771 )
772 }
773
774 /// Check if this is a punctuation token.
775 pub fn is_punctuation(self) -> bool {
776 matches!(
777 self,
778 L_PAREN
779 | R_PAREN
780 | L_BRACKET
781 | R_BRACKET
782 | L_BRACE
783 | R_BRACE
784 | COMMA
785 | DOT
786 | DOT_DOT
787 | DOT_DOT_EQ
788 | SEMICOLON
789 | COLON
790 | COLON_COLON
791 | QUESTION
792 | ARROW
793 | FAT_ARROW
794 | UNDERSCORE
795 | AT
796 )
797 }
798
799 /// Check if this is an operator token.
800 pub fn is_operator(self) -> bool {
801 matches!(
802 self,
803 EQ | PLUS_EQ
804 | MINUS_EQ
805 | STAR_EQ
806 | SLASH_EQ
807 | PERCENT_EQ
808 | STAR2_EQ
809 | AMP2_EQ
810 | PIPE2_EQ
811 | AMP_EQ
812 | PIPE_EQ
813 | CARET_EQ
814 | SHL_EQ
815 | SHR_EQ
816 | PLUS
817 | MINUS
818 | STAR
819 | SLASH
820 | PERCENT
821 | STAR2
822 | EQ2
823 | BANG_EQ
824 | LT
825 | LT_EQ
826 | GT
827 | GT_EQ
828 | AMP2
829 | PIPE2
830 | BANG
831 | AMP
832 | PIPE
833 | CARET
834 | SHL
835 | SHR
836 )
837 }
838
839 /// Returns a user-friendly name for this token kind, suitable for error messages.
840 pub fn user_friendly_name(self) -> &'static str {
841 match self {
842 // Special
843 ERROR => "an error",
844 EOF => "end of file",
845
846 // Trivia
847 WHITESPACE | LINEBREAK => "whitespace",
848 COMMENT_LINE | COMMENT_BLOCK => "a comment",
849
850 // Literals
851 INTEGER => "an integer literal",
852 STRING => "a static string",
853 ADDRESS_LIT => "an address literal",
854 IDENT_LIT => "an identifier literal",
855
856 // Identifiers
857 IDENT => "an identifier",
858
859 // Boolean literals
860 KW_TRUE => "'true'",
861 KW_FALSE => "'false'",
862 KW_NONE => "'none'",
863
864 // Type keywords
865 KW_ADDRESS => "'address'",
866 KW_BOOL => "'bool'",
867 KW_FIELD => "'field'",
868 KW_GROUP => "'group'",
869 KW_SCALAR => "'scalar'",
870 KW_SIGNATURE => "'signature'",
871 KW_STRING => "'string'",
872 KW_RECORD => "'record'",
873 KW_DYN => "'dyn'",
874 KW_IDENTIFIER => "'identifier'",
875 KW_FINAL_UPPER => "'Final'",
876 KW_I8 => "'i8'",
877 KW_I16 => "'i16'",
878 KW_I32 => "'i32'",
879 KW_I64 => "'i64'",
880 KW_I128 => "'i128'",
881 KW_U8 => "'u8'",
882 KW_U16 => "'u16'",
883 KW_U32 => "'u32'",
884 KW_U64 => "'u64'",
885 KW_U128 => "'u128'",
886
887 // Control flow keywords
888 KW_IF => "'if'",
889 KW_ELSE => "'else'",
890 KW_FOR => "'for'",
891 KW_IN => "'in'",
892 KW_RETURN => "'return'",
893
894 // Declaration keywords
895 KW_LET => "'let'",
896 KW_CONST => "'const'",
897 KW_CONSTANT => "'constant'",
898 KW_FINAL => "'final'",
899 KW_VIEW => "'view'",
900 KW_FN => "'fn'",
901 KW_FN_UPPER => "'Fn'",
902 KW_STRUCT => "'struct'",
903 KW_CONSTRUCTOR => "'constructor'",
904 KW_INTERFACE => "'interface'",
905
906 // Program structure keywords
907 KW_PROGRAM => "'program'",
908 KW_IMPORT => "'import'",
909 KW_MAPPING => "'mapping'",
910 KW_STORAGE => "'storage'",
911 KW_NETWORK => "'network'",
912 KW_ALEO => "'aleo'",
913 KW_SCRIPT => "'script'",
914 KW_BLOCK => "'block'",
915
916 // Visibility and assertion keywords
917 KW_PUBLIC => "'public'",
918 KW_PRIVATE => "'private'",
919 KW_AS => "'as'",
920 KW_SELF => "'self'",
921 KW_ASSERT => "'assert'",
922 KW_ASSERT_EQ => "'assert_eq'",
923 KW_ASSERT_NEQ => "'assert_neq'",
924
925 // Delimiters
926 L_PAREN => "'('",
927 R_PAREN => "')'",
928 L_BRACKET => "'['",
929 R_BRACKET => "']'",
930 L_BRACE => "'{'",
931 R_BRACE => "'}'",
932
933 // Separators
934 COMMA => "','",
935 DOT => "'.'",
936 DOT_DOT => "'..'",
937 DOT_DOT_EQ => "'..='",
938 SEMICOLON => "';'",
939 COLON => "':'",
940 COLON_COLON => "'::'",
941 QUESTION => "'?'",
942 ARROW => "'->'",
943 FAT_ARROW => "'=>'",
944 UNDERSCORE => "'_'",
945 AT => "'@'",
946
947 // Assignment operators
948 EQ => "'='",
949 PLUS_EQ => "'+='",
950 MINUS_EQ => "'-='",
951 STAR_EQ => "'*='",
952 SLASH_EQ => "'/='",
953 PERCENT_EQ => "'%='",
954 STAR2_EQ => "'**='",
955 AMP2_EQ => "'&&='",
956 PIPE2_EQ => "'||='",
957 AMP_EQ => "'&='",
958 PIPE_EQ => "'|='",
959 CARET_EQ => "'^='",
960 SHL_EQ => "'<<='",
961 SHR_EQ => "'>>='",
962
963 // Arithmetic operators
964 PLUS => "'+'",
965 MINUS => "'-'",
966 STAR => "'*'",
967 SLASH => "'/'",
968 PERCENT => "'%'",
969 STAR2 => "'**'",
970
971 // Comparison operators
972 EQ2 => "'=='",
973 BANG_EQ => "'!='",
974 LT => "'<'",
975 LT_EQ => "'<='",
976 GT => "'>'",
977 GT_EQ => "'>='",
978
979 // Logical operators
980 AMP2 => "'&&'",
981 PIPE2 => "'||'",
982 BANG => "'!'",
983
984 // Bitwise operators
985 AMP => "'&'",
986 PIPE => "'|'",
987 CARET => "'^'",
988 SHL => "'<<'",
989 SHR => "'>>'",
990
991 // Composite nodes - these shouldn't appear in "expected" messages typically
992 _ => "a token",
993 }
994 }
995}
996
997impl From<SyntaxKind> for rowan::SyntaxKind {
998 fn from(kind: SyntaxKind) -> Self {
999 Self(kind as u16)
1000 }
1001}
1002
1003/// Convert a raw rowan SyntaxKind to our SyntaxKind.
1004///
1005/// # Panics
1006/// Panics if the raw value is out of range.
1007pub fn syntax_kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
1008 SYNTAX_KIND_TABLE.get(raw.0 as usize).copied().unwrap_or_else(|| panic!("invalid SyntaxKind: {}", raw.0))
1009}
1010
1011#[cfg(test)]
1012mod tests {
1013 use super::*;
1014
1015 #[test]
1016 fn syntax_kind_table_is_correct() {
1017 // Verify that the table matches the enum discriminants
1018 for (i, &kind) in SYNTAX_KIND_TABLE.iter().enumerate() {
1019 assert_eq!(
1020 kind as u16, i as u16,
1021 "SYNTAX_KIND_TABLE[{i}] = {:?} has discriminant {}, expected {i}",
1022 kind, kind as u16
1023 );
1024 }
1025 }
1026
1027 #[test]
1028 fn syntax_kind_roundtrip() {
1029 // Test that we can convert to rowan::SyntaxKind and back
1030 for &kind in SYNTAX_KIND_TABLE.iter() {
1031 if kind == __LAST {
1032 continue;
1033 }
1034 let raw: rowan::SyntaxKind = kind.into();
1035 let back = syntax_kind_from_raw(raw);
1036 assert_eq!(kind, back);
1037 }
1038 }
1039
1040 #[test]
1041 fn is_trivia() {
1042 assert!(WHITESPACE.is_trivia());
1043 assert!(LINEBREAK.is_trivia());
1044 assert!(COMMENT_LINE.is_trivia());
1045 assert!(COMMENT_BLOCK.is_trivia());
1046 assert!(!IDENT.is_trivia());
1047 assert!(!KW_LET.is_trivia());
1048 }
1049
1050 #[test]
1051 fn is_keyword() {
1052 assert!(KW_LET.is_keyword());
1053 assert!(KW_FN.is_keyword());
1054 assert!(KW_TRUE.is_keyword());
1055 assert!(!IDENT.is_keyword());
1056 assert!(!PLUS.is_keyword());
1057 }
1058
1059 #[test]
1060 fn is_literal() {
1061 assert!(INTEGER.is_literal());
1062 assert!(STRING.is_literal());
1063 assert!(ADDRESS_LIT.is_literal());
1064 assert!(KW_TRUE.is_literal());
1065 assert!(KW_FALSE.is_literal());
1066 assert!(KW_NONE.is_literal());
1067 assert!(!IDENT.is_literal());
1068 }
1069}