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
fixum = const, varia = let
figendum/variandum = const/let with await
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)
- Return verbs:
fit (sync), fiet (async), fiunt (generator), fient (async generator)
- Parameter prefixes:
de (read), in (mutate), ex (consume)
si marks optional, ceteri marks rest parameter
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+
sub = extends, implet = implements
generis = static, nexum = bound/property
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)
si = if, sin = else-if, secus = else
ergo for one-liners, reddit for early return
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?
dum = while
ex...pro = for-of (values)
de...pro = for-in (keys)
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)?
tempta = try, cape = catch, demum = finally
iace = throw (recoverable), mori = panic (fatal)
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)*
scribe = log, vide = debug, mone = warn
Entry Points
incipitStmt := 'incipit' (blockStmt | 'ergo' statement | 'reddit' expression)
incipietStmt := 'incipiet' (blockStmt | 'ergo' statement | 'reddit' expression)
incipit = sync entry, incipiet = async entry
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'
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)?
- Creates scope, optionally with catch or do-while
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
- Type-first parameters:
functio f(numerus x) NOT functio f(x: numerus)
- Type-first declarations:
fixum textus name NOT fixum name: textus
- For-of loops:
ex collection pro item { } (collection first)
- Parentheses around conditions are valid but not idiomatic: prefer
si x > 0 { } or si positivum x { } over si (x > 0) { }
- Output keywords are statements, not functions —
scribe x works, scribe(x) also works (parentheses group the expression), but scribe is not a callable value