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

SymbolMeaning
=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:

PrecedenceOperatorAssociativityDescription
1 (lowest)|> ~|>LeftPipe, Tap pipe
2|| orLeftLogical OR
3&& andLeftLogical AND
4== !=LeftEquality
5< <= > >= inLeftComparison
6.. ..=NoneRange
7??LeftNil coalescing
8+ - ++LeftAddition, concatenation
9* / %LeftMultiplication
10- ! notRight (prefix)Unary
11**RightExponentiation
12 (highest)() [] . ?.LeftPostfix