Full Language Reference

Parser-accurate specification of the Grove language. Optimized for LLM consumption: EBNF grammar, lexical rules, semantic constraints, and generation rules.

Purpose: Complete language description for machine generation and validation.

1. Grammar Overview

1.1 Module

Module        := [ModuleHeader] Item*
ModuleHeader  := "module" Ident

1.2 Top-Level Items

Item := ImportDecl
     | TypeDecl
     | EnumDecl
     | RecordDecl
     | EventDecl
     | ActionDecl
     | ValidateDefDecl
     | UpcastDecl
     | FunctionDecl
     | TriggerDecl
     | ScheduleDecl
     | WorkflowDecl
     | ActivityDecl
     | ServiceDecl
     | RouteDecl
     | QueryDecl
     | WebhookDecl
     | TestDecl

Lifecycle/delete annotation prefixes before action/event:

2. Lexical Rules

2.1 Comments and Whitespace

2.2 Identifiers

2.3 Literals

String escapes: \\, \", \n, \t, \r, \$

2.4 Operators and Punctuation

Operators: + - * / % == != < <= > >= && || ! ?? ?. = -> => ...

Delimiters: () {} [] . , : ; @ ? |

2.5 Keywords

Hard keywords (dedicated token kinds):

Contextual keywords (lexed as Ident): module apply state invariant node edge start spawn branch parallel map compensate search with operation source sink credentials auth protocol data when fetch publish invoke retry_policy after host host_fn signal run request expect assert ok error status errors headers input output timeout max_history backoff workflow on compensated index args sql gsql verify

3. Expression Grammar

3.1 Precedence (lowest to highest)

  1. ||
  2. &&
  3. == !=
  4. < > <= >=
  5. + -
  6. * / %
  7. ??
  8. unary: ! -
  9. postfix: . ?. [] and call chaining

3.2 Expression Forms

Expr := IntLit | DecimalLit | BoolLit | StringLit | InterpolatedString
      | "null" | DurationLit | Ident
      | FnCall | MethodCall | FieldAccess | OptionalChain | IndexExpr
      | ListExpr | ObjectExpr
      | UnaryExpr | BinaryExpr | NullCoalesce
      | IfExpr | MatchExpr | LambdaExpr | SpreadExpr
      | "(" Expr ")"

Concrete forms:

Notes:

4. Type Grammar

TypeRef := BaseType ["?"]

BaseType := "Int" | "Decimal" | "Bool" | "String" | "Id"
          | "Date" | "Time" | "DateTime" | "Duration" | "Epoch"
          | "Value" | "Blob"
          | "List" "<" TypeRef ">"
          | "Map" ["<" TypeRef "," TypeRef ">"]
          | "[" TypeRef "]"
          | "{" FieldDecl* "}"
          | QualifiedName

QualifiedName := Ident ("." Ident)*

5. Statement Grammar

Stmt := LetStmt | IfStmt | ForStmt | ReturnStmt
      | EmitStmt | FailStmt | PublishStmt | ExprStmt

LetStmt    := "let" Ident [":" TypeRef] "=" Expr
IfStmt     := "if" Expr Block ["else" (IfStmt | Block)]
ForStmt    := "for" [Ident ","] Ident "in" Expr Block
ReturnStmt := "return" Expr
EmitStmt   := "emit" Ident [VersionTag] "{" FieldAssign* "}"
FailStmt   := "fail" Expr Expr
PublishStmt:= "publish" Ident "{" FieldAssign* "}"

let bindings are immutable. Allowed in: pure functions, action apply, event apply, activity apply, route apply, upcast blocks. Not allowed in: edge mappings, trigger mappings.

6. Declaration Grammar

6.1 Import

ImportDecl := "import" ImportPath VersionTag ["as" Ident]
ImportPath := Ident ("/" Ident)*
VersionTag := "v" Int

grove/ prefix is reserved for standard library.

6.2 Type and Enum

TypeDecl := "type" Ident "{" FieldDecl* "}"
EnumDecl := "enum" Ident "{" Ident ("," Ident)* "}"
FieldDecl := Ident ":" TypeRef ["=" DefaultExpr] [Annotation*]

6.3 Record

RecordDecl := "record" [Ident] ["@parent" "(" Ident ")"] "{" RecordBody "}"
RecordBody := KindDecl? FieldDecl* (InvariantDecl | StateDecl)*
KindDecl := "kind" StringLiteral

InvariantDecl := "invariant" Ident "{" Expr "}"
StateDecl := "state" Ident "{" StateTransition* "}"
StateTransition := QualifiedName "->" QualifiedName "on" Ident [VersionTag]

At most one root record per module. Root records are unnamed and must declare a kind string (2-5 lowercase ASCII letters, not starting with mz, unique per project). Named records may use @parent(<root>) to mark themselves as child records; child records have no kind.

6.4 Event

EventDecl := [DeleteAnnotation] "event" Ident [VersionTag] "{" FieldDecl* [ApplyBlock] "}"
ApplyBlock := "apply" "{" Stmt* "}"

6.5 Action

ActionDecl := [LifecycleAnnotation] "action" Ident [VersionTag] "{"
               FieldDecl*
               ValidateRef*
               ApplyBlock
             "}"
LifecycleAnnotation := "@create" | "@upsert" | "@delete" | "@delete" "(" "hard" ")"
ValidateRef := "validate" Ident ["{" Expr "}"]

