Vitte Grammar Practical Guide

Practical usage guide generated from src/vitte/grammar/vitte.ebnf.

Two Ways to Use Grammar Docs

Voie 1: Comprendre

Commence ici si tu veux apprendre calmement le sens des règles.

Voie 2: Référence brute

Utilise cette voie pour audit, tooling et validation stricte.

Reading Paths

Beginner

Intermediate

Expert

  • Focus on compiler surface: compiler_decl, query_decl, backend_decl.
  • Use grammar as strict contract for tooling and tests.
  • Track parser behavior against edge cases per production.

Rule Validation Table

RuleValid ExampleInvalid ExampleExpected Diagnostic
space_declspace vitte/bootstrap/stage2spaceMissing module path after `space`.
use_decluse vitte/iouseImport path missing after `use`.
proc_declproc main() -> int { give 0 }proc main( -> int { give 0 }Malformed parameter list or signature.
const_declconst VERSION: string = "1.0"const = "1.0"Const identifier is required.
entry_declentry app at vitte/bootstrap { }entry app vitte/bootstrap { }Missing `at` in entry declaration.
expra + b * ca + * cUnexpected operator placement in expression.

Rule Anchors Index

Grammar Tools

Full EBNF (Anchored)

<<< =========================================================
   Vitte — Complete Core Grammar
   systems + application + kernel + compiler surface
   canonical blocks: { }
   low-level capable
   compiler-capable
   no aliases, reduced duplicates
   ========================================================= >>>

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
          ;

space_decl ::=  "space" WS1 module_path ;

use_decl ::=  "use" WS1 package_path [ use_group | use_glob ] [ WS1 "as" WS1 ident ] ;
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? "}" ) ;

const_decl ::=  { attr_prefix WS? } "const" WS1 ident [ WS? ":" WS? type_expr ] WS? "=" WS? expr ;
static_decl ::=  { attr_prefix WS? } "static" WS1 ident [ WS? ":" WS? type_expr ] WS? "=" WS? expr ;
global_decl ::=  { attr_prefix WS? } "global" WS1 ident [ WS? ":" WS? type_expr ] WS? "=" WS? expr ;

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

form_decl ::=  { attr_prefix WS? } "form" WS1 ident [ generic_params ] [ WS? where_clause ] WS? "{" WS? form_items? WS? "}" ;
class_decl ::=  { attr_prefix WS? } "class" WS1 ident [ generic_params ] [ WS? where_clause ] WS? "{" WS? class_items? WS? "}" ;
union_decl ::=  { attr_prefix WS? } "union" WS1 ident [ generic_params ] [ WS? where_clause ] WS? "{" WS? field_list? WS? "}" ;

form_items ::=  form_item { WS? ","? WS? form_item } [ WS? "," ] ;
form_item ::=  field_item | const_decl | type_alias_decl | proc_decl ;

class_items ::=  class_item { WS? ","? WS? class_item } [ WS? "," ] ;
class_item ::=  field_item | const_decl | type_alias_decl | proc_decl ;

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

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 ;

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_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 ] ;

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 ] ;

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 ;

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

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 | ";" )
              ;

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_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*
                     WS? ";"
                     ;

extern_clause ::=  "extern" WS1 extern_abi ;
extern_abi ::=  callconv | string_lit ;
callconv ::=  "C" | "sysv64" | "win64" | "interrupt" | "naked" ;

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

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? ")" ;
test_decl ::=  { attr_prefix WS? } "test" WS1 string_lit WS? block ;
bench_decl ::=  { attr_prefix WS? } "bench" WS1 string_lit WS? block ;
entry_decl ::=  { attr_prefix WS? } "entry" WS1 ident WS1 "at" WS1 module_path WS? block ;

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

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
                ;

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 } ;

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_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 } ;

module_path ::=  relative? package_parts ;
package_path ::=  relative? package_parts ;
relative ::=  { "." } ;
package_parts ::=  ident { ( "/" | "." | "::" ) ident } ;
ident_list ::=  ident { WS? "," WS? ident } [ WS? "," ] ;

