TS parser 100% done now
This commit is contained in:
2
spec.md
2
spec.md
@@ -358,8 +358,6 @@ def add = a -> b -> a + b
|
|||||||
- `func(arg1, arg2)`: function application. requires at least one argument. partial function applications are allowed too
|
- `func(arg1, arg2)`: function application. requires at least one argument. partial function applications are allowed too
|
||||||
- `func(_, arg)`: bind some args from function, return funciton taking in the args with `_`, or the non-specified ones
|
- `func(_, arg)`: bind some args from function, return funciton taking in the args with `_`, or the non-specified ones
|
||||||
- `expr :: type`: down-cast type
|
- `expr :: type`: down-cast type
|
||||||
- `recExpr with fieldname: newFieldValue`: overwrites or adds a field to a record type.
|
|
||||||
type checking: identical to `recExpr and {fieldname: newFieldValue}`
|
|
||||||
- `recExpr and otherRecExpr`: "sum" fields together of both record expressions.
|
- `recExpr and otherRecExpr`: "sum" fields together of both record expressions.
|
||||||
type checking: phi-unify `recExpr` with `otherRecExpr`, and require that both are non-nominal record types
|
type checking: phi-unify `recExpr` with `otherRecExpr`, and require that both are non-nominal record types
|
||||||
- `if cond then a else b`
|
- `if cond then a else b`
|
||||||
|
@@ -24,6 +24,10 @@ module.exports = grammar({
|
|||||||
|
|
||||||
precedences: _ => [
|
precedences: _ => [
|
||||||
[
|
[
|
||||||
|
"parentrized",
|
||||||
|
"function_call",
|
||||||
|
"expr_atom",
|
||||||
|
|
||||||
"ident",
|
"ident",
|
||||||
"exponent",
|
"exponent",
|
||||||
"multiplication",
|
"multiplication",
|
||||||
@@ -34,54 +38,67 @@ module.exports = grammar({
|
|||||||
"equal",
|
"equal",
|
||||||
"if",
|
"if",
|
||||||
"let",
|
"let",
|
||||||
"new_match_arm",
|
|
||||||
"match_arm",
|
"match_arm",
|
||||||
|
"new_match_arm",
|
||||||
"await",
|
"await",
|
||||||
"tag",
|
"tag",
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
conflicts: $ => [
|
|
||||||
[$.match_expr, $.match_expr], // TODO
|
|
||||||
],
|
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
source_file: $ => repeat($._definition),
|
source_file: $ => repeat($.definition),
|
||||||
|
|
||||||
_identifier_tok: $ => token(/[a-zA-Z_]+[a-zA-Z0-9_]*/),
|
_identifier_tok: $ => token(/[a-zA-Z_]+[a-zA-Z0-9_]*/),
|
||||||
identifier: $ => reserved('toplevel_kw', $._identifier_tok),
|
identifier: $ => reserved('toplevel_kw', $._identifier_tok),
|
||||||
path: $ => prec.left(seq($.identifier, repeat(seq('.', $.identifier)))),
|
path: $ => prec.left(seq($.identifier, repeat(seq('.', $.identifier)))),
|
||||||
|
|
||||||
comment: $ =>
|
comment: $ =>
|
||||||
token(seq("#", /.*/)),
|
token(seq("# ", /.*/)),
|
||||||
|
|
||||||
_definition: $ => choice(
|
doc_comment: $ =>
|
||||||
$.full_partial_type_definition,
|
repeat1(seq('## ', token.immediate(/.*/))),
|
||||||
$.type_definition,
|
|
||||||
$.extensible_union,
|
definition: $ => seq(
|
||||||
$.extend_decl,
|
optional(field('doc', $.doc_comment)),
|
||||||
$.def,
|
field('body', choice(
|
||||||
|
$.full_partial_type_definition,
|
||||||
|
$.type_definition,
|
||||||
|
$.extensible_union,
|
||||||
|
$.extend_decl,
|
||||||
|
$.def,
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
|
|
||||||
extensible_union: $ => seq(
|
extensible_union: $ => seq(
|
||||||
'extensible', 'union', $.path),
|
'extensible', 'union', $.path),
|
||||||
|
|
||||||
extend_decl: $ => seq(
|
extend_decl: $ => seq(
|
||||||
'extend', $.path, 'with', $.tag, $._type),
|
'extend',
|
||||||
|
field('what', $.path),
|
||||||
|
'with',
|
||||||
|
field('tag', $.tag),
|
||||||
|
field('ty', $._type)),
|
||||||
|
|
||||||
full_partial_type_definition: $ => seq(
|
full_partial_type_definition: $ => seq(
|
||||||
"type",
|
"type",
|
||||||
"?", $.path,
|
"?", field('name', $.path),
|
||||||
"=",
|
"=",
|
||||||
$._type
|
field('type', $._type)
|
||||||
),
|
),
|
||||||
|
|
||||||
type_definition: $ => seq(
|
type_definition: $ => seq(
|
||||||
"type",
|
"type",
|
||||||
repeat($.identifier),
|
optional(choice(
|
||||||
$.path,
|
field('arg', $.identifier),
|
||||||
|
seq(
|
||||||
|
'[',
|
||||||
|
repeat(seq(field('arg', $.identifier), ',')),
|
||||||
|
field('arg', $.identifier),
|
||||||
|
']'),
|
||||||
|
)),
|
||||||
|
field('name', $.path),
|
||||||
"=",
|
"=",
|
||||||
$._type
|
field('type', $._type)
|
||||||
),
|
),
|
||||||
|
|
||||||
_type_atom: $ => choice(
|
_type_atom: $ => choice(
|
||||||
@@ -107,45 +124,63 @@ module.exports = grammar({
|
|||||||
),
|
),
|
||||||
|
|
||||||
union_type: $ => prec.left(1,
|
union_type: $ => prec.left(1,
|
||||||
seq($._type, '|', $._type)),
|
seq(
|
||||||
|
field('left', $._type),
|
||||||
|
'|',
|
||||||
|
field('right', $._type))),
|
||||||
|
|
||||||
partial_union_type: $ => prec.left(1,
|
partial_union_type: $ => prec.left(1,
|
||||||
seq($._type, '|', '...', $.partial_type)),
|
seq(
|
||||||
|
field('left', $._type),
|
||||||
|
'|', '...',
|
||||||
|
field('partial', $.partial_type))),
|
||||||
|
|
||||||
tag: $ => new RustRegex("'(?:[a-zA-Z_][a-zA-Z0-9_]*(?:[.][a-zA-Z_0-9]+)*)"),
|
tag: $ => new RustRegex("'(?:[a-zA-Z_][a-zA-Z0-9_]*(?:[.][a-zA-Z_0-9]+)*)"),
|
||||||
tagged_type: $ => prec.right(3,
|
tagged_type: $ => prec.right(3,
|
||||||
seq($.tag, optional(
|
seq(field('tag', $.tag), optional(
|
||||||
choice(
|
field('type', choice(
|
||||||
$._type_atom,
|
$._type_atom,
|
||||||
$.parametrized_type)))),
|
$.parametrized_type))))),
|
||||||
|
|
||||||
multi_type_parameters: $ => seq('[', $._type, repeat(seq(',', $._type)), ']'),
|
multi_type_parameters: $ => seq('[',
|
||||||
|
field('arg', $._type),
|
||||||
|
repeat(seq(',', field('arg', $._type))),
|
||||||
|
']'),
|
||||||
parametrized_type: $ => prec.left(4, seq(
|
parametrized_type: $ => prec.left(4, seq(
|
||||||
choice(
|
field('nest', choice(
|
||||||
$.multi_type_parameters,
|
$.multi_type_parameters,
|
||||||
$._type_atom
|
$._type_atom,
|
||||||
),
|
)),
|
||||||
repeat1($.path)
|
repeat(field('nest', $.path)),
|
||||||
|
field('type', $.path),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
with_type: $ => seq('with', $.identifier, repeat(seq(',', $.identifier)), ':', $._type),
|
with_type: $ => seq('with',
|
||||||
|
field('arg', $.identifier),
|
||||||
|
repeat(seq(',', field('arg', $.identifier))),
|
||||||
|
':',
|
||||||
|
field('type', $._type)),
|
||||||
|
|
||||||
recursive_type: $ => seq('&', $.identifier, $._type),
|
recursive_type: $ => seq('&',
|
||||||
|
field('name', $.identifier),
|
||||||
|
field('type', $._type)),
|
||||||
|
|
||||||
partial_type: $ => seq('?', $.identifier),
|
partial_type: $ => seq('?', $.identifier),
|
||||||
|
|
||||||
fn_type: $ => prec.left(-10,
|
fn_type: $ => prec.left(-10,
|
||||||
seq($._type, '->', $._type)),
|
seq(field('arg', $._type), '->', field('res', $._type))),
|
||||||
|
|
||||||
just_type: $ => prec(-1, $.path),
|
just_type: $ => prec(-1, $.path),
|
||||||
|
|
||||||
record_type_field: $ => seq($.identifier, ':', $._type),
|
// TODO: doc comments
|
||||||
|
|
||||||
|
record_type_field: $ => seq(field('name', $.identifier), ':', field('type', $._type)),
|
||||||
record_type: $ => seq(
|
record_type: $ => seq(
|
||||||
'{',
|
'{',
|
||||||
repeat(seq($.record_type_field, ',')),
|
repeat(seq(field('field', $.record_type_field), ',')),
|
||||||
optional(choice(
|
optional(choice(
|
||||||
$.record_type_field,
|
field('field', $.record_type_field),
|
||||||
seq('...', $.partial_type),
|
seq('...', field('partial', $.partial_type)),
|
||||||
)),
|
)),
|
||||||
'}'),
|
'}'),
|
||||||
|
|
||||||
@@ -159,6 +194,7 @@ module.exports = grammar({
|
|||||||
char_literal: $ =>
|
char_literal: $ =>
|
||||||
seq('\'', choice($.escape_sequence, $.char_middle), '\''),
|
seq('\'', choice($.escape_sequence, $.char_middle), '\''),
|
||||||
|
|
||||||
|
// TODO: fstrings
|
||||||
string_literal: $ =>
|
string_literal: $ =>
|
||||||
seq('"', repeat(choice($.escape_sequence, $.string_middle)), '"'),
|
seq('"', repeat(choice($.escape_sequence, $.string_middle)), '"'),
|
||||||
|
|
||||||
@@ -179,18 +215,21 @@ module.exports = grammar({
|
|||||||
']'),
|
']'),
|
||||||
|
|
||||||
field_access: $ => prec.left(
|
field_access: $ => prec.left(
|
||||||
seq($._atom, ':', $.identifier)),
|
seq(field('expr', $._atom), ':', field('field', $.identifier))),
|
||||||
|
|
||||||
function_call: $ => prec.left(1,
|
function_call: $ => prec.left("function_call",
|
||||||
seq($._atom, '(',
|
seq(
|
||||||
repeat(seq($._expression, ',')), optional($._expression),
|
field('fn', $._atom),
|
||||||
|
'(',
|
||||||
|
repeat(seq(field('arg', $._expression), ',')),
|
||||||
|
optional(field('arg', $._expression)),
|
||||||
')')),
|
')')),
|
||||||
|
|
||||||
ident_expr: $ => prec("ident",
|
ident_expr: $ => prec("ident",
|
||||||
$.path),
|
$.path),
|
||||||
|
|
||||||
record_expr_field: $ =>
|
record_expr_field: $ =>
|
||||||
seq($.identifier, ':', $._expression),
|
seq(field('field', $.identifier), ':', field('value', $._expression)),
|
||||||
|
|
||||||
record_expr: $ => seq(
|
record_expr: $ => seq(
|
||||||
'{',
|
'{',
|
||||||
@@ -199,7 +238,7 @@ module.exports = grammar({
|
|||||||
'}'),
|
'}'),
|
||||||
|
|
||||||
_atom: $ => choice(
|
_atom: $ => choice(
|
||||||
prec(0, seq('(', $._expression, ')')),
|
prec("parentrized", seq('(', $._expression, ')')),
|
||||||
$.ident_expr,
|
$.ident_expr,
|
||||||
$.char_literal,
|
$.char_literal,
|
||||||
$.string_literal,
|
$.string_literal,
|
||||||
@@ -241,68 +280,75 @@ module.exports = grammar({
|
|||||||
field('body', $._expression)
|
field('body', $._expression)
|
||||||
)),
|
)),
|
||||||
|
|
||||||
with_expr: $ => prec.left("with",
|
|
||||||
seq($._expression, 'with', $._atom)),
|
|
||||||
|
|
||||||
and_expr: $ => prec.left("with",
|
and_expr: $ => prec.left("with",
|
||||||
seq($._expression, 'and', $._atom)),
|
seq(
|
||||||
|
field('left', $._expression),
|
||||||
|
'and',
|
||||||
|
field('right', $._atom))),
|
||||||
|
|
||||||
if_expr: $ => prec("if",
|
if_expr: $ => prec("if",
|
||||||
seq('if', $._expression, 'then', $._expression, 'else', $._expression)),
|
seq(
|
||||||
|
'if',
|
||||||
|
field('condition', $._expression),
|
||||||
|
'then',
|
||||||
|
field('then', $._expression),
|
||||||
|
'else',
|
||||||
|
field('else', $._expression))),
|
||||||
|
|
||||||
sub_expr: $ => prec.left("addition",
|
sub_expr: $ => prec.left("addition",
|
||||||
seq($._expression, '-', $._expression)),
|
seq(field('left', $._expression), '-', field('right', $._expression))),
|
||||||
add_expr: $ => prec.left("addition",
|
add_expr: $ => prec.left("addition",
|
||||||
seq($._expression, '+', $._expression)),
|
seq(field('left', $._expression), '+', field('right', $._expression))),
|
||||||
|
|
||||||
divide_expr: $ => prec.left("multiplication",
|
divide_expr: $ => prec.left("multiplication",
|
||||||
seq($._expression, '/', $._expression)),
|
seq(field('left', $._expression), '/', field('right', $._expression))),
|
||||||
multiply_expr: $ => prec.left("multiplication",
|
multiply_expr: $ => prec.left("multiplication",
|
||||||
seq($._expression, '*', $._expression)),
|
seq(field('left', $._expression), '*', field('right', $._expression))),
|
||||||
|
|
||||||
equal_expr: $ => prec.left("equal",
|
equal_expr: $ => prec.left("equal",
|
||||||
seq($._expression, '=', $._expression)),
|
seq(field('left', $._expression), '=', field('right', $._expression))),
|
||||||
|
|
||||||
concat_expr: $ => prec.left("concat",
|
concat_expr: $ => prec.left("concat",
|
||||||
seq($._expression, '++', $._expression)),
|
seq(field('left', $._expression), '++', field('right', $._expression))),
|
||||||
|
|
||||||
compose_expr: $ => prec.left("concat",
|
compose_expr: $ => prec.left("concat",
|
||||||
seq($._expression, '=>', $._expression)),
|
seq(field('left', $._expression), '=>', field('right', $._expression))),
|
||||||
|
|
||||||
exponent_expr: $ => prec.left("exponent",
|
exponent_expr: $ => prec.left("exponent",
|
||||||
seq($._expression, '^', $._atom)),
|
seq(field('left', $._expression), '^', field('right', $._atom))),
|
||||||
|
|
||||||
match_arm: $ => prec("match_arm",
|
match_arm: $ => prec("match_arm",
|
||||||
seq(
|
seq(
|
||||||
field('cases', seq($._atom, repeat(seq('|', $._atom)))),
|
field('cases', seq($._atom, repeat(seq('|', $._atom)))),
|
||||||
'->', $._expression)),
|
'->', field('expr', $._atom))),
|
||||||
|
|
||||||
match_expr: $ =>
|
match_expr: $ =>
|
||||||
seq('match', $._expression, 'with',
|
seq('match', field('on', $._expression), 'with',
|
||||||
$.match_arm,
|
field('arm', $.match_arm),
|
||||||
prec("new_match_arm", repeat(seq('|', $.match_arm)))),
|
prec("new_match_arm", repeat(seq('|', field('arm', $.match_arm))))),
|
||||||
|
|
||||||
negate_expr: $ => prec.right("negate",
|
negate_expr: $ => prec.right("negate",
|
||||||
seq('-', $._expression)),
|
seq('-', field('expr', $._expression))),
|
||||||
|
|
||||||
tag_expr: $ => prec.right("tag",
|
tag_expr: $ => prec.right("tag",
|
||||||
seq($.tag, $._expression)),
|
seq(
|
||||||
|
field('tag', $.tag),
|
||||||
|
field('expr', $._expression))),
|
||||||
|
|
||||||
await_expr: $ => prec.right("await",
|
await_expr: $ => prec.right("await",
|
||||||
seq('await', $._expression)),
|
seq('await', field('expr', $._expression))),
|
||||||
|
|
||||||
_expression: $ => choice(
|
_expression: $ => choice(
|
||||||
$._atom,
|
prec("expr_atom", $._atom),
|
||||||
$.let_binding,
|
$.let_binding,
|
||||||
$.await_binding,
|
$.await_binding,
|
||||||
$.await_expr,
|
$.await_expr,
|
||||||
$.type_downcast,
|
$.type_downcast,
|
||||||
$.lambda,
|
$.lambda,
|
||||||
$.with_expr,
|
|
||||||
$.and_expr,
|
$.and_expr,
|
||||||
$.if_expr,
|
$.if_expr,
|
||||||
$.match_expr,
|
|
||||||
$.tag_expr,
|
$.tag_expr,
|
||||||
|
$.match_expr,
|
||||||
|
|
||||||
$.add_expr,
|
$.add_expr,
|
||||||
$.sub_expr,
|
$.sub_expr,
|
||||||
|
775
tree-sitter/src/grammar.json
generated
775
tree-sitter/src/grammar.json
generated
File diff suppressed because it is too large
Load Diff
7400
tree-sitter/src/node-types.json
generated
7400
tree-sitter/src/node-types.json
generated
File diff suppressed because it is too large
Load Diff
54301
tree-sitter/src/parser.c
generated
54301
tree-sitter/src/parser.c
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user