difftastic/vendor/tree-sitter-ocaml/ocaml/grammar.js

2063 lines
46 KiB
JavaScript

const PREC = {
prefix: 19,
dot: 18,
hash: 17,
app: 16,
neg: 15,
pow: 14,
mult: 13,
add: 12,
cons: 11,
concat: 10,
rel: 9,
and: 8,
or: 7,
prod: 6,
assign: 5,
if: 4,
seq: 3,
match: 2
}
const OP_CHAR = /[!$%&*+\-./:<=>?@^|~]/
const HASH_OP_CHAR = /[#!$%&*+\-./:<=>?@^|~]/
const NUMBER = token(choice(
/[0-9][0-9_]*(\.[0-9_]*)?([eE][+\-]?[0-9][0-9_]*)?[g-zG-Z]?/,
/0[xX][0-9A-Fa-f][0-9A-Fa-f_]*(\.[0-9A-Fa-f_]*)?([pP][+\-]?[0-9][0-9_]*)?[g-zG-Z]?/,
/0[oO][0-7][0-7_]*[g-zG-Z]?/,
/0[bB][01][01_]*[g-zG-Z]?/
))
module.exports = grammar({
name: 'ocaml',
extras: $ => [
/\s/,
$.comment,
$.line_number_directive,
$.attribute
],
inline: $ => [
$._module_type_ext,
$._module_expression_ext,
$._module_expression_ext,
$._simple_type_ext,
$._simple_expression_ext,
$._expression_ext,
$._quoted_string,
$._label_name,
$._field_name,
$._class_name,
$._class_type_name,
$._method_name,
$._type_constructor,
$._instance_variable_name,
$._module_name,
$._module_type_name,
$._constructor_name,
],
word: $ => $._identifier,
supertypes: $ => [
$._structure_item,
$._parameter,
$._module_type,
$._simple_module_expression,
$._module_expression,
$._simple_class_type,
$._class_type,
$._class_field_specification,
$._simple_class_expression,
$._class_expression,
$._class_field,
$._polymorphic_type,
$._simple_type,
$._tuple_type,
$._tag_spec,
$._type,
$._simple_expression,
$._expression,
$._sequence_expression,
$._argument,
$._simple_pattern,
$._pattern,
$._binding_pattern,
$._extension,
$._item_extension,
$._constant,
$._signed_constant,
$._value_name,
$._value_pattern
],
rules: {
compilation_unit: $ => seq(
optional($.shebang),
optional($._structure)
),
shebang: $ => /#!.*/,
_structure: $ => choice(
repeat1(';;'),
seq(
repeat(';;'),
choice($._structure_item_ext, $.toplevel_directive, $.expression_item),
repeat(choice(
seq(repeat(';;'), choice($._structure_item_ext, $.toplevel_directive)),
seq(repeat1(';;'), $.expression_item)
)),
repeat(';;')
)
),
expression_item: $ => seq(
$._sequence_expression_ext,
repeat($.item_attribute)
),
_signature: $ => choice(
repeat1(';;'),
seq(repeat1(seq(repeat(';;'), $._signature_item_ext)), repeat(';;'))
),
// Toplevel
toplevel_directive: $ => seq(
$.directive,
optional(choice(
$._constant,
$.value_path,
$.module_path
))
),
// Module implementation
_structure_item: $ => choice(
$.value_definition,
$.external,
$.type_definition,
$.exception_definition,
$.module_definition,
$.module_type_definition,
$.open_module,
$.include_module,
$.class_definition,
$.class_type_definition,
$.floating_attribute
),
_structure_item_ext: $ => choice(
$._structure_item,
$._item_extension
),
value_definition: $ => seq(
choice(seq('let', optional($._attribute), optional('rec')), $.let_operator),
sep1(choice('and', $.and_operator), $.let_binding)
),
let_binding: $ => prec.right(seq(
field('pattern', $._binding_pattern_ext),
optional(seq(
repeat($._parameter),
optional($._polymorphic_typed),
optional(seq(':>', $._type_ext)),
'=',
field('body', $._sequence_expression_ext),
)),
repeat($.item_attribute)
)),
_parameter: $ => choice(
$.parameter,
alias($._parenthesized_abstract_type, $.abstract_type)
),
parameter: $ => choice(
field('pattern', $._simple_pattern_ext),
seq(
choice('~', '?'),
field('pattern', alias($._identifier, $.value_pattern))
),
seq(
$._label,
token.immediate(':'),
field('pattern', $._simple_pattern_ext)
),
seq(
choice('~', '?'),
'(',
field('pattern', alias($._identifier, $.value_pattern)),
optional($._typed),
optional(seq('=', $._sequence_expression_ext)),
')'
),
seq(
$._label,
token.immediate(':'),
'(',
field('pattern', $._pattern_ext),
optional($._typed),
seq('=', $._sequence_expression_ext),
')'
)
),
external: $ => seq(
'external',
optional($._attribute),
$._value_name,
$._polymorphic_typed,
'=',
repeat1($.string),
repeat($.item_attribute)
),
type_definition: $ => seq(
'type',
optional($._attribute),
optional('nonrec'),
sep1('and', $.type_binding)
),
type_binding: $ => seq(
optional($._type_params),
choice(
seq(
field('name', $._type_constructor),
optional($._type_equation),
optional(seq(
'=',
optional('private'),
field('body', choice($.variant_declaration, $.record_declaration, '..'))
)),
repeat($.type_constraint)
),
seq(
field('name', $.type_constructor_path),
seq(
'+=',
optional('private'),
field('body', $.variant_declaration)
)
)
),
repeat($.item_attribute)
),
_type_params: $ => choice(
$._type_param,
parenthesize(sep1(',', $._type_param))
),
_type_param: $ => seq(
optional(choice(
seq('+', optional('!')),
seq('-', optional('!')),
seq('!', optional(choice('+', '-'))),
)),
choice($.type_variable, alias('_', $.type_variable))
),
_type_equation: $ => seq(
choice('=', ':='),
optional('private'),
$._type_ext
),
variant_declaration: $ => choice(
seq('|', sep('|', $.constructor_declaration)),
sep1('|', $.constructor_declaration)
),
constructor_declaration: $ => seq(
choice(
$._constructor_name,
alias(choice(seq('[', ']'), seq('(', ')'), 'true', 'false'), $.constructor_name)
),
optional(choice(
seq('of', $._constructor_argument),
seq(
':',
optional(seq(repeat1($.type_variable), '.')),
optional(seq($._constructor_argument, '->')),
$._simple_type_ext
),
seq('=', $.constructor_path)
))
),
_constructor_argument: $ => choice(
sep1('*', $._simple_type_ext),
$.record_declaration
),
record_declaration: $ => seq(
'{',
sep1(';', $.field_declaration),
optional(';'),
'}'
),
field_declaration: $ => seq(
optional('mutable'),
$._field_name,
$._polymorphic_typed,
),
type_constraint: $ => seq(
'constraint',
$._type_ext,
'=',
$._type_ext
),
exception_definition: $ => seq(
'exception',
optional($._attribute),
$.constructor_declaration,
repeat($.item_attribute)
),
module_definition: $ => seq(
'module', optional($._attribute), optional('rec'),
sep1('and', $.module_binding)
),
module_binding: $ => seq(
field('name', choice($._module_name, alias('_', $.module_name))),
repeat($.module_parameter),
optional($._module_typed),
optional(seq(choice('=', ':='), field('body', $._module_expression_ext))),
repeat($.item_attribute)
),
module_parameter: $ => parenthesize(optional(seq(
field('name', choice($._module_name, alias('_', $.module_name))),
$._module_typed
))),
module_type_definition: $ => seq(
'module', 'type',
optional($._attribute),
field('name', $._module_type_name),
optional(seq(choice('=', ':='), field('body', $._module_type_ext))),
repeat($.item_attribute)
),
open_module: $ => seq(
'open',
optional('!'),
optional($._attribute),
$._module_expression_ext,
repeat($.item_attribute)
),
include_module: $ => seq(
'include',
optional($._attribute),
$._module_expression_ext,
repeat($.item_attribute)
),
class_definition: $ => seq(
'class', optional($._attribute),
sep1('and', $.class_binding)
),
class_binding: $ => prec.right(seq(
optional('virtual'),
optional(seq(
'[',
sep1(',', $._type_param),
']'
)),
field('name', $._class_name),
repeat($._parameter),
optional($._class_typed),
optional(seq('=', field('body', $._class_expression_ext))),
repeat($.item_attribute)
)),
class_type_definition: $ => seq(
'class', 'type', optional($._attribute),
sep1('and', $.class_type_binding)
),
class_type_binding: $ => seq(
optional('virtual'),
optional(seq(
'[',
sep1(',', $._type_param),
']'
)),
field('name', $._class_type_name),
'=',
field('body', $._simple_class_type_ext),
repeat($.item_attribute)
),
// Module signature
_signature_item: $ => choice(
$.value_specification,
$.external,
$.type_definition,
$.exception_definition,
$.module_definition,
$.module_type_definition,
$.open_module,
$.include_module_type,
$.class_definition,
$.class_type_definition,
$.floating_attribute
),
_signature_item_ext: $ => choice(
$._signature_item,
$._item_extension
),
value_specification: $ => seq(
'val',
optional($._attribute),
$._value_name,
$._polymorphic_typed,
repeat($.item_attribute)
),
include_module_type: $ => seq(
'include',
optional($._attribute),
$._module_type_ext,
repeat($.item_attribute)
),
// Module types
_module_typed: $ => seq(':', $._module_type_ext),
_module_type: $ => choice(
$.module_type_path,
$.signature,
$.module_type_constraint,
$.module_type_of,
$.functor_type,
$.parenthesized_module_type
),
_module_type_ext: $ => choice(
$._module_type,
$._extension
),
signature: $ => seq(
'sig',
optional($._signature),
'end'
),
module_type_constraint: $ => prec.right(seq(
$._module_type_ext,
'with',
sep1('and', choice(
$.constrain_type,
$.constrain_module,
$.constrain_module_type
))
)),
constrain_type: $ => seq(
'type',
optional($._type_params),
$.type_constructor_path,
$._type_equation,
repeat($.type_constraint)
),
constrain_module: $ => seq(
'module',
$.module_path,
choice('=', ':='),
$.extended_module_path
),
constrain_module_type: $ => prec.left(seq(
'module', 'type',
$.module_type_path,
choice('=', ':='),
$._module_type_ext
)),
module_type_of: $ => seq(
'module', 'type', 'of',
$._module_expression_ext
),
functor_type: $ => prec.right(seq(
choice(
seq('functor', repeat($.module_parameter)),
$._module_type_ext
),
'->',
$._module_type_ext
)),
parenthesized_module_type: $ => seq(
parenthesize($._module_type_ext)
),
// Module expressions
_simple_module_expression: $ => choice(
$.typed_module_expression,
$.parenthesized_module_expression,
$.packed_module
),
_simple_module_expression_ext: $ => choice(
$._simple_module_expression,
$._extension
),
_module_expression: $ => choice(
$._simple_module_expression,
$.module_path,
$.structure,
$.functor,
$.module_application
),
_module_expression_ext: $ => choice(
$._module_expression,
$._extension
),
structure: $ => seq(
'struct',
optional($._structure),
'end'
),
functor: $ => prec.right(seq(
'functor',
repeat1($.module_parameter),
'->',
field('body', $._module_expression_ext),
)),
module_application: $ => seq(
field('functor', $._module_expression_ext),
choice(
field('argument', $._simple_module_expression_ext),
seq('(', ')')
)
),
typed_module_expression: $ => parenthesize(seq(
$._module_expression_ext,
$._module_typed
)),
packed_module: $ => parenthesize(seq(
'val',
$._expression_ext,
optional($._module_typed),
optional(seq(':>', $._module_type_ext))
)),
parenthesized_module_expression: $ => parenthesize($._module_expression_ext),
// Class types
_class_typed: $ => seq(':', $._class_type_ext),
_simple_class_type: $ => choice(
$.class_type_path,
$.instantiated_class_type,
$.class_body_type,
$.let_open_class_type
),
_simple_class_type_ext: $ => choice(
$._simple_class_type,
$._extension,
),
_class_type: $ => choice(
$._simple_class_type,
$.class_function_type
),
_class_type_ext: $ => choice(
$._class_type,
$._extension
),
instantiated_class_type: $ => seq(
'[',
sep1(',', $._type_ext),
']',
$.class_type_path
),
class_body_type: $ => seq(
'object',
optional(parenthesize($._type_ext)),
repeat(choice(
$._class_field_specification_ext,
$.floating_attribute
)),
'end'
),
_class_field_specification: $ => choice(
$.inheritance_specification,
$.instance_variable_specification,
$.method_specification,
$.type_parameter_constraint
),
_class_field_specification_ext: $ => choice(
$._class_field_specification,
$._item_extension
),
inheritance_specification: $ => seq(
'inherit',
$._simple_class_type_ext,
repeat($.item_attribute)
),
instance_variable_specification: $ => seq(
'val',
repeat(choice('mutable', 'virtual')),
$._instance_variable_name,
$._typed,
repeat($.item_attribute)
),
method_specification: $ => seq(
'method',
repeat(choice('private', 'virtual')),
$._method_name,
$._polymorphic_typed,
repeat($.item_attribute)
),
type_parameter_constraint: $ => seq(
'constraint',
$._type_ext,
'=',
$._type_ext,
repeat($.item_attribute)
),
let_open_class_type: $ => prec.right(PREC.match, seq(
'let',
$.open_module,
'in',
field('body', $._simple_class_type_ext)
)),
class_function_type: $ => prec.right(PREC.seq, seq(
optional(seq(optional('?'), $._label_name, ':')),
$._tuple_type_ext,
'->',
$._class_type_ext
)),
// Class expressions
_simple_class_expression: $ => choice(
$.class_path,
$.instantiated_class,
$.object_expression,
$.typed_class_expression,
$.parenthesized_class_expression
),
_class_expression: $ => choice(
$._simple_class_expression,
$.class_function,
$.class_application,
$.let_class_expression,
$.let_open_class_expression
),
_class_expression_ext: $ => choice(
$._class_expression,
$._extension
),
instantiated_class: $ => seq(
'[',
sep1(',', $._type_ext),
']',
$.class_path
),
typed_class_expression: $ => seq(
parenthesize(seq(
$._class_expression_ext,
$._class_typed
))
),
class_function: $ => prec.right(PREC.match, seq(
'fun',
repeat1($._parameter),
'->',
field('body', $._class_expression_ext)
)),
class_application: $ => prec.right(PREC.app, seq(
field('class', $._simple_class_expression),
repeat1(field('argument', $._argument))
)),
let_class_expression: $ => prec.right(PREC.match, seq(
$.value_definition,
'in',
field('body', $._class_expression_ext)
)),
_class_field: $ => choice(
$.inheritance_definition,
$.instance_variable_definition,
$.method_definition,
$.type_parameter_constraint,
$.class_initializer
),
_class_field_ext: $ => choice(
$._class_field,
$._item_extension
),
inheritance_definition: $ => seq(
'inherit',
optional('!'),
$._class_expression_ext,
optional(seq('as', $._value_pattern)),
repeat($.item_attribute)
),
instance_variable_definition: $ => seq(
'val',
optional('!'),
repeat(choice('mutable', 'virtual')),
field('name', $._instance_variable_name),
optional($._typed),
optional(seq(':>', $._type_ext)),
optional(seq('=', field('body', $._sequence_expression_ext))),
repeat($.item_attribute)
),
method_definition: $ => seq(
'method',
optional('!'),
repeat(choice('private', 'virtual')),
field('name', $._method_name),
repeat($._parameter),
optional($._polymorphic_typed),
optional(seq('=', field('body', $._sequence_expression_ext))),
repeat($.item_attribute)
),
class_initializer: $ => seq(
'initializer',
$._sequence_expression_ext,
repeat($.item_attribute)
),
let_open_class_expression: $ => prec.right(PREC.match, seq(
'let',
$.open_module,
'in',
field('body', $._class_expression_ext)
)),
parenthesized_class_expression: $ => seq(
parenthesize($._class_expression_ext)
),
// Types
_typed: $ => seq(':', $._type_ext),
_simple_typed: $ => seq(':', $._simple_type_ext),
_polymorphic_typed: $ => seq(':', $._polymorphic_type),
_polymorphic_type: $ => choice(
$.polymorphic_type,
$._type_ext
),
polymorphic_type: $ => seq(
choice(
repeat1($.type_variable),
alias($._abstract_type, $.abstract_type)
),
'.',
$._type_ext
),
_abstract_type: $ => seq(
'type',
repeat1($._type_constructor)
),
_parenthesized_abstract_type: $ => parenthesize($._abstract_type),
_simple_type: $ => choice(
$.type_variable,
$.type_constructor_path,
$.constructed_type,
$.polymorphic_variant_type,
$.package_type,
$.hash_type,
$.object_type,
$.parenthesized_type
),
_simple_type_ext: $ => choice(
$._simple_type,
$._extension
),
_tuple_type: $ => choice(
$._simple_type,
$.tuple_type
),
_tuple_type_ext: $ => choice(
$._tuple_type,
$._extension
),
_type: $ => choice(
$._tuple_type,
$.function_type,
$.aliased_type,
),
_type_ext: $ => choice(
$._type,
$._extension
),
function_type: $ => prec.right(PREC.seq, seq(
choice($.typed_label, $._type_ext),
'->',
$._type_ext
)),
typed_label: $ => prec.left(PREC.seq, seq(
optional('?'),
$._label_name,
':',
$._type_ext
)),
tuple_type: $ => prec(PREC.prod, seq(
$._tuple_type_ext,
'*',
$._simple_type_ext
)),
constructed_type: $ => prec(PREC.app, seq(
choice(
$._simple_type_ext,
parenthesize(sep1(',', $._type_ext))
),
$.type_constructor_path
)),
aliased_type: $ => prec(PREC.match, seq(
$._type_ext,
'as',
$.type_variable
)),
polymorphic_variant_type: $ => seq(
choice(
seq('[', $.tag_specification, ']'),
seq('[', optional($._tag_spec), '|', sep1('|', $._tag_spec), ']'),
seq('[>', optional('|'), sep('|', $._tag_spec), ']'),
seq('[<', optional('|'), sep1('|', $._tag_spec), optional(seq('>', repeat1($.tag))), ']'),
)
),
_tag_spec: $ => choice(
$._type_ext,
$.tag_specification
),
tag_specification: $ => seq(
$.tag,
optional(seq(
'of',
optional('&'),
sep1('&', $._type_ext)
))
),
package_type: $ => parenthesize(seq(
'module',
optional($._attribute),
$._module_type_ext
)),
object_type: $ => seq(
'<',
optional(choice(
seq(
sep1(';', choice(
$.method_type,
$._simple_type_ext
)),
optional(seq(';', optional('..')))
),
'..'
)),
'>'
),
method_type: $ => seq(
$._method_name,
$._polymorphic_typed
),
hash_type: $ => prec(PREC.hash, seq(
optional(choice(
$._simple_type_ext,
parenthesize(sep1(',', $._type_ext))
)),
'#',
$.class_type_path
)),
parenthesized_type: $ => parenthesize($._type_ext),
// Expressions
_simple_expression: $ => choice(
$.value_path,
$._constant,
$.typed_expression,
$.constructor_path,
$.tag,
$.list_expression,
$.array_expression,
$.record_expression,
$.prefix_expression,
$.hash_expression,
$.field_get_expression,
$.array_get_expression,
$.string_get_expression,
$.bigarray_get_expression,
$.coercion_expression,
$.local_open_expression,
$.package_expression,
$.new_expression,
$.object_copy_expression,
$.method_invocation,
$.object_expression,
$.parenthesized_expression,
$.ocamlyacc_value
),
_simple_expression_ext: $ => choice(
$._simple_expression,
$._extension
),
_expression: $ => choice(
$._simple_expression,
$.product_expression,
$.cons_expression,
$.application_expression,
$.infix_expression,
$.sign_expression,
$.set_expression,
$.if_expression,
$.while_expression,
$.for_expression,
$.match_expression,
$.function_expression,
$.fun_expression,
$.try_expression,
$.let_expression,
$.assert_expression,
$.lazy_expression,
$.let_module_expression,
$.let_open_expression,
$.let_exception_expression
),
_expression_ext: $ => choice(
$._expression,
$._extension
),
_sequence_expression: $ => choice(
$._expression,
$.sequence_expression
),
_sequence_expression_ext: $ => choice(
$._sequence_expression,
$._extension
),
typed_expression: $ => parenthesize(seq(
$._sequence_expression_ext,
$._typed
)),
product_expression: $ => prec.left(PREC.prod, seq(
field('left', $._expression_ext),
',',
field('right', $._expression_ext)
)),
cons_expression: $ => prec.right(PREC.cons, seq(
field('left', $._expression_ext),
'::',
field('right', $._expression_ext)
)),
list_expression: $ => seq(
'[',
optional(seq(
sep1(';', $._expression_ext),
optional(';')
)),
']'
),
array_expression: $ => seq(
'[|',
optional(seq(
sep1(';', $._expression_ext),
optional(';')
)),
'|]'
),
record_expression: $ => seq(
'{',
optional(seq($._simple_expression_ext, 'with')),
sep1(';', $.field_expression),
optional(';'),
'}'
),
field_expression: $ => prec(PREC.seq, seq(
field('name', $.field_path),
optional($._typed),
optional(seq('=', field('body', $._expression_ext)))
)),
application_expression: $ => prec.right(PREC.app, seq(
field('function', $._simple_expression_ext),
repeat1(field('argument', $._argument))
)),
_argument: $ => choice(
$._simple_expression_ext,
$.labeled_argument
),
labeled_argument: $ => choice(
$._label,
seq(
$._label,
token.immediate(':'),
$._simple_expression_ext
),
seq(
choice('~', '?'),
'(',
$._label_name,
$._typed,
')'
),
),
prefix_expression: $ => prec(PREC.prefix, seq(
$.prefix_operator,
field('right', $._simple_expression_ext)
)),
sign_expression: $ => prec(PREC.neg, seq(
$.sign_operator,
field('right', $._expression_ext)
)),
hash_expression: $ => prec.left(PREC.hash, seq(
field('left', $._simple_expression_ext),
$.hash_operator,
field('right', $._simple_expression_ext)
)),
infix_expression: $ => {
const table = [
{
operator: $._pow_operator,
precedence: PREC.pow,
associativity: 'right'
},
{
operator: $._mult_operator,
precedence: PREC.mult,
associativity: 'left'
},
{
operator: $._add_operator,
precedence: PREC.add,
associativity: 'left'
},
{
operator: $._concat_operator,
precedence: PREC.concat,
associativity: 'right'
},
{
operator: $._rel_operator,
precedence: PREC.rel,
associativity: 'left'
},
{
operator: $._and_operator,
precedence: PREC.and,
associativity: 'right'
},
{
operator: $._or_operator,
precedence: PREC.or,
associativity: 'right'
},
{
operator: $._assign_operator,
precedence: PREC.assign,
associativity: 'right'
}
]
return choice(...table.map(({operator, precedence, associativity}) =>
prec[associativity](precedence, seq(
field('left', $._expression_ext),
alias(operator, $.infix_operator),
field('right', $._expression_ext)
))
))
},
field_get_expression: $ => prec.left(PREC.dot, seq(
$._simple_expression_ext,
'.',
$.field_path
)),
array_get_expression: $ => prec(PREC.dot, seq(
$._simple_expression_ext,
'.',
optional($.indexing_operator_path),
'(',
$._sequence_expression_ext,
')'
)),
string_get_expression: $ => prec(PREC.dot, seq(
$._simple_expression_ext,
'.',
optional($.indexing_operator_path),
'[',
$._sequence_expression_ext,
']'
)),
bigarray_get_expression: $ => prec(PREC.dot, seq(
$._simple_expression_ext,
'.',
optional($.indexing_operator_path),
'{',
$._sequence_expression_ext,
'}'
)),
set_expression: $ => prec.right(PREC.assign, seq(
choice(
$.field_get_expression,
$.array_get_expression,
$.string_get_expression,
$.bigarray_get_expression,
$._instance_variable_name
),
'<-',
field('body', $._expression_ext)
)),
if_expression: $ => prec.right(PREC.if, seq(
'if',
optional($._attribute),
field('condition', $._sequence_expression_ext),
$.then_clause,
optional($.else_clause)
)),
then_clause: $ => seq(
'then',
$._expression_ext
),
else_clause: $ => seq(
'else',
$._expression_ext
),
while_expression: $ => seq(
'while',
optional($._attribute),
field('condition', $._sequence_expression_ext),
$.do_clause
),
do_clause: $ => seq(
'do',
optional($._sequence_expression_ext),
'done'
),
for_expression: $ => seq(
'for',
optional($._attribute),
field('name', $._value_pattern),
'=',
field('from', $._sequence_expression_ext),
choice('to', 'downto'),
field('to', $._sequence_expression_ext),
$.do_clause
),
sequence_expression: $ => prec.right(PREC.seq, seq(
field('left', $._expression_ext),
';',
optional(seq(
optional($._attribute),
field('right', $._sequence_expression_ext)
))
)),
match_expression: $ => prec.right(PREC.match, seq(
choice(
seq('match', optional($._attribute)),
$.match_operator
),
$._sequence_expression_ext,
'with',
$._match_cases
)),
_match_cases: $ => prec.right(seq(
optional('|'),
sep1('|', $.match_case)
)),
match_case: $ => seq(
field('pattern', $._pattern_ext),
optional($.guard),
'->',
field('body', choice($._sequence_expression_ext, $.refutation_case))
),
guard: $ => seq(
'when',
$._sequence_expression_ext
),
refutation_case: $ => '.',
function_expression: $ => prec.right(PREC.match, seq(
'function',
optional($._attribute),
$._match_cases
)),
fun_expression: $ => prec.right(PREC.match, seq(
'fun',
optional($._attribute),
repeat1($._parameter),
optional($._simple_typed),
'->',
field('body', $._sequence_expression_ext)
)),
try_expression: $ => prec.right(PREC.match, seq(
'try',
optional($._attribute),
$._sequence_expression_ext,
'with',
$._match_cases
)),
let_expression: $ => prec.right(PREC.match, seq(
$.value_definition,
'in',
$._sequence_expression_ext
)),
coercion_expression: $ => parenthesize(seq(
$._sequence_expression_ext,
optional($._typed),
':>',
$._type_ext
)),
assert_expression: $ => prec.left(PREC.app, seq(
'assert',
optional($._attribute),
$._simple_expression_ext
)),
lazy_expression: $ => prec.left(PREC.app, seq(
'lazy',
optional($._attribute),
$._simple_expression_ext
)),
let_module_expression: $ => prec.right(PREC.match, seq(
'let',
$.module_definition,
'in',
field('body', $._sequence_expression_ext)
)),
let_open_expression: $ => prec.right(PREC.match, seq(
'let',
$.open_module,
'in',
field('body', $._sequence_expression_ext)
)),
local_open_expression: $ => seq(
$.module_path,
'.',
choice(
parenthesize(optional($._sequence_expression_ext)),
$.list_expression,
$.array_expression,
$.record_expression,
$.object_copy_expression,
$.package_expression
)
),
package_expression: $ => parenthesize(seq(
'module',
optional($._attribute),
$._module_expression_ext,
optional($._module_typed)
)),
let_exception_expression: $ => prec.right(PREC.match, seq(
'let',
$.exception_definition,
'in',
field('body', $._sequence_expression_ext)
)),
new_expression: $ => seq(
'new',
optional($._attribute),
$.class_path
),
object_copy_expression: $ => seq(
'{<',
sep(';', $.instance_variable_expression),
optional(';'),
'>}'
),
instance_variable_expression: $ => seq(
$._instance_variable_name,
optional(seq('=', $._expression_ext))
),
method_invocation: $ => prec.right(PREC.hash, seq(
$._simple_expression_ext,
'#',
$._method_name
)),
object_expression: $ => seq(
'object',
optional($._attribute),
optional(parenthesize(seq(
$._pattern_ext,
optional($._typed)
))),
repeat(choice(
$._class_field_ext,
$.floating_attribute
)),
'end'
),
parenthesized_expression: $ => choice(
seq(
'begin',
optional($._attribute),
$._sequence_expression_ext,
'end'
),
parenthesize($._sequence_expression_ext)
),
ocamlyacc_value: $ => /\$[0-9]+/,
// Patterns
_simple_pattern: $ => choice(
$._value_pattern,
$._signed_constant,
$.typed_pattern,
$.constructor_path,
$.tag,
$.polymorphic_variant_pattern,
$.record_pattern,
$.list_pattern,
$.array_pattern,
$.local_open_pattern,
$.package_pattern,
$.parenthesized_pattern
),
_simple_pattern_ext: $ => choice(
$._simple_pattern,
$._extension
),
_pattern: $ => choice(
$._simple_pattern,
$.alias_pattern,
$.or_pattern,
$.constructor_pattern,
$.tag_pattern,
$.tuple_pattern,
$.cons_pattern,
$.range_pattern,
$.lazy_pattern,
$.exception_pattern
),
_pattern_ext: $ => choice(
$._pattern,
$._extension
),
_binding_pattern: $ => choice(
$._value_name,
$._signed_constant,
alias($.typed_binding_pattern, $.typed_pattern),
$.constructor_path,
$.tag,
$.polymorphic_variant_pattern,
alias($.record_binding_pattern, $.record_pattern),
alias($.list_binding_pattern, $.list_pattern),
alias($.array_binding_pattern, $.array_pattern),
alias($.local_open_binding_pattern, $.local_open_pattern),
$.package_pattern,
alias($.parenthesized_binding_pattern, $.parenthesized_pattern),
alias($.alias_binding_pattern, $.alias_pattern),
alias($.or_binding_pattern, $.or_pattern),
alias($.constructor_binding_pattern, $.constructor_pattern),
alias($.tag_binding_pattern, $.tag_pattern),
alias($.tuple_binding_pattern, $.tuple_pattern),
alias($.cons_binding_pattern, $.cons_pattern),
$.range_pattern,
alias($.lazy_binding_pattern, $.lazy_pattern)
),
_binding_pattern_ext: $ => choice(
$._binding_pattern,
$._extension
),
alias_pattern: $ => prec.left(PREC.match, seq(
$._pattern_ext,
'as',
$._value_pattern
)),
alias_binding_pattern: $ => prec.left(PREC.match, seq(
$._binding_pattern_ext,
'as',
$._value_name
)),
typed_pattern: $ => seq(
parenthesize(seq(
$._pattern_ext,
$._typed
))
),
typed_binding_pattern: $ => seq(
parenthesize(seq(
field('pattern', $._binding_pattern_ext),
$._typed
))
),
or_pattern: $ => prec.left(PREC.seq, seq(
$._pattern_ext,
'|',
$._pattern_ext
)),
or_binding_pattern: $ => prec.left(PREC.seq, seq(
$._binding_pattern_ext,
'|',
$._binding_pattern_ext
)),
constructor_pattern: $ => prec.right(PREC.app, seq(
$.constructor_path,
optional(alias($._parenthesized_abstract_type, $.abstract_type)),
$._pattern_ext
)),
constructor_binding_pattern: $ => prec.right(PREC.app, seq(
$.constructor_path,
field('pattern', $._binding_pattern_ext)
)),
tag_pattern: $ => prec.right(PREC.app, seq(
$.tag,
$._pattern_ext
)),
tag_binding_pattern: $ => prec.right(PREC.app, seq(
$.tag,
field('pattern', $._binding_pattern_ext)
)),
polymorphic_variant_pattern: $ => seq(
'#',
$.type_constructor_path
),
tuple_pattern: $ => prec.left(PREC.prod, seq(
$._pattern_ext,
',',
$._pattern_ext
)),
tuple_binding_pattern: $ => prec.left(PREC.prod, seq(
$._binding_pattern_ext,
',',
$._binding_pattern_ext
)),
record_pattern: $ => prec.left(seq(
'{',
sep1(';', $.field_pattern),
optional(seq(';', '_')),
optional(';'),
'}'
)),
field_pattern: $ => seq(
$.field_path,
optional($._typed),
optional(seq('=', $._pattern_ext))
),
record_binding_pattern: $ => prec.left(seq(
'{',
sep1(';', alias($.field_binding_pattern, $.field_pattern)),
optional(seq(';', '_')),
optional(';'),
'}'
)),
field_binding_pattern: $ => seq(
$.field_path,
optional($._typed),
optional(seq('=', field('pattern', $._binding_pattern_ext)))
),
list_pattern: $ => prec.left(seq(
'[',
optional(seq(
sep1(';', $._pattern_ext),
optional(';')
)),
']'
)),
list_binding_pattern: $ => prec.left(seq(
'[',
optional(seq(
sep1(';', $._binding_pattern_ext),
optional(';')
)),
']'
)),
cons_pattern: $ => prec.right(PREC.cons, seq(
$._pattern_ext,
'::',
$._pattern_ext
)),
cons_binding_pattern: $ => prec.right(PREC.cons, seq(
$._binding_pattern_ext,
'::',
$._binding_pattern_ext
)),
array_pattern: $ => prec.left(seq(
'[|',
optional(seq(
sep1(';', $._pattern_ext),
optional(';')
)),
'|]'
)),
array_binding_pattern: $ => prec.left(seq(
'[|',
optional(seq(
sep1(';', $._binding_pattern_ext),
optional(';')
)),
'|]'
)),
range_pattern: $ => prec(PREC.dot, seq(
$._signed_constant,
'..',
$._signed_constant
)),
lazy_pattern: $ => prec(PREC.hash, seq(
'lazy',
optional($._attribute),
$._pattern_ext
)),
lazy_binding_pattern: $ => prec(PREC.hash, seq(
'lazy',
optional($._attribute),
$._binding_pattern_ext
)),
local_open_pattern: $ => seq(
$.module_path,
'.',
choice(
parenthesize(optional($._pattern_ext)),
$.list_pattern,
$.array_pattern,
$.record_pattern
)
),
local_open_binding_pattern: $ => seq(
$.module_path,
'.',
choice(
parenthesize(optional($._binding_pattern_ext)),
$.list_binding_pattern,
$.array_binding_pattern,
$.record_binding_pattern
)
),
package_pattern: $ => parenthesize(seq(
'module',
optional($._attribute),
choice($._module_name, alias('_', $.module_name)),
optional($._module_typed)
)),
parenthesized_pattern: $ => parenthesize($._pattern_ext),
parenthesized_binding_pattern: $ => parenthesize($._binding_pattern_ext),
exception_pattern: $ => seq(
'exception',
optional($._attribute),
$._pattern_ext
),
// Attributes and extensions
attribute: $ => seq(
'[@',
$.attribute_id,
optional($.attribute_payload),
']'
),
item_attribute: $ => seq(
'[@@',
$.attribute_id,
optional($.attribute_payload),
']'
),
floating_attribute: $ => seq(
'[@@@',
$.attribute_id,
optional($.attribute_payload),
']'
),
attribute_payload: $ => choice(
$._structure,
seq(':', optional(choice($._type_ext, $._signature))),
seq(
'?',
$._pattern_ext,
optional($.guard)
)
),
_extension: $ => choice(
$.extension,
$.quoted_extension
),
extension: $ => seq(
'[%',
$.attribute_id,
optional($.attribute_payload),
']'
),
quoted_extension: $ => seq(
'{%',
$.attribute_id,
optional(/\s+/),
$._quoted_string,
'}'
),
_item_extension: $ => choice(
$.item_extension,
$.quoted_item_extension
),
item_extension: $ => seq(
'[%%',
$.attribute_id,
optional($.attribute_payload),
']',
repeat($.item_attribute)
),
quoted_item_extension: $ => seq(
'{%%',
$.attribute_id,
optional(/\s+/),
$._quoted_string,
'}',
repeat($.item_attribute)
),
_attribute: $ => seq('%', $.attribute_id),
// Constants
_constant: $ => choice(
$.number,
$.character,
$.string,
$.quoted_string,
$.boolean,
$.unit
),
_signed_constant: $ => choice(
$._constant,
$.signed_number
),
number: $ => NUMBER,
signed_number: $ => seq(
choice('+', '-'),
NUMBER
),
character: $ => seq("'", $.character_content, "'"),
character_content: $ => choice(
/[^\\']/,
$._null,
$.escape_sequence
),
string: $ => seq('"', optional($.string_content), '"'),
string_content: $ => repeat1(choice(
token.immediate(' '),
token.immediate('\n'),
token.immediate('\t'),
token.immediate('[@'),
token.immediate('[@@'),
token.immediate('[@@@'),
/[^\\"%@]+|%|@/,
$._null,
$.escape_sequence,
alias(/\\u\{[0-9A-Fa-f]+\}/, $.escape_sequence),
alias(/\\\n[\t ]*/, $.escape_sequence),
$.conversion_specification,
$.pretty_printing_indication
)),
quoted_string: $ => seq('{', $._quoted_string, '}'),
_quoted_string: $ => seq(
$._left_quoted_string_delimiter,
optional($.quoted_string_content),
$._right_quoted_string_delimiter,
),
quoted_string_content: $ => repeat1(choice(
token.immediate(' '),
token.immediate('\n'),
token.immediate('\t'),
token.immediate('[@'),
token.immediate('[@@'),
token.immediate('[@@@'),
/[^%@|]+|%|@|\|/,
$._null,
$.conversion_specification,
$.pretty_printing_indication
)),
escape_sequence: $ => choice(
/\\[\\"'ntbr ]/,
/\\[0-9][0-9][0-9]/,
/\\x[0-9A-Fa-f][0-9A-Fa-f]/,
/\\o[0-3][0-7][0-7]/
),
conversion_specification: $ => token(seq(
'%',
optional(/[\-0+ #]/),
optional(/[1-9][0-9]*|\*/),
optional(/\.([0-9]*|\*)/),
choice(
/[diunlLNxXosScCfFeEgGhHbBat!%@,]/,
/[lnL][diuxXo]/
)
)),
pretty_printing_indication: $ => /@([\[\], ;.{}?]|\\n|<[0-9]+>)/,
boolean: $ => choice('true', 'false'),
unit: $ => choice(
seq('(', ')'),
seq('begin', 'end')
),
// Operators
prefix_operator: $ => token(choice(
seq('!', choice(optional(/[#!$%&*+\-./:<>?@^|~]/), repeat2(HASH_OP_CHAR))),
seq(/[~?]/, repeat1(HASH_OP_CHAR))
)),
sign_operator: $ => choice('+', '-', '+.', '-.'),
infix_operator: $ => choice(
$._pow_operator,
$._mult_operator,
$._add_operator,
$._concat_operator,
$._rel_operator,
$._and_operator,
$._or_operator,
$._assign_operator
),
hash_operator: $ => token(seq('#', repeat1(HASH_OP_CHAR))),
_pow_operator: $ => choice(
token(seq('**', repeat(OP_CHAR))),
'lsl', 'lsr', 'asr'
),
_mult_operator: $ => choice(
token(seq(/[*/%]/, repeat(OP_CHAR))),
'mod', 'land', 'lor', 'lxor'
),
_add_operator: $ => choice(
'+', '-', '+.', '-.',
token(choice(
seq('+', repeat1(OP_CHAR)),
seq('-', choice(repeat1(/[!$%&*+\-./:<=?@^|~]/), repeat2(OP_CHAR)))
))
),
_concat_operator: $ => token(
seq(/[@^]/, repeat(OP_CHAR))
),
_rel_operator: $ => token(choice(
seq(/[=>$]/, repeat(OP_CHAR)),
seq('<', choice(optional(/[!$%&*+./:<=>?@^|~]/), repeat2(OP_CHAR))),
seq('&', choice(/[!$%*+\-./:<=>?@^|~]/, repeat2(OP_CHAR))),
seq('|', choice(/[!$%&*+\-./:<=>?@^~]/, repeat2(OP_CHAR))),
'!='
)),
_and_operator: $ => choice('&', '&&'),
_or_operator: $ => choice('or', '||'),
_assign_operator: $ => choice(':='),
indexing_operator: $ => token(
seq(/[!$%&*+\-/:=>?@^|]/, repeat(OP_CHAR))
),
indexing_operator_path: $ => path($.module_path, $.indexing_operator),
let_operator: $ => token(
seq('let', /[$&*+\-/<=>@^|]/, repeat(OP_CHAR))
),
and_operator: $ => token(
seq('and', /[$&*+\-/<=>@^|]/, repeat(OP_CHAR))
),
match_operator: $ => token(
seq('match', /[$&*+\-/<=>@^|]/, repeat(OP_CHAR))
),
// Names
_value_name: $ => choice(
alias($._identifier, $.value_name),
$.parenthesized_operator
),
_value_pattern: $ => choice(
alias($._identifier, $.value_pattern),
$.parenthesized_operator
),
parenthesized_operator: $ => parenthesize(choice(
$.prefix_operator,
$.infix_operator,
$.hash_operator,
seq(
'.',
$.indexing_operator,
choice(
seq('(', optional(seq(';', '..')), ')'),
seq('[', optional(seq(';', '..')), ']'),
seq('{', optional(seq(';', '..')), '}')
),
optional('<-')
),
$.let_operator,
$.and_operator,
$.match_operator
)),
value_path: $ => path($.module_path, $._value_name),
module_path: $ => prec(1, path($.module_path, $._module_name)),
extended_module_path: $ => choice(
path($.extended_module_path, $._module_name),
seq(
$.extended_module_path,
parenthesize($.extended_module_path)
)
),
module_type_path: $ => path($.extended_module_path, $._module_type_name),
field_path: $ => path($.module_path, $._field_name),
constructor_path: $ => path($.module_path, $._constructor_name),
type_constructor_path: $ => prec(1, path($.extended_module_path, $._type_constructor)),
class_path: $ => path($.module_path, $._class_name),
class_type_path: $ => path($.extended_module_path, $._class_type_name),
_label_name: $ => alias($._identifier, $.label_name),
_field_name: $ => alias($._identifier, $.field_name),
_class_name: $ => alias($._identifier, $.class_name),
_class_type_name: $ => alias($._identifier, $.class_type_name),
_method_name: $ => alias($._identifier, $.method_name),
_type_constructor: $ => alias($._identifier, $.type_constructor),
_instance_variable_name: $ => alias($._identifier, $.instance_variable_name),
_module_name: $ => alias($._capitalized_identifier, $.module_name),
_module_type_name: $ => alias(choice($._capitalized_identifier, $._identifier), $.module_type_name),
_constructor_name: $ => choice(
alias($._capitalized_identifier, $.constructor_name),
parenthesize(alias('::', $.constructor_name))
),
_identifier: $ => /[a-z_][a-zA-Z0-9_']*/,
_capitalized_identifier: $ => /[A-Z][a-zA-Z0-9_']*/,
_label: $ => seq(choice('~', '?'), $._label_name),
directive: $ => seq('#', choice($._identifier, $._capitalized_identifier)),
type_variable: $ => seq("'", choice($._identifier, $._capitalized_identifier)),
tag: $ => seq('`', choice($._identifier, $._capitalized_identifier)),
attribute_id: $ => sep1('.', choice($._identifier, $._capitalized_identifier))
},
externals: $ => [
$.comment,
$._left_quoted_string_delimiter,
$._right_quoted_string_delimiter,
'"',
$.line_number_directive,
$._null
]
})
function sep(delimiter, rule) {
return optional(sep1(delimiter, rule))
}
function sep1(delimiter, rule) {
return seq(rule, repeat(seq(delimiter, rule)))
}
function repeat2(rule) {
return seq(rule, repeat1(rule))
}
function parenthesize(rule) {
return seq('(', rule, ')')
}
function path(prefix, final) {
return choice(final, seq(prefix, '.', final))
}