Skip to main content

Grammar

The concrete syntax of Flex, in EBNF.

Root = ModuleDecl ImportDecl* Decl*

ModuleDecl = 'module' IDENT*

ImportDecl = 'import' IDENT* (ImportAlias | ImportElementList)

Decl =
AnnotationDecl
| ConstDecl
| EnumDecl
| FunctionDecl
| TransformDecl
| ContractDecl
| StructDecl
| NewtypeDecl
| VariantDecl
| TypeAliasDecl
| ComponentDecl
| ConnectionDecl
| GroupDecl
| SystemDecl
| GlobalProtocolDecl
| LocalProtocolDecl

ImportAlias = 'as' Name

ImportElementList = '(' ImportElement* ')'

Name = IDENT

ImportElement = IDENT ('=>' Name)?

AnnotationDecl = AnnotationUse* 'annotation' Name AnnotationParamList? AnnotationScopeList?

ConstDecl = AnnotationUse* 'const' Name ':' Type '=' Expr ';'

EnumDecl = AnnotationUse* 'enum' Name PrimitiveType EnumMember*

FunctionDecl = AnnotationUse* 'function' Name FunctionParam* '->' Type (Expr | BlockExpr)

TransformDecl = AnnotationUse* 'transform' Name TransformParam* '->' Type ContextParam* (Expr | BlockExpr)

ContractDecl = AnnotationUse* 'contract' Name ContractParam* ContractBody

StructDecl = AnnotationUse* 'abstract'? 'extensible'? 'message'? 'struct' Name ('extends' NamedType)? StructField* StructAssertion*

NewtypeDecl = AnnotationUse* 'newtype' Name NewtypeField StructAssertion*

VariantDecl = AnnotationUse* 'message'? 'variant' Name VariantConstructor*

TypeAliasDecl = AnnotationUse* 'type' Name '=' Type ';'

ComponentDecl = AnnotationUse* 'component' Name ';'

ConnectionDecl = AnnotationUse* 'connection' Name 'from' Path 'to' Path ';'

GroupDecl = AnnotationUse* 'group' Name '{' GroupMember* '}'

SystemDecl = AnnotationUse* 'system' Name SystemProtocolRef*

GlobalProtocolDecl = AnnotationUse* 'global' 'protocol' Name GlobalStmt*

LocalProtocolDecl = AnnotationUse* 'local' 'protocol' Name 'in' Path LocalStmt*

AnnotationUse = '@' AnnotationArgList?

AnnotationArgList = '(' AnnotationArg* ')'

AnnotationArg = AnnotationConstRef?

AnnotationConstRef = IDENT*

AnnotationParamList = '(' AnnotationParam* ')'

AnnotationScopeList = '|' Name* '|'

AnnotationParam = Name ':' Type

Type =
PrimitiveType
| TupleType
| OptionalType
| ArrayType
| NamedType

Expr =
BitLiteral
| StringLiteral
| IntegerLiteral
| FloatLiteral
| RefExpr
| ContextParamRefExpr
| ParenExpr
| BinaryExpr
| UnaryExpr
| TypeAscriptionExpr
| MemberAccessExpr
| ArrayAccessExpr
| CallExpr
| StructLitExpr
| IfExpr
| MatchExpr
| SomeExpr
| NoneExpr
| TryExpr
| ValueCastExpr
| FoldExpr
| MapExpr
| FilterExpr
| FlatmapExpr
| ArrayComprehensionExpr
| ArrayLitExpr
| BlockExpr

PrimitiveType = 'bit' | 'string' | 'float32' | 'float64' | INT_TYPE | UINT_TYPE

EnumMember = AnnotationUse* Name '=' ';'

FunctionParam = Name ':' Type

BlockExpr = '{' Stmt* Expr? '}'

TransformParam = Name ':' Type

ContextParam = '?' Name ':' Type

ContractParam = Name ':' Type

ContractBody = '{' Stmt* '}'

Stmt =
LetStatement
| AssertStatement
| IfStatement

NamedType = Path

StructField = AnnotationUse* Name ':' Type ';'

StructAssertion = 'assert' (Name '=')? Expr ';'

NewtypeField = Name ':' Type ';'

VariantConstructor = AnnotationUse* Name Type* ';'

Path = IDENT*

SystemProtocolRef = Path ';'

GroupMember = Path ';'

TupleType = '(' Type* ')'

OptionalType = 'Optional' '<' Type '>'

ArrayType = Type '[' ']'

BitLiteral = 'true' | 'false'

StringLiteral = STRING

IntegerLiteral = INTEGER

FloatLiteral = FLOAT

RefExpr = Path

ContextParamRefExpr = '?' IDENT

ParenExpr = '(' Expr TupleElement* ')'

BinaryExpr = Expr ('+' | '-' | '*' | '/' | '%' | '++' | '&&' | '&' | '||' | '|' | '^' | '==' | '!=' | '<' | '>' | '<=' | '>=' | '<<') Expr

UnaryExpr = ('!' | '~' | '-') Expr

TypeAscriptionExpr = Expr ':' Type

MemberAccessExpr = Expr '.' IDENT

ArrayAccessExpr = Expr '[' Expr ('..' Expr)? ']'

CallExpr = Expr CallArgList GivingArgList?

StructLitExpr = Expr StructFieldBinding* NewtypeLitValue? StructUpdateBody?

IfExpr = 'if' Expr 'then'? Expr 'else' Expr

MatchExpr = 'match' '(' Expr ')' MatchArm*

SomeExpr = 'some' '(' Expr ')'

