Vitte EBNF Memory Guide (EN)

Source of truth: src/vitte/grammar/vitte.ebnf.

Compiler-aligned corpus: src/vitte/compiler/**/*.vit, parser/frontend implementation, and validated project templates.

Checksum (SHA-256): 58f260a17d3e532b00b4d67ed97a72b1a0f2d5503135eb6f28d7d52cfec6f6a6

Prompt Contract

  1. Use this grammar as the canonical syntax reference.
  2. Cross-check ambiguous syntax against validated src/vitte/compiler/**/*.vit sources.
  3. If neither grammar nor validated compiler sources establish a construct, answer: unknown.
  4. Validate rule by rule with production names.
  5. Return compliant/non-compliant with evidence.
  6. Provide minimal valid/invalid examples per rule.
<<< =========================================================
   Vitte — Complete Core Grammar
   systems + application + kernel + compiler surface

   canonical sources:
     src/vitte/compiler/**/*.vit
     parser/frontend implementation
     validated project templates

   canonical blocks: { }
   canonical module paths: /
   canonical scoped names: ::
   canonical member access: .
   statement semicolons: optional where accepted
   form fields: whitespace/newline separated
   pick variants: comma separated
   low-level capable
   compiler-capable
   reduced aliases and duplicate productions
   ========================================================= >>>

program ::= WS? { toplevel WS? } EOF ;

<<< ================= Top-level ================= >>>

toplevel ::= inner_attribute
          | space_decl
          | use_decl
          | export_decl
          | const_decl
          | static_decl
          | global_decl
          | type_alias_decl
          | opaque_type_decl
          | extern_type_decl
          | form_decl
          | class_decl
          | union_decl
          | bits_decl
          | pick_decl
          | flags_decl
          | trait_decl
          | impl_decl
          | extern_block
          | proc_decl
          | intrinsic_decl
          | compiler_decl
          | query_decl
          | pass_decl
          | backend_decl
          | diagnostic_decl
          | macro_decl
          | comptime_decl
          | static_assert_decl
          | test_decl
          | bench_decl
          | entry_decl
          ;

<<< ================= Modules ================= >>>

space_decl ::= "space" WS1 module_path [ stmt_term ] ;

module_path ::= relative_module? module_parts ;
package_path ::= relative_module? module_parts ;

relative_module ::= "." { "." } ;

module_parts ::= ident { "/" ident } ;

<<< ================= Imports / Exports ================= >>>

use_decl ::= "use" WS1 package_path
             [ use_group | use_glob ]
             [ WS1 "as" WS1 ident ]
             [ stmt_term ]
             ;

use_glob ::= "." "*" ;

use_group ::= "." "{"
              WS?
              (
                  "*"
                | import_items [ WS? "," WS? "*" ]
              )?
              WS?
              "}"
              ;

import_items ::= import_item
                 { WS? "," WS? import_item }
                 [ WS? "," ]
                 ;

import_item ::= ident [ WS1 "as" WS1 ident ] ;

export_decl ::= "export" WS1
                (
                    "*"
                  | ident_list
                  | "{" WS? ident_list WS? "}"
                )
                [ stmt_term ]
                ;

ident_list ::= ident
               { WS? "," WS? ident }
               [ WS? "," ]
               ;

<<< ================= Constants / Globals ================= >>>

const_decl ::= { attr_prefix WS? }
               "const" WS1 ident
               [ WS? ":" WS? type_expr ]
               WS? "=" WS? expr
               [ stmt_term ]
               ;

static_decl ::= { attr_prefix WS? }
                "static" WS1 ident
                [ WS? ":" WS? type_expr ]
                WS? "=" WS? expr
                [ stmt_term ]
                ;

global_decl ::= { attr_prefix WS? }
                "global" WS1 ident
                [ WS? ":" WS? type_expr ]
                WS? "=" WS? expr
                [ stmt_term ]
                ;

<<< ================= Type Declarations ================= >>>

type_alias_decl ::= { attr_prefix WS? }
                    "type" WS1 ident
                    [ generic_params ]
                    WS? "=" WS? type_expr
                    [ stmt_term ]
                    ;

opaque_type_decl ::= { attr_prefix WS? }
                     "opaque" WS1 "type" WS1 ident
                     [ generic_params ]
                     [ WS? "=" WS? type_expr ]
                     [ stmt_term ]
                     ;

extern_type_decl ::= { attr_prefix WS? }
                     "extern" WS1 "type" WS1 ident
                     [ generic_params ]
                     [ stmt_term ]
                     ;

<<< ================= Forms / Classes / Unions ================= >>>

form_decl ::= { attr_prefix WS? }
              "form" WS1 ident
              [ generic_params ]
              [ WS? where_clause ]
              WS? "{"
              WS?
              form_items?
              WS?
              "}"
              ;

form_items ::= form_item
               { form_item_separator form_item }
               [ WS? "," ]
               ;

