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-31 22:06:30 +03:00
|
|
|
/\s/,
|
2023-07-16 20:54:43 +03:00
|
|
|
],
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
$.function_definition,
|
2023-07-31 12:33:08 +03:00
|
|
|
$.type_definition,
|
2023-07-31 22:06:30 +03:00
|
|
|
$.extra,
|
2023-07-25 19:08:23 +03:00
|
|
|
$.empty_lines,
|
2023-07-16 20:54:43 +03:00
|
|
|
),
|
|
|
|
|
|
|
|
|
|
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_name_identifier,
|
|
|
|
|
seq('(',$.operator, ')'),
|
2023-07-31 22:06:30 +03:00
|
|
|
$.simple_type_identifier,
|
|
|
|
|
$.typeclass_identifier,
|
2023-07-16 20:54:43 +03:00
|
|
|
)))),
|
|
|
|
|
';',
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
constraint: $ => seq('?', $._expression),
|
|
|
|
|
|
|
|
|
|
// --- definitions
|
|
|
|
|
|
|
|
|
|
function_definition: $ => seq(
|
|
|
|
|
optional($.definition_info),
|
|
|
|
|
repeat($.annotation_info),
|
|
|
|
|
repeat(seq($.constraint, ';')),
|
2023-07-31 22:06:30 +03:00
|
|
|
optional('.'), // for methods
|
2023-07-19 10:25:24 +03:00
|
|
|
choice(field('name', $.simple_name_identifier), seq('(', field('name', $.operator), ')')),
|
2023-07-31 22:06:30 +03:00
|
|
|
optional($._optional_or_result),
|
2023-07-16 20:54:43 +03:00
|
|
|
repeat(seq(
|
|
|
|
|
optional($.annotation_identifier),
|
2023-07-19 11:01:02 +03:00
|
|
|
optional($._reference),
|
2023-07-16 20:54:43 +03:00
|
|
|
$.argument_name_identifier,
|
2023-07-31 22:06:30 +03:00
|
|
|
optional($._optional_or_result),
|
|
|
|
|
)),
|
|
|
|
|
optional(seq(
|
|
|
|
|
':',
|
|
|
|
|
repeat1(seq(
|
|
|
|
|
optional($.annotation_identifier),
|
|
|
|
|
optional($._reference),
|
|
|
|
|
$.type,
|
|
|
|
|
)),
|
2023-07-16 20:54:43 +03:00
|
|
|
)),
|
2023-07-25 12:28:44 +03:00
|
|
|
choice(seq('=', choice(prec(2, choice($.block, $.array)), seq($._super_expression, ';'))), ';'),
|
2023-07-16 20:54:43 +03:00
|
|
|
),
|
|
|
|
|
|
2023-07-31 22:06:30 +03:00
|
|
|
// datatype or typeclass definition
|
2023-07-31 12:33:08 +03:00
|
|
|
type_definition: $ => seq(
|
|
|
|
|
optional($.definition_info),
|
2023-07-31 22:06:30 +03:00
|
|
|
repeat($.annotation_info), // for datatypes only
|
2023-07-31 12:33:08 +03:00
|
|
|
optional('^'),
|
2023-07-31 22:06:30 +03:00
|
|
|
field('name', choice($.simple_type_identifier, $.typeclass_identifier)),
|
|
|
|
|
optional(seq('[', repeat($.typeclass_identifier), ']')), // parametric typeclasses ??
|
|
|
|
|
repeat($.argument_type_identifier), // for datatypes only
|
|
|
|
|
optional(seq('=', $.variant_type)), // for datatypes only
|
|
|
|
|
';',
|
2023-07-16 20:54:43 +03:00
|
|
|
),
|
|
|
|
|
|
|
|
|
|
// --- flow control
|
|
|
|
|
|
|
|
|
|
case: $ => seq(
|
|
|
|
|
choice(':=', '=:'),
|
|
|
|
|
$._expression,
|
2023-07-22 13:34:19 +03:00
|
|
|
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,
|
2023-07-19 11:01:02 +03:00
|
|
|
$._do,
|
2023-07-16 20:54:43 +03:00
|
|
|
$._expression,
|
|
|
|
|
repeat(seq(
|
|
|
|
|
choice('!!', 'elif'),
|
|
|
|
|
$._expression,
|
2023-07-19 11:01:02 +03:00
|
|
|
$._do,
|
2023-07-16 20:54:43 +03:00
|
|
|
$._expression,
|
|
|
|
|
)),
|
2023-07-19 11:01:02 +03:00
|
|
|
optional(seq(choice('!!=>', 'else'), $._expression)),
|
2023-07-16 20:54:43 +03:00
|
|
|
),
|
|
|
|
|
|
|
|
|
|
loop: $ => seq(
|
|
|
|
|
choice('@', 'for'),
|
|
|
|
|
optional(choice(
|
2023-07-22 13:34:19 +03:00
|
|
|
$._expression,
|
|
|
|
|
seq($._expression, ':', $._expression),
|
2023-07-16 20:54:43 +03:00
|
|
|
)),
|
2023-07-19 11:01:02 +03:00
|
|
|
$._do,
|
2023-07-22 13:34:19 +03:00
|
|
|
$._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
|
|
|
|
|
|
2023-07-31 22:06:30 +03:00
|
|
|
block: $ => seq('{', repeat(choice(seq($._super_expression, ';'), $.extra, $.empty_lines)), '}'),
|
2023-07-16 20:54:43 +03:00
|
|
|
|
|
|
|
|
array: $ => seq('[[', repeat1($._scoped_expression), ']]'),
|
|
|
|
|
|
|
|
|
|
// --- modifiers
|
|
|
|
|
|
2023-07-22 13:34:19 +03:00
|
|
|
return: $ => seq(choice('return', 'bring'), $._expression),
|
2023-07-16 20:54:43 +03:00
|
|
|
|
|
|
|
|
name_definition: $ => seq(
|
2023-07-31 22:06:30 +03:00
|
|
|
choice(choice('%', 'let'), choice('$', 'var')),
|
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'),
|
|
|
|
|
|
2023-07-19 11:01:02 +03:00
|
|
|
reference_expression: $ => prec(-1, seq($._reference, $._scoped_expression)),
|
2023-07-16 20:54:43 +03:00
|
|
|
|
2023-07-31 22:06:30 +03:00
|
|
|
suffix_expression: $ => seq($._scoped_expression, $._optional_or_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(
|
2023-07-22 13:34:19 +03:00
|
|
|
field('type', $.type),
|
2023-07-16 20:54:43 +03:00
|
|
|
repeat1(seq(optional($.annotation_identifier), $._scoped_expression)),
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
lambda: $ => seq(
|
2023-07-19 11:01:02 +03:00
|
|
|
choice('\\', 'lambda'),
|
2023-07-18 11:39:18 +03:00
|
|
|
repeat($.argument_name_identifier),
|
2023-07-19 11:01:02 +03:00
|
|
|
$._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,
|
2023-07-19 11:01:02 +03:00
|
|
|
$.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),
|
2023-07-31 22:06:30 +03:00
|
|
|
optional($._optional_or_result),
|
2023-07-16 20:54:43 +03:00
|
|
|
optional(seq('[', repeat1($.type), ']'))
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
// --- comments
|
|
|
|
|
|
2023-07-24 13:02:21 +03:00
|
|
|
definition_info: $ => repeat1(seq(': ', $.info)),
|
2023-07-25 19:08:23 +03:00
|
|
|
annotation_info: $ => seq($.annotation_identifier, ' ', $.info),
|
2023-07-24 13:02:21 +03:00
|
|
|
|
|
|
|
|
info: $ => /[^\n]*/,
|
2023-07-16 20:54:43 +03:00
|
|
|
|
2023-07-31 22:06:30 +03:00
|
|
|
extra: $ => choice($._exec_comment, $._line_comment, $._block_comment),
|
|
|
|
|
empty_lines: $ => prec.left(repeat1('\n')),
|
2023-07-25 19:08:23 +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
|
|
|
|
|
|
2023-07-19 11:01:02 +03:00
|
|
|
_do: $ => choice('=>', 'do'),
|
2023-07-31 22:06:30 +03:00
|
|
|
_optional_or_result: $ => choice('?', '!'),
|
2023-07-31 12:33:08 +03:00
|
|
|
|
|
|
|
|
_reference: $ => choice(choice('<-', '<>', '--', '->',
|
|
|
|
|
'<-|<>', '<-|--', '<>|->', '--|->', '<>|--', '<-|->',
|
|
|
|
|
'<-|<>|->', '<-|--|->', '<-|<>|--', '<>|--|->',
|
|
|
|
|
'<-|<>|--|->'),
|
|
|
|
|
choice('in', 'ref', 'const', 'out',
|
|
|
|
|
'in|ref', 'in|const', 'ref|out', 'const|out', 'ref|const', 'in|out',
|
|
|
|
|
'in|ref|out', 'in|const|out', 'in|ref|const', 'ref|const|out',
|
|
|
|
|
'in|ref|const|out')),
|
2023-07-19 11:01:02 +03:00
|
|
|
|
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_]+)|([+\-*/%^!?|&,<>=]+\.?\.?\.?)|\.+/,
|
|
|
|
|
}
|
|
|
|
|
});
|