NoneExpr = 'none'

TryExpr = 'try' '(' Expr ')'

ValueCastExpr = 'value_cast' '?'? '<' Type '>' '(' Expr ')'

FoldExpr = 'fold' FoldAccumulator LetPattern 'in' Expr BlockExpr

MapExpr = 'map' '(' LetPattern 'in' Expr ')' BlockExpr

FilterExpr = 'filter' '(' LetPattern 'in' Expr ')' BlockExpr

FlatmapExpr = 'flatmap' '(' LetPattern 'in' Expr ')' BlockExpr

ArrayComprehensionExpr = '[' Expr CompClause* ']'

ArrayLitExpr = '[' Expr* ']'

TupleElement = Expr

CallArgList = '(' Expr* ')'

GivingArgList = 'giving' '(' Expr* ')'

StructFieldBinding = IDENT '=' Expr ';'

NewtypeLitValue = Expr

StructUpdateBody = Expr 'with' StructFieldBinding*

MatchArm = MatchPattern '=>' Expr ';'?

MatchPattern =
DiscardPattern
| LiteralPattern
| SomePattern
| NonePattern
| QualifiedPattern
| TupleMatchPattern
| ArrayMatchPattern
| IdentPattern
| StructMatchPattern
| TypeMatchPattern

FoldAccumulator = LetPattern (':' Type)? '=' Expr

LetPattern =
IdentBinding
| DiscardBinding
| TuplePattern
| TypedBinding

CompClause =
ForClause
| FilterClause
| ScanClause
| LetClause
| ZipClause

ForClause = 'for' LetPattern 'in' Expr

FilterClause = 'if' Expr

ScanClause = 'scan' LetPattern (':' Type)? '=' Expr 'in' Expr

LetClause = 'let' LetPattern '=' Expr

ZipClause = 'zip' 'for' LetPattern 'in' Expr

LetStatement = 'let' LetPattern (':' Type)? '=' Expr ';'

AssertStatement = 'assert' Expr ';'

IfStatement = 'if' Expr 'then'? StmtList 'else' StmtList

StmtList =
'{' Stmt* '}'
| Stmt

IdentBinding = Name

DiscardBinding = _

TuplePattern = '(' LetPattern* ')'

TypedBinding = LetPattern ':' Type

DiscardPattern = _

LiteralPattern = INTEGER | FLOAT | STRING | 'true' | 'false'

SomePattern = 'some' '(' MatchPattern ')'

NonePattern = 'none'

QualifiedPattern = Path MatchPattern*

TupleMatchPattern = '(' MatchPattern* ')'

ArrayMatchPattern = '[' MatchPattern* ']'

IdentPattern = Name

StructMatchPattern = MatchPattern 'as' Type

TypeMatchPattern = MatchPattern ':' Type

LocalStmt =
ProtocolLetStatement
| VarStatement
| SetStatement
| SendStatement
| RecvStatement
| BranchBlock
| ListenBlock
| LoopBlock
| BreakStatement
| DoStatement
| StateAnnotationStatement

ProtocolLetStatement = 'let' IdentBinding (':' Type)? '=' Expr ';'

VarStatement = 'var' IdentBinding (':' Type)? '=' Expr ';'

SetStatement = 'set' Path '=' Expr ';'

SendStatement = 'send' SendWhat ConnectionClause AnnotationUse* ';'

RecvStatement = 'recv' RecvWhat ConnectionClause AnnotationUse* ';'

BranchBlock = 'branch' BranchArm* 'end'

ListenBlock = 'listen' ListenArm* 'end'

LoopBlock = 'loop' Name? ('invariant' Expr)? LocalStmt*

BreakStatement = 'break' Name? ';'

DoStatement = 'do' 'tail'? Path ';'

StateAnnotationStatement = AnnotationUse

SendWhat =
SendExpression
| SendAny
| SendAnyBind
| SendLet

ConnectionClause = 'from'? 'to'? 'on'? Path*

RecvWhat =
RecvVar
| RecvDiscard
| RecvAnyBind
| RecvLet

SendExpression = Expr

SendAny = 'any' Type

SendAnyBind = 'any' Name ':' Type 'where' Expr

SendLet = 'let' LetPattern ':' Type ('where' Expr)?

RecvVar = Path ('assuming' Expr)?

RecvDiscard = _ (':' Type)?

RecvAnyBind = 'any' Name ':' Type 'assuming' Expr

RecvLet = 'let' LetPattern ':' Type ('assuming' Expr)?

BranchArm = '|' ('else' | Expr) '=>' LocalStmt*

ListenArm = '|' 'recv' RecvWhat ConnectionClause AnnotationUse* '=>' LocalStmt*

GlobalStmt =
ExchStatement
| ChoiceBlock
| LoopBlock
| BreakStatement
| ParallelBlock
| InBlock
| DoStatement
| StateAnnotationStatement

ExchStatement = 'exch' SendWhat ('into' RecvWhat)? ConnectionClause AnnotationUse* ';'

ChoiceBlock = 'choice' 'in' ChoiceComponent* SyncWhereClause? ChoiceArm* 'end'

ParallelBlock = 'parallel' GlobalStmt* ParallelWithBranch*

InBlock = 'in' Path LocalStmt*

ChoiceComponent = Path

SyncWhereClause = 'where' SyncVarDef*

ChoiceArm = '|' ('else' | Expr) '=>' GlobalStmt*

SyncVarDef = Name '=' SyncExpr*

SyncExpr = 'in' Path '{' Expr '}'

ParallelWithBranch = 'with' GlobalStmt*