35. Grammar
This chapter is a BNF-style summary of MALDA syntax accepted by the reference parser (MaldaLang/Parser/Parser.cs, MaldaLang/Lexer.cs). Tier 0 semantics are defined in Malda Language Specification 1.0.
api declarations, async/await, pipes, comprehensions, dict/graph/object literals, variant patterns, and send/spawn/receive. Narrative examples stay in the topic chapters (for example Durable Workflows and Actors). If the grammar and the parser disagree, the parser wins until a spec amendment.
35.1 Program
Program ::= TopLevelItem*
TopLevelItem::= IncludeStmt | UsingStmt | ImportStmt
| WorkflowDecl | ActorDecl | ClassDecl | PromptDecl | TypeDecl | ComponentDecl
| SchemaDecl | ApiDecl
| DecoratedFunctionDecl | DecoratedPropertyDecl | PropertyDecl
| ExportableDecl | Statement
IncludeStmt ::= "include" StringLiteral ";"
UsingStmt ::= "using" (Identifier "=")? QualifiedName ";"
ImportStmt ::= "import" (
"{" Identifier ("," Identifier)* "}" "from" ( StringLiteral | QualifiedName )
| (Identifier "=")? StringLiteral
| (Identifier "=")? QualifiedName
) ";"
ExportableDecl ::= "export"? ( FunctionDecl | ClassDecl | TypeDecl | SchemaDecl
| "var" Identifier TypeHint? "=" Expression ";" )
QualifiedName ::= Identifier ("." Identifier)*
function and decorated declarations are parsed at top level (and inside blocks via Declaration()). They are not valid as nested Statement forms inside ordinary blocks. fn and def are not productions.
35.2 Top-level declarations
FunctionDecl ::= "function" Identifier "(" ParamList? ")" ReturnType?
( Block | Expression ";" )
DecoratedFunctionDecl ::= Decorator+ FunctionDecl
ReturnType ::= ("->" | "=>") (Identifier | "program" "(" Identifier ")")
ClassDecl ::= "class" Identifier (
"(" ParamList? ")" ( "{" ClassMember* "}" | ";" )
| ("extends" Identifier)? "{" ClassMember* "}"
)
ClassMember ::= AccessModifier? (FieldDecl | MethodDecl | ConstructorDecl)
FieldDecl ::= "var" Identifier TypeHint? ("=" Expression)? ";"
MethodDecl ::= AccessModifier? FunctionDecl
ConstructorDecl ::= AccessModifier? FunctionDecl /* name equals class name; forbidden when a primary constructor is present */
TypeDecl ::= "type" Identifier "=" Constructor ("|" Constructor)* ";"
Constructor ::= Identifier ("(" CtorParamList? ")")?
CtorParamList ::= CtorParam ("," CtorParam)*
CtorParam ::= Identifier (":" SchemaType)?
SchemaDecl ::= "schema" Identifier "{" SchemaField* "}"
SchemaField ::= Identifier ":" SchemaType ";"
SchemaType ::= Identifier "[]"? "?"? /* e.g. string, int[], string? */
ApiDecl ::= "api" Identifier "{" ApiMethodSig* "}"
ApiMethodSig ::= "function" Identifier "(" CtorParamList? ")" ";"
/* optional SchemaType per param, same as CtorParam; impl = top-level function of the same name */
ActorDecl ::= "actor" Identifier "{" ActorBodyItem* "}"
ActorBodyItem ::= MessageDecl | ActorMember
MessageDecl ::= "message" Identifier "(" ParamList? ")" ReturnType? ";"
ActorMember ::= AccessModifier? ( FieldDecl | "on" Identifier "(" ParamList? ")" ReturnType? Block
| MethodDecl | ConstructorDecl )
PromptDecl ::= "prompt" Identifier "(" ParamList? ")" ReturnType? PromptBody
PromptBody ::= Block | ObjectLiteral /* statement body or object-literal config; object fields may end with optional ';' */
PromptBodyField ::= "system" | "user" | "model" | "temperature" | "tools" | "gather" | "maxTokens" | "examples"
/* gather + -> Type = Mode C (tool round, then typed extract). tools: stays Mode B. */
ComponentDecl ::= "component" Identifier ComponentParams? Block
ComponentParams ::= "(" ParamList? ")"
PropertyDecl ::= "property" Identifier PropertyParams? Block
DecoratedPropertyDecl ::= Decorator+ PropertyDecl
Decorator ::= "@" Identifier "(" DecoratorArgList? ")"
DecoratorArgList ::= DecoratorArg ("," DecoratorArg)*
DecoratorArg ::= (Identifier ":")? Expression
/* named keys are decorator-only; @budget(tokens: 4000, tools: 8). Call-site ArgList stays positional. */
WorkflowDecl ::= "workflow" Identifier "(" ParamList? ")" "{" WorkflowStmt* "}"
WorkflowStmt ::= StepStmt | ApprovalStmt | WaitStmt | Statement
StepStmt ::= "step" Identifier "=" CallExpr StepOptions? ";"
StepOptions ::= ("retry" Integer | "backoff" String | "delay" Integer
| "maxDelay" Integer | "timeout" Integer | "compensate" CallExpr)*
ApprovalStmt ::= "approval" Identifier "=" "approval"
"(" Expression ("," Expression)? ")" ApprovalOptions? ";"
ApprovalOptions ::= ("timeout" Integer | "onReject" CallExpr)*
WaitStmt ::= "wait" Identifier "=" "awaitSignal"
"(" Expression ("," Expression)? ")" ("timeout" Integer)* ";"
AccessModifier ::= ("public" | "private")? "static"?
TypeHint ::= ":" "out"? Identifier
ParamList ::= Param ("," Param)*
Param ::= Decorator* Identifier TypeHint?
CallExpr ::= Expression PostfixSuffix* /* see §34.4 */
Property declarations can include decorators such as @requires(...) and @targets(...) for backend capability hints.
35.3 Statements
Statement ::= VarDecl | DestructuringVarDecl
| Assignment | DestructuringAssignment
| IfStmt | WhileStmt | ForStmt | ForeachStmt
| ReturnStmt | PrintStmt | BreakStmt | ContinueStmt
| TryStmt | ThrowStmt | SendStmt
| DeferStmt | UsingResourceStmt
| MatchStmt | ExpressionStmt | Block
VarDecl ::= ("var" | "const") Identifier TypeHint? "=" Expression ";"
DestructuringVarDecl ::= "var" DestructuringPattern TypeHint? "=" Expression ";"
Assignment ::= LValue AssignOp Expression ";"
AssignOp ::= "=" | "+=" | "-=" | "*=" | "/="
LValue ::= Identifier | MemberAccess | ArrayAccess
DestructuringAssignment ::= DestructuringPattern "=" Expression ";"
IfStmt ::= "if" "(" Expression ")" Statement ("else" Statement)?
WhileStmt ::= "while" "(" Expression ")" Statement
ForStmt ::= "for" "(" (VarDecl | Assignment)? ";" Expression? ";" Assignment? ")" Statement
ForeachStmt ::= "foreach" "(" "var" Identifier "in" Expression ")" Statement
| "for" "(" "var" Identifier "in" Expression ")" Statement
ReturnStmt ::= "return" Expression? ";"
PrintStmt ::= "print" "(" Expression ")" ";"
BreakStmt ::= "break" ";"
ContinueStmt::= "continue" ";"
TryStmt ::= "try" Block CatchClause+ FinallyClause?
| "try" Block FinallyClause
CatchClause ::= "catch" ("(" Identifier ("if" Expression)? ")")? Block
FinallyClause ::= "finally" Block
ThrowStmt ::= "throw" Expression ";"
SendStmt ::= "send" SendTarget SendOptions? ";"
SendTarget ::= Expression /* send target.handler(args) or send target(args) */
SendOptions ::= "then" "(" Identifier ")" Block
| "timeout" Expression ("catch" "(" Identifier ")" Block)?
DeferStmt ::= "defer" Block
UsingResourceStmt ::= "using" Identifier "=" Expression Block
MatchStmt ::= "match" Expression "{" MatchCase* DefaultCase? "}" (";")?
MatchCase ::= "case" Pattern ("if" Expression)? ":" Statement (";")?
DefaultCase ::= "default" ":" Statement (";")?
ExpressionStmt ::= Expression ";"
Block ::= "{" (TopLevelItem | Statement)* "}"
A bare match { ... } expression may appear as a statement without a trailing semicolon after }.
35.4 Expressions (precedence)
Lowest to highest: assignment, pipe |>, ternary ? :, null coalescing ??, match expression, or/||, and/&&, equality, comparison, additive, multiplicative, unary (await, async, not/!, -, ++/--), postfix ((), [], ., ?., ?[], ++/--). The full table is in Appendix B.
Expression ::= AssignExpr
AssignExpr ::= Pipe (AssignOp Expression)?
Pipe ::= Ternary ("|>" Ternary)*
Ternary ::= MatchExpr ("?" Expression ":" Expression)?
MatchExpr ::= "match" Expression "{" MatchCase* DefaultCase? "}"
| LogicalOr
LogicalOr ::= LogicalAnd (("or" | "||") LogicalAnd)*
LogicalAnd ::= Equality (("and" | "&&") Equality)*
Equality ::= Comparison (("==" | "!=") Comparison)*
Comparison ::= Additive (("<" | "<=" | ">" | ">=") Additive)*
Additive ::= Multiplicative (("+" | "-") Multiplicative)*
Multiplicative ::= Unary (("*" | "/" | "%") Unary)*
Unary ::= "await" Unary | "async" Unary
| ("not" | "!" | "-" | "++" | "--") Unary
| Postfix
Postfix ::= Primary PostfixSuffix*
PostfixSuffix ::= "(" ArgList? ")" | "[" Expression "]" | "." Identifier
| "?." Identifier | "?[" Expression "]" /* null-conditional */
| "++" | "--"
Primary ::= Literal | Identifier | "(" Expression ")"
| "this" | "super" | "self" | "null"
| "new" Identifier "(" ArgList? ")"
| "spawn" Identifier "(" ArgList? ")"
| "receive" "(" ")"
| ArrayLiteral | DictLiteral | GraphLiteral | ObjectLiteral
| InterpolatedString | LambdaExpr
LambdaExpr ::= LambdaParams Arrow (Expression | Block)
LambdaParams::= "(" ParamList? ")" | Identifier
Arrow ::= "=>" | "->" /* same Arrow token in lexer */
ArrayLiteral ::= "[" (Expression ("," Expression)*)? "]"
| ListComprehension
ListComprehension ::= "[" Expression "for" Identifier "in" Expression
("if" Expression)? "]"
DictLiteral ::= "dict" "{" (Expression ":" Expression ("," Expression ":" Expression)*)? "}"
| DictComprehension
DictComprehension ::= "dict" "{" Expression ":" Expression "for" Identifier "in" Expression
("if" Expression)? "}"
GraphLiteral ::= "graph" ("directed" | "undirected") "{"
("nodes" ":" Expression ("," "edges" ":" Expression)?)
("edges" ":" Expression ("," "nodes" ":" Expression)?)?
"}"
ObjectLiteral ::= "{" (ObjectEntry ("," ObjectEntry)*)? "}"
ObjectEntry ::= (StringLiteral | Identifier) ":" Expression
InterpolatedString ::= '$"' … '"' | '$"""' … '"""'
35.5 Patterns
Pattern ::= LiteralPattern | IdentifierPattern | WildcardPattern
| VariantPattern | ArrayPattern | ObjectPattern
LiteralPattern ::= Integer | Float | StringLiteral | Boolean | "null"
IdentifierPattern ::= Identifier
WildcardPattern ::= "_"
VariantPattern ::= Identifier "(" (Pattern ("," Pattern)*)? ")"
/* Bare Identifier that names a declared constructor is also a
VariantPattern with implicit '_' payloads of that arity. */
ArrayPattern ::= "[" (Pattern ("," Pattern)*)? RestPattern? "]"
RestPattern ::= "..." Identifier?
ObjectPattern ::= "{" ObjectPatternEntry ("," ObjectPatternEntry)* "}"
ObjectPatternEntry ::= (Identifier | StringLiteral) (":" Pattern)?
DestructuringPattern ::= ArrayPattern | ObjectPattern
35.6 Lexical and tokens
Keywords, operators, comments, strings, and numeric literals are defined in Lexical Structure. fn and def are not keywords. Both => and -> produce the same Arrow token (lambda bodies and return types).
Identifier ::= [A-Za-z_][A-Za-z0-9_]*
ArgList ::= Expression ("," Expression)*
See Also
- Lexical Structure — tokens and keywords
- Appendix — operator precedence table
- Language spec 1.0 — Tier 0 semantics
- Durable Workflows — workflow examples
- Actors — actor messaging examples