Quartz v5.25

Quartz Language Grammar — Formal Specification

Version: 5.25.0
Status: Living document — tracks the parser implementation
Source of truth: self-hosted/frontend/parser.qz (5712 lines)

Notation

This grammar uses Extended Backus-Naur Form (EBNF) with the following conventions:

NotationMeaning
'keyword'Terminal keyword (literal text)
TOKENTerminal token from lexer
ruleNon-terminal (grammar rule)
rule?Optional (zero or one)
rule*Zero or more
rule+One or more
rule1 | rule2Alternation
( ... )Grouping
NLNewline or semicolon

1. Program Structure

program        = NL* ( top_level NL* )* EOF ;

top_level      = import_decl
               | struct_decl
               | enum_decl
               | trait_decl
               | impl_decl
               | extend_decl
               | type_alias_decl
               | newtype_decl
               | const_decl
               | extern_decl
               | macro_decl
               | visibility_decl
               | func_decl
               | annotation top_level ;

visibility_decl = 'private' ;

2. Import Declarations

import_decl    = 'import' import_path
               | 'import' '*' 'from' import_path ;

import_path    = IDENT ( '/' IDENT )* ;

3. Type Expressions

type           = borrow_type
               | never_type
               | record_type
               | function_type
               | named_type
               | type union_or_intersect ;

borrow_type    = '&' 'mut'? type ;
never_type     = '!' ;

record_type    = '{' ( field_type ( ',' field_type )* )? '}'
                 union_or_intersect? ;

field_type     = IDENT ':' type ;

function_type  = 'Fn' '(' ( type ( ',' type )* )? ')' ( ':' type )? ;

named_type     = IDENT ( '.' IDENT )* type_args? ;

type_args      = '<' type ( ',' type )* '>' ;

type_params    = '<' IDENT ( ',' IDENT )* '>' ;

union_or_intersect = ( '|' type | '&' type )* ;

4. Function Declarations

func_decl      = 'def' IDENT type_params?
                 '(' param_list? ')' ( ':' type )?
                 ( '=' expr | NL body 'end' )
               | 'def' IDENT type_params?
                 '(' param_list? ')' ( ':' type )?
                 where_clause?
                 NL body 'end' ;

param_list     = param ( ',' param )* ;
param          = IDENT ':' type ( '=' expr )? ;

where_clause   = 'where' constraint ( ',' constraint )* ;
constraint     = IDENT ':' type ( '+' type )* ;

5. Struct, Enum, Trait, Impl, Extend

struct_decl    = annotation? 'struct' IDENT type_params? NL
                 ( doc_comment? field_decl NL )* 'end' ;

field_decl     = IDENT ':' type ( '=' expr )? ;

enum_decl      = 'enum' IDENT type_params? NL
                 ( doc_comment? variant_decl NL )* 'end' ;

variant_decl   = IDENT ( '(' type ( ',' type )* ')' )? ;

trait_decl     = 'trait' IDENT type_params? NL
                 ( func_decl NL )* 'end' ;

impl_decl      = 'impl' IDENT 'for' type NL
                 ( func_decl NL )* 'end' ;

extend_decl    = 'extend' type type_params? NL
                 ( func_decl NL )* 'end' ;

6. Type Aliases and Newtypes

type_alias_decl = 'type' IDENT type_params? '=' type ;

newtype_decl   = 'newtype' IDENT '=' type ;

7. Constants

const_decl     = 'const' IDENT ( ':' type )? '=' expr ;

8. Extern (FFI)

extern_decl    = 'extern' STRING 'def' IDENT
                 '(' param_list? ')' ( ':' type )? ;

9. Macro Declarations

macro_decl     = 'macro' IDENT '(' param_list? ')' NL
                 body 'end' ;

10. Annotations

annotation     = '@' IDENT ( '(' annotation_args ')' )? ;
annotation_args = IDENT ( ',' IDENT )* ;

11. Statements

body           = ( stmt NL )* ;