form_item_separator ::= WS1
                      | WS? "," WS?
                      ;

form_item ::= field_item
            | const_decl
            | type_alias_decl
            | proc_decl
            ;

class_decl ::= { attr_prefix WS? }
               "class" WS1 ident
               [ generic_params ]
               [ WS? where_clause ]
               WS? "{"
               WS?
               class_items?
               WS?
               "}"
               ;

class_items ::= class_item
                { form_item_separator class_item }
                [ WS? "," ]
                ;

class_item ::= field_item
             | const_decl
             | type_alias_decl
             | proc_decl
             ;

union_decl ::= { attr_prefix WS? }
               "union" WS1 ident
               [ generic_params ]
               [ WS? where_clause ]
               WS? "{"
               WS?
               field_items?
               WS?
               "}"
               ;

field_items ::= field_item
                { form_item_separator field_item }
                [ WS? "," ]
                ;

field_item ::= { attr_prefix WS? }
               [ visibility WS1 ]
               ident
               WS? ":" WS? type_expr
               [ WS? "=" WS? expr ]
               ;

<<< ================= Bits ================= >>>

bits_decl ::= { attr_prefix WS? }
              "bits" WS1 ident
              [ WS? ":" WS? type_expr ]
              WS? "{"
              WS?
              bitfield_list?
              WS?
              "}"
              ;

bitfield_list ::= bitfield_item
                  { WS? "," WS? bitfield_item }
                  [ WS? "," ]
                  ;

bitfield_item ::= ident
                  WS? ":" WS? expr
                  WS? ".." WS? expr
                  ;

<<< ================= Picks ================= >>>

pick_decl ::= { attr_prefix WS? }
              "pick" WS1 ident
              [ generic_params ]
              [ WS? ":" WS? type_expr ]
              [ WS? where_clause ]
              WS? "{"
              WS?
              case_list?
              WS?
              "}"
              ;

case_list ::= case_item
              { WS? "," WS? case_item }
              [ WS? "," ]
              ;

case_item ::= [ "case" WS1 ]
              ident
              [ "(" WS? case_payload? WS? ")" ]
              [ WS? "=" WS? expr ]
              ;

case_payload ::= case_field
                 { WS? "," WS? case_field }
                 [ WS? "," ]
                 ;

case_field ::= ident WS? ":" WS? type_expr
             | type_expr
             ;

<<< ================= Flags ================= >>>

flags_decl ::= { attr_prefix WS? }
               "flags" WS1 ident
               [ WS? ":" WS? type_expr ]
               WS? "{"
               WS?
               flag_list?
               WS?
               "}"
               ;

flag_list ::= flag_item
              { WS? "," WS? flag_item }
              [ WS? "," ]
              ;

flag_item ::= ident [ WS? "=" WS? expr ] ;

<<< ================= Traits ================= >>>

trait_decl ::= { attr_prefix WS? }
               [ "unsafe" WS1 ]
               "trait" WS1 ident
               [ generic_params ]
               [ WS? where_clause ]
               WS? "{"
               WS?
               trait_item*
               WS?
               "}"
               ;

trait_item ::= proc_signature
             | const_decl
             | associated_type_decl
             ;

associated_type_decl ::= "type" WS1 ident
                         [ WS? ":" WS? trait_bound ]
                         [ WS? "=" WS? type_expr ]
                         [ stmt_term ]
                         ;

<<< ================= Implementations ================= >>>

impl_decl ::= { attr_prefix WS? }
              [ "unsafe" WS1 ]
              "impl" WS1 impl_head
              [ WS? where_clause ]
              WS? "{"
              WS?
              impl_item*
              WS?
              "}"
              ;

impl_head ::= type_expr
            | type_expr WS1 "for" WS1 type_expr
            ;

impl_item ::= const_decl
            | type_alias_decl
            | associated_type_decl
            | proc_decl
            ;

<<< ================= Procedures ================= >>>

proc_signature ::= { attr_prefix WS? }
                   "proc" WS1 ident
                   [ generic_params ]
                   "(" WS? param_list? WS? ")"
                   [ WS? "->" WS? type_expr ]
                   WS? proc_suffix*
                   stmt_term
                   ;

proc_decl ::= { attr_prefix WS? }
              [ visibility WS1 ]
              proc_modifier*
              [ extern_clause WS1 ]
              "proc" WS1 proc_name
              [ generic_params ]
              "(" WS? param_list? WS? ")"
              [ WS? "->" WS? type_expr ]
              WS? proc_suffix*
              WS?
              (
                  block
                | stmt_term
              )
              ;

proc_name ::= ident
            | "operator" WS? operator_symbol
            ;

operator_symbol ::= "+"
                  | "-"
                  | "*"
                  | "/"
                  | "%"
                  | "=="
                  | "!="
                  | "<"
                  | "<="
                  | ">"
                  | ">="
                  | "[]"
                  | "()"
                  ;

