Appendix A: Grammar

This appendix contains the complete EBNF grammar for Rue.

(* Program structure *)
program        = { item } ;
item           = function | struct_def | enum_def ;

(* Functions *)
function       = "fn" IDENT "(" [ params ] ")" [ "->" type ] "{" block "}" ;
params         = param { "," param } ;
param          = IDENT ":" type ;
block          = { statement } [ expression ] ;

(* Structs *)
struct_def     = "struct" IDENT "{" [ struct_fields ] "}" ;
struct_fields  = struct_field { "," struct_field } [ "," ] ;
struct_field   = IDENT ":" type ;

(* Enums *)
enum_def       = "enum" IDENT "{" [ enum_variants ] "}" ;
enum_variants  = IDENT { "," IDENT } [ "," ] ;

(* Statements *)
statement      = let_stmt | assign_stmt | expr_stmt ;
let_stmt       = "let" [ "mut" ] IDENT [ ":" type ] "=" expression ";" ;
assign_stmt    = IDENT "=" expression ";"
               | IDENT "[" expression "]" "=" expression ";"
               | expression "." IDENT "=" expression ";" ;
expr_stmt      = expression ";" ;

(* Types *)
type           = "i8" | "i16" | "i32" | "i64"
               | "u8" | "u16" | "u32" | "u64"
               | "bool" | "()"
               | "[" type ";" INTEGER "]"
               | IDENT ;

(* Expressions *)
expression     = or_expr ;
or_expr        = and_expr { "||" and_expr } ;
and_expr       = comparison { "&&" comparison } ;
comparison     = bitor_expr { ( "==" | "!=" | "<" | ">" | "<=" | ">=" ) bitor_expr } ;
bitor_expr     = bitxor_expr { "|" bitxor_expr } ;
bitxor_expr    = bitand_expr { "^" bitand_expr } ;
bitand_expr    = shift_expr { "&" shift_expr } ;
shift_expr     = additive { ( "<<" | ">>" ) additive } ;
additive       = multiplicative { ( "+" | "-" ) multiplicative } ;
multiplicative = unary { ( "*" | "/" | "%" ) unary } ;
unary          = "-" unary | "!" unary | "~" unary | postfix ;
postfix        = primary { "[" expression "]" | "(" [ args ] ")" | "." IDENT } ;
args           = expression { "," expression } ;
primary        = INTEGER | BOOL | IDENT | enum_variant_expr
               | "(" expression ")"
               | block_expr
               | if_expr
               | match_expr
               | while_expr
               | loop_expr
               | "break" | "continue"
               | return_expr
               | array_literal
               | struct_literal
               | intrinsic ;
enum_variant_expr = IDENT "::" IDENT ;
intrinsic      = "@" IDENT "(" [ intrinsic_args ] ")" ;
intrinsic_args = intrinsic_arg { "," intrinsic_arg } ;
intrinsic_arg  = expression | type ;

(* Compound expressions *)
block_expr     = "{" block "}" ;
if_expr        = "if" expression "{" block "}" [ else_clause ] ;
else_clause    = "else" ( "{" block "}" | if_expr ) ;
match_expr     = "match" expression "{" { match_arm "," } [ match_arm ] "}" ;
match_arm      = pattern "=>" expression ;
pattern        = "_" | INTEGER | BOOL | enum_variant_pattern ;
enum_variant_pattern = IDENT "::" IDENT ;
while_expr     = "while" expression "{" block "}" ;
loop_expr      = "loop" "{" block "}" ;
return_expr    = "return" expression ;
array_literal  = "[" [ expression { "," expression } ] "]" ;
struct_literal = IDENT "{" [ field_inits ] "}" ;
field_inits    = field_init { "," field_init } [ "," ] ;
field_init     = IDENT ":" expression ;

(* Lexical elements *)
IDENT          = ( letter | "_" ) { letter | digit | "_" } ;
INTEGER        = digit { digit } ;
BOOL           = "true" | "false" ;
letter         = "a" | ... | "z" | "A" | ... | "Z" ;
digit          = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;

(* Whitespace and comments are ignored between tokens *)
whitespace     = " " | "\t" | "\n" | "\r" ;
line_comment   = "//" { any_char_except_newline } newline ;