Skip to main content

Flex Complete Syntax

Flex syntax is specified using a parser expression grammar (PEG). PEG is an un-ambiguous, rule based description of a language. PEG descriptions are useful in that they are more closely related to how standard parsing algorithms, i.e. recursive descent, work in practice.

Complete Flex Syntax

Postfix operators

  • * — Zero or more.
  • + — One or more.
  • ? — Zero or one.

Prefix operators

  • & — Positive forward lookup (parse the following and consume no input).
  • ! — Negative forward lookup (parse not the following and consume no input).

Infix operators

  • | — Ordered choice.

Concatenation is indicated by placing two grammar expressions next to each other. Concatenation of two terms could or could not mean that whitespace is allowed to appear between them.

Identifiers and literals

(No whitespace between concatenated terms.)

IDENT : (LETTER | '_') (LETTER | DIGIT | '_')*
QIDENT : IDENT ('.' IDENT)*
CIDENT : '?' IDENT

LITERAL : STR_LIT | BIT_LIT | NUM_LIT
STR_LIT : '"' ((!('"' | '\\' | '\n' | '\r') ANY_CHAR) | ('\\' ANY_CHAR))* '"'
BIT_LIT : 'false' | 'true'
NUM_LIT : DEC_LIT
| HEX_LIT
| BIN_LIT
| NAT_LIT
| NEG_LIT
DEC_LIT : '-'? DIGIT+ ('.' DIGIT+)? ('e' | 'E') '-'? (DIGIT+ ('.' DIGIT+)?)
| '-'? DIGIT+ '.' DIGIT+
HEX_LIT : '0x' (DIGIT | 'a' | 'A' | 'b' | 'B' | 'c' | 'C' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F')+
BIN_LIT : '0b' ('0' | '1')+
NAT_LIT : DIGIT+
NEG_LIT : '-' DIGIT+

Modules and Declarations

(Whitespace is allowed between concatenated terms.)

----------------------------------- Modules ------------------------------------

MODULE : 'module' QIDENT IMPORT* ANNOTATED_DECL*

IMPORT : 'import' QIDENT '(' IDENT (',' IDENT)* ')'
| 'import' QIDENT 'as' IDENT

--------------------------------- Declarations ---------------------------------

ANNOTATED_DECL : ANNOTATION* DECL

DECL : DECL_FUNCTION
| DECL_TRANSFORM
| DECL_DERIVE_TRANSFORM
| DECL_ANNOTATION
| DECL_STRUCT
| DECL_NEWTYPE
| DECL_VARIANT
| DECL_ENUM
| DECL_TYPE_ALIAS
| DECL_CONST
| DECL_COMPONENT
| DECL_CONNECTION
| DECL_LOCAL_PROTOCOL
| DECL_GLOBAL_PROTOCOL
| DECL_SYSTEM

DECL_ANNOTATION : 'annotation' IDENT ('(' PARAMS ')')? ('|' ANNOTATION_SCOPE (' ' ANNOTATION_SCOPE)* '|')?
ANNOTATION_SCOPE : 'EnumValue'
| 'Enum'
| 'Struct'
| 'Field'
| 'VariantConstructor'
| 'Variant'
| 'Newtype'
| 'TypeAlias'

DECL_CONST : 'const' IDENT ':' TYPE '=' EXP ';'

Data Type Declarations

DECL_STRUCT      : STRUCT_MODIFIERS 'struct' IDENT ('extends' QIDENT)? '{' FIELD* STRUCT_PROPERTY* '}'
STRUCT_MODIFIERS : ('abstract'? 'extensible')? 'message'?
FIELD : ANNOTATION* IDENT ':' TYPE ';'
STRUCT_PROPERTY : 'assert' EXP ';'

DECL_NEWTYPE : 'newtype' IDENT '{' FIELD STRUCT_PROPERTY* '}'

DECL_VARIANT : 'message'? 'variant' IDENT '{' VARIANT_CONSTRUCTOR+ '}'
VARIANT_CONSTRUCTOR : ANNOTATION* IDENT '(' (TYPE (',' TYPE)*)? ')' ';'

DECL_ENUM : 'enum' IDENT TYPE '{' ENUM_VALUE+ '}'
ENUM_VALUE : ANNOTATION* IDENT '=' LITERAL ';'

DECL_TYPE_ALIAS : 'type' IDENT '=' TYPE ';'

--------------------------------- Annotations ----------------------------------

ANNOTATION : '@' QIDENT '(' EXP (',' EXP)* ')'
| '@' QIDENT

Functions and Transforms

DECL_FUNCTION : 'function' IDENT '(' PARAMS ')' '->' TYPE BODY

DECL_TRANSFORM : 'transform' IDENT '(' PARAMS ')' '->' TYPE GIVEN_CLAUSE? BODY

DECL_DERIVE_TRANSFORM : 'derive' 'transform' IDENT '(' PARAMS ')' '->' TYPE GIVEN_CLAUSE? (';' | BODY)

PARAMS : (PARAM (',' PARAM)*)?
PARAM : IDENT ':' TYPE

GIVEN_CLAUSE : 'given' '(' CTX_PARAMS ')'
CTX_PARAMS : CTX_PARAM (',' CTX_PARAM)*
CTX_PARAM : CIDENT ':' TYPE

BODY : '=' EXP ';'
| BLOCK

BLOCK : '{' STMT* EXP ';' '}'

Expressions and Statements

EXP  : 'if' EXP 'then' EXP 'else' EXP
| 'try' EXP
| 'map' '(' LET_PATTERN 'in' EXP ')' BLOCK
| 'filter' '(' LET_PATTERN 'in' EXP ')' BLOCK
| 'fold' '(' LET_PATTERN '=' EXP ';' LET_PATTERN 'in' EXP ')' BLOCK
| EXP1 (('^' | '||' | '&&') EXP1)*
EXP1 : EXP2 (('>' | '>=' | '<' | '<=' | '==' | '!=') EXP2)*
EXP2 : EXP3 ('++' EXP3)*
EXP3 : EXP4 (('+' | '-') EXP4)*
EXP4 : EXP5 (('*' | '/' | '%') EXP5)*
EXP5 : ('!' | '-')* EXP6
EXP6 : EXP7 (':' TYPE)?
EXP7 : EXP8 ('.' IDENT | '[' EXP ']' | '[' EXP '..' EXP ']')*
EXP8 : '(' EXP (',' EXP)* ')'
| BLOCK
| 'match' '(' EXP ')' '{' (MATCH_PATTERN '=>' EXP ';')+ '}'
| 'value_cast' '<' TYPE '>' '(' EXP ')'
| 'value_cast?' '<' TYPE '>' '(' EXP ')'
| QIDENT '(' EXP (',' EXP)* ')' ('giving' '(' EXP (',' EXP)* ')')?
| QIDENT '{' EXP '}'
| QIDENT '{' STRUCT_BUILDER* '}'
| '[' (EXP (',' EXP)*)? ']'
| '[' EXP COMP_CHAIN ('zip' COMP_CHAIN)* ']'
| LITERAL
| QIDENT
| CIDENT

STMT : 'let' LET_PATTERN '=' EXP ';'
| 'assert' EXP ';'

LET_PATTERN : '(' LET_PATTERN (',' LET_PATTERN)+ ')' (':' TYPE)?
| IDENT (':' TYPE)?

MATCH_PATTERN : MATCH_PATTERN1 (':' TYPE | 'as' TYPE)?
MATCH_PATTERN1 : '(' MATCH_PATTERN (',' MATCH_PATTERN)+ ')'
| '[' (MATCH_PATTERN (',' MATCH_PATTERN)*)? ']'
| 'some' '(' MATCH_PATTERN ')'
| 'none'
| QIDENT '(' (MATCH_PATTERN (',' MATCH_PATTERN)*)? ')'
| LITERAL
| '_'
| QIDENT

COMP_CHAIN : COMP_CLAUSE+
COMP_CLAUSE : 'if' EXP
| 'for' LET_PATTERN 'in' EXP
| 'scan' LET_PATTERN '=' EXP 'in' EXP
| 'let' LET_PATTERN '=' EXP

Types

TYPE  : TYPE1 ('[' ']')*
TYPE1 : '(' TYPE (',' TYPE)+ ')'
| 'Optional' '<' TYPE '>'
| INT_TYPE
| UINT_TYPE
| 'bit'
| 'float32'
| 'float64'
| 'string'
| QIDENT

Protocols

------------------------ Components and Connections ----------------------------

DECL_COMPONENT : 'component' IDENT ';'

DECL_CONNECTION : 'connection' IDENT 'from' IDENT 'to' IDENT ';'

---------------------------- Protocol Declarations -----------------------------

DECL_LOCAL_PROTOCOL : 'local' 'protocol' IDENT 'in' IDENT '{' LOCAL_STMT* '}'

DECL_GLOBAL_PROTOCOL : 'global' 'protocol' IDENT '{' GLOBAL_STMT* '}'

DECL_SYSTEM : 'system' IDENT '{' (IDENT ';')* '}'

----------------------------- Local Protocol Statements ------------------------

LOCAL_STMT : ANNOTATION
| LOCAL_VAR_DECL
| LOCAL_SET_STMT
| LOCAL_SEND_STMT
| LOCAL_RECV_STMT
| LOCAL_BRANCH_BLOCK
| LOCAL_LISTEN_BLOCK
| LOCAL_LOOP_BLOCK
| LOCAL_BREAK_STMT
| LOCAL_DO_STMT

LOCAL_VAR_DECL : ('var' | 'let') IDENT ':' TYPE '=' EXP ';'

LOCAL_SET_STMT : 'set' IDENT '=' EXP ';'

LOCAL_SEND_STMT : 'send' SEND_WHAT CONNECTION_CLAUSE ANNOTATION* ';'

LOCAL_RECV_STMT : 'recv' RECV_WHAT CONNECTION_CLAUSE ANNOTATION* ';'

SEND_WHAT : EXP
| 'any' TYPE
| 'any' IDENT ':' TYPE 'where' EXP
| 'let' IDENT ':' TYPE ('where' EXP)?

RECV_WHAT : IDENT ('assuming' EXP)?
| '_' (':' TYPE)?
| 'any' IDENT ':' TYPE 'assuming' EXP
| 'let' IDENT ':' TYPE ('assuming' EXP)?

CONNECTION_CLAUSE : ('from' IDENT)? ('to' IDENT)? ('on' IDENT)?

LOCAL_BRANCH_BLOCK : 'branch' LOCAL_BRANCH+ 'end'

LOCAL_BRANCH : '|' (EXP | 'else') '=>' LOCAL_STMT*

LOCAL_LISTEN_BLOCK : 'listen' LOCAL_LISTEN_BRANCH+ 'end'

LOCAL_LISTEN_BRANCH : '|' 'recv' RECV_WHAT CONNECTION_CLAUSE '=>' LOCAL_STMT*

LOCAL_LOOP_BLOCK : 'loop' IDENT? ('invariant' EXP)? '{' LOCAL_STMT* '}'

LOCAL_BREAK_STMT : 'break' IDENT? ';'

LOCAL_DO_STMT : 'do' ('tail')? IDENT ';'

----------------------------- Global Protocol Statements -----------------------

GLOBAL_STMT : ANNOTATION
| GLOBAL_EXCH_STMT
| GLOBAL_CHOICE_BLOCK
| GLOBAL_LOOP_BLOCK
| GLOBAL_BREAK_STMT
| GLOBAL_PARALLEL_BLOCK
| GLOBAL_IN_BLOCK
| GLOBAL_DO_STMT

GLOBAL_EXCH_STMT : 'exch' SEND_WHAT ('into' RECV_WHAT)? CONNECTION_CLAUSE ANNOTATION* ';'

GLOBAL_CHOICE_BLOCK : 'choice' 'in' IDENT (',' IDENT)* ('where' SYNCH_VAR_DECL+)? GLOBAL_BRANCH+ 'end'

SYNCH_VAR_DECL : IDENT '=' 'in' IDENT '{' EXP '}' (',' 'in' IDENT '{' EXP '}')*

GLOBAL_BRANCH : '|' (EXP | 'else') '=>' GLOBAL_STMT*

GLOBAL_LOOP_BLOCK : 'loop' IDENT? '{' GLOBAL_STMT* '}'

GLOBAL_BREAK_STMT : 'break' IDENT? ';'

GLOBAL_PARALLEL_BLOCK : 'parallel' '{' GLOBAL_STMT* '}' ('with' '{' GLOBAL_STMT* '}')+

GLOBAL_IN_BLOCK : 'in' IDENT '{' LOCAL_STMT* '}'

GLOBAL_DO_STMT : 'do' ('tail')? IDENT ';'