proc_modifier ::= "async" WS1
                | "unsafe" WS1
                | "const" WS1
                | "inline" WS1
                | "noinline" WS1
                | "naked" WS1
                | "interrupt" WS1
                ;

proc_suffix ::= effects_clause
              | requires_clause
              | where_clause
              | "noexcept"
              ;

<<< ================= Extern ================= >>>

extern_block ::= { attr_prefix WS? }
                 "extern" WS1 extern_abi
                 WS? "{"
                 WS?
                 extern_item*
                 WS?
                 "}"
                 ;

extern_item ::= extern_proc_decl
              | extern_type_decl
              | const_decl
              ;

extern_proc_decl ::= { attr_prefix WS? }
                     "proc" WS1 ident
                     [ generic_params ]
                     "(" WS? param_list? WS? ")"
                     [ WS? "->" WS? type_expr ]
                     WS? proc_suffix*
                     stmt_term
                     ;

extern_clause ::= "extern" WS1 extern_abi ;

extern_abi ::= callconv
             | string_lit
             ;

callconv ::= "C"
           | "sysv64"
           | "win64"
           | "interrupt"
           | "naked"
           ;

<<< ================= Intrinsics ================= >>>

intrinsic_decl ::= { attr_prefix WS? }
                   "intrinsic" WS1 ident
                   [ generic_params ]
                   "(" WS? param_list? WS? ")"
                   [ WS? "->" WS? type_expr ]
                   stmt_term
                   ;

<<< ================= Macros / Comptime ================= >>>

macro_decl ::= { attr_prefix WS? }
               "macro" WS1 ident
               "(" WS? macro_param_list? WS? ")"
               WS? block
               ;

macro_param_list ::= macro_param
                     { WS? "," WS? macro_param }
                     [ WS? "," ]
                     ;

macro_param ::= ident [ WS? ":" WS? macro_kind ] ;

macro_kind ::= "expr"
             | "stmt"
             | "type"
             | "ident"
             | "block"
             | "item"
             ;

comptime_decl ::= "comptime" WS? block ;

static_assert_decl ::= "static_assert"
                       WS? "("
                       WS? expr
                       [ WS? "," WS? expr ]
                       WS? ")"
                       [ stmt_term ]
                       ;

test_decl ::= { attr_prefix WS? }
              "test" WS1 string_lit
              WS? block
              ;

bench_decl ::= { attr_prefix WS? }
               "bench" WS1 string_lit
               WS? block
               ;

<<< ================= Entry ================= >>>

entry_decl ::= { attr_prefix WS? }
               "entry" WS1 ident
               WS1 "at" WS1 module_path
               WS? block
               ;

<<< ================= Visibility ================= >>>

visibility ::= "pub"
             | "priv"
             | "pub" WS? "(" WS? visibility_scope WS? ")"
             ;

visibility_scope ::= "package"
                   | "module"
                   | "super"
                   ;

<<< ================= Generics ================= >>>

generic_params ::= "["
                   WS?
                   generic_param_list?
                   WS?
                   "]"
                   ;

generic_param_list ::= generic_param
                       { WS? "," WS? generic_param }
                       [ WS? "," ]
                       ;

generic_param ::= ident
                  [ WS? ":" WS? trait_bound ]
                  [ WS? "=" WS? type_expr ]

                | "const" WS1 ident
                  WS? ":" WS? type_expr

                | "comptime" WS1 ident
                  WS? ":" WS? type_expr
                ;

generic_args ::= "["
                 WS?
                 type_list?
                 WS?
                 "]"
                 ;

<<< ================= Constraints ================= >>>

where_clause ::= "where" WS1 where_bounds ;

where_bounds ::= where_bound
                 { WS? "," WS? where_bound }
                 [ WS? "," ]
                 ;

where_bound ::= type_expr WS? ":" WS? trait_bound
              | type_expr WS? "==" WS? type_expr
              | expr WS? rel_op WS? expr
              ;

trait_bound ::= type_expr
                { WS? "+" WS? type_expr }
                ;

<<< ================= Parameters ================= >>>

param_list ::= param
               { WS? "," WS? param }
               [ WS? "," ]
               ;

param ::= self_param
        | normal_param
        | variadic_param
        ;

self_param ::= [ "&" WS? ]
               [ "mut" WS1 ]
               "self"
               ;

normal_param ::= [ param_mode WS1 ]
                 pattern
                 [ WS? ":" WS? type_expr ]
                 [ WS? "=" WS? expr ]
                 ;

variadic_param ::= "..."
                 | ident WS? ":" WS? "..." type_expr
                 ;

param_mode ::= "mut"
             | "owned"
             | "borrow"
             | "move"
             ;

<<< ================= Effects / Capabilities ================= >>>

effects_clause ::= "effects"
                   WS? "("
                   WS? ident_list?
                   WS? ")"
                   ;

requires_clause ::= "requires"
                    WS? "("
                    WS? capability_list?
                    WS? ")"
                    ;

