7. The Complete Syntax

Here is the complete syntax of Som in a simplified BNF. Do note that it might be incomplete due to the continuing development of the Som language. The irony of this has been duly noted.

program            = toplevel*

toplevel           = import_statement
                   | module_definition
                   | value_definition
                   | type_definition
                   | extern_definition

import_statement   = "use" LONG_LIDENT
                   | "from" LONG_LIDENT "use" "*"
                   | "from" LONG_LIDENT "use" (LONG_IDENT ",")* LONG_IDENT

module_definition  = "mod" "{" toplevel* "}"

value_definition   = "let" LIDENT pattern* "=" expression

type_definition    = "type" PIDENT* UIDENT "is" type
                   | "type" PIDENT* UIDENT "of" complex_type
                   
extern_definition  = "ext" LIDENT ":" type
                   | "ext" LIDENT "as" LIDENT pattern* ":" type

complex_type       = "|"? variant ("|" variant)*
                   | "{" (field ("," field)*)? "}"
                   
variant            = UIDENT (type (";" type)*)?
field              = LIDENT ":" type

type               = forall_type
forall_type        = (PIDENT+ ".")? function_type
function_type      = (function_type "->")? tuple_type
tuple_type         = constructed_type (";" constructed_type)*
constructed_type   = effect_type LONG_UIDENT?
effect_type        = "!"* atom_type
atom_type          = "(" type ")"
                   | PRIMITIVE_TYPE
                   | PIDENT
                   | LONG_UIDENT

pattern            = atom_pattern
atom_pattern       = LIDENT
                   | "_"

expression         = let_epxr
                   | sequence_expr
let_epxr           = "let" LIDENT pattern* "=" let_epxr "in" let_epxr
sequence_expr      = (sequence_expr ",")? lambda_expr
lambda_expr        = ("\\" pattern* "->") tuple_expr
tuple_expr         = contraint_expr (";" constraint_expr)*
constraint_expr    = BASIC_EXPR (":" type)?

The meaning of the tokens such as LIDENT are as follows:

tokenmeaning
IDENTAny identifier, such as foo, Bar or baz'
LIDENTA lowercase identifier, such as foo
UIDENTAn uppercase identifier, such as Bar
PIDENTA lowercase identifier starting with a ', such as 'var
LONG_*The qualified version of the identifier, such as foo::Bar
PRIMITIVE_TYPEA primitive type, such as $i.s.32 or $f.*
BASIC_EXPRA simple expression, such as 1 + 2 or "foo"