Annex A (normative) — Formal grammar

This annex defines the complete formal grammar of the Ori language in Extended Backus-Naur Form (EBNF). The notation conventions are defined in Clause 5.

// ============================================================================
// Ori Language Grammar
// Version: 2026
//
// This is the unified formal grammar for the Ori programming language.
// All productions are authoritative and take precedence over prose descriptions.
//
// Notation:
//   production = expression .     Production definition
//   "keyword"                     Literal token
//   |                             Alternation
//   [ ]                           Optional (0 or 1)
//   { }                           Repetition (0 or more)
//   ( )                           Grouping
//   /* comment */                 Informative note
//
// Cross-references to detailed explanations are provided in comments.
// ============================================================================


// ============================================================================
// LEXICAL GRAMMAR
// See: 06-source-code.md, 07-lexical-elements.md
// ============================================================================

// --- Characters ---
// See: 06-source-code.md § 6.1 Characters, § 6.1.2 Letters and digits

unicode_char  = /* any Unicode code point except NUL (U+0000) */ .
letter        = 'A''Z' | 'a''z' .
digit         = '0''9' .
hex_digit     = digit | 'A''F' | 'a''f' .
bin_digit     = '0' | '1' .
newline       = /* U+000A */ .
whitespace    = ' ' | '\t' | '\r' | newline .

// --- Tokens ---

token = identifier | keyword | literal | operator | delimiter .

// --- Comments ---
// See: 07-lexical-elements.md § 7.1 Comments

comment      = "//" { unicode_char - newline } newline .
doc_comment  = "//" [ " " ] [ doc_marker ] { unicode_char - newline } newline .
doc_marker   = "*" | "!" | ">" .
member_doc   = "//" " " "*" " " identifier ":" [ " " { unicode_char - newline } ] .
warning_doc  = "//" " " "!" " " { unicode_char - newline } .
example_doc  = "//" " " ">" " " { unicode_char - newline } .

// --- Identifiers ---
// See: 07-lexical-elements.md § 7.2 Identifiers

identifier = ( letter | "_" ) { letter | digit | "_" } .

// --- Keywords ---
// See: 07-lexical-elements.md § 7.3 Keywords
//
// Reserved (36): as, break, continue, def, div, do, else, extend, extension, extern,
//           false, for, if, impl, in, let, loop, match, Never, pub, self, Self, suspend,
//           tests, then, trait, true, type, unsafe, use, uses, void, where, while, with, yield
// Reserved (future, 5): asm, inline, static, union, view
// Context-sensitive (patterns, 9): cache, catch, handler, nursery, parallel, recurse, spawn,
//           timeout, try
// Context-sensitive (pattern args, 10): body, buffer, default, expr, map, on_error, over,
//           pre, post, state
// Context-sensitive (imports, 2): from (extern blocks), without (import items, before "def")
// Context-sensitive (other, 3): args (@main params), by (after range), max (fixed-capacity lists)
// Context-sensitive (embed, 2): embed (file embedding), has_embed (file existence check)
// Context-sensitive (type names, 5): bool, byte, float, int, str
// Built-in constructors (4): channel, channel_all, channel_in, channel_out

// --- Operators ---
// See: 07-lexical-elements.md § 7.4 Operators

arith_op  = "+" | "-" | "*" | "/" | "%" | "div" | "**" .
comp_op   = "==" | "!=" | "<" | ">" | "<=" | ">=" .
logic_op  = "&&" | "||" | "!" .
bit_op    = "&" | "|" | "^" | "~" | "<<" | ">>" .
unary_op  = "!" | "-" | "~" .
other_op  = ".." | "..=" | "??" | "?" | "->" | "=>" | "|>" .

// --- Delimiters ---

delimiter = "(" | ")" | "[" | "]" | "{" | "}"
          | "," | ":" | "." | "@" | "$" | ";" .

// --- Literals ---
// See: 07-lexical-elements.md § 7.7 Literals

literal = int_literal | float_literal | string_literal | template_literal | char_literal
        | byte_literal | bool_literal | duration_literal | size_literal .

// Integer literals
// See: 07-lexical-elements.md § 7.7.1 Integer literals
int_literal    = decimal_lit | hex_lit | bin_lit .
decimal_lit    = "0" | non_zero_digit { [ "_" ] digit } .
non_zero_digit = "1""9" .
hex_lit        = "0" ( "x" | "X" ) hex_digit { [ "_" ] hex_digit } .
bin_lit        = "0" ( "b" | "B" ) bin_digit { [ "_" ] bin_digit } .

