CSL grammar¶
The following grammar describes the CSL language.
CSL is whitespace insensitive.
This means that the syntax allows an arbitrary amount of whitespace and comment lines around tokens (written as "token"
).
Anything on a line between //
and the newline character is treated as a comment and ignored.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The top-level entry point to the grammar
csl-unit = declaration*
declaration = type-declaration
| value-declaration
| contract-declaration
| template-declaration
| module-declaration
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; modules
module-declaration = "module" upper-case-identifier "{" declaration* "}"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; types
type-declaration = "type" (sum-type-declaration | record-type-declaration)
sum-type-declaration = upper-case-identifier
lower-case-identifier*
("|" upper-case-identifier type-atom*)+
record-type-declaration = upper-case-identifier [ ":" type ]
"{" [ record-field-declaration ( "," record-field-declaration)* ] "}"
record-field-declaration = lower-case-identifier ":" type
type = type-atom
| type-application
| type "->" type ; function type
type-application = type-name
| type-application type
type-name = qualifier upper-case-identifier ; type name
type-atom = lower-case-identifier ; type variable
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; expressions
value-declaration = "val" val-bindings
val-bindings =
(val-binding "with")* val-binding
val-binding =
[ "report" ]
; Note: patterns other than 'x : T' are only allowed
; if the binding occurs within an expression.
pattern
"="
expression
expression = expression expression
| expression BINARY_OPERATOR expression
| "(" (expression ",")* expression ")"
| if-expression
| type-case-expression
| function-expression
| let-expression
| record-expression
| qualifier lower-case-identifier ; variable
| literal
| qualifier upper-case-identifier ; constructor
| "[" [ (expression ",")* expression ] "]" ; list
| expression ":>" type ; upcast operator
if-expression =
"if" "(" expression ")" expression "else" expression
type-case-expression =
"type" lower-case-identifier "=" expression "of"
"{"
(type-atom "->" expression ";")*
"_" "->" expression
"}"
function-expression =
"\" pattern "->" expression
[ "|" pattern "->" expression
("|" pattern "->" expression)* ]
let-expression =
"let" ("val" pattern "=" expression)+
"in" expression
record-expression =
type "{" [ "use" expression "with" ] (lower-case-identifier "=" expression ",")* "}"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; patterns
pattern =
(pattern-atom | pattern-apply) ("as" lower-case-identifier)* (":" type)*
pattern-apply = qualifier upper-case-identifier pattern-atom*
pattern-atom = "_"
| "(" (pattern ",")* pattern ")"
| record-pattern
| qualifier upper-case-identifier ; constructor
| lower-case-identifier ; variable
| literal
record-pattern =
"?" type
"{"
[ (lower-case-identifier "=" pattern ",")*
lower-case-identifier "=" pattern ]
"}"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; contracts
template-declaration = rec-template-declaration
| meta-template-declaration
rec-template-declaration = "template" ["rec"] rec-template-bindings
rec-template-bindings =
(rec-template-binding "with")* rec-template-binding
rec-template-binding =
[ "entrypoint" ]
[ "[" "]" ] ; Optional empty list of contract parameters
upper-case-identifier
"("
[ (pattern ",")* pattern ]
")" "=" contract
meta-template-declaration = "template" meta-template-bindings
meta-template-bindings =
(meta-template-binding "with")* meta-template-binding
meta-template-binding =
"[" (lower-case-identifier ",")* lower-case-identifier "]" ; List of contract parameters
upper-case-identifier
"("
[ (pattern ",")* pattern ]
")" "=" contract
contract-declaration = "contract" contract-bindings
contract-bindings =
(contract-binding "with")* contract-binding
contract-binding =
lower-case-identifier
"="
contract
local-declaration = template-declaration
| contract-declaration
| value-declaration
contract = "success"
| "failure"
| contract "and" contract
| contract "or" contract
| contract "then" contract
| "(" contract ")"
| application-contract
| variable-contract
| prefix-contract
| let-contract
application-contract =
qualifier upper-case-identifier
[ "[" [ (contract ",")* contract ] "]" ]
"(" [ (expression ",")* expression ] ")"
variable-contract = lower-case-identifier
prefix-contract =
"<" ( "*" | expression) ">"
[ lower-case-identifier ":" ] type
[ "where" expression ]
let-contract =
"let" (local-declaration)+
"in" contract
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Basic grammar components
lower-case-identifier = /[a-z][a-zA-Z0-9_]*/
upper-case-identifier = /[A-Z][a-zA-Z0-9_]*/
literal = float-literal
| integer-literal
| duration-literal
| date-time-literal
| string-literal
float-literal = /[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?/
integer-literal = /[0-9]+/
fixed3 = /[0-9]+(\.[0-9]{1,3})?/
duration-literal =
"#"
/[+-]?P/ (duration-time | duration-date duration-time?)
"#"
duration-date = fixed3 "D"
duration-time = "T" (duration-hours | duration-minutes | duration-seconds)
duration-hours = fixed3 "H" (duration-minutes | duration-seconds)?
duration-minutes = fixed3 "M" duration-seconds?
duration-seconds = fixed3 "S"
; These two are defined elsewhere.
date-time-literal =
"#"
( ( /[0-9]{4}/
| /[0-9]{4}-[0-9]{2}/
| /[0-9]{4}-[0-9]{2}-[0-9]{2}/
| /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}/
| /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}/
| /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}/
| /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{0,3}/
)
[ /[+-][0-9]{4}|[+-][0-9]{2}:[0-9]{2}|Z/ ]
) "#"
string-literal = haskell-style-string ; see Haskell 98 report
; A sequence of zero or more qualifer names interspersed with '::'.
qualifier = (upper-case-identifier "::")*
BINARY_OPERATOR = "+" | "-" | "*" | "/"
| "<=" | ">=" | "<" | ">"
| "=" | "&&" | "||"