Grammar Reference
This page is the formal grammar of BioLang in EBNF-like notation. It serves as a reference for the language syntax — no runnable examples, just structure.
Notation
| Symbol | Meaning |
|---|---|
= | Definition |
| | Alternative |
( ) | Grouping |
[ ] | Optional (zero or one) |
{ } | Repetition (zero or more) |
" " | Terminal string |
; | End of rule |
Program Structure
program = { statement } ;
statement = import_stmt
| from_import_stmt
| let_stmt
| const_stmt
| assign_stmt
| fn_decl
| struct_decl
| enum_decl
| trait_decl
| impl_block
| type_alias
| for_stmt
| while_stmt
| return_stmt
| break_stmt
| continue_stmt
| assert_stmt
| pipeline_stmt
| stage_stmt
| defer_stmt
| parallel_for_stmt
| unless_stmt
| guard_stmt
| expression
;
terminator = NEWLINE | EOF ;
Newlines serve as statement terminators. The lexer automatically suppresses newlines after operators and opening delimiters, so multi-line expressions work without explicit line continuation characters.
Declarations
import_stmt = "import" STRING [ "as" IDENT ] ;
from_import_stmt = "from" STRING "import" ident_list ;
ident_list = IDENT { "," IDENT } ;
let_stmt = "let" IDENT [ ":" type_expr ] "=" expression ;
const_stmt = "const" IDENT [ ":" type_expr ] "=" expression ;
assign_stmt = IDENT "=" expression ;
fn_decl = "fn" IDENT "(" [ param_list ] ")" [ "->" type_expr ] block ;
param_list = param { "," param } ;
param = IDENT [ ":" type_expr ] [ "=" expression ] ;
struct_decl = "struct" IDENT "{" { field_decl } "}" ;
field_decl = IDENT ":" type_expr [ "=" expression ] ;
enum_decl = "enum" IDENT "{" variant { "," variant } [ "," ] "}" ;
variant = IDENT [ "(" ident_list ")" ] ;
trait_decl = "trait" IDENT "{" { trait_method } "}" ;
trait_method = "fn" IDENT "(" [ param_list ] ")" [ "->" type_expr ] [ block ] ;
impl_block = "impl" IDENT [ "for" IDENT ] "{" { fn_decl } "}" ;
type_alias = "type" IDENT "=" type_expr ;
Pipelines & Stages
pipeline_stmt = "pipeline" ( IDENT | STRING ) [ "(" param_list ")" ] block ;
stage_stmt = "stage" ( IDENT | STRING ) "->" expression ;
defer_stmt = "defer" expression ;
parallel_for_stmt = "parallel" "for" IDENT "in" expression block ;
Expressions
expression = pipe_expr ;
pipe_expr = or_expr { "|>" or_expr } ;
or_expr = and_expr { ( "||" | "or" ) and_expr } ;
and_expr = equality_expr { ( "&&" | "and" ) equality_expr } ;
equality_expr = comparison_expr { ( "==" | "!=" ) comparison_expr } ;
comparison_expr = range_expr { ( "<" | "<=" | ">" | ">=" | "in" ) range_expr } ;
range_expr = nil_coalesce_expr [ ( ".." | "..=" ) nil_coalesce_expr ] ;
nil_coalesce_expr = add_expr { "??" add_expr } ;
add_expr = mul_expr { ( "+" | "-" | "++" ) mul_expr } ;
mul_expr = unary_expr { ( "*" | "/" | "%" ) unary_expr } ;
unary_expr = ( "-" | "!" | "not" ) unary_expr
| power_expr
;
power_expr = postfix_expr [ "**" unary_expr ] ;
postfix_expr = primary { postfix_op } ;
postfix_op = "(" [ arg_list ] ")" (* function call *)
| "[" expression "]" (* index *)
| "[" expression ".." [ expression ] "]" (* slice *)
| "." IDENT (* field access *)
| "?." IDENT (* safe navigation *)
;
arg_list = arg { "," arg } ;
arg = [ IDENT ":" ] expression ; (* positional or named *)
primary = INT_LITERAL
| FLOAT_LITERAL
| STRING_LITERAL
| BOOL_LITERAL
| DNA_LITERAL
| RNA_LITERAL
| PROTEIN_LITERAL
| IDENT
| lambda_expr
| if_expr
| match_expr
| try_expr
| list_literal
| record_literal
| "(" expression ")"
| block
;
Compound Expressions
lambda_expr = "|" [ param_list ] "|" ( expression | block ) ;
if_expr = "if" expression ( block | "then" expression )
{ "else" "if" expression ( block | "then" expression ) }
[ "else" ( block | expression ) ] ;
match_expr = "match" expression "{"
{ match_arm }
"}" ;
match_arm = pattern [ "if" expression ] "=>" ( expression | block ) [ "," ] ;
try_expr = "try" block "catch" [ IDENT ] block ;
block = "{" { statement } [ expression ] "}" ;
list_literal = "[" [ expression { "," expression } [ "," ] ] "]" ;
record_literal = "{" [ field_init { "," field_init } [ "," ] ] "}" ;
field_init = ( IDENT | STRING ) ":" expression ;
Patterns
pattern = literal_pattern
| ident_pattern
| wildcard_pattern
| enum_pattern
| type_pattern
| or_pattern
;
literal_pattern = INT_LITERAL | FLOAT_LITERAL | STRING_LITERAL | BOOL_LITERAL ;
ident_pattern = IDENT ;
wildcard_pattern = "_" ;
enum_pattern = IDENT [ "(" ident_list ")" ] ;
type_pattern = IDENT "(" [ IDENT | "_" ] ")" ;
or_pattern = pattern "|" pattern ;
Control Flow Statements
for_stmt = "for" IDENT "in" expression block ;
while_stmt = "while" expression block ;
return_stmt = "return" [ expression ] ;
break_stmt = "break" ;
continue_stmt = "continue" ;
assert_stmt = "assert" "(" expression "," expression ")" ;
unless_stmt = "unless" expression block ;
guard_stmt = "guard" expression "else" block ;
Reserved Words
keyword = "let" | "const" | "fn" | "if" | "else" | "then" | "for" | "while"
| "in" | "match" | "return" | "break" | "continue" | "assert"
| "try" | "catch" | "import" | "from" | "as"
| "struct" | "enum" | "trait" | "impl"
| "pipeline" | "stage" | "defer" | "parallel"
| "unless" | "guard" | "with" | "given" | "otherwise"
| "yield" | "async" | "await" | "do" | "end" | "when"
| "retry" | "where" | "into" | "and" | "or" | "not"
| "true" | "false" | "nil"
;
Literals
INT_LITERAL = DIGIT { DIGIT | "_" }
| "0x" HEX_DIGIT { HEX_DIGIT | "_" }
| "0b" BIN_DIGIT { BIN_DIGIT | "_" }
| "0o" OCT_DIGIT { OCT_DIGIT | "_" }
;
FLOAT_LITERAL = DIGIT { DIGIT } "." DIGIT { DIGIT } [ EXPONENT ]
| DIGIT { DIGIT } EXPONENT
;
EXPONENT = ( "e" | "E" ) [ "+" | "-" ] DIGIT { DIGIT } ;
STRING_LITERAL = '"' { CHAR | ESCAPE } '"' ;
(* f-strings: f"text {expr} text" *)
FSTRING = 'f"' { CHAR | ESCAPE | "{" expression "}" } '"' ;
(* Raw strings: no escape processing *)
RAW_STRING = 'r"' { CHAR } '"' ;
ESCAPE = "\" ( "n" | "t" | "r" | "\" | '"' | "{" | "0" ) ;
DNA_LITERAL = 'dna"' { DNA_CHAR } '"' ;
DNA_CHAR = "A" | "T" | "C" | "G" | "N"
| "a" | "t" | "c" | "g" | "n" ;
RNA_LITERAL = 'rna"' { RNA_CHAR } '"' ;
RNA_CHAR = "A" | "U" | "C" | "G" | "N"
| "a" | "u" | "c" | "g" | "n" ;
PROTEIN_LITERAL = 'protein"' { AMINO_CHAR } '"' ;
AMINO_CHAR = "A" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "K" | "L"
| "M" | "N" | "P" | "Q" | "R" | "S" | "T" | "V" | "W" | "Y"
| "*"
;
REGEX_LITERAL = '~/' { CHAR } '/' ;
BOOL_LITERAL = "true" | "false" ;
Identifiers, Comments, Whitespace
IDENT = ( ALPHA | "_" ) { ALPHA | DIGIT | "_" } ;
ALPHA = "a".."z" | "A".."Z" ;
DIGIT = "0".."9" ;
COMMENT = "#" { any character except NEWLINE } NEWLINE ;
DOC_COMMENT = "##" { any character except NEWLINE } NEWLINE ;
WHITESPACE = " " | "\t" ;
NEWLINE = "\n" | "\r\n" ;
Newline Suppression
Newlines are suppressed (not emitted as tokens) when they follow any of these tokens, allowing expressions to span multiple lines:
suppress_after = "|>" | "~|>" | "=>" | "->" | "," | ":" | "=" | "."
| "(" | "[" | "{" | "#{" | "@"
| "+" | "++" | "-" | "*" | "**" | "/" | "%"
| "+=" | "-=" | "*=" | "/="
| "==" | "!=" | "<" | "<=" | ">" | ">="
| "&&" | "||" | "and" | "or" | "|" | "??" | "?."
| ".." | "..=" | "..." | "~"
| "else" | "do" | "when"
;
Operator Precedence
Operators listed from lowest to highest precedence:
| Precedence | Operator | Associativity | Description |
|---|---|---|---|
| 1 (lowest) | |> ~|> | Left | Pipe, Tap pipe |
| 2 | || or | Left | Logical OR |
| 3 | && and | Left | Logical AND |
| 4 | == != | Left | Equality |
| 5 | < <= > >= in | Left | Comparison |
| 6 | .. ..= | None | Range |
| 7 | ?? | Left | Nil coalescing |
| 8 | + - ++ | Left | Addition, concatenation |
| 9 | * / % | Left | Multiplication |
| 10 | - ! not | Right (prefix) | Unary |
| 11 | ** | Right | Exponentiation |
| 12 (highest) | () [] . ?. | Left | Postfix |