capability_list ::= capability
                    { WS? "," WS? capability }
                    [ WS? "," ]
                    ;

capability ::= ident { "." ident } ;

<<< ================= Compiler Declarations ================= >>>

compiler_decl ::= { attr_prefix WS? }
                  "compiler" WS1 ident
                  WS? "{"
                  WS?
                  compiler_items?
                  WS?
                  "}"
                  ;

compiler_items ::= compiler_item
                   { WS? compiler_item }
                   ;

compiler_item ::= compiler_phase_decl
                | compiler_stage_decl
                | compiler_artifact_decl
                | compiler_pipeline_decl
                | compiler_cache_decl
                | compiler_target_decl
                ;

compiler_phase_decl ::= "phase" WS1 ident
                        WS? "{"
                        WS?
                        "input" WS? ":" WS? type_expr [ stmt_term ]
                        "output" WS? ":" WS? type_expr [ stmt_term ]
                        [ "errors" WS? ":" WS? type_expr [ stmt_term ] ]
                        WS?
                        "}"
                        ;

compiler_stage_decl ::= "stage" WS1 ident
                        WS? ":" WS? ident_list
                        [ stmt_term ]
                        ;

compiler_artifact_decl ::= "artifact" WS1 ident
                           WS? ":" WS? type_expr
                           [ stmt_term ]
                           ;

compiler_pipeline_decl ::= "pipeline" WS1 ident
                           WS? "{"
                           WS?
                           pipeline_step*
                           WS?
                           "}"
                           ;

pipeline_step ::= "run" WS1 ident
                  [ WS1 "as" WS1 ident ]
                  [ stmt_term ]

                | "dump" WS1 ident
                  [ stmt_term ]

                | "verify" WS1 ident
                  [ stmt_term ]
                ;

compiler_cache_decl ::= "cache" WS1 ident
                        WS? "{"
                        WS?
                        cache_item*
                        WS?
                        "}"
                        ;

cache_item ::= "key" WS? ":" WS? type_expr [ stmt_term ]
             | "value" WS? ":" WS? type_expr [ stmt_term ]
             | "strategy" WS? ":" WS? ident [ stmt_term ]
             ;

compiler_target_decl ::= "target" WS1 ident
                         WS? "{"
                         WS?
                         target_item*
                         WS?
                         "}"
                         ;

target_item ::= ident
                WS? ":" WS? expr
                [ stmt_term ]
                ;

<<< ================= Queries ================= >>>

query_decl ::= { attr_prefix WS? }
               "query" WS1 ident
               "(" WS? param_list? WS? ")"
               WS? "->" WS? type_expr
               WS? query_body
               ;

query_body ::= block
             | stmt_term
             ;

<<< ================= Passes ================= >>>

pass_decl ::= { attr_prefix WS? }
              "pass" WS1 ident
              WS? "{"
              WS?
              pass_items?
              WS?
              "}"
              ;

pass_items ::= pass_item
               { WS? pass_item }
               ;

pass_item ::= "input" WS? ":" WS? type_expr [ stmt_term ]
            | "output" WS? ":" WS? type_expr [ stmt_term ]
            | "requires" WS? ":" WS? ident_list [ stmt_term ]
            | "invalidates" WS? ":" WS? ident_list [ stmt_term ]
            | proc_decl
            ;

<<< ================= Backends ================= >>>

backend_decl ::= { attr_prefix WS? }
                 "backend" WS1 ident
                 WS? "{"
                 WS?
                 backend_items?
                 WS?
                 "}"
                 ;

backend_items ::= backend_item
                  { WS? backend_item }
                  ;

backend_item ::= "target" WS? ":" WS? string_lit [ stmt_term ]
               | "format" WS? ":" WS? backend_format [ stmt_term ]
               | "emits" WS? ":" WS? backend_output [ stmt_term ]
               | "requires" WS? ":" WS? ident_list [ stmt_term ]
               | proc_decl
               ;

backend_format ::= "c"
                 | "llvm"
                 | "asm"
                 | "object"
                 | "wasm"
                 | "ir"
                 ;

backend_output ::= "source"
                 | "assembly"
                 | "object"
                 | "executable"
                 | "library"
                 ;

<<< ================= Diagnostics ================= >>>

diagnostic_decl ::= { attr_prefix WS? }
                    "diagnostic" WS1 diagnostic_code
                    WS? "{"
                    WS?
                    diagnostic_items?
                    WS?
                    "}"
                    ;

diagnostic_code ::= ident
                  | string_lit
                  ;

diagnostic_items ::= diagnostic_item
                     { WS? diagnostic_item }
                     ;

diagnostic_item ::= "level" WS? ":" WS? diagnostic_level [ stmt_term ]
                  | "message" WS? ":" WS? string_lit [ stmt_term ]
                  | "label" WS? ":" WS? string_lit [ stmt_term ]
                  | "help" WS? ":" WS? string_lit [ stmt_term ]
                  | "note" WS? ":" WS? string_lit [ stmt_term ]
                  | "suggest" WS? ":" WS? string_lit [ stmt_term ]
                  ;

