MALDA™ Reference Manual

The AI-First Programming Language - Version 1.0.11

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.

Scope: the productions below cover top-level declarations, control flow, exceptions, resource cleanup, actors, workflows, sum types, schemas, closed 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