6.6 Validate

ValidateDefDecl := "validate" Ident "{" Expr "}"

Body must evaluate to boolean.

6.7 Upcast

UpcastDecl := "upcast" ("action" | "event") Ident VersionTag "->" VersionTag "{" Stmt* "}"

Source version must be lower than target version.

6.8 Function

FunctionDecl := "function" Ident "(" ParamList ")" ["->" TypeRef] "{" Stmt* "}"
ParamList := [Param ("," Param)*]
Param := Ident ":" TypeRef

6.9 Workflow

WorkflowDecl := "workflow" Ident VersionTag "{" WorkflowBody* "}"
WorkflowBody := NodeDecl | EdgeDecl | SearchDecl | CompensatedDecl

NodeDecl := "node" Ident "=" ActivityRef ["{" FieldMapping* "}"]
          | "node" Ident "=" "branch" "{" BranchArm* "}"
          | "node" Ident "=" "parallel" "{" ParallelItem* "}"
          | "node" Ident "=" "map" Expr "{" ... "}"
          | "node" Ident "=" "start" WorkflowRef "{" FieldMapping* "}"
          | "node" Ident "=" "spawn" WorkflowRef "{" FieldMapping* "}"

EdgeDecl := "edge" Ident "->" Ident
SearchDecl := "search" "{" FieldMapping* "}"
CompensatedDecl := "on" "compensated" "->" TypeRef "{" Stmt* "}"

6.10 Activity

ActivityDecl := "activity" Ident VersionTag "{" DataBlock* [ApplyBlock] [RetryPolicy] "}"
DataBlock := "data" Ident "{" DataOp "}"
DataOp := FetchOp | InvokeOp | PublishOp | QueryOp | HostOp
        | StartOp | SpawnOp | SignalOp

FetchOp := "fetch" QualifiedName "{" FieldMapping* "}"
InvokeOp := "invoke" QualifiedName "{" FieldMapping* "}"
RetryPolicy := "retry_policy" "{" RetryField* "}"

6.11 Service

ServiceDecl := "service" Ident [VersionTag] "{"
                [CredentialsBlock]
                [AuthBlock]
                OperationDecl*
              "}"
OperationDecl := "operation" Ident "{" FieldMapping* "}"

6.12 Route

RouteDecl := "route" StringLit "{" [VerifyBlock] RouteMethod* "}"
RouteMethod := HttpMethod "{" DataBlock* ApplyBlock "}"
HttpMethod := "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
VerifyBlock := "verify" Ident "{" FieldMapping* "}"

6.13 Query

QueryDecl := "query" Ident "{" [ArgsBlock] (SqlBlock | GsqlBlock) [OutputDecl] [IndexBlock] "}"
ArgsBlock := "args" "{" FieldDecl* "}"
SqlBlock := "sql" "{" StringLit "}"
OutputDecl := "output" ":" TypeRef
IndexBlock := "index" "{" IndexCol* "}"

6.14 Trigger

TriggerDecl := "trigger" Ident "from" QualifiedName "{" TriggerBody "}"
TriggerBody := "start" Ident VersionTag "{" FieldMapping* "}"

6.15 Schedule

ScheduleDecl := "schedule" Ident "{" ScheduleBody "}"
ScheduleBody := "when" StringLit  // cron expression
                "start" Ident VersionTag "{" FieldMapping* "}"

6.16 Webhook

WebhookDecl := "webhook" Ident StringLit "{" [SecretDecl] WebhookEvent* "}"
WebhookEvent := "on" EventPattern "->" QualifiedName
EventPattern := Ident | Ident "." Ident | "*"

Built-in providers: github, stripe, slack, gitlab.

6.17 Test

TestDecl := "test" Ident "{" [TestWorkflow] TestRun* "}"
TestWorkflow := "workflow" Ident VersionTag
TestRun := "run" Ident "{" TestDirective* "}"
TestDirective := "request" "{" ... "}"
              | "mock" Ident "{" ... "}"
              | "expect" ("ok" | "error")
              | "assert" Expr
              | "advance_time" DurationLit
              | "deliver_signal" Ident "{" ... "}"
              | "cancel"
              | "start_time" IntLit

7. Semantic Constraints

8. Method Chains

String: .trim(), .lower(), .upper(), .split(sep), .replace(old, new), .contains(sub), .startsWith(prefix), .endsWith(suffix), .substring(start, end), .padLeft(len, char), .padRight(len, char), .len

List: .map(|i| expr), .filter(|i| expr), .find(|i| expr), .contains(item), .flatten(), .unique(), .sort(|i| expr), .reverse(), .first(), .last(), .sum(), .join(sep), .append(item), .len

Map: .get(key), .keys(), .values(), .entries(), .contains_key(key), .merge(other), .remove(key), .len

Numeric: .round(), .ceil(), .floor(), .abs(), .min(other), .max(other), .toString(), .toDecimal()

Date/Time: .addDays(n), .addHours(n), .addMinutes(n), .addSeconds(n), .format(pattern), .diffDays(other), .startOfMonth(), .endOfMonth(), .toEpoch(), .toDateTime()

Crypto: .sha256(), .hmac(key), .base64Encode(), .base64Decode()

Coercion: .toInt(), .toDecimal(), .toBool(), .tryToInt(), .tryToDecimal(), .tryToBool()