mirror of https://github.com/Wilfred/difftastic/
1745 lines
41 KiB
JavaScript
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
|
|
),
|
|
}
|
|
|
|
});
|