diagnostic_level ::= "error"
                   | "warning"
                   | "note"
                   | "help"
                   | "fatal"
                   ;

<<< ================= Attributes ================= >>>

attr_prefix ::= outer_attribute
              | doc_comment
              | docstring
              ;

inner_attribute ::= "#!["
                    attr_path
                    [ "(" WS? attr_arg_list? WS? ")" ]
                    "]"
                    ;

outer_attribute ::= "#["
                    attr_path
                    [ "(" WS? attr_arg_list? WS? ")" ]
                    "]"
                    ;

doc_comment ::= "///" { ~NEWLINE ANY } ;

docstring ::= raw_string_lit ;

attr_path ::= ident { "." ident } ;

attr_arg_list ::= attr_arg
                  { WS? "," WS? attr_arg }
                  [ WS? "," ]
                  ;

attr_arg ::= ident
           | string_lit
           | int_lit
           | bool_lit
           | ident WS? "=" WS? literal
           ;

<<< ================= Blocks / Statements ================= >>>

block ::= "{"
          WS?
          { stmt WS? }
          "}"
          ;

stmt ::= local_const_stmt stmt_term?
       | let_stmt stmt_term?
       | set_stmt stmt_term?
       | give_stmt stmt_term?
       | try_stmt stmt_term?
       | defer_stmt
       | asm_stmt stmt_term?
       | unsafe_stmt
       | emit_stmt stmt_term?
       | assert_stmt stmt_term?
       | panic_stmt stmt_term?
       | unreachable_stmt stmt_term?
       | if_stmt
       | while_stmt
       | loop_stmt
       | for_stmt
       | break_stmt stmt_term?
       | continue_stmt stmt_term?
       | select_stmt
       | match_stmt
       | when_match_stmt
       | with_stmt
       | critical_stmt
       | expr_stmt stmt_term?
       ;

stmt_term ::= WS? ";" ;

local_const_stmt ::= "const" WS1 ident
                     [ WS? ":" WS? type_expr ]
                     WS? "=" WS? expr
                     ;

let_stmt ::= "let" WS1
             [ "mut" WS1 ]
             pattern
             [ WS? ":" WS? type_expr ]
             WS? "=" WS? expr
             ;

set_stmt ::= "set" WS1
             assign_target
             WS? assign_op WS?
             expr
             ;

assign_target ::= unary_expr ;

give_stmt ::= "give" [ WS1 expr ] ;

try_stmt ::= "try" WS1 expr ;

defer_stmt ::= "defer" WS? block ;

asm_stmt ::= "asm"
             WS? "("
             WS? asm_arg_list?
             WS? ")"
             ;

asm_arg_list ::= asm_arg
                 { WS? "," WS? asm_arg }
                 [ WS? "," ]
                 ;

asm_arg ::= string_lit
          | ident WS? "(" WS? arg_list? WS? ")"
          | ident WS? ":" WS? expr
          ;

unsafe_stmt ::= "unsafe" WS? block ;

emit_stmt ::= "emit" WS1 expr ;

assert_stmt ::= "assert" WS1 expr
                [ WS? "," WS? expr ]
                ;

panic_stmt ::= "panic" WS1 expr ;

unreachable_stmt ::= "unreachable" ;

if_stmt ::= "if" WS1 expr
            WS? block
            { WS? "elif" WS1 expr WS? block }
            [ WS? "else" WS? block ]
            ;

while_stmt ::= "while" WS1 expr WS? block ;

loop_stmt ::= "loop" WS? block ;

for_stmt ::= "for" WS1 pattern
             WS1 "in" WS1 expr
             WS? block
             ;

break_stmt ::= "break" [ WS1 expr ] ;

continue_stmt ::= "continue" ;

select_stmt ::= "select" WS1 expr
                WS? "{"
                WS?
                { "when" WS1 pattern WS? block WS? }
                [ "else" WS? block ]
                WS?
                "}"
                ;

match_stmt ::= "match" WS1 expr
               WS? "{"
               WS?
               {
                   "case" WS1 pattern
                   [ WS1 "if" WS1 expr ]
                   WS? match_arm_body
                   WS?
               }
               [ "else" WS? match_arm_body ]
               WS?
               "}"
               ;

match_arm_body ::= block
                 | "=>" WS? expr [ stmt_term ]
                 ;

when_match_stmt ::= "when" WS1 expr
                    WS1 "is" WS1 pattern
                    WS? block
                    ;

with_stmt ::= "with" WS1 expr
              [ WS1 "as" WS1 pattern ]
              WS? block
              ;

critical_stmt ::= "critical" WS? block ;

expr_stmt ::= expr ;

<<< ================= Expressions ================= >>>

expr ::= assign_expr ;