stmt           = const_assign
               | var_stmt
               | return_stmt
               | if_stmt
               | unless_stmt
               | while_stmt
               | loop_stmt
               | for_stmt
               | match_expr
               | break_stmt
               | continue_stmt
               | defer_stmt
               | arena_stmt
               | try_stmt
               | spawn_stmt
               | select_stmt
               | task_group_stmt
               | assign_stmt
               | expr ;

const_assign   = IDENT ( ':' type )? '=' expr ;
var_stmt       = 'var' IDENT ( ':' type )? '=' expr ;

return_stmt    = 'return' expr? ;

if_stmt        = 'if' expr NL body
                 ( 'elsif' expr NL body )*
                 ( 'else' NL body )?
                 'end'
               | expr 'if' expr          (* postfix if *)
               | expr 'unless' expr ;    (* postfix unless *)

unless_stmt    = 'unless' expr NL body 'end' ;

while_stmt     = 'while' expr NL body 'end' ;

loop_stmt      = 'loop' NL body 'end' ;

for_stmt       = 'for' IDENT 'in' expr '..' expr NL body 'end'
               | 'for' IDENT 'in' expr NL body 'end' ;

break_stmt     = 'break' ;
continue_stmt  = 'continue' ;

defer_stmt     = 'defer' expr ;

arena_stmt     = 'arena' NL body 'end' ;

try_stmt       = 'try' NL body
                 ( 'catch' IDENT NL body )?
                 'end' ;

spawn_stmt     = 'spawn' expr ;

select_stmt    = 'select' NL
                 ( 'when' expr NL body )*
                 ( 'default' NL body )?
                 'end' ;

task_group_stmt = 'task_group' IDENT NL body 'end' ;

12. Assignment

assign_stmt    = lvalue '=' expr
               | lvalue compound_op expr ;

lvalue         = IDENT
               | expr '.' IDENT
               | expr '[' expr ']' ;

compound_op    = '+=' | '-=' | '*=' | '/=' | '%=' | '^=' ;

13. Expressions

expr           = arrow_lambda
               | or_expr
               | or_expr '?' expr ':' expr    (* ternary *)
               | or_expr '??' expr            (* nil coalesce *)
               | or_expr '|>' expr            (* pipe *)
               | expr 'as' type              (* type cast *)
               | 'not' expr ;

or_expr        = and_expr ( 'or' and_expr )* ;
and_expr       = eq_expr ( 'and' eq_expr )* ;
eq_expr        = cmp_expr ( ( '==' | '!=' | '=~' | '!~' | '?=' ) cmp_expr )* ;
cmp_expr       = bitor_expr ( ( '<' | '>' | '<=' | '>=' ) bitor_expr )* ;
bitor_expr     = bitxor_expr ( '|' bitxor_expr )* ;
bitxor_expr    = bitand_expr ( '^' bitand_expr )* ;
bitand_expr    = shift_expr ( '&' shift_expr )* ;
shift_expr     = add_expr ( ( '<<' | '>>' ) add_expr )* ;
add_expr       = mul_expr ( ( '+' | '-' ) mul_expr )* ;
mul_expr       = unary_expr ( ( '*' | '/' | '%' ) unary_expr )* ;

unary_expr     = '-' unary_expr
               | '~' unary_expr
               | '!' unary_expr
               | '&' 'mut'? unary_expr      (* address-of / borrow *)
               | '*' unary_expr             (* dereference *)
               | postfix_expr ;

postfix_expr   = primary ( postfix_op )* ;

postfix_op     = '.' IDENT ( '(' arg_list? ')' )?    (* field access / method call *)
               | '?.' IDENT                            (* optional chaining *)
               | '[' expr ']'                          (* index *)
               | '(' arg_list? ')' do_block?           (* function call *)
               | '!' IDENT                             (* unwrap variant *)
               | '$' IDENT ( '(' arg_list? ')' )?      (* qualified call *)
               | 'as' type ;                           (* type cast *)

14. Primary Expressions

