Pre-alpha: Published for early evaluation only

Faber Language Specification

Formal grammar for the Faber programming language. This is the authoritative specification that both faber (TypeScript) and rivus (Faber) compilers implement.


Program Structure

program     := statement*
statement   := importDecl | varDecl | funcDecl | genusDecl | pactumDecl
             | typeAliasDecl | enumDecl | discretioDecl
             | ifStmt | whileStmt | exStmt | deStmt | inStmt
             | eligeStmt | discerneStmt | guardStmt | curaStmt
             | tryStmt | returnStmt | breakStmt | continueStmt | throwStmt
             | assertStmt | outputStmt | adStmt | incipitStmt
             | probandumDecl | probaStmt | blockStmt | exprStmt
blockStmt   := '{' statement* '}'

Declarations

Variables

varDecl      := ('fixum' | 'varia' | 'figendum' | 'variandum') typeAnnotation? IDENTIFIER ('=' expression)?
arrayDestruct := ('fixum' | 'varia') arrayPattern '=' expression
objectDestruct := ('fixum' | 'varia') objectPattern '=' expression

Functions

funcDecl     := 'functio' IDENTIFIER '(' paramList ')' funcModifier* returnClause? blockStmt
paramList    := (typeParamDecl ',')* (parameter (',' parameter)*)?
typeParamDecl := 'prae' 'typus' IDENTIFIER
parameter    := ('de' | 'in' | 'ex')? 'si'? 'ceteri'? typeAnnotation? IDENTIFIER ('ut' IDENTIFIER)? ('vel' expression)?
funcModifier := 'futura' | 'cursor' | 'curata' IDENTIFIER
returnClause := ('->' | 'fit' | 'fiet' | 'fiunt' | 'fient') typeAnnotation
lambdaExpr   := ('pro' | 'fit' | 'fiet') params? ('->' type)? (':' expression | blockStmt)

Classes

genusDecl    := 'abstractus'? 'genus' IDENTIFIER typeParams? ('sub' IDENTIFIER)? ('implet' IDENTIFIER (',' IDENTIFIER)*)? '{' genusMember* '}'
genusMember  := annotation* (fieldDecl | methodDecl)
fieldDecl    := 'generis'? 'nexum'? typeAnnotation IDENTIFIER (':' expression)?
methodDecl   := 'functio' IDENTIFIER '(' paramList ')' funcModifier* returnClause? blockStmt?
annotation   := '@' IDENTIFIER+

Interfaces

pactumDecl   := 'pactum' IDENTIFIER typeParams? '{' pactumMethod* '}'
pactumMethod := 'functio' IDENTIFIER '(' paramList ')' funcModifier* returnClause?

Type Aliases

typeAliasDecl := 'typus' IDENTIFIER '=' typeAnnotation

Enums

enumDecl   := 'ordo' IDENTIFIER '{' enumMember (',' enumMember)* ','? '}'
enumMember := IDENTIFIER ('=' ('-'? NUMBER | STRING))?

Tagged Unions

discretioDecl := 'discretio' IDENTIFIER typeParams? '{' variant (',' variant)* ','? '}'
variant       := IDENTIFIER ('{' variantFields '}')?
variantFields := (typeAnnotation IDENTIFIER (',' typeAnnotation IDENTIFIER)*)?

Imports

importDecl    := 'ex' (STRING | IDENTIFIER) 'importa' (specifierList | '*')
specifierList := specifier (',' specifier)*
specifier     := IDENTIFIER ('ut' IDENTIFIER)?

Types

typeAnnotation := ('de' | 'in')? IDENTIFIER typeParams? '?'? arrayBrackets*
typeParams     := '<' typeParameter (',' typeParameter)* '>'
typeParameter  := typeAnnotation | NUMBER | MODIFIER
arrayBrackets  := '[]' '?'?

Primitive Types

Faber Meaning
textus string
numerus integer
fractus float
bivalens boolean
nihil null
vacuum void
numquam never
ignotum unknown
octeti bytes

Generic Collections

Faber Meaning
lista<T> array
tabula<K,V> map
copia<T> set
promissum<T> promise
cursor<T> iterator
unio<A,B> union