assign_expr ::= ternary_expr
                [ WS? assign_op WS? assign_expr ]
                ;

assign_op ::= "="
            | "+="
            | "-="
            | "*="
            | "/="
            | "%="
            | "&="
            | "|="
            | "^="
            | "<<="
            | ">>="
            ;

ternary_expr ::= coalesce_expr
                 [
                     WS? "?"
                     WS? expr
                     WS? ":"
                     WS? expr
                 ]
                 ;

coalesce_expr ::= range_expr
                  { WS? "??" WS? range_expr }
                  ;

range_expr ::= or_expr
               [
                   WS? ( ".." | "..=" )
                   WS? or_expr
               ]
               ;

or_expr ::= and_expr
            { WS? ( "or" | "||" ) WS? and_expr }
            ;

and_expr ::= bit_or_expr
             { WS? ( "and" | "&&" ) WS? bit_or_expr }
             ;

bit_or_expr ::= bit_xor_expr
                { WS? "|" WS? bit_xor_expr }
                ;

bit_xor_expr ::= bit_and_expr
                 { WS? "^" WS? bit_and_expr }
                 ;

bit_and_expr ::= eq_expr
                 { WS? "&" WS? eq_expr }
                 ;

eq_expr ::= rel_expr
            { WS? ( "==" | "!=" ) WS? rel_expr }
            ;

rel_expr ::= shift_expr
             { WS? rel_op WS? shift_expr }
             ;

rel_op ::= "<"
         | "<="
         | ">"
         | ">="
         | "in"
         | "not" WS1 "in"
         ;

shift_expr ::= add_expr
               { WS? ( "<<" | ">>" ) WS? add_expr }
               ;

add_expr ::= mul_expr
             { WS? ( "+" | "-" ) WS? mul_expr }
             ;

mul_expr ::= cast_expr
             { WS? ( "*" | "/" | "%" ) WS? cast_expr }
             ;

cast_expr ::= unary_expr
              {
                  WS?
                  (
                      "as" WS? type_expr
                    | "is" WS? pattern
                    | "is" WS1 "not" WS1 pattern
                  )
              }
              ;

unary_expr ::= (
                   "not"
                 | "-"
                 | "~"
                 | "*"
                 | "&"
                 | "move"
                 | "await"
               )
               WS? unary_expr
             | postfix_expr
             ;

postfix_expr ::= primary
                 {
                     call_suffix
                   | member_suffix
                   | index_suffix
                   | try_suffix
                   | await_suffix
                 }
                 ;

call_suffix ::= "(" WS? arg_list? WS? ")" ;

member_suffix ::= "." ident ;

index_suffix ::= "[" WS? index_expr WS? "]" ;

try_suffix ::= "?" ;

await_suffix ::= "." "await" ;

index_expr ::= expr
             | slice_expr
             ;

slice_expr ::= [ expr ]
               ":"
               [ expr ]
               [ ":" expr ]
               ;

<<< ================= Primary Expressions ================= >>>

primary ::= literal
          | builtin_expr
          | path_expr
          | struct_lit
          | list_lit
          | tuple_lit
          | set_lit
          | map_lit
          | bytes_lit
          | resource_lit
          | if_expr
          | proc_expr
          | match_expr
          | lambda_expr
          | unsafe_expr
          | block
          | "(" WS? expr WS? ")"
          ;

path_expr ::= value_path { "." ident } ;

value_path ::= ident { "::" ident } ;

arg_list ::= arg
             { WS? "," WS? arg }
             [ WS? "," ]
             ;

arg ::= ident WS? ":" WS? expr
      | expr
      ;

<<< ================= Structured Literals ================= >>>

struct_lit ::= type_path
               WS? "{"
               WS?
               field_init_list?
               WS?
               "}"
               ;

field_init_list ::= field_init
                    { WS? "," WS? field_init }
                    [ WS? "," ]
                    ;

field_init ::= ident WS? ":" WS? expr
             | ident
             | ".." expr
             ;

tuple_lit ::= "("
              WS? expr
              WS? ","
              WS? expr
              { WS? "," WS? expr }
              [ WS? "," ]
              WS?
              ")"
              ;

set_lit ::= "set"
            WS? "{"
            WS? arg_list?
            WS? "}"
            ;

map_lit ::= "map"
            WS? "{"
            WS? map_items?
            WS? "}"
            ;

map_items ::= map_item
              { WS? "," WS? map_item }
              [ WS? "," ]
              ;

map_item ::= expr WS? ":" WS? expr ;

bytes_lit ::= "b" string_lit ;

resource_lit ::= "resource"
                 WS? "{"
                 WS? resource_items?
                 WS? "}"
                 ;

resource_items ::= resource_item
                   { WS? "," WS? resource_item }
                   [ WS? "," ]
                   ;

resource_item ::= ident WS? ":" WS? expr ;

<<< ================= Expression Forms ================= >>>

