Grammar
bedrock-lang grammar
# Program
program = { item }
item = import_def | function | proc_def | struct_def | enum_def | extern_def
| var_def | const_def
import_def = "import" IDENT { "." IDENT } ";"
# Generics
type_params = "[" type_param { "," type_param } [ "," ] "]"
type_param = IDENT
# Functions and Procedures
function = [ "pub" ] [ "inline" ] "func" IDENT [ type_params ] "(" [ params ] ")" result block "end"
proc_def = [ "pub" ] [ "inline" ] "proc" IDENT [ type_params ] "(" [ params ] ")" block "end"
result = "->" type
params = param { "," param } [ "," ]
param = IDENT ":" [ "const" ] type
block = { statement }
# Foreign Function Interface
extern_def = "extern" ( "func" IDENT "(" [ extern_params ] ")" "->" type
| "proc" IDENT "(" [ extern_params ] ")" ) ";"
extern_params = extern_param { "," extern_param } [ "," "..." ]
| "..."
extern_param = IDENT ":" type
# Structs and Enums
struct_def = [ "pub" ] "type" IDENT [ type_params ] "=" "struct" [ struct_members ] "end"
struct_literal = ( IDENT | "_" ) "where" [ field_inits ] "end"
field_inits = field_init { "," field_init } [ "," ]
field_init = IDENT "=" expression
struct_members = struct_member { struct_member }
struct_member = struct_field ","
| method_def
struct_field = [ "pub" ] IDENT ":" type
method_def = [ "pub" ] [ "inline" ] "func" IDENT [ type_params ] "(" [ params ] ")" result block "end"
| [ "pub" ] [ "inline" ] "proc" IDENT [ type_params ] "(" [ params ] ")" block "end"
enum_def = [ "pub" ] "type" IDENT [ type_params ] "=" "enum" [ enum_variants ] "end"
enum_variants = enum_variant { "," enum_variant } [ "," ]
enum_variant = IDENT [ "(" type_list ")" ]
# Statements
statement = var_stmt | local_static_var_stmt | assign_stmt | defer_stmt
| unsafe_stmt | control_flow_stmt | return_stmt | expr_stmt
var_stmt = "var" IDENT [ ":" type ] "=" expression ";"
assign_stmt = place_expr ( "=" | compound_op ) expression ";"
var_def = [ "pub" ] "var" IDENT [ ":" type ] "=" expression ";"
# like c, does not change value in simultanous calls.
local_static_var_stmt = "static" "var" IDENT [ ":" type ] "=" expression ";"
const_def = [ "pub" ] "const" IDENT [ ":" type ] "=" expression ";"
place_expr = "*" "(" expression ")"
| "*" IDENT
| IDENT { ( "." IDENT ) | ( "[" expression "]") }
compound_op = "+=" | "-=" | "*=" | "/=" | "%="
| "&=" | "|=" | "^=" | "<<=" | ">>="
defer_stmt = "defer" block "end"
unsafe_stmt = "unsafe" block "end"
control_flow_stmt = control_flow_expr # if/match/while/for used as a statement — no ";", it ends on "end"
return_stmt = return_expr ";" # return is statement-only, never nested inside an expression
expr_stmt = expression ";"
comptime_expr = "comptime" block "end"
control_flow_expr = if_expr | match_expr | while_expr | for_expr
if_expr = "if" expression block { elif_clause } [ else_clause ] "end"
elif_clause = "elif" expression block
else_clause = "else" block
return_expr = "return" [ expression ]
for_expr = "for" IDENT [ "," IDENT ] "in" expression [ "," additive ".." ] block "end"
while_expr = "while" expression block "end"
# Match expression
match_expr = "match" expression [ match_arms ] "end"
match_arms = match_arm { match_arm } [ else_arm ]
match_arm = "case" pattern block
else_arm = "else" block
pattern = literal_pattern | variant_pattern
literal_pattern = INTEGER | FLOAT | CHAR | STRING | BOOL
variant_pattern = IDENT [ "(" [ pattern_params ] ")" ]
pattern_params = pattern { "," pattern } [ "," ]
expression = orelse_expr
orelse_expr = or_expr [ "orelse" expression ]
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 = range_expr { ( "<<" | ">>" ) range_expr }
range_expr = additive [ ( ".." | "..=" ) additive ]
additive = multiplicative { ( "+" | "-" ) multiplicative }
multiplicative = unary { ( "*" | "/" | "%" ) unary }
unary = ( "-" | "!" | "~" | "&" | "*" | "try" ) unary | postfix
postfix = primary { suffix }
suffix = "." IDENT
| "(" [ call_args ] ")"
| "[" expression { "," expression } [ "," ] "]" # handles both foo[index] and foo[type]
| "?"
primary = INTEGER | FLOAT | CHAR | STRING | BOOL | IDENT
| control_flow_expr
| comptime_expr
| array_literal
| struct_literal
| "(" expression ")"
array_literal = "[" [ array_elems ] "]"
array_elems = expression { "," expression } [ "," ]
call_args = call_arg { "," call_arg } [ "," ]
call_arg = expression
type = [ "?" ] base_type [ "!" ]
base_type = "i8" | "i16" | "i32" | "i64"
| "u8" | "u16" | "u32" | "u64"
| "usize" | "isize"
| "f32" | "f64"
| "bool" | "char" | "str"
| "*" type
| array_type
| slice_type
| named_type
| func_type
| proc_type
array_type = "[" ( INTEGER | "_" ) "]" type
slice_type = "[" "]" type
named_type = IDENT [ "[" type { "," type } [ "," ] "]" ]
type_list = type { "," type } [ "," ]
func_type = "func" "(" [ type_list ] ")" result
proc_type = "proc" "(" [ type_list ] ")"
# Lexical elements
INTEGER = dec_literal | hex_literal | oct_literal | bin_literal
FLOAT = dec_literal "." dec_literal
CHAR = "'" ( char_char | escape ) "'"
char_char = any character except "'" or "\"
dec_literal = digit { digit | "_" }
hex_literal = "0x" { hex_digit | "_" }
oct_literal = "0o" { oct_digit | "_" }
bin_literal = "0b" { bin_digit | "_" }
hex_digit = digit | "a" | ... | "f" | "A" | ... | "F"
oct_digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7"
bin_digit = "0" | "1"
STRING = '"' { string_char | escape } '"'
escape = "\\" ( "\\" | '"' | "n" | "t" | "r" | "0" )
BOOL = "true" | "false"
letter = "a" | ... | "z" | "A" | ... | "Z"
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
whitespace = " " | "\t" | "\n" | "\r"
line_comment = "//" { any_char_except_newline }