Control Flow

Conditionals

ifStmt     := 'si' expression (blockStmt | 'ergo' statement | 'reddit' expression)
              ('cape' IDENTIFIER blockStmt)? (elseClause | 'sin' ifStmt)?
elseClause := 'secus' (ifStmt | blockStmt | statement)

Loops

whileStmt := 'dum' expression (blockStmt | 'ergo' statement | 'reddit' expression) ('cape' IDENTIFIER blockStmt)?
exStmt    := 'ex' expression (forBinding | destructBinding)
forBinding := ('pro' | 'fit' | 'fiet') IDENTIFIER (blockStmt | 'ergo' statement | 'reddit' expression) catchClause?
deStmt    := 'de' expression ('pro' | 'fit' | 'fiet') IDENTIFIER (blockStmt | 'ergo' statement) catchClause?

Switch/Match

eligeStmt    := 'elige' expression '{' eligeCase* defaultCase? '}' catchClause?
eligeCase    := 'casu' expression (blockStmt | 'ergo' statement | 'reddit' expression)
defaultCase  := 'ceterum' (blockStmt | statement)

Pattern Matching

discerneStmt := 'discerne' discriminants '{' variantCase* '}'
discriminants := expression (',' expression)*
variantCase  := 'casu' patterns (blockStmt | 'ergo' statement | 'reddit' expression)
patterns     := pattern (',' pattern)*
pattern      := '_' | (IDENTIFIER patternBind?)
patternBind  := ('ut' IDENTIFIER) | ('pro' IDENTIFIER (',' IDENTIFIER)*)

Guards

guardStmt   := 'custodi' '{' guardClause+ '}'
guardClause := 'si' expression (blockStmt | 'ergo' statement | 'reddit' expression)

Resource Management

curaStmt    := 'cura' curatorKind? expression? ('pro' | 'fit' | 'fiet') typeAnnotation? IDENTIFIER blockStmt catchClause?
curatorKind := 'arena' | 'page'

Control Transfer

returnStmt   := 'redde' expression?
breakStmt    := 'rumpe'
continueStmt := 'perge'

Error Handling

tryStmt     := 'tempta' blockStmt ('cape' IDENTIFIER blockStmt)? ('demum' blockStmt)?
throwStmt   := ('iace' | 'mori') expression
catchClause := 'cape' IDENTIFIER blockStmt
assertStmt  := 'adfirma' expression (',' expression)?

Expressions

Operators (by precedence, lowest to highest)

expression := assignment
assignment := ternary (('=' | '+=' | '-=' | '*=' | '/=' | '&=' | '|=') assignment)?
ternary    := or (('?' expression ':' | 'sic' expression 'secus') ternary)?
or         := and (('||' | 'aut') and)* | and ('vel' and)*
and        := equality (('&&' | 'et') equality)*
equality   := comparison (('==' | '!=' | '===' | '!==' | 'est' | 'non' 'est') comparison)*
comparison := bitwiseOr (('<' | '>' | '<=' | '>=' | 'intra' | 'inter') bitwiseOr)*
bitwiseOr  := bitwiseXor ('|' bitwiseXor)*
bitwiseXor := bitwiseAnd ('^' bitwiseAnd)*
bitwiseAnd := shift ('&' shift)*
shift      := range (('<<' | '>>') range)*
range      := additive (('..' | 'ante' | 'usque') additive ('per' additive)?)?
additive   := multiplicative (('+' | '-') multiplicative)*
multiplicative := unary (('*' | '/' | '%') unary)*
unary      := ('!' | '-' | 'non' | 'nulla' | 'nonnulla' | 'nihil' | 'nonnihil' | 'negativum' | 'positivum' | 'cede' | 'novum' | 'finge') unary | cast
cast       := call ('qua' typeAnnotation | 'innatum' typeAnnotation)*

Call and Member Access

call          := primary (callSuffix | memberSuffix | optionalSuffix | nonNullSuffix)*
callSuffix    := '(' argumentList ')'
memberSuffix  := '.' IDENTIFIER | '[' expression ']'
optionalSuffix := '?.' IDENTIFIER | '?[' expression ']' | '?(' argumentList ')'
nonNullSuffix := '!.' IDENTIFIER | '![' expression ']' | '!(' argumentList ')'
argumentList  := (argument (',' argument)*)?
argument      := 'sparge'? expression

