(* ======================== *) (* Core Character Sequences *) (* ======================== *) white_space ::= '\u0020' | '\u0009' | '\u000D' | '\u000A' lparen ::= '('; rparen ::= ')'; paren ::= lparen | rparen; lbracket ::= '['; rbracket ::= ']'; bracket ::= lbracket | rbracket; lbrace ::= '{'; rbrace ::= '}'; brace ::= lbrace | rbrace; digit ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; hex ::= '0' | ... | '9' | 'A' | ... | 'F' | 'a' | ... | 'f' ; upper ::= 'A' | ... | 'Z' | Lu | Lt | Nl | Lo upper only | Lm upper only; lower ::= 'a' | ... | 'z' | Ll | Lo lower only | Lm lower only; letter ::= upper | lower; escape_unicode ::= '\', 'u', hex, hex, hex, hex; escape_char ::= '\', ('b' | 'f' | 'n' | 'r' | 't' | '\' | '"'); escape_seq ::= escape_unicode | escape_char; number_integer ::= '0' | digit, [{digit}]; number_float ::= number_integer, '.', number_integer; newline ::= '\n'; printable_char ::= printable utf8; char_char ::= printable_char without newline or single quote | escape_seq; string_char ::= printable_char without newline or double quote | escape_seq; (* Comments *) comment ::= '-', '-', {utf8}; docstring ::= '-', '-', '-', {utf8}; (* ======== *) (* Keywords *) (* ======== *) k_type ::= 't', 'y', 'p', 'e'; k_class ::= 'c', 'l', 'a', 's', 's'; k_alias ::= 'a', 'l', 'i', 'a', 's'; k_const ::= 'c', 'o', 'n', 's', 't'; k_enum ::= 'e', 'n', 'u', 'm'; k_record ::= 'r', 'e', 'c', 'o', 'r', 'd'; k_object ::= 'o', 'b', 'j', 'e', 'c', 't'; k_let ::= 'l', 'e', 't'; k_mut ::= 'm', 'u', 't'; k_export ::= 'e', 'x', 'p', 'o', 'r', 't'; (* Starts an import definition. *) k_import ::= 'i', 'm', 'p', 'o', 'r', 't'; (* Denotes a namespace declaration. *) k_namespace ::= 'n', 'a', 'm', 'e', 's', 'p', 'a', 'c', 'e'; (* Starts an infix function definition *) k_infix ::= 'i', 'n', 'f', 'i', 'x'; (* Starts a function definition. *) k_fn ::= 'f', 'n'; (* Ends any block definition. Must be followed by the keyword of the block. *) k_end ::= 'e', 'n', 'd'; (* Initiates a pattern match against some value. *) k_match ::= 'm', 'a', 't', 'c', 'h'; (* Initiates a pattern matching case. Applicable to functions and matches. *) k_case ::= 'c', 'a', 's', 'e'; k_lambda ::= 'λ'; (* Used in if/else syntax. Starts such a block and used in 'else if'. *) k_if ::= 'i', 'f'; (* Used in if/else syntax. Must follow the condition of any 'if'. *) k_then ::= 't', 'h', 'e', 'n'; (* Used in if/else syntax. Indicates an 'else if' or 'else'. *) k_else ::= 'e', 'l', 's', 'e'; (* Used in do/return syntax. Indicates the start of such a structure. *) k_do ::= 'd', 'o'; (* Used in do/return syntax. Indicates the final output value. *) k_return ::= 'r', 'e', 't', 'u', 'r', 'n'; (* Indicates a type constructor. *) k_given ::= 'g', 'i', 'v', 'e', 'n'; (* Function modifier which restricts use to the enclosing scope. *) k_private ::= 'p', 'r', 'i', 'v', 'a', 't', 'e'; (* true is a Boolean literal *) k_true ::= 't', 'r', 'u', 'e'; (* false is a Boolean literal *) k_false ::= 'f', 'a', 'l', 's', 'e'; (* defn is fn but for definitions without implementations *) k_false ::= 'd', 'e', 'f', 'n'; keyword ::= k_type | k_class | k_alias | k_const | k_enum | k_record | k_object | k_let | k_mut | k_export | k_import | k_namespace | k_infix | k_fn | k_end | k_match | k_case | k_lambda | k_if | k_then | k_else | k_do | k_return | k_given | k_private | k_true | k_false | k_defn; (* ============== *) (* Literal Values *) (* ============== *) literal_bool ::= k_true | k_false; literal_integer ::= ['-'], number_integer; literal_float ::= ['-'], number_float; literal_char ::= "'", char_char, "'"; literal_string ::= '"', {string_char}, "'"; empty_tuple ::= op_tuple, lparen, rparen; empty_list ::= lbracket, rbracket; literal ::= literal_bool | literal_integer | literal_float | literal_char | literal_string | empty_tuple | empty_list; (* ========= *) (* Operators *) (* ========= *) (* Type hole used for development -- will resolve/compile, but fail at runtime. *) hole ::= '?', '?', '?'; (* Used for splat imports: import foo.bar.baz.* is an example. *) op_import_splat ::= '*'; (* Used to access members. Relevant for namespaces, records, enums, classes. *) op_member ::= '.'; (* Standard separator for type definitions, tuples and records. *) op_comma ::= ','; (* A | B is a type which can be either A or B. *) op_type_union ::= '|'; (* List operator. Prepend LHS to RHS. Can be used in pattern matching. *) op_list_prepend ::= ':', '-'; (* Only valid adjacent to a name declaration. Explicitly declare the type that the name has. *) op_bind_type ::= ':'; (* Bind the RHS expression to the LHS name. *) op_bind_value ::= ':', '='; (* Used in function definitions: the LHS input produces RHS output. *) op_fn_return ::= '-', '>'; (* Binds the result contained in the RHS expression to the name on the LHS. *) (* Note that "contained" refers to the value in the [Bi]Monad. *) op_bind_do ::= '<', '-'; (* Indicates some type is constrained by some type class, ex F * :: Functor *) op_class_member ::= ':', ':'; (* Indicates the start of a pattern matching case, used in both forms: case => λ => The λ form is preferred for functions, 'case' is preferred for 'match'. *) op_case ::= '=', '>'; (* Declares a tuple, as in #(a, b, c) *) op_tuple ::= '#'; operator ::= hole | op_import_splat | op_member | op_comma | op_type_union | op_list_prepend | op_bind_type | op_bind_value | op_fn_return | -> op_bind_do | op_class_member | op_case | op_tuple; (* ===== *) (* Names *) (* ===== *) (* Used to denote an anonymous value, such as ignoring a pattern part. *) name_anon_value ::= '_'; (* Used to denote an anonymous parameter in a type definition. Helps to describe some type with a particular shape without naming each part. *) name_anon_type ::= '*';