<<< ================= 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 WS? ";"
                        "output" WS? ":" WS? type_expr WS? ";"
                        [ "errors" WS? ":" WS? type_expr WS? ";" ]
                        WS? "}" ;

compiler_stage_decl ::=  "stage" WS1 ident WS? ":" WS? ident_list WS? ";" ;
compiler_artifact_decl ::=  "artifact" WS1 ident WS? ":" WS? type_expr WS? ";" ;

compiler_pipeline_decl ::=  "pipeline" WS1 ident WS? "{" WS? pipeline_step* WS? "}" ;
pipeline_step ::=  "run" WS1 ident [ WS? "as" WS? ident ] WS? ";"
                | "dump" WS1 ident WS? ";"
                | "verify" WS1 ident WS? ";"
                ;

compiler_cache_decl ::=  "cache" WS1 ident WS? "{" WS? cache_item* WS? "}" ;
cache_item ::=  "key" WS? ":" WS? type_expr WS? ";"
             | "value" WS? ":" WS? type_expr WS? ";"
             | "strategy" WS? ":" WS? ident WS? ";"
             ;

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

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

query_body ::=  block | ";" ;

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 WS? ";"
            | "output" WS? ":" WS? type_expr WS? ";"
            | "requires" WS? ":" WS? ident_list WS? ";"
            | "invalidates" WS? ":" WS? ident_list WS? ";"
            | proc_decl
            ;

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 WS? ";"
               | "format" WS? ":" WS? backend_format WS? ";"
               | "emits" WS? ":" WS? backend_output WS? ";"
               | "requires" WS? ":" WS? ident_list WS? ";"
               | proc_decl
               ;

backend_format ::=  "c" | "llvm" | "asm" | "object" | "wasm" | "ir" ;
backend_output ::=  "source" | "assembly" | "object" | "executable" | "library" ;

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 WS? ";"
                  | "message" WS? ":" WS? string_lit WS? ";"
                  | "label" WS? ":" WS? string_lit WS? ";"
                  | "help" WS? ":" WS? string_lit WS? ";"
                  | "note" WS? ":" WS? string_lit WS? ";"
                  | "suggest" WS? ":" WS? string_lit WS? ";"
                  ;

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_end
       | let_stmt stmt_end
       | set_stmt stmt_end
       | give_stmt stmt_end
       | try_stmt stmt_end
       | defer_stmt
       | asm_stmt stmt_end
       | unsafe_stmt
       | emit_stmt stmt_end
       | assert_stmt stmt_end
       | panic_stmt stmt_end
       | unreachable_stmt stmt_end
       | if_stmt
       | while_stmt
       | loop_stmt
       | for_stmt
       | break_stmt stmt_end
       | continue_stmt stmt_end
       | select_stmt
       | match_stmt
       | when_match_stmt
       | with_stmt
       | critical_stmt
       | expr_stmt stmt_end
       ;

stmt_end ::=  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? }
               [ WS? "else" WS? match_arm_body ]
               WS? "}" ;

match_arm_body ::=  block | "=>" WS? expr WS? ";" ;

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 ::=  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 ::=  ident { ( "." | "::" ) ident } ;

arg_list ::=  arg { WS? "," WS? arg } [ WS? "," ] ;
arg ::=  ident WS? ":" WS? expr | 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 ;

struct_lit ::=  type_path WS? "{" WS? field_init_list? WS? "}" ;
type_path ::=  ident { ( "." | "::" ) ident } ;
field_init_list ::=  field_init { WS? "," WS? field_init } [ WS? "," ] ;
field_init ::=  ident WS? ":" WS? expr
             | ident
             | ".." expr
             ;

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? }
               [ WS? "else" WS? match_arm_body ]
               WS? "}" ;

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

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 [ "[" WS? type_list? WS? "]" ]
               | primitive_type
               | "Self"
               ;

lifetime ::=  "'" ident ;

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"
                 | "TokenId"
                 | "NodeId"
                 | "DefId"
                 | "HirId"
                 | "MirId"
                 | "TypeId"
                 | "SymbolId"
                 | "ScopeId"
                 | "BlockId"
                 | "ValueId"
                 | "InstrId"
                 ;

<<< ================= 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 ;