Primary Expressions

primary := IDENTIFIER | NUMBER | STRING | TEMPLATE_STRING
         | 'ego' | 'verum' | 'falsum' | 'nihil'
         | arrayLiteral | objectLiteral
         | '(' expression ')'

Special Expressions

newExpr       := 'novum' IDENTIFIER ('(' argumentList ')')? (objectLiteral | 'de' expression)?
fingeExpr     := 'finge' IDENTIFIER ('{' fieldList '}')? ('qua' IDENTIFIER)?
praefixumExpr := 'praefixum' (blockStmt | '(' expression ')')
scriptumExpr  := 'scriptum' '(' STRING (',' expression)* ')'
legeExpr      := 'lege' 'lineam'?
regexLiteral  := 'sed' STRING IDENTIFIER?

Patterns

objectPattern  := '{' patternProperty (',' patternProperty)* '}'
patternProperty := 'ceteri'? IDENTIFIER (':' IDENTIFIER)?
arrayPattern   := '[' arrayPatternElement (',' arrayPatternElement)* ']'
arrayPatternElement := '_' | 'ceteri'? IDENTIFIER

Output

outputStmt := ('scribe' | 'vide' | 'mone') expression (',' expression)*

Entry Points

incipitStmt  := 'incipit' (blockStmt | 'ergo' statement | 'reddit' expression)
incipietStmt := 'incipiet' (blockStmt | 'ergo' statement | 'reddit' expression)

Testing

probandumDecl := 'probandum' STRING '{' probandumBody '}'
probandumBody := (praeparaBlock | probandumDecl | probaStmt)*
probaStmt     := 'proba' probaModifier? STRING blockStmt
probaModifier := 'omitte' STRING | 'futurum' STRING
praeparaBlock := ('praepara' | 'praeparabit' | 'postpara' | 'postparabit') 'omnia'? blockStmt

Endpoint Dispatch

adStmt        := 'ad' STRING '(' argumentList ')' adBinding? blockStmt? catchClause?
adBinding     := adBindingVerb typeAnnotation? 'pro' IDENTIFIER ('ut' IDENTIFIER)?
adBindingVerb := 'fit' | 'fiet' | 'fiunt' | 'fient'

DSL Transforms

dslExpr      := 'ex' expression dslTransforms
dslTransforms := dslTransform (',' dslTransform)*
dslTransform := dslVerb expression?
dslVerb      := 'prima' | 'ultima' | 'summa'

abExpr := 'ab' expression filter? (',' dslTransform)*
filter := 'non'? ('ubi' condition | IDENTIFIER)

Fac Block

facBlockStmt := 'fac' blockStmt ('cape' IDENTIFIER blockStmt)? ('dum' expression)?

Mutation Block

inStmt := 'in' expression blockStmt

Keyword Reference

Category Faber Meaning
Declarations fixum const
varia let
functio function
genus class
pactum interface
typus type alias
ordo enum
discretio tagged union
Control Flow si / sin / secus if / else-if / else
dum while
ex...pro for-of
de...pro for-in
elige / casu switch / case
discerne pattern match
custodi guard
redde return
rumpe break
perge continue
Error Handling tempta try
cape catch
demum finally
iace throw
mori panic
adfirma assert
Async futura async modifier
cede await
Boolean verum true
falsum false
et and
aut or
non not
vel nullish coalescing
Objects ego this/self
novum new
finge construct variant
Output scribe log
vide debug
mone warn

Critical Syntax Rules

  1. Type-first parameters: functio f(numerus x) NOT functio f(x: numerus)
  2. Type-first declarations: fixum textus name NOT fixum name: textus
  3. For-of loops: ex collection pro item { } (collection first)
  4. Parentheses around conditions are valid but not idiomatic: prefer si x > 0 { } or si positivum x { } over si (x > 0) { }
  5. Output keywords are statements, not functions — scribe x works, scribe(x) also works (parentheses group the expression), but scribe is not a callable value