// Float literals
// See: 07-lexical-elements.md § 7.7.2 Float literals
float_literal   = decimal_digits "." decimal_digits [ exponent ]
                | decimal_digits exponent .
decimal_digits  = digit { [ "_" ] digit } .
exponent        = ( "e" | "E" ) [ "+" | "-" ] decimal_digits .

// String literals
// See: 07-lexical-elements.md § 7.7.3 String literals
string_literal  = '"' { string_char | escape_seq } '"' .
string_char     = unicode_char - ( '"' | '\' | newline ) .
escape_seq      = '\' ( '"' | '\' | 'n' | 't' | 'r' | '0' )
                | unicode_escape
                | hex_escape .
unicode_escape  = '\' 'u' '{' hex_digit { hex_digit } '}' .  /* 1-6 hex digits */
hex_escape      = '\' 'x' hex_digit hex_digit .               /* \x00-\xFF */

// Template string literals (with interpolation)
// See: 07-lexical-elements.md § 7.7.4 Template strings
template_literal = '`' { template_char | template_escape | unicode_escape | template_brace | interpolation } '`' .
template_char    = unicode_char - ( '`' | '\' | '{' | '}' ) .
template_escape  = '\' ( '`' | '\' | 'n' | 't' | 'r' | '0' ) .
template_brace   = "{{" | "}}" .
interpolation    = '{' expression [ ':' format_spec ] '}' .

// Format specifiers for template strings
// See: 07-properties-of-types.md § Format Spec Syntax
// Syntax: [[fill]align][sign][#][0][width][.precision][type]
format_spec      = [ [ fill ] align ] [ sign ] [ alt_form ] [ zero_pad ] [ width ] [ '.' precision ] [ format_type ] .
fill             = unicode_char - ( align | sign ) .
align            = '<' | '>' | '^' .
sign             = '+' | '-' | ' ' .
alt_form         = '#' .
zero_pad         = '0' .
width            = decimal_lit .
precision        = decimal_lit .
format_type      = 'b' | 'o' | 'x' | 'X' | 'e' | 'E' | 'f' | '%' .

// Character literals
// See: 07-lexical-elements.md § 7.7.5 Character literals
char_literal = "'" ( char_char | char_escape ) "'" .
char_char    = unicode_char - ( "'" | '\' | newline ) .
char_escape  = '\' ( "'" | '\' | 'n' | 't' | 'r' | '0' )
             | unicode_escape
             | char_hex_escape .
char_hex_escape = '\' 'x' hex_digit hex_digit .  /* \x00-\x7F only; \x80-\xFF is an error */

// Byte literals
// See: 07-lexical-elements.md § 7.7.6 Byte literals
byte_literal = "b'" ( byte_char | byte_escape ) "'" .
byte_char    = ascii_char - ( "'" | '\' ) .      /* U+0020-U+007E, excluding ' and \ */
byte_escape  = '\' ( "'" | '\' | 'n' | 't' | 'r' | '0' )
             | hex_escape .                       /* \x00-\xFF; no \u{} or \" */
ascii_char   = '\x20''\x7E' .                 /* printable ASCII */

// Boolean literals
bool_literal = "true" | "false" .

// Duration literals
// See: 07-lexical-elements.md § 7.7.8 Duration literals
// Decimal syntax (e.g., 0.5s) is compile-time sugar computed via integer arithmetic
duration_literal = duration_number duration_unit .
duration_number  = decimal_lit | decimal_lit "." digit { digit } .
duration_unit    = "ns" | "us" | "ms" | "s" | "m" | "h" .

// Size literals
// See: 07-lexical-elements.md § 7.7.9 Size literals
// Decimal syntax (e.g., 1.5kb) is compile-time sugar computed via integer arithmetic
size_literal = size_number size_unit .
size_number  = decimal_lit | decimal_lit "." digit { digit } .
size_unit    = "b" | "kb" | "mb" | "gb" | "tb" .


// ============================================================================
// SOURCE STRUCTURE
// See: 06-source-code.md, 18-modules.md
// ============================================================================

source_file = [ file_attribute ] { import | reexport | extension_import } { declaration } .

// File-level attribute (conditional compilation)
// See: 24-conditional-compilation.md § File-Level Conditions
file_attribute = "#!" identifier "(" [ attribute_arg { "," attribute_arg } ] ")" .

// --- Imports ---
// See: 12-modules.md § Imports

import      = "use" import_path [ import_list | "as" identifier ] ";" .
import_path = string_literal | identifier { "." identifier } .
import_list = "{" import_item { "," import_item } "}" .
import_item = [ "::" ] identifier [ "without" "def" ] [ "as" identifier ] | "$" identifier .

// --- Re-exports ---

reexport = "pub" "use" import_path import_list ";" .

// --- Extensions ---
// See: 12-modules.md § Extensions

extension_def    = "extend" [ generics ] type [ where_clause ] "{" { method } "}" .
extension_import = [ "pub" ] "extension" import_path "{" extension_item { "," extension_item } "}" .
extension_item   = identifier "." identifier .

// --- FFI (Foreign Function Interface) ---
// See: spec/24-ffi.md

extern_block  = [ "pub" ] "extern" string_literal [ "from" string_literal ]
                { block_attribute } "{" { extern_item } "}" .
extern_item   = "@" identifier extern_params "->" [ ownership ] type
                [ "as" string_literal ]
                { item_attribute } .
extern_params = "(" [ extern_param { "," extern_param } ] [ c_variadic ] ")" .
extern_param  = [ param_modifier ] identifier ":" [ ownership ] type .
c_variadic    = "," "..." .  /* C-style variadic - only valid in extern "c" blocks */

// Deep FFI annotations (see: proposals/approved/deep-ffi-proposal.md)
param_modifier  = "out" | "mut" .
ownership       = "owned" | "borrowed" .
block_attribute = "#" identifier "(" { attribute_arg } ")" .  /* #error(...), #free(...) */
item_attribute  = "#" identifier "(" { attribute_arg } ")" .  /* per-function overrides */

// Parametric FFI capability
ffi_capability  = "FFI" [ "(" string_literal ")" ] .


// ============================================================================
// DECLARATIONS
// See: 08-declarations.md
// ============================================================================

declaration = { attribute } [ "pub" ] ( function | type_def | trait_def | impl_block | extension_def | test | constant_decl | extern_block | capset_decl ) .

// --- Attributes ---
// See: 08-declarations.md § Attributes, 24-conditional-compilation.md
// Item-level: #derive(...), #skip(...), #target(...), #cfg(...)

attribute      = "#" identifier [ "(" [ attribute_arg { "," attribute_arg } ] ")" ] .
attribute_arg  = expression | identifier ":" expression | array_literal .
array_literal  = "[" [ string_literal { "," string_literal } ] "]" .

// --- Functions ---
// See: 08-declarations.md § Functions

function      = "@" identifier [ generics ] clause_params "->" type [ uses_clause ] [ where_clause ] [ guard_clause ] { contract } "=" expression [ ";" ] .
/* Semicolon rule: ";" is required when the body expression does not end with "}".
   When the body is a block_expr (ending with "}"), ";" is omitted — same as Rust's fn. */
clause_params = "(" [ clause_param { "," clause_param } ] ")" .
clause_param  = match_pattern [ ":" type ] [ "=" expression ] .  /* pattern with optional type and default */
guard_clause  = "if" expression .

// --- Generics ---
// See: 06-types.md § Const Generic Parameters

generics      = "<" generic_param { "," generic_param } ">" .
generic_param = type_param | const_param .
type_param    = identifier [ ":" bounds ] [ "=" type ] .
const_param   = "$" identifier ":" const_type [ "=" const_expr ] .
const_type    = "int" | "bool" .
bounds        = type_path { "+" type_path } .
where_clause  = "where" constraint { "," constraint } .
constraint    = type_constraint | const_constraint .
type_constraint = identifier ":" bounds .
const_constraint = const_bound_expr .

// Const bound expressions (for where clauses)
// See: 06-types.md § Const Bounds
const_bound_expr = const_or_expr .
const_or_expr    = const_and_expr { "||" const_and_expr } .
const_and_expr   = const_not_expr { "&&" const_not_expr } .
const_not_expr   = "!" const_not_expr | const_cmp_expr .
const_cmp_expr   = const_expr comparison_op const_expr
                 | "(" const_bound_expr ")" .
comparison_op    = ">" | "<" | ">=" | "<=" | "==" | "!=" .

// --- Capabilities ---
// See: 14-capabilities.md

uses_clause  = "uses" identifier { "," identifier } .
capset_decl  = "capset" identifier "=" identifier { "," identifier } ";" .

// --- Type Definitions ---
// See: 08-declarations.md § Types, 06-types.md § User-Defined Types

type_def    = "type" identifier [ generics ] [ where_clause ] "=" type_body [ ";" ] .
/* Semicolon rule: ";" required for sum types and newtypes (no "}"); omitted for struct types (end with "}") */
type_body   = struct_body | sum_body | type .
struct_body = "{" [ field { "," field } ] "}" .
sum_body    = variant { "|" variant } .
variant     = identifier [ "(" [ field { "," field } ] ")" ] .
field       = identifier ":" type .

// --- Traits ---
// See: 08-declarations.md § Traits

trait_def      = "trait" identifier [ generics ] [ ":" bounds ] "{" { trait_item } "}" .
trait_item     = method_sig | default_method | assoc_type .
method_sig     = "@" identifier params "->" type ";" .
default_method = "@" identifier params "->" type "=" expression [ ";" ] .
/* Semicolon rule: same as function — ";" required unless body ends with "}" */
assoc_type     = "type" identifier [ ":" bounds ] [ "=" type ] .
params         = "(" [ param { "," param } ] ")" .
param          = identifier ":" type | variadic_param .
variadic_param = identifier ":" "..." type .

// --- Implementations ---
// See: 08-declarations.md § Implementations

impl_block    = inherent_impl | trait_impl | def_impl .
inherent_impl = "impl" [ generics ] type_path [ where_clause ] "{" { method } "}" .
trait_impl    = "impl" [ generics ] type ":" type_path [ where_clause ] "{" { method } "}" .
def_impl      = "def" "impl" identifier "{" { def_impl_method } "}" .
method        = "@" identifier params "->" type [ uses_clause ] "=" expression [ ";" ] .
def_impl_method = "@" identifier params "->" type "=" expression [ ";" ] .  /* no self, no uses */
/* Semicolon rule: same as function — ";" required unless body ends with "}" */

// --- Tests ---
// See: 13-testing.md

test         = "@" identifier "tests" test_targets "()" "->" "void" "=" expression [ ";" ] .
/* Semicolon rule: same as function — ";" required unless body ends with "}" */
test_targets = "_" | test_target { "tests" test_target } .
test_target  = "@" identifier .

// --- Constants (Immutable Bindings) ---
// See: 04-constants.md

constant_decl = "let" "$" identifier [ ":" type ] "=" expression ";" .


// ============================================================================
// TYPES
// See: 06-types.md
// ============================================================================

type          = type_path [ type_args ]
              | trait_object_bounds            /* Printable + Hashable */
              | list_type | fixed_list_type | map_type | tuple_type | function_type
              | impl_trait_type .
type_path     = identifier { "." identifier } .

// --- Bounded Trait Objects ---
// See: 06-types.md § Bounded Trait Objects
// Multiple trait bounds as a type: `@store (item: Printable + Hashable) -> void`
trait_object_bounds = type_path "+" type_path { "+" type_path } .

// --- Existential Types (impl Trait) ---
// See: 06-types.md § Existential Types

impl_trait_type   = "impl" trait_bounds [ impl_where_clause ] .
trait_bounds      = type_path { "+" type_path } .
impl_where_clause = "where" assoc_constraint { "," assoc_constraint } .
assoc_constraint  = identifier "==" type .
type_args     = "<" type_or_const { "," type_or_const } ">" .
type_or_const = type | const_expr .
list_type     = "[" type "]" .
fixed_list_type = "[" type "," "max" const_expr "]" .
map_type      = "{" type ":" type "}" .
tuple_type    = "(" type { "," type } ")" | "()" .
function_type = "(" [ type { "," type } ] ")" "->" type .
/* const_expr is defined in § CONSTANT EXPRESSIONS below */


// ============================================================================
// EXPRESSIONS
// See: 09-expressions.md
// ============================================================================

expression = with_expr | let_expr | if_expr | for_expr | while_expr | loop_expr | lambda | break_expr | continue_expr | unsafe_expr | block_expr | match_expr | try_expr | binary_expr .

// --- Primary Expressions ---

primary       = literal | identifier | "self" | "Self"
              | "(" expression ")"
              | "#"                                   /* length in index context */
              | list_literal | map_literal | struct_literal
              | block_expr                            /* { expr \n expr \n result } */
              | match_expr                            /* match expr { arms } */
              | try_expr                              /* try { block_body } */
              | pattern_expr                          /* parallel, spawn, etc. */
              | unsafe_expr
              | embed_expr | has_embed_expr .

// --- Block Expression ---
// See: proposals/approved/block-expression-syntax.md
// Semicolons terminate statements inside blocks. The last expression without ";"
// is the block's value. A block where every expression has ";" returns void.

block_expr  = "{" { statement } [ expression ] "}" .
statement   = ( let_expr | assignment | expression ) ";" .

// --- Unsafe Expression ---
// See: spec/24-ffi.md § Unsafe Blocks

unsafe_expr = "unsafe" block_expr .

// --- Embed Expressions ---
// See: 11-built-in-functions.md § embed, § has_embed
// See: proposals/approved/embed-expression-proposal.md

embed_expr     = "embed" "(" expression ")" .
has_embed_expr = "has_embed" "(" expression ")" .

// List literals with spread support
// See: 09-expressions.md § Spread Operator
list_literal   = "[" [ list_element { "," list_element } ] "]" .
list_element   = "..." expression | expression .

// Map literals with spread support
// See: computed-map-keys-proposal.md for key semantics
map_literal    = "{" [ map_element { "," map_element } ] "}" .
map_element    = "..." expression | map_entry .
map_entry      = map_key ":" expression .
map_key        = "[" expression "]"       /* computed key: evaluates expression */
               | identifier               /* literal string key: "foo" from foo */
               | string_literal .         /* literal string key */

// Struct literals with spread support
struct_literal  = type_path "{" [ struct_element { "," struct_element } ] "}" .
struct_element  = "..." expression | field_init .
field_init      = identifier [ ":" expression ] .

// --- Postfix Expressions ---
// See: 09-expressions.md § Postfix Expressions

postfix_expr   = primary { postfix_op } .
postfix_op     = "." member_name [ call_args ]       /* field/method access */
               | "." match_method                    /* method-style match */
               | "[" expression "]"                  /* index access */
               | call_args                           /* function call */
               | "?"                                 /* error propagation */
               | "as" type                           /* infallible type conversion */
               | "as?" type .                        /* fallible type conversion */
member_name    = identifier | keyword | int_literal .  /* keywords/ints valid after "." (tuple: t.0) */
match_method   = "match" "(" match_arm { "," match_arm } ")" .
call_args      = "(" [ call_arg { "," call_arg } ] ")" .
call_arg       = named_arg | positional_arg | spread_arg .
named_arg      = identifier ":" [ expression ] .  /* punned when expression omitted: f(x:) = f(x: x) */
positional_arg = expression .
spread_arg     = "..." expression .  /* spread into variadic position only */

// --- Unary Expressions ---
// See: 09-expressions.md § Unary Expressions

unary_expr = [ "!" | "-" | "~" ] power_expr .

// --- Power Expression ---
// See: operator-rules.md § Power
// ** binds tighter than unary: -x ** 2 = -(x ** 2)

power_expr = postfix_expr [ "**" power_expr ] .  /* right-associative */

// --- Binary Expressions ---
// See: 09-expressions.md § Binary Expressions
// Precedence (lowest to highest): |>, ??, ||, &&, |, ^, &, ==, cmp, range, shift, add, mul, unary, power

binary_expr   = pipe_expr .
pipe_expr     = coalesce_expr { "|>" pipe_step } .
pipe_step     = "." member_name [ call_args ]    /* method on piped value */
              | postfix_expr [ call_args ]        /* function call with implicit fill */
              | lambda .                          /* expression-level operation */
coalesce_expr = or_expr [ "??" coalesce_expr ] .  /* right-associative */
or_expr       = and_expr { "||" and_expr } .
and_expr      = bit_or_expr { "&&" bit_or_expr } .
bit_or_expr   = bit_xor_expr { "|" bit_xor_expr } .
bit_xor_expr  = bit_and_expr { "^" bit_and_expr } .
bit_and_expr  = eq_expr { "&" eq_expr } .
eq_expr       = cmp_expr { ( "==" | "!=" ) cmp_expr } .
cmp_expr      = range_expr { ( "<" | ">" | "<=" | ">=" ) range_expr } .
range_expr    = shift_expr [ ( ".." | "..=" ) [ shift_expr ] [ "by" shift_expr ] ] .
shift_expr    = add_expr { ( "<<" | ">>" ) add_expr } .
add_expr      = mul_expr { ( "+" | "-" ) mul_expr } .
mul_expr      = unary_expr { ( "*" | "/" | "%" | "div" | "@" ) unary_expr } .

// --- With Expression ---
// See: 09-expressions.md § With Expression, 14-capabilities.md § Providing Capabilities

with_expr           = "with" capability_binding { "," capability_binding } "in" expression .
capability_binding  = identifier "=" ( handler_expr | expression ) .

// --- Handler Expression (Stateful Effect Handlers) ---
// See: 14-capabilities.md § Stateful Handlers, proposals/approved/stateful-mock-testing-proposal.md
// `handler` is context-sensitive: valid only in the expression position of a capability_binding.

handler_expr        = "handler" "(" "state" ":" expression ")" "{" handler_operations "}" .
handler_operations  = handler_operation { "," handler_operation } .
handler_operation   = identifier ":" expression .

// --- Let Binding ---
// See: 09-expressions.md § Let Binding, 05-variables.md

let_expr = "let" binding_pattern [ ":" type ] "=" expression .
assignment        = assignment_target "=" expression
                  | assignment_target compound_op expression .
assignment_target = identifier { "[" expression "]" | "." identifier } .
compound_op       = "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "@="
                  | "&=" | "|=" | "^=" | "<<=" | ">>="
                  | "&&=" | "||=" .
binding           = let_expr | assignment .  /* convenience grouping; not currently referenced */

// --- Conditional ---
// See: 09-expressions.md § Conditional

if_expr = "if" expression "then" expression
          { "else" "if" expression "then" expression }
          [ "else" expression ] .

// --- For Expression ---
// See: 09-expressions.md § For Expression, 19-control-flow.md § Labeled Loops

for_expr       = "for" [ label ] binding_pattern "in" expression [ "if" expression ] { for_clause } ( "do" | "yield" ) expression .
for_clause     = "for" binding_pattern "in" expression [ "if" expression ] .

// --- Loop Expression ---
// See: 09-expressions.md § Loop Expression, 19-control-flow.md § Labeled Loops

loop_expr = "loop" [ label ] block_expr .

// --- While Expression ---
// See: 16-control-flow.md § While Loop
// Desugars to: loop { if !condition then break; body }

while_expr = "while" [ label ] expression "do" expression .

// --- Labels ---
// See: 19-control-flow.md § Labeled Loops
label = ":" identifier .  /* no space around colon */

// --- Lambda ---
// See: 09-expressions.md § Lambda

lambda        = simple_lambda | typed_lambda .
simple_lambda = lambda_params "->" expression .
typed_lambda  = "(" [ typed_param { "," typed_param } ] ")" "->" type "=" expression .
lambda_params = identifier | "(" [ identifier { "," identifier } ] ")" .
typed_param   = identifier ":" type .

// --- Control Flow ---
// See: 19-control-flow.md

break_expr    = "break" [ label ] [ expression ] .
continue_expr = "continue" [ label ] [ expression ] .


// ============================================================================
// PATTERNS (COMPILER CONSTRUCTS)
// See: 10-patterns.md
// ============================================================================

// --- Pattern Categories ---

pattern_expr = function_exp | function_val | channel_expr | for_pattern | catch_expr | nursery_expr .
function_exp = pattern_name "(" pattern_arg { "," pattern_arg } ")" .
pattern_name = "recurse" | "parallel" | "spawn" | "timeout" | "cache" | "with" .  /* nursery has explicit nursery_expr */
pattern_arg  = identifier ":" expression .

// Type conversion patterns (call position only)
function_val = ( "int" | "float" | "str" | "byte" ) "(" expression ")" .

// --- Block-Based Expressions ---
// See: proposals/approved/block-expression-syntax.md

// match: Pattern matching with scrutinee before block
match_expr = "match" expression "{" match_arms "}" .
match_arms = [ match_arm { "," match_arm } [ "," ] ] .
match_arm  = match_pattern [ "if" expression ] "->" expression .

// try: Error-propagating block (returns early on Err)
try_expr = "try" block_expr .

// --- Function-Level Contracts ---
// See: proposals/approved/block-expression-syntax.md § Function-Level Contracts
// Contracts sit between the return type and the "=" in function declarations.

contract       = pre_contract | post_contract .
pre_contract   = "pre" "(" check_expr ")" .
post_contract  = "post" "(" postcheck_expr ")" .
check_expr     = expression [ "|" string_literal ] .
postcheck_expr = lambda_params "->" check_expr .

// for pattern: First-match iteration
// See: 10-patterns.md § for Pattern
for_pattern = "for" "(" for_pattern_args ")" .
for_pattern_args = "over" ":" expression "," "match" ":" match_pattern "->" expression "," "default" ":" expression
                 | "over" ":" expression "," "map" ":" expression "," "match" ":" match_pattern "->" expression "," "default" ":" expression .

// catch: Panic recovery
// See: 20-errors-and-panics.md § Catching Panics
catch_expr = "catch" "(" "expr" ":" expression ")" .

// nursery: Structured concurrency
// See: 10-patterns.md § Concurrency
nursery_expr = "nursery" "(" nursery_args ")" .
nursery_args = "body" ":" lambda "," "on_error" ":" expression [ "," "timeout" ":" expression ] .

// --- Channel Constructors ---
// See: 06-types.md § Channel Types
channel_expr = channel_constructor "(" "buffer" ":" expression ")" .
channel_constructor = "channel" [ type_args ] | "channel_in" [ type_args ] | "channel_out" [ type_args ] | "channel_all" [ type_args ] .

// --- Match Patterns ---
// See: 10-patterns.md § Match Patterns

match_pattern = literal_pattern
              | identifier_pattern
              | wildcard_pattern
              | variant_pattern
              | struct_pattern
              | tuple_pattern
              | list_pattern
              | range_pattern
              | or_pattern
              | at_pattern .

literal_pattern     = [ "-" ] int_literal | string_literal | char_literal | byte_literal | bool_literal .
identifier_pattern  = identifier .
wildcard_pattern    = "_" .
variant_pattern     = type_path [ "(" [ variant_field { "," variant_field } ] ")" ] .
variant_field       = identifier ":" [ match_pattern ]   /* named; punned if pattern omitted */
                    | match_pattern .                     /* positional */
struct_pattern      = [ type_path ] "{" [ field_pattern { "," field_pattern } ] [ ".." ] "}" .
field_pattern       = identifier [ ":" match_pattern ] .
tuple_pattern       = "(" [ match_pattern { "," match_pattern } ] ")" .
list_pattern        = "[" [ list_pattern_elems ] "]" .
list_pattern_elems  = match_pattern { "," match_pattern } [ "," ".." [ identifier ] ]
                    | ".." [ identifier ] .
range_pattern       = literal_pattern ( ".." | "..=" ) literal_pattern .
or_pattern          = match_pattern "|" match_pattern .
at_pattern          = identifier "@" match_pattern .

// --- Binding Patterns ---
// See: 05-variables.md § Destructuring
// The "$" prefix marks immutable bindings; without "$", bindings are mutable.

binding_pattern = [ "$" ] identifier
                | "_"
                | "{" [ field_binding { "," field_binding } ] "}"
                | "(" [ binding_pattern { "," binding_pattern } ] ")"
                | "[" [ binding_pattern { "," binding_pattern } [ ".." [ "$" ] identifier ] ] "]" .
field_binding   = [ "$" ] identifier [ ":" binding_pattern ] .


// ============================================================================
// CONSTANT EXPRESSIONS
// See: 04-constants.md, 21-constant-expressions.md
// ============================================================================

const_expr = literal
           | "$" identifier
           | const_expr ( arith_op | comp_op | "&&" | "||" | "&" | "|" | "^" | "<<" | ">>" ) const_expr
           | unary_op const_expr
           | "(" const_expr ")" .


// ============================================================================
// PROGRAM ENTRY
// See: 18-program-execution.md
// ============================================================================

main_function = "@main" main_params "->" main_return "=" expression [ ";" ] .
main_params   = "()" | "(" "args" ":" "[" "str" "]" ")" .
main_return   = "void" | "int" | "Never" .


// ============================================================================
// END OF GRAMMAR
// ============================================================================