primary        = INT_LIT
               | FLOAT_LIT
               | CHAR_LIT
               | STRING_LIT
               | INTERP_STRING
               | REGEX_LIT
               | SYMBOL_LIT
               | 'true' | 'false'
               | 'nil'
               | IDENT enum_or_struct_or_call?
               | '(' expr ')'                          (* grouped *)
               | '(' expr ',' expr ( ',' expr )* ')'   (* tuple *)
               | '[' ( expr ( ',' expr )* )? ']'       (* array *)
               | '{' map_or_set_literal '}'             (* map/set *)
               | match_expr
               | if_expr
               | do_block
               | macro_call
               | '_'                                    (* wildcard *)
               | 'await' expr ;

match_expr     = 'match' expr NL
                 ( pattern '=>' ( expr | NL body 'end' ) NL )*
                 'end' ;

if_expr        = 'if' expr 'then' expr 'else' expr ;

do_block       = 'do' ( param ( ',' param )* '->' )?
                 NL body 'end' ;

macro_call     = '$' IDENT '(' arg_list? ')' ;

15. Patterns

pattern        = '_'                                    (* wildcard *)
               | INT_LIT
               | STRING_LIT
               | 'true' | 'false' | 'nil'
               | IDENT '::' IDENT ( '(' pattern_list ')' )?  (* enum variant *)
               | IDENT                                  (* binding *)
               | pattern 'if' expr                      (* guard *)
               | pattern '|' pattern ;                  (* or-pattern *)

pattern_list   = pattern ( ',' pattern )* ;

16. Argument Lists

arg_list       = expr ( ',' expr )* ;

17. Operator Precedence (highest to lowest)

PrecOperatorsAssocDescription
14. ?. [] () ! $LeftPostfix
13- ~ ! & * (unary)RightUnary
12* / %LeftMultiplicative
11+ -LeftAdditive
10<< >>LeftShift
9&LeftBitwise AND
8^LeftBitwise XOR
7|LeftBitwise OR
6< > <= >=LeftComparison
5== != =~ !~ ?=LeftEquality
4andLeftLogical AND
3orLeftLogical OR
2|>LeftPipe
1??RightNil coalesce
0? :RightTernary

18. Lexical Grammar

(* Whitespace *)
WS             = ' ' | '\t' | '\r' ;

(* Newline *)
NL             = '\n' | ';' ;

(* Comments *)
comment        = '#' (not '\n')* ;
doc_comment    = '##' (not '\n')* ;
module_doc     = '##!' (not '\n')* ;

(* Identifiers *)
IDENT          = letter ( letter | digit | '_' )* ;
letter         = 'a'..'z' | 'A'..'Z' | '_' ;
digit          = '0'..'9' ;

(* Integer literals *)
INT_LIT        = decimal_lit | hex_lit | binary_lit ;
decimal_lit    = digit ( digit | '_' )* type_suffix? ;
hex_lit        = '0' ('x'|'X') hex_digit ( hex_digit | '_' )* ;
binary_lit     = '0' ('b'|'B') ('0'|'1') ( '0' | '1' | '_' )* ;
type_suffix    = '_' ('u8'|'i8'|'u16'|'i16'|'u32'|'i32'|'u64'|'i64') ;

(* Float literals *)
FLOAT_LIT      = digit+ '.' digit+ ;

(* String literals *)
STRING_LIT     = '"' string_char* '"' ;
string_char    = escape_seq | (not '"' and not '\') ;
escape_seq     = '\' ('n'|'t'|'r'|'\\'|'"'|'0'|'e') ;

(* Regex literals *)
REGEX_LIT      = '~r"' (not '"')* '"' ;

(* Character literals *)
CHAR_LIT       = "'" (escape_seq | not "'") "'" ;

(* Symbol literals *)
SYMBOL_LIT     = ':' IDENT ;

19. Keywords (Reserved)

and       arena     as        await     break     catch
const     continue  def       default   defer     do
else      elsif     end       enum      extend    extern
false     for       from      if        impl      import
in        let       loop      macro     match     newtype
nil       not       or        private   public    quote
return    select    spawn     struct    task_group then
trait     true      try       type      unless    unquote
unquote_each        var       when      where     while