difftastic/vendored_parsers/tree-sitter-f-sharp/grammar.js

1745 lines
41 KiB
JavaScript

function imm(x) {
return token.immediate(x);
}
const PREC = {
SEQ_EXPR: 1,
APP_EXPR: 16,
THEN_EXPR: 2,
RARROW: 3,
INFIX_OP: 4,
NEW_EXPR: 5,
LET_EXPR: 6,
LET_DECL: 7,
DO_EXPR: 8,
FUN_EXPR: 8,
MATCH_EXPR: 8,
MATCH_DECL: 9,
DO_DECL: 10,
ELSE_EXPR: 11,
INTERFACE: 12,
COMMA: 13,
DOTDOT: 14,
PREFIX_EXPR: 0,
SPECIAL_INFIX: 16,
LARROW: 16,
TUPLE_EXPR: 16,
CE_EXPR: 17,
SPECIAL_PREFIX: 17,
DO_EXPR: 17,
IF_EXPR: 18,
NEW_OBJ: 18,
DOT: 19,
INDEX_EXPR: 20,
PAREN_APP: 21,
TYPED_EXPR: 22,
PAREN_EXPR: 21,
DOTDOT_SLICE: 22,
}
module.exports = grammar({
name: 'fsharp',
// The external scanner (scanner.cc) allows us to inject "dummy" tokens into the grammar.
// These tokens are used to track the indentation-based scoping used in F#
externals: $ => [
$._virtual_open_section, // Signal the external scanner that a new indentation scope should be opened. Add the indetation size to the stack.
$._virtual_end_section, // end an indentation scope, popping the indentation off the stack.
$._virtual_end_decl, // end an indentation scope with equal alignment, popping the indentation off the stack.
$.block_comment_content
],
extras: $ => [
/[ \s\f\uFEFF\u2060\u200B]|\\\r?n/,
],
conflicts: $ => [
[$.long_identifier, $._identifier_or_op],
[$.type_argument, $.static_type_argument],
[$.symbolic_op, $.infix_op],
[$.union_type_case, $.long_identifier],
],
words: $ => $.identifier,
inline: $ => [ $._module_elem, $._infix_or_prefix_op, $._base_call, $.access_modifier, $._quote_op_left, $._quote_op_right, $._inner_literal_expressions, $._expression_or_range, $._infix_expression_inner, $._seq_expressions, $._seq_inline],
supertypes: $ => [ $._module_elem, $._pattern, $._expression_inner, $._type_defn_body ],
rules: {
//
// Top-level rules (BEGIN)
//
file: $ =>
choice(
$.named_module,
$.namespace,
repeat1($._module_elem),
),
namespace: $ =>
seq(
"namespace",
choice(
"global",
field("name", $.long_identifier),
),
repeat($._module_elem),
),
named_module: $ =>
seq(
"module",
optional($.access_modifier),
field("name", $.long_identifier),
repeat($._module_elem)
),
_module_elem: $ =>
choice(
$.block_comment,
$.line_comment,
$.value_declaration,
$.module_defn,
$.module_abbrev,
$.import_decl,
$.compiler_directive_decl,
$.fsi_directive_decl,
$.type_definition,
// $.exception_defn
),
module_abbrev: $ =>
seq(
"module",
$.identifier,
"=",
$._virtual_open_section,
$.long_identifier,
$._virtual_end_section,
),
module_defn: $ =>
prec.left(
seq(
optional($.attributes),
"module",
optional($.access_modifier),
$.identifier,
"=",
$._virtual_open_section,
repeat1($._module_elem),
$._virtual_end_section,
)),
compiler_directive_decl: $ =>
seq(
"#nowarn",
repeat($.string),
),
fsi_directive_decl: $ =>
choice(
seq("#r", repeat($.string)),
seq("#load", repeat($.string)),
),
import_decl: $ =>
seq(
"open",
$.long_identifier,
),
//
// Attributes (BEGIN)
//
attributes: $ => prec.left(repeat1($.attribute_set)),
attribute_set: $ =>
seq(
"[<",
$.attribute,
repeat(seq(";", $.attribute)),
">]"
),
attribute: $ => seq(
optional(seq($.attribute_target, ":")),
$.object_construction
),
attribute_target: $ => choice(
"assembly",
"module",
"return",
"field",
"property",
"param",
"type",
"constructor",
"event"
),
object_construction: $ =>
prec.left(
seq(
$.type,
optional($._expressions),
)),
//
// Attributes (END)
//
value_declaration: $ =>
choice(
prec(PREC.LET_DECL, $.function_or_value_defn),
prec(PREC.DO_DECL, $.do)
),
do: $ => prec(PREC.DO_EXPR,
seq(
"do",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
)),
_function_or_value_defns : $ =>
seq($._function_or_value_defn_body, repeat1(seq("and", $._function_or_value_defn_body))),
function_or_value_defn: $ =>
seq(
choice("let", "let!"),
choice(
$._function_or_value_defn_body,
seq("rec", $._function_or_value_defns)
),
),
_function_or_value_defn_body: $ =>
seq(
choice(
$.function_declaration_left,
$.value_declaration_left,
),
"=",
$._virtual_open_section,
field("body", $._expressions),
$._virtual_end_section,
),
function_declaration_left: $ =>
prec.left(2,seq(
optional("inline"),
optional($.access_modifier),
$._identifier_or_op,
optional($.type_arguments),
$.argument_patterns,
optional(seq(":", $.type))
)),
value_declaration_left: $ =>
prec.left(2,seq(
optional("mutable"),
optional($.access_modifier),
$._pattern,
optional($.type_arguments),
optional(seq(":", $.type))
)),
access_modifier: $ => choice("private", "internal", "public"),
//
// Top-level rules (END)
//
//
// Pattern rules (BEGIN)
_pattern: $ =>
choice(
alias("null", $.null_pattern),
alias("_", $.wildcard_pattern),
alias($.const, $.const_pattern),
$.identifier_pattern,
$.as_pattern,
$.disjunct_pattern,
$.conjunct_pattern,
$.cons_pattern,
$.repeat_pattern,
$.paren_pattern,
$.list_pattern,
$.array_pattern,
$.record_pattern,
$.typed_pattern,
$.attribute_pattern,
// :? atomic-type
// :? atomic-type as ident
),
attribute_pattern: $ => prec.left(seq($.attributes, $._pattern)),
paren_pattern: $ => seq("(", $._virtual_open_section, $._pattern, $._virtual_end_section, ")"),
repeat_pattern: $ =>
prec.right(
seq(
$._pattern, ",",
repeat(prec.right(seq($._virtual_end_decl, $._pattern, ","))),
$._pattern
)),
identifier_pattern: $ =>
prec.left(
seq($.long_identifier, optional($._pattern_param), optional($._pattern)),
),
as_pattern: $ => prec.left(0,seq($._pattern, "as", $.identifier)),
cons_pattern: $ => prec.left(0,seq($._pattern, "::", $._pattern)),
disjunct_pattern: $ => prec.left(0,seq($._pattern, "|", $._pattern)),
conjunct_pattern: $ => prec.left(0,seq($._pattern, "&", $._pattern)),
typed_pattern: $ => prec.left(3,seq($._pattern, ":", $.type)),
argument_patterns: $ => repeat1($._atomic_pattern),
field_pattern: $ => prec(1, seq($.long_identifier, '=', $._pattern)),
_atomic_pattern: $ =>
choice(
"null",
"_",
$.const,
$.long_identifier,
$.list_pattern,
$.record_pattern,
$.array_pattern,
seq("(", $._virtual_open_section, $._pattern, $._virtual_end_section, ")"),
// :? atomic_type
),
list_pattern: $ => choice(
seq('[', ']'),
seq('[', $._pattern, repeat(seq(";", $._pattern)), ']')),
array_pattern: $ => choice(
seq('[|', '|]'),
seq('[|', $._pattern, repeat(seq(";", $._pattern)), '|]')),
record_pattern: $ =>
prec.left(
seq(
'{', $.field_pattern, repeat(seq(";", $.field_pattern)))),
_pattern_param: $ =>
prec(2,
choice(
$.const,
$.long_identifier,
// seq($.long_identifier, $._pattern_param),
// seq($._pattern_param, ":", $.type),
// seq(
// "[",
// $._pattern_param,
// repeat(seq($._seperator, $._pattern_param)),
// "]",
// ),
// seq(
// "(",
// $._pattern_param,
// repeat(seq($._seperator, $._pattern_param)),
// ")",
// ),
// seq("<@", $._expression_inner, "@>"),
// seq("<@@", $._expression_inner, "@@>"),
"null",
)
),
//
// Pattern rules (END)
//
//
// Expressions (BEGIN)
//
//
_seq_infix: $ =>
prec.right(
seq(
$._expression_inner,
repeat1(
seq(
$._virtual_end_decl,
$.infix_op,
$._expressions,
),
),
)),
_seq_expressions: $ =>
seq(
$._expression_inner,
repeat(seq($._virtual_end_decl, $._expressions)),
),
_expressions: $ =>
prec.left(PREC.SEQ_EXPR,
choice(
alias($._seq_infix, $.infix_expression),
$._seq_expressions,
),
),
_expression_inner: $ =>
choice(
$.line_comment,
$.block_comment,
$.const,
$.paren_expression,
$.begin_end_expression,
$.long_identifier_or_op,
$.dot_expression,
$.typed_expression,
$.infix_expression,
$.index_expression,
$.mutate_expression,
$.object_instantiation_expression,
$.list_expression,
$.array_expression,
$.ce_expression,
$.prefixed_expression,
$.brace_expression,
// [ comp_or_range_expr ]
// [| comp_or_range_expr |]
"null",
$.typecast_expression,
$.declaration_expression,
$.do_expression,
$.fun_expression,
$.function_expression,
$.if_expression,
$.while_expression,
$.for_expression,
$.match_expression,
$.try_expression,
$.literal_expression,
$.call_expression,
$.tuple_expression,
$.application_expression,
$.return_expression,
$.yield_expression,
// (static-typars : (member-sig) expr)
),
application_expression: $ =>
prec.right(PREC.APP_EXPR,
seq(
$._expression_inner,
repeat1($._expression_inner),
)
),
call_expression: $ =>
prec.right(PREC.PAREN_APP+100,
seq(
$._expression_inner,
imm("("),
optional($._expressions),
")",
)
),
tuple_expression: $ =>
prec.left(PREC.TUPLE_EXPR,
seq(
$._expression_inner,
repeat1(prec.left(PREC.TUPLE_EXPR, seq(",", $._expression_inner))),
)
),
brace_expression: $ =>
prec(PREC.PAREN_EXPR,
seq(
"{",
choice(
$.with_field_expression,
$.field_expression,
$.object_expression,
),
"}",
)),
with_field_expression: $ =>
seq(
$._expressions,
"with",
$._virtual_open_section,
$.field_initializers,
$._virtual_end_section,
),
field_expression: $ => $.field_initializers,
object_expression: $ =>
prec(PREC.NEW_EXPR,
seq(
"new",
$._base_call,
$._virtual_open_section,
$._object_members,
$._interface_implementations,
$._virtual_end_section,
)),
_base_call: $ =>
choice(
$.object_construction,
seq($.object_construction, "as", $.identifier),
),
prefixed_expression: $ =>
prec.left(PREC.PREFIX_EXPR,
seq(
choice("lazy", "assert", "upcast", "downcast", "%", "%%", $.prefix_op),
$._expression_inner,
)),
return_expression: $ =>
prec.left(PREC.SPECIAL_PREFIX,
seq(
choice("return", "return!"),
$._expression_inner,
)),
yield_expression: $ =>
prec.left(PREC.SPECIAL_PREFIX,
seq(
choice("yield", "yield!"),
$._expression_inner,
)),
ce_expression: $ =>
prec(PREC.CE_EXPR,
seq(
$._expression_inner,
"{",
$._virtual_open_section,
$._comp_or_range_expression,
$._virtual_end_section,
"}",
)),
infix_expression: $ =>
prec.right(PREC.SPECIAL_INFIX,
seq(
$._expression_inner,
$.infix_op,
$._expression_inner,
)),
literal_expression: $ =>
prec(PREC.PAREN_EXPR,
choice(
seq("<@", $._expression_inner, "@>"),
seq("<@@", $._expression_inner, "@@>"),
)),
typecast_expression: $ =>
prec(PREC.SPECIAL_INFIX,
seq(
$._expression_inner,
choice(
":",
":>",
":?",
":?>"
),
$.type
)),
begin_end_expression: $ => prec(PREC.PAREN_EXPR, seq("begin", $._expressions, "end")),
paren_expression: $ => prec(PREC.PAREN_EXPR, seq("(", $._virtual_open_section, $._expressions, $._virtual_end_section, ")")),
for_expression: $ =>
prec.left(
seq(
"for",
choice(
seq($._pattern, "in", $._expression_or_range),
seq($.identifier, "=", $._expression_inner, choice("to","downto"), $._expression_inner),
),
"do",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
optional("done"),
)),
while_expression: $ =>
prec.left(
seq(
"while",
$._expression_inner,
"do",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
optional("done"),
)),
_else_expression: $ =>
prec(PREC.ELSE_EXPR,
seq(
"else",
$._virtual_open_section,
field("else_branch", $._expressions),
$._virtual_end_section,
)),
elif_expression: $ =>
prec(PREC.ELSE_EXPR,
seq(
"elif",
field("guard", $._expression_inner),
"then",
$._virtual_open_section,
field("then", $._expressions),
$._virtual_end_section,
)),
if_expression: $ =>
prec.left(PREC.IF_EXPR,
seq(
"if",
field("guard", $._expression_inner),
"then",
field("then", $._expressions),
repeat($.elif_expression),
optional($._else_expression),
)),
fun_expression: $ =>
prec.right(PREC.FUN_EXPR,
seq(
"fun",
$.argument_patterns,
"->",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
)),
try_expression: $ =>
prec(PREC.MATCH_EXPR,
seq(
"try",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
choice(
seq("with", $.rules),
seq("finally", $._virtual_open_section, $._expressions, $._virtual_end_section),
),
)),
match_expression: $ =>
prec(PREC.MATCH_EXPR,
seq(
choice("match", "match!"),
$._expression_inner,
"with",
$.rules,
)),
function_expression: $ =>
prec(PREC.MATCH_EXPR,
seq(
"function",
$.rules,
)),
object_instantiation_expression: $ =>
prec(PREC.NEW_OBJ,
seq(
"new",
$.type,
imm("("),
$._expression_inner,
")"
)),
mutate_expression: $ =>
prec.right(PREC.LARROW,
seq(
field("assignee", $._expression_inner),
"<-",
field("value", $._expression_inner),
)),
index_expression: $ =>
prec(PREC.INDEX_EXPR,
seq(
$._expression_inner,
optional(imm(".")),
imm("["),
$._virtual_open_section,
choice(
field("index", $._expressions),
$.slice_ranges,
),
$._virtual_end_section,
"]",
)),
dot_expression: $ =>
prec.right(PREC.DOT,
seq(
field("base", $._expression_inner),
imm("."),
field("field", $.long_identifier_or_op),
)),
typed_expression: $ =>
prec(PREC.PAREN_EXPR,
seq(
$._expression_inner,
imm("<"),
optional($.types),
">",
)),
declaration_expression: $ =>
prec.right(PREC.LET_EXPR,
seq(
choice(
seq(choice("use", "use!"), $.identifier, "=", $._virtual_open_section, $._expressions, $._virtual_end_section),
$.function_or_value_defn,
),
$._virtual_open_section,
field("in", $._expressions),
$._virtual_end_section,
)),
do_expression: $ =>
prec(PREC.DO_EXPR,
seq(
choice("do", "do!"),
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
)),
_list_elements: $ =>
prec.right(PREC.COMMA+100,
seq(
$._virtual_open_section,
$._expression_inner,
repeat(prec.right(PREC.COMMA+100, seq($._virtual_end_decl, $._expression_inner))),
$._virtual_end_section,
),
),
_list_element: $ =>
choice(
$._list_elements,
$._comp_or_range_expression,
),
list_expression: $ =>
seq(
"[",
optional($._list_element),
"]",
),
array_expression: $ =>
seq(
"[|",
optional($._list_element),
"|]",
),
range_expression: $ =>
prec.left(PREC.DOTDOT,
seq(
$._expressions,
"..",
$._expressions,
optional(seq(
"..",
$._expressions,
)))),
_expression_or_range: $ =>
choice(
$._expression_inner,
$.range_expression,
),
rule: $ =>
prec.right(
seq(
$._pattern,
"->",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
)),
rules: $ =>
prec.right(PREC.MATCH_EXPR,
seq(
$._virtual_open_section,
optional("|"),
$.rule,
repeat(seq("|", $.rule)),
$._virtual_end_section,
)),
//
// Expressions (END)
//
//
// Computation expression (BEGIN)
//
_comp_or_range_expression: $ =>
choice(
$._expressions,
$.short_comp_expression,
// $.range_expression, TODO
),
// _comp_expressions: $ =>
// choice(
// $.let_ce_expressions,
// $.do_ce_expressions,
// $.use_ce_expressions,
// $.yield_ce_expressions,
// $.return_ce_expressions,
// $.if_ce_expressions,
// $.match_ce_expressions,
// $.try_ce_expressions,
// $.while_expressions,
// $.for_ce_expressions,
// $.sequential_ce_expressions,
// $._expressions,
// ),
// for_ce_expressions: $ =>
// prec.left(
// seq(
// "for",
// choice(
// seq($._pattern, "in", $._expressions_or_range),
// seq($.identifier, "=", $._expressions, "to", $._expression),
// ),
// "do",
// $._virtual_open_section,
// $._comp_expressions,
// $._virtual_end_section,
// optional("done"),
// )),
//
// try_ce_expressions: $ =>
// prec(PREC.MATCH_EXPR,
// seq(
// "try",
// $._virtual_open_section,
// $._comp_expressions,
// $._virtual_end_section,
// choice(
// seq("with", $.comp_rules),
// seq("finally", $.comp_rules)
// ),
// )),
//
// match_ce_expressions: $ =>
// prec(PREC.MATCH_EXPR,
// seq(
// "match",
// $._expressions,
// "with",
// $.comp_rules,
// )),
//
// sequential_ce_expressions: $ =>
// prec.left(PREC.SEQ_EXPR,
// seq(
// $._comp_expressions,
// repeat1(prec.right(PREC.SEQ_EXPR, seq(choice(";", $._newline), $._comp_expressions))),
// )),
//
// _else_ce_expressions: $ =>
// prec(PREC.ELSE_EXPR,
// seq(
// "else",
// $._virtual_open_section,
// field("else_branch", $._comp_expressions),
// $._virtual_end_section,
// )),
//
// elif_ce_expressions: $ =>
// prec(PREC.ELSE_EXPR,
// seq(
// "elif",
// $._virtual_open_section,
// field("guard", $._expressions),
// $._virtual_end_section,
// "then",
// $._virtual_open_section,
// field("then", $._comp_expressions),
// $._virtual_end_section,
// )),
//
// if_ce_expressions: $ =>
// prec.left(PREC.IF_EXPR,
// seq(
// "if",
// $._virtual_open_section,
// field("guard", $._expressions),
// $._virtual_end_section,
// "then",
// field("then", $._comp_expressions),
// repeat($.elif_ce_expressions),
// optional($._else_ce_expressions),
// )),
//
// return_ce_expressions: $ =>
// prec.left(PREC.PREFIX_EXPR,
// seq(
// choice("return!", "return"),
// $._expressions,
// )),
//
// yield_ce_expressions: $ =>
// prec.left(PREC.PREFIX_EXPR,
// seq(
// choice("yield!", "yield"),
// $._expressions,
// )),
//
// do_ce_expressions: $ =>
// seq(
// choice("do!", "do"),
// $._expressions,
// $._comp_expressions,
// ),
//
// use_ce_expressions: $ =>
// seq(
// choice("use!", "use"),
// $._pattern,
// "=",
// $._virtual_open_section,
// $._expressions,
// $._virtual_end_section,
// $._comp_expressions,
// ),
//
// let_ce_expressions: $ =>
// seq(
// choice("let!", "let"),
// $._pattern,
// "=",
// $._virtual_open_section,
// $._expressions,
// $._virtual_end_section,
// $._comp_expressions,
// ),
short_comp_expression: $ =>
seq(
"for",
$._pattern,
"in",
$._expression_or_range,
"->",
$._expressions,
),
// comp_rule: $ =>
// seq(
// $._pattern,
// "->",
// $._comp_expressions,
// ),
//
// comp_rules: $ =>
// prec.left(2,
// seq(
// optional("|"),
// $.comp_rule,
// repeat(seq("|", $.comp_rule)),
// )),
slice_ranges: $ =>
seq($.slice_range, repeat(seq(",", $.slice_range))),
_slice_range_special: $ =>
prec.left(PREC.DOTDOT_SLICE,
choice(
seq($._expressions, ".."),
seq("..", $._expressions),
seq($._expressions, "..", $._expressions),
)
),
slice_range: $ =>
choice(
$._slice_range_special,
$._expressions,
"*",
),
//
// Computation expression (END)
//
//
// Type rules (BEGIN)
//
type: $ =>
prec(4, choice(
$.long_identifier,
prec.right(seq($.long_identifier, "<", optional($.type_attributes), ">")),
seq("(", $.type, ")"),
prec.right(seq($.type, "->", $.type)),
prec.right(seq($.type, repeat1(prec.right(seq("*", $.type))))),
prec.left(4, seq($.type, $.long_identifier)),
seq($.type, "[", repeat(","), "]"), // TODO: FIXME
seq($.type, $.type_argument_defn),
$.type_argument,
prec.right(seq($.type_argument, ":>", $.type)),
prec.right(seq(imm("#"), $.type)),
)),
types: $ =>
seq(
$.type,
repeat1(prec.left(PREC.COMMA, seq(",", $.type))),
),
type_attribute: $ =>
choice(
$.type,
// measure
// static-parameter
),
type_attributes: $ => seq($.type_attribute, repeat(prec.left(PREC.COMMA, seq(",", $.type_attribute)))),
atomic_type: $ =>
choice(
seq("#", $.type),
$.type_argument,
seq("(", $.type, ")"),
$.long_identifier,
seq($.long_identifier, "<", $.type_attributes, ">"),
),
constraint: $ =>
choice(
seq($.type_argument, ":>", $.type),
seq($.type_argument, ":", "null"),
seq($.static_type_argument, ":", "(", $.trait_member_constraint, ")"),
seq($.type_argument, ":", "(", "new", ":", "unit", "->", "'T", ")"),
seq($.type_argument, ":", "struct"),
seq($.type_argument, ":", "not", "struct"),
seq($.type_argument, ":", "enum", "<", $.type, ">"),
seq($.type_argument, ":", "unmanaged"),
seq($.type_argument, ":", "equality"),
seq($.type_argument, ":", "comparison"),
seq($.type_argument, ":", "delegate", "<", $.type, ",", $.type, ">"),
),
type_argument_constraints: $ =>
seq(
"when",
$.constraint,
repeat(seq("and", $.constraint))
),
type_argument: $ =>
choice(
"_",
seq("'", $.identifier),
seq("^", $.identifier),
),
type_argument_defn: $ =>
seq(
optional($.attributes),
$.type_argument
),
static_type_argument: $ =>
choice(
seq(choice("^", "'"), $.identifier),
seq(choice("^", "'"), $.identifier, repeat(seq("or", choice("^", "'"), $.identifier)))
),
type_arguments: $ =>
seq(
"<",
$.type_argument_defn,
repeat(prec.left(PREC.COMMA, seq(",", $.type_argument_defn))),
optional($.type_argument_constraints),
">"
),
trait_member_constraint: $ =>
seq(
optional("static"),
"member",
$.identifier,
':',
$.type
),
member_signature: $ =>
seq(
$.identifier,
optional($.type_arguments),
":",
$.type,
optional(
choice(
seq("with", "get"),
seq("with", "set"),
seq("with", "get", ",", "set"),
seq("with", "set", ",", "get"),
)
)
),
argument_spec: $ =>
seq(
optional($.attributes),
optional($.argument_name_spec),
$.type,
),
arguments_spec: $ =>
seq(
$.argument_spec,
repeat(seq("*", $.argument_spec))
),
argument_name_spec: $ =>
seq(
optional("?"),
$.identifier,
":"
),
interface_spec: $ =>
seq(
"interface",
$.type
),
static_parameter: $ =>
choice(
$.static_parameter_value,
seq("id", "=", $.static_parameter_value)
),
static_parameter_value: $ =>
choice(
$.const,
seq($.const, $._expressions)
),
type_definition: $ =>
prec.left(seq(
optional($.attributes),
"type",
$._type_defn_body,
repeat(seq(
optional($.attributes),
"and",
$._type_defn_body,
)))),
_type_defn_body: $ =>
choice(
$.delegate_type_defn,
$.record_type_defn,
$.union_type_defn,
$.anon_type_defn,
// $.class_type_defn,
// $.struct_type_defn,
// $.interface_type_defn,
$.enum_type_defn,
$.type_abbrev_defn,
$.type_extension,
),
type_name: $ =>
seq(
optional($.attributes),
optional($.access_modifier),
choice(
seq($.identifier, optional($.type_arguments)),
seq(optional($.type_argument), $.identifier) // Covers `type 'a option = Option<'a>`
),
),
type_extension: $ =>
seq(
$.type_name,
$.type_extension_elements,
),
delegate_type_defn: $ =>
seq(
$.type_name,
"=",
$._virtual_open_section,
$.delegate_signature,
$._virtual_end_section,
),
delegate_signature: $ =>
seq(
"delegate",
"of",
$.type,
),
type_abbrev_defn: $ =>
seq(
$.type_name,
"=",
$._virtual_open_section,
$.type,
$._virtual_end_section,
),
// class_type_defn: $ =>
// seq(
// $.type_name,
// optional($.primary_constr_args),
// "=",
// "class",
// $.class_type_body,
// "end",
// ),
//
// struct_type_defn: $ =>
// seq(
// $.type_name,
// optional($.primary_constr_args),
// "=",
// "struct",
// $.class_type_body,
// "end",
// ),
//
// interface_type_defn: $ =>
// seq(
// $.type_name,
// optional($.primary_constr_args),
// "=",
// "interface",
// $.class_type_body,
// "end",
// ),
_class_type_body_inner: $ =>
choice(
$.class_inherits_decl,
$._class_function_or_value_defn,
$._type_defn_elements,
),
_class_type_body: $ =>
seq(
$._virtual_open_section,
$._class_type_body_inner,
repeat(seq($._virtual_end_decl,$._class_type_body_inner)),
$._virtual_end_section,
),
record_type_defn: $ =>
prec.left(
seq(
$.type_name,
"=",
$._virtual_open_section,
"{",
$._virtual_open_section,
$.record_fields,
$._virtual_end_section,
"}",
optional($.type_extension_elements),
$._virtual_end_section,
)),
record_fields: $ =>
seq(
$.record_field,
repeat(seq($._virtual_end_decl, $.record_field)),
optional(";"),
),
record_field: $ =>
seq(
optional($.attributes),
optional("mutable"),
optional($.access_modifier),
$.identifier,
":",
$.type
),
enum_type_defn: $ =>
seq(
$.type_name,
"=",
$._virtual_open_section,
$.enum_type_cases,
$._virtual_end_section,
),
enum_type_cases: $ =>
seq(
optional("|"),
$.enum_type_case,
repeat(seq($._virtual_end_decl, "|", $.enum_type_case))
),
enum_type_case: $ =>
seq(
$.identifier,
"=",
$.const
),
union_type_defn: $ =>
prec.left(
seq(
$.type_name,
"=",
$._virtual_open_section,
$.union_type_cases,
optional($.type_extension_elements),
$._virtual_end_section,
)),
union_type_cases: $ =>
seq(
optional("|"),
$.union_type_case,
repeat(seq("|", $.union_type_case))
),
union_type_case: $ =>
prec(8,
seq(
optional($.attributes),
choice(
$.identifier,
seq($.identifier, "of", $.union_type_fields),
seq($.identifier, ":", $.type),
))),
union_type_fields: $ =>
seq(
$.union_type_field,
repeat(seq("*", $.union_type_field)),
),
union_type_field: $ =>
prec.left(choice(
$.type,
seq($.identifier, ":", $.type)
)),
anon_type_defn: $ =>
seq(
$.type_name,
$.primary_constr_args,
"=",
$._virtual_open_section,
$._class_type_body,
$._virtual_end_section,
),
primary_constr_args: $ =>
seq(
optional($.attributes),
optional($.access_modifier),
"(",
optional(seq(
$.simple_pattern,
repeat(prec.left(PREC.COMMA, seq(",", $.simple_pattern))))),
")"
),
simple_pattern: $ =>
choice(
$.identifier,
seq($.simple_pattern, ":", $.type)
),
_class_function_or_value_defn: $ =>
seq(
optional($.attributes),
optional("static"),
choice(
$.function_or_value_defn,
seq("do", $._virtual_open_section, $._expressions, $._virtual_end_section),
)
),
type_extension_elements: $ =>
seq(
choice(
seq(
"with",
$._virtual_open_section,
$._type_defn_elements,
$._virtual_end_section,
),
$._type_defn_elements,
)
),
_type_defn_elements: $ =>
choice(
$._member_defns,
$._interface_implementations,
// $.interface_signature
),
_interface_implementations: $ => prec.right(repeat1($.interface_implementation)),
interface_implementation: $ =>
prec.left(
seq(
"interface",
$.type,
optional($._object_members),
)),
_member_defns: $ =>
prec.left(
seq(
$.member_defn,
repeat(seq($._virtual_end_decl, $.member_defn)),
)),
_object_members: $ =>
seq(
"with",
$._virtual_open_section,
$._member_defns,
$._virtual_end_section,
),
member_defn: $ =>
seq(
optional($.attributes),
choice(
seq(optional("static"), "member", optional($.access_modifier), $.method_or_prop_defn),
seq("abstract", optional("member"), optional($.access_modifier), $.member_signature),
seq("override", optional($.access_modifier), $.method_or_prop_defn),
seq("default", optional($.access_modifier), $.method_or_prop_defn),
seq(optional("static"), "val", optional("mutable"), optional($.access_modifier), $.identifier, ":", $.type),
$.additional_constr_defn,
),
),
property_or_ident: $ =>
choice(
seq(field("instance", $.identifier), ".", $.identifier),
$.identifier,
),
_method_defn: $ =>
choice(
seq($.property_or_ident, $._pattern, "=", $._virtual_open_section, $._expressions, $._virtual_end_section),
),
_property_defn: $ =>
seq(
$.property_or_ident,
"=",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
optional(
seq(
"with",
choice(
"get",
"set",
seq("get", ",", "set"),
seq("set", ",", "get"),
)
)
),
),
method_or_prop_defn: $ =>
prec(3,
choice(
seq($.property_or_ident, "with", $._virtual_open_section, $._function_or_value_defns, $._virtual_end_section),
$._method_defn,
$._property_defn,
)
),
additional_constr_defn: $ =>
seq(
// optional($.attributes),
optional($.access_modifier),
"new",
$._pattern,
$.as_defn,
"=",
// $.additional_constr_expr
),
additional_constr_expr: $ =>
choice(
seq($.additional_constr_expr, ";", $.additional_constr_expr),
seq($.additional_constr_expr, "then", $._expressions),
seq("if", $._expressions, "then", $.additional_constr_expr, "else", $.additional_constr_expr),
seq("let", $._function_or_value_defn_body, "in", $.additional_constr_expr), // TODO: "in" is optional?
$.additional_constr_init_expr
),
additional_constr_init_expr: $ =>
choice(
seq("{", $.class_inherits_decl, $.field_initializers, "}"),
seq("new", $.type, $._expressions)
),
class_inherits_decl: $ =>
prec.left(
seq(
"inherit",
$.type,
$._virtual_open_section,
optional($._expressions),
$._virtual_end_section,
)
),
as_defn: $ => seq("as", $.identifier),
field_initializer: $ => prec.right(seq($.long_identifier, "=",
$._virtual_open_section,
$._expressions,
$._virtual_end_section,
)),
field_initializers: $ =>
prec.left(PREC.COMMA+100,
seq(
$.field_initializer,
repeat(prec.left(PREC.COMMA+100, seq($._virtual_end_decl, $.field_initializer)))
)),
//
// Type rules (END)
//
//
// Constants (BEGIN)
//
_escape_char: $ => imm(/\\["\'ntbrafv]/),
_non_escape_char: $ => imm(/\\[^"\'ntbrafv]/),
// using \u0008 to model \b
_simple_char_char: $ => imm(/[^\n\t\r\u0008\a\f\v'\\]/),
_hex_digit_imm: $ => imm(/[0-9a-fA-F]/),
_digit_char_imm: $ => imm(/[0-9]/),
_unicodegraph_short: $ => seq(
imm('\\u'),
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
),
_unicodegraph_long: $ => seq(
imm('\\U'),
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
$._hex_digit_imm,
),
_trigraph: $ => seq(imm('\\'), $._digit_char_imm, $._digit_char_imm, $._digit_char_imm),
_char_char: $ => choice(
$._simple_char_char,
$._escape_char,
$._trigraph,
$._unicodegraph_short
),
// note: \n is allowed in strings
_simple_string_char: $ => /[^\t\r\u0008\a\f\v\\"]/,
_string_char: $ => choice(
$._simple_string_char,
$._escape_char,
$._non_escape_char,
$._trigraph,
$._unicodegraph_short,
$._unicodegraph_long,
),
_string_elem: $ => choice(
$._string_char,
seq('\\', $._string_elem)
),
char: $ => seq("'", $._char_char, imm("'")),
string: $ => seq('"', repeat($._string_char), imm('"')),
_verbatim_string_char: $ => choice(
$._simple_string_char,
$._non_escape_char,
'\\',
),
verbatim_string: $ => seq('@"', repeat($._verbatim_string_char), imm('"')),
bytechar: $ => seq("'", $._char_char, imm("'B")),
bytearray: $ => seq('"', repeat($._string_char), imm('"B')),
verbatim_bytearray: $ => seq('@"', repeat($._verbatim_string_char), imm('"B')),
_simple_or_escape_char: $ => choice($._escape_char, imm(/[^'\\]/)),
triple_quoted_string: $ => seq('"""', repeat($._simple_or_escape_char), imm('"""')),
_newline: $ => /\r?\n/,
unit: $ => seq("(", optional(seq($._virtual_open_section, $._virtual_end_section)), ")"),
const: $ => choice(
$.sbyte, $.int16, $.int32, $.int64, $.byte, $.uint16, $.uint32, $.int,
$.nativeint, $.unativeint, $.decimal,
$.uint64, $.ieee32, $.ieee64, $.bignum, $.char, $.string,
$.verbatim_string, $.triple_quoted_string, $.bytearray,
$.verbatim_bytearray, $.bytechar, "false", "true", $.unit),
// Identifiers:
long_identifier_or_op: $ => prec.right(
alias(
choice(
$.long_identifier,
seq($.long_identifier, ".", $._identifier_or_op),
$._identifier_or_op
),
$.long_identifier)
),
long_identifier : $ =>
prec.right(seq($.identifier, repeat(seq(".", $.identifier)))),
_identifier_or_op: $ => choice(
$.identifier,
seq('(', $.op_name, ')'),
"(*)"
),
op_name: $ => choice(
$.symbolic_op,
$.range_op_name,
$.active_pattern_op_name
),
range_op_name: $ => choice(
"..",
".. .."
),
active_pattern_op_name: $ => choice(
// full pattern
seq("|", $.identifier, repeat1(seq("|", $.identifier)), "|"),
// partial pattern
seq("|", $.identifier, repeat(seq("|", $.identifier)), "|", "_", "|"),
),
_infix_or_prefix_op: $ =>
choice(
"+",
"-",
"+.",
"-.",
"%",
"&",
"&&",
),
prefix_op: $ =>
prec.left(
choice(
$._infix_or_prefix_op,
repeat1("~"),
$.symbolic_op,
)),
infix_op: $ =>
prec(PREC.INFIX_OP,
choice(
$._infix_or_prefix_op,
$.symbolic_op,
"||",
"=",
"!=",
":=",
"::",
"$",
"or",
"?",
)),
// Symbolic Operators
_quote_op_left: $ => choice("<@", "<@@"),
_quote_op_right: $ => choice("@>", "@@>"),
symbolic_op: $ => choice(
"?",
"?<-",
/[!%&*+-./<=>@^|~][!%&*+-./<=>@^|~?]*/,
$._quote_op_left,
$._quote_op_right),
// Numbers
_octaldigit_imm: $ => imm(/[0-7]/),
_bitdigit_imm: $ => imm(/[0-1]/),
int: $ => seq(/[0-9]/, repeat($._digit_char_imm)),
xint: $ => choice(
seq(/0[xX]/, repeat1($._hex_digit_imm)),
seq(/0[oO]/, repeat1($._octaldigit_imm)),
seq(/0[bB]/, repeat1($._bitdigit_imm)),
),
sbyte: $ => seq(choice($.int, $.xint), imm('y')),
byte: $ => seq(choice($.int, $.xint), imm('uy')),
int16: $ => seq(choice($.int, $.xint), imm('s')),
uint16: $ => seq(choice($.int, $.xint), imm('us')),
int32: $ => seq(choice($.int, $.xint), imm('l')),
uint32: $ => seq(choice($.int, $.xint), imm(choice('ul', 'u'))),
nativeint: $ => seq(choice($.int, $.xint), imm('n')),
unativeint: $ => seq(choice($.int, $.xint), imm('un')),
int64: $ => seq(choice($.int, $.xint), imm('L')),
uint64: $ => seq(choice($.int, $.xint), imm(choice('UL', 'uL'))),
ieee32: $ => choice(seq($.float, imm("f")), seq($.xint, imm("lf"))),
ieee64: $ => seq($.xint, imm("LF")),
bignum: $ => seq($.int, imm(/[QRZING]/)),
decimal: $ => seq(choice($.float,$.int), imm(/[Mm]/)),
float: $ => token(choice(
seq(/[0-9]+/, imm(/\.[0-9]*/)),
seq(/[0-9]+/, optional(imm(/\.[0-9]*/)), imm(/[eE]/), optional(imm(/[+-]/)), imm(/[0-9]+/)))),
//
// Constants (END)
//
block_comment: $ => seq("(*", $.block_comment_content, "*)"),
line_comment: $ => token(seq("//", repeat(/[^\n\r]/))),
identifier: $ => choice(
/[_\p{XID_Start}][_'\p{XID_Continue}]*/,
/``([^`\n\r\t])+``/ //TODO: Not quite the spec
),
}
});