tree-sitter-lang/grammar.js

294 lines
8 KiB
JavaScript
Raw Normal View History

2023-07-16 20:54:43 +03:00
module.exports = grammar({
2023-07-24 10:35:32 +03:00
name: 'lang',
2023-07-16 20:54:43 +03:00
word: $ => $.identifier,
extras: $ => [
2023-07-21 14:11:13 +03:00
$._exec_comment,
2023-07-16 20:54:43 +03:00
$._line_comment,
$._block_comment,
/\s/
],
rules: {
// --- sources
2023-07-17 23:14:39 +03:00
source_file: $ => repeat1($._statement),
2023-07-16 20:54:43 +03:00
2023-07-17 23:14:39 +03:00
_statement: $ => choice(
2023-07-16 20:54:43 +03:00
$.import,
$.type_definition,
$.function_definition,
$.typeclass_definition,
),
import: $ => seq(
choice('::', 'import'),
2023-07-23 19:40:38 +03:00
field('name', choice($.simple_name_identifier, $.placeholder)),
2023-07-16 20:54:43 +03:00
optional(seq('=', field('module', $.simple_name_identifier))),
2023-07-22 19:50:12 +03:00
optional(seq(':', repeat1(choice(
2023-07-16 20:54:43 +03:00
$.simple_type_identifier,
$.simple_name_identifier,
$.typeclass_identifier,
seq('(',$.operator, ')'),
)))),
';',
),
constraint: $ => seq('?', $._expression),
// --- definitions
type_definition: $ => seq(
optional($.definition_info),
repeat($.annotation_info),
optional('^'),
field('name', $.simple_type_identifier),
2023-07-23 19:40:38 +03:00
optional(seq(repeat($.argument_type_identifier), '=', $.variant_type)),
2023-07-16 20:54:43 +03:00
choice(seq('{', repeat($.function_definition), '}'), ';')
),
function_definition: $ => seq(
optional($.definition_info),
repeat($.annotation_info),
repeat(seq($.constraint, ';')),
2023-07-23 19:40:38 +03:00
optional($._var_let),
2023-07-19 10:25:24 +03:00
choice(field('name', $.simple_name_identifier), seq('(', field('name', $.operator), ')')),
2023-07-16 20:54:43 +03:00
repeat(seq(
optional($.annotation_identifier),
optional($._reference),
2023-07-16 20:54:43 +03:00
$.argument_name_identifier,
optional($._optional_result),
2023-07-16 20:54:43 +03:00
)),
optional(seq(':', repeat1(seq(
optional($.annotation_identifier),
optional($._reference),
2023-07-16 20:54:43 +03:00
$.type,
)))),
choice(seq('=', choice(prec(2, choice($.block, $.array)), seq($._super_expression, ';'))), ';'),
2023-07-16 20:54:43 +03:00
),
typeclass_definition: $ => seq(
optional($.definition_info),
2023-07-23 19:40:38 +03:00
// no argumenmts => no annotation info
2023-07-22 19:50:12 +03:00
field('name', $.typeclass_identifier),
optional(seq(':', repeat1($.typeclass_identifier))),
2023-07-16 20:54:43 +03:00
choice(seq('{', repeat($.function_definition), '}'), ';'),
),
// --- flow control
case: $ => seq(
choice(':=', '=:'),
$._expression,
optional(seq(choice('??', 'if'), field('condition', $._expression))),
optional(field('expression', seq($._do, $._expression))),
2023-07-16 20:54:43 +03:00
),
match: $ => seq(
$._expression,
repeat1($.case),
),
condition: $ => seq(
choice('??', 'if'),
$._expression,
$._do,
2023-07-16 20:54:43 +03:00
$._expression,
repeat(seq(
choice('!!', 'elif'),
$._expression,
$._do,
2023-07-16 20:54:43 +03:00
$._expression,
)),
optional(seq(choice('!!=>', 'else'), $._expression)),
2023-07-16 20:54:43 +03:00
),
loop: $ => seq(
choice('@', 'for'),
optional(choice(
$._expression,
seq($._expression, ':', $._expression),
2023-07-16 20:54:43 +03:00
)),
$._do,
$._expression,
2023-07-16 20:54:43 +03:00
),
2023-07-18 11:39:18 +03:00
// --- operators
2023-07-16 20:54:43 +03:00
comma_expression: $ => prec.left(seq($._super_expression, ',', $._super_expression)),
operator_expression: $ => prec.left(choice(
prec(4, seq($._expression, field('name', $.operator), $._expression)),
prec(3, seq($._expression, field('name', $.operator_tail1), $._expression)),
prec(2, seq($._expression, field('name', $.operator_tail2), $._expression)),
prec(1, seq($._expression, field('name', $.operator_tail3), $._expression)),
)),
// --- continers
block: $ => seq('{', repeat(seq($._super_expression, ';')), '}'),
array: $ => seq('[[', repeat1($._scoped_expression), ']]'),
// --- modifiers
return: $ => seq(choice('return', 'bring'), $._expression),
2023-07-16 20:54:43 +03:00
name_definition: $ => seq(
$._var_let,
2023-07-16 20:54:43 +03:00
choice($.simple_name_identifier, $.placeholder),
),
2023-07-18 15:17:02 +03:00
array_access: $ => seq($._scoped_expression, '[', $._super_expression, ']'),
2023-07-16 20:54:43 +03:00
2023-07-18 11:03:11 +03:00
tuple_access: $ => seq($._scoped_expression, '.', $.number_literal),
2023-07-16 20:54:43 +03:00
loop_control: $ => choice('break', 'continue'),
reference_expression: $ => prec(-1, seq($._reference, $._scoped_expression)),
2023-07-16 20:54:43 +03:00
suffix_expression: $ => seq($._scoped_expression, $._optional_result),
2023-07-16 20:54:43 +03:00
// --- other
name_expression: $ => seq(
choice(
seq($.type, '.', field('name', $.simple_name_identifier)),
seq($._scoped_expression, '.', field('name', $.simple_name_identifier)),
field('name', $._name_identifier),
seq('(', field('name', $.operator), ')'),
),
repeat(seq(optional($.annotation_identifier), $._scoped_expression)),
),
constructor: $ => seq(
field('type', $.type),
2023-07-16 20:54:43 +03:00
repeat1(seq(optional($.annotation_identifier), $._scoped_expression)),
),
lambda: $ => seq(
choice('\\', 'lambda'),
2023-07-18 11:39:18 +03:00
repeat($.argument_name_identifier),
$._do,
2023-07-16 20:54:43 +03:00
$._expression,
),
// --- expression
_super_expression: $ => choice(
$.match,
$.condition,
$.loop,
$.comma_expression,
$._expression,
),
_expression: $ => choice(
$.operator_expression,
$.return,
$.name_expression,
$.constructor,
$.lambda,
$._not_name_scoped_expression,
),
_scoped_expression: $ => choice(
$._name_identifier,
$._not_name_scoped_expression,
),
_not_name_scoped_expression: $ => choice(
2023-07-18 14:37:16 +03:00
$.block,
2023-07-16 20:54:43 +03:00
$.array,
$.placeholder,
$.name_definition,
2023-07-18 15:17:02 +03:00
$.array_access,
2023-07-18 11:03:11 +03:00
$.tuple_access,
2023-07-16 20:54:43 +03:00
$.loop_control,
$.reference_expression,
2023-07-16 20:54:43 +03:00
$.suffix_expression,
$._literal,
seq('(', $._super_expression, ')'),
),
// --- type
variant_type: $ => seq(
optional('|'),
$.tuple_type,
2023-07-23 19:40:38 +03:00
repeat(seq('|', $.tuple_type)),
2023-07-16 20:54:43 +03:00
),
tuple_type: $ => seq(
optional('&'),
$._annotated_type,
repeat(seq('&', $._annotated_type)),
),
_annotated_type: $ => seq(optional($.annotation_identifier), $.type),
type: $ => seq(
optional('^'),
field('name', $._type_identifier),
optional($._optional_result),
2023-07-16 20:54:43 +03:00
optional(seq('[', repeat1($.type), ']'))
),
// --- comments
definition_info: $ => repeat1(seq(': ', $.info)),
annotation_info: $ => seq($.annotation_identifier, $.info),
info: $ => /[^\n]*/,
2023-07-16 20:54:43 +03:00
2023-07-21 14:11:13 +03:00
_exec_comment: $ => token(seq('#!', /[^\n]*/)),
2023-07-16 20:54:43 +03:00
_line_comment: $ => token(seq('//', /[^\n]*/)),
_block_comment: $ => token(seq('/*', /([^*]|(\*[^/]))*/, '*/')),
// --- tokens
_do: $ => choice('=>', 'do'),
_var_let: $ => choice(choice('%', 'let'), choice('$', 'var')),
_optional_result: $ => choice('?', '!'),
_reference: $ => choice(choice('->', 'out'), choice('<-', 'in'), choice('<>', 'ref')),
2023-07-16 20:54:43 +03:00
_name_identifier: $ => choice($.argument_name_identifier, $.simple_name_identifier),
_type_identifier: $ => choice($.argument_type_identifier, $.simple_type_identifier),
placeholder: $ => '_',
simple_name_identifier: $ => token(seq(repeat(seq(/[a-z_][a-z0-9_]*/, '.')), /[a-z_][a-z0-9_]*/)),
simple_type_identifier: $ => /([a-z_][a-z0-9_]*\.)*[A-Z][a-zA-Z0-9]*/,
typeclass_identifier: $ => /([a-z_][a-z0-9_]*\.)*#[A-Z][a-zA-Z0-9]*/,
argument_name_identifier: $ => /'[a-z_][a-z0-9_]*/,
argument_type_identifier: $ => /'[A-Z][a-zA-Z0-9]*/,
annotation_identifier: $ => /@[a-z_][a-z0-9_]*/,
operator: $ => /([+\-*/%^!?|&,<>=]+)|\.+/,
operator_tail1: $ => /[+\-*/%^!?|&,<>=]+\./,
operator_tail2: $ => /[+\-*/%^!?|&,<>=]+\.\./,
operator_tail3: $ => /[+\-*/%^!?|&,<>=]+\.\.\./,
float_number_literal: $ => /[0-9]+\.[0-9]+/,
number_literal: $ => /[0-9]+/,
string_literal: $ => seq('\"', /([^\\\"]|(\\.))*/, '\"'),
char_literal: $ => seq('\'\'', /[^\\\']|(\\.)/, '\'\''),
bool_literal: $ => choice('true', 'false'),
unit_literal: $ => '()',
null_literal: $ => 'null',
_literal: $ => choice(
$.float_number_literal,
$.number_literal,
$.string_literal,
$.char_literal,
$.bool_literal,
$.unit_literal,
$.null_literal,
),
identifier: $ => /([@'#]?[a-zA-Z0-9_]+)|([+\-*/%^!?|&,<>=]+\.?\.?\.?)|\.+/,
}
});