Grammar

Semi-formal grammar for Cleat syntax. Uses EBNF-style notation.

Top-level declarations

ebnf
File        = Import* Decl*
Import      = "import" STRING
Decl        = FnDecl | ToolDecl | StreamDecl | StateDecl | ChainDecl
            | AgentDecl | GuardDecl | ServerDecl | TypeDecl | TestDecl

FnDecl      = Annotation* "fn" ["(" Param ":" Type ")"] IDENT ParamList
              ["->" Type] [NeedsClause] Block
ToolDecl    = "tool" IDENT ParamList "->" Type
              [NeedsClause] [TimeoutClause] [RetryClause] Block
StreamDecl  = "stream" IDENT ParamList "->" Type
              [NeedsClause] [BufferClause] Block
StateDecl   = "state" IDENT "{" StateBody "}"
ChainDecl   = "chain" IDENT "{" ChainBody "}"
AgentDecl   = "agent" IDENT "{" AgentBody "}"
GuardDecl   = "guard" IDENT "{" GuardBody "}"
ServerDecl  = "server" IDENT "{" ServerBody "}"
TypeDecl    = "type" IDENT "=" Type
TestDecl    = "test" STRING Block

Clauses

ebnf
NeedsClause   = "needs" "{" IDENT ("," IDENT)* "}"
TimeoutClause = "timeout:" DurationLit
RetryClause   = "retry:" INT
BufferClause  = "buffer:" INT
ParamList     = "(" [Param ("," Param)*] ")"
Param         = IDENT ":" Type ["=" Expr]

Statements

ebnf
Stmt        = LetStmt | ReturnStmt | IfStmt | ForStmt | ExprStmt
            | IndexAssignStmt | YieldStmt | AssertStmt | UsingStmt | BlockStmt
LetStmt     = "let" ["_" | IDENT] [":" Type] "=" Expr
ReturnStmt  = "return" [Expr]
IfStmt      = "if" Expr Block ["else" (IfStmt | Block)]
ForStmt     = "for" IDENT "in" Expr Block
ExprStmt    = Expr
IndexAssign = Expr "[" Expr "]" "=" Expr
YieldStmt   = "yield" Expr
AssertStmt  = "assert" "(" Expr ["," STRING] ")"
UsingStmt   = "using" IDENT "=" Expr

Expressions

ebnf
Expr        = MatchExpr | PipeExpr
PipeExpr    = UnaryExpr ("|>" UnaryExpr)*
UnaryExpr   = ["!" | "-"] PostfixExpr
PostfixExpr = Primary ("." IDENT | "[" Expr "]" | "(" ArgList ")" | "?")*
Primary     = INT | FLOAT | STRING | BOOL | IDENT | "(" Expr ")"
            | ListLit | MapLit | StructLit | MatchExpr | LambdaExpr
            | OkExpr | ErrExpr | SpawnExpr | BlockExpr | InterpString

MatchExpr   = "match" [Expr] "{" MatchArm ("," MatchArm)* "}"
MatchArm    = Pattern ["if" Expr] "=>" (Expr | BlockExpr)
Pattern     = "Ok" "(" Pattern ")" | "Err" "(" Pattern ")" | "_" | Expr

LambdaExpr  = "fn" ParamList ["->" Type] Block
OkExpr      = "Ok" "(" Expr ")"
ErrExpr     = "Err" "(" Expr ")"
BlockExpr   = "{" Stmt* "}"

ListLit     = "[" [Expr ("," Expr)*] "]"
MapLit      = "map" "[" Type "]" Type "{" [MapEntry ("," MapEntry)*] "}"
MapEntry    = Expr ":" Expr
StructLit   = IDENT "{" [FieldInit ("," FieldInit)*] "}"
FieldInit   = IDENT ":" Expr

Types

ebnf
Type        = NamedType | SliceType | MapType | GenericType | FuncType | QualifiedType
NamedType   = IDENT
QualifiedType = IDENT "." IDENT
SliceType   = "[" "]" Type
MapType     = "map" "[" Type "]" Type
GenericType = IDENT "[" Type ("," Type)* "]"
FuncType    = "fn" "(" [Type ("," Type)*] ")" ["->" Type]

StructType  = "struct" "{" [StructField ("," StructField)*] "}"
StructField = Annotation* IDENT ":" Type ["=" Expr]
EnumType    = "enum" "{" IDENT ("," IDENT)* "}"

Annotations

ebnf
Annotation  = "@" IDENT ["(" Expr ("," Expr)* ")"]

Operators (by precedence, lowest first)

PrecedenceOperators
1`\\`
2&&
3== !=
4< > <= >=
5+ -
6* / %
7! - (unary)
8. [] () ?

Literals

ebnf
INT         = [0-9]+
FLOAT       = [0-9]+ "." [0-9]+
STRING      = '"' (char | EscapeSeq | Interpolation)* '"'
EscapeSeq   = "\" ("n" | "t" | "r" | "\" | '"' | "$")
Interpolation = "${" Expr "}"
BOOL        = "true" | "false"
DurationLit = INT ("ms" | "s" | "h" | "y")
Edit this page on GitHub