if_expr ::= "if" WS1 expr
            WS? block
            { WS? "elif" WS1 expr WS? block }
            [ WS? "else" WS? block ]
            ;

proc_expr ::= { attr_prefix WS? }
              proc_modifier*
              "proc"
              WS? "("
              WS? param_list?
              WS? ")"
              [ WS? "->" WS? type_expr ]
              WS? proc_suffix*
              WS? block
              ;

match_expr ::= "match" WS1 expr
               WS? "{"
               WS?
               {
                   "case" WS1 pattern
                   [ WS1 "if" WS1 expr ]
                   WS? match_arm_body
                   WS?
               }
               [ "else" WS? match_arm_body ]
               WS?
               "}"
               ;

lambda_expr ::= "|"
                WS? param_list?
                WS? "|"
                WS?
                ( expr | block )
                ;

unsafe_expr ::= "unsafe" WS? block ;

<<< ================= Builtins ================= >>>

builtin_expr ::= sizeof_expr
               | alignof_expr
               | offsetof_expr
               | typeof_expr
               | nameof_expr
               ;

sizeof_expr ::= "sizeof"
                WS? "("
                WS? ( type_expr | expr )
                WS? ")"
                ;

alignof_expr ::= "alignof"
                 WS? "("
                 WS? type_expr
                 WS? ")"
                 ;

offsetof_expr ::= "offsetof"
                  WS? "("
                  WS? type_expr
                  WS? ","
                  WS? ident
                  WS? ")"
                  ;

typeof_expr ::= "typeof"
                WS? "("
                WS? expr
                WS? ")"
                ;

nameof_expr ::= "nameof"
                WS? "("
                WS? path_expr
                WS? ")"
                ;

<<< ================= Patterns ================= >>>

pattern ::= pattern_or ;

pattern_or ::= pattern_atom
               { WS? "|" WS? pattern_atom }
               ;

pattern_atom ::= "_"
               | literal
               | "mut" WS1 pattern_bind
               | "ref" WS1 pattern_bind
               | pattern_bind
               | pattern_ctor
               | pattern_struct
               | pattern_tuple
               | pattern_list
               | pattern_range
               ;

pattern_bind ::= ident ;

pattern_ctor ::= pattern_head
                 [ "(" WS? pattern_args? WS? ")" ]
                 ;

pattern_head ::= ident { ( "." | "::" ) ident } ;

pattern_args ::= pattern
                 { WS? "," WS? pattern }
                 [ WS? "," ]
                 ;

pattern_struct ::= pattern_head
                   WS? "{"
                   WS? pattern_fields?
                   WS? "}"
                   ;

pattern_fields ::= pattern_field
                   { WS? "," WS? pattern_field }
                   [ WS? "," ]
                   ;

pattern_field ::= ident [ WS? ":" WS? pattern ]
                | ".."
                ;

pattern_tuple ::= "("
                  WS? pattern
                  WS? ","
                  WS? pattern
                  { WS? "," WS? pattern }
                  [ WS? "," ]
                  WS?
                  ")"
                  ;

pattern_list ::= "["
                 WS? pattern_args?
                 WS? "]"
                 ;

pattern_range ::= literal
                  WS? ( ".." | "..=" )
                  WS? literal
                  ;

<<< ================= Types ================= >>>

type_expr ::= type_union ;

type_union ::= type_prefix
               { WS? "|" WS? type_prefix }
               ;

type_prefix ::= type_qualifier* type_atom ;

type_qualifier ::= type_qual WS1
                 | addr_space WS1
                 ;

type_qual ::= "const"
            | "volatile"
            | "atomic"
            | "mut"
            | "owned"
            | "borrow"
            ;

addr_space ::= "user"
             | "kernel"
             | "phys"
             | "mmio"
             | "dma"
             ;

type_atom ::= reference_type
            | pointer_type
            | optional_type
            | fixed_array_type
            | slice_type
            | tuple_type
            | proc_type
            | dyn_type
            | impl_trait_type
            | type_primary
            ;

reference_type ::= "&"
                   WS?
                   [ lifetime WS? ]
                   [ "mut" WS1 ]
                   type_expr
                   ;

pointer_type ::= "*"
                 WS?
                 [
                     "const" WS1
                   | "mut" WS1
                   | "volatile" WS1
                   | addr_space WS1
                 ]
                 type_expr
                 ;

optional_type ::= "?" WS? type_expr ;

fixed_array_type ::= "["
                     WS?
                     type_expr
                     WS? ";"
                     WS? expr
                     WS?
                     "]"
                     ;

slice_type ::= "["
               WS?
               type_expr
               WS?
               "]"
               ;

tuple_type ::= "("
               WS? type_expr
               WS? ","
               WS? type_expr
               { WS? "," WS? type_expr }
               [ WS? "," ]
               WS?
               ")"
               ;

proc_type ::= "proc"
              WS? "("
              WS? type_list?
              WS? ")"
              [ WS? "->" WS? type_expr ]
              ;

