Skip to main content

Flex Complete Syntax

Flex syntax is specified using a parser expression grammar (PEG).

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* DECL*

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

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

DECL : DECL_FUNCTION
| DECL_TRANSFORM
| DECL_DERIVE_TRANSFORM
| DECL_ANNOTATION
| ANNOTATION* ANNOTATED_DECL
| DECL_CONST

ANNOTATED_DECL : DECL_STRUCT
| DECL_NEWTYPE
| DECL_VARIANT
| DECL_ENUM
| DECL_TYPE_ALIAS

DECL_ANNOTATION : 'annotation' IDENT ('(' PARAMS ')')? ('|' 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 ';'
| '{' STMT* EXP ';' '}'

Expressions and Statements

EXP  : 'if' EXP 'then' EXP 'else' EXP
| 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)* ')'
| '{' STMT* EXP ';' '}'
| '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