type_list ::= type_param
              { WS? "," WS? type_param }
              [ WS? "," ]
              ;

type_param ::= ident WS? ":" WS? type_expr
             | type_expr
             ;

dyn_type ::= "dyn" WS1 trait_bound ;

impl_trait_type ::= "impl" WS1 trait_bound ;

type_primary ::= type_path [ generic_args ]
               | primitive_type
               | "Self"
               ;

type_path ::= ident { ( "." | "::" ) ident } ;

lifetime ::= "'" ident ;

<<< ================= Primitive Types ================= >>>

primitive_type ::= "void"
                 | "never"
                 | "unit"
                 | "bool"
                 | "char"
                 | "rune"
                 | "str"
                 | "string"
                 | "bytes"
                 | "cstr"
                 | "int"
                 | "i8"
                 | "i16"
                 | "i32"
                 | "i64"
                 | "i128"
                 | "u8"
                 | "u16"
                 | "u32"
                 | "u64"
                 | "u128"
                 | "usize"
                 | "isize"
                 | "intptr"
                 | "uintptr"
                 | "f16"
                 | "f32"
                 | "f64"
                 | "f128"
                 | "c_char"
                 | "c_int"
                 | "c_uint"
                 | "c_long"
                 | "c_ulong"
                 | "c_void"
                 ;

<<< ================= Literals ================= >>>

literal ::= bool_lit
          | null_lit
          | int_lit
          | float_lit
          | char_lit
          | string_lit
          | list_lit
          ;

list_lit ::= "["
             WS?
             ( list_comp | arg_list? )
             WS?
             "]"
             ;

list_comp ::= expr
              WS1 "for" WS1 pattern
              WS1 "in" WS1 expr
              [ WS1 "if" WS1 expr ]
              ;

bool_lit ::= "true"
           | "false"
           ;

null_lit ::= "null" ;

int_lit ::= [ "-" ]
            DIGIT
            { DIGIT | "_" }
            [ suffix ]

          | [ "-" ]
            "0x"
            HEXDIGIT
            { HEXDIGIT | "_" }
            [ suffix ]

          | [ "-" ]
            "0b"
            BINDIGIT
            { BINDIGIT | "_" }
            [ suffix ]

          | [ "-" ]
            "0o"
            OCTDIGIT
            { OCTDIGIT | "_" }
            [ suffix ]
          ;

float_lit ::= [ "-" ]
              DIGIT
              { DIGIT | "_" }
              "."
              DIGIT
              { DIGIT | "_" }
              [ exponent ]
              [ suffix ]
              ;

exponent ::= ( "e" | "E" )
             [ "+" | "-" ]
             DIGIT
             { DIGIT | "_" }
             ;

char_lit ::= "'"
             char_char
             "'"
             ;

char_char ::= escape_seq
            | ~"'"
            ;

string_lit ::= "\""
               { string_char }
               "\""

             | raw_string_lit
             ;

string_char ::= escape_seq
              | ~"\""
              ;

escape_seq ::= "\\n"
             | "\\r"
             | "\\t"
             | "\\0"
             | "\\\""
             | "\\'"
             | "\\\\"
             | "\\x" HEXDIGIT HEXDIGIT
             | "\\u{" HEXDIGIT { HEXDIGIT } "}"
             ;

raw_string_lit ::= "\"\"\""
                   { raw_string_char }
                   "\"\"\""

                 | "r\""
                   { raw_string_char }
                   "\""
                 ;

raw_string_char ::= ~"\"\"\"" ;

<<< ================= Lexical ================= >>>

line_comment ::= "#"
                 { ~NEWLINE ANY }

               | "//"
                 { ~NEWLINE ANY }
               ;

block_comment ::= "/*"
                  { ~"*/" ANY }
                  "*/"
                  ;

zone_comment ::= "<<<"
                 { ~">>>" ANY }
                 ">>>"
                 ;

ident ::= ( LETTER | "_" )
          { LETTER | DIGIT | "_" }
          ;

suffix ::= LETTER
           { LETTER | DIGIT }
           ;

WS ::= {
           " "
         | "\t"
         | NEWLINE
         | line_comment
         | block_comment
         | zone_comment
       }
       ;

WS1 ::= (
            " "
          | "\t"
          | NEWLINE
          | line_comment
          | block_comment
          | zone_comment
        )
        {
            " "
          | "\t"
          | NEWLINE
          | line_comment
          | block_comment
          | zone_comment
        }
        ;

NEWLINE ::= "\n"
          | "\r\n"
          ;

LETTER ::= "a"..."z"
         | "A"..."Z"
         ;

DIGIT ::= "0"..."9" ;

BINDIGIT ::= "0"
           | "1"
           ;

OCTDIGIT ::= "0"..."7" ;

HEXDIGIT ::= DIGIT
           | "a"..."f"
           | "A"..."F"
           ;

EOF ::= !ANY ;