Skip to content

Commit 5cb02bb

Browse files
authored
Merge pull request #239 from Emilios1995/main
Integrate open PRs and update instructions
2 parents 6376fa0 + 857272e commit 5cb02bb

File tree

14 files changed

+253
-47
lines changed

14 files changed

+253
-47
lines changed

README.md

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,62 @@
22

33
This repository contains a parser definition of the [ReScript](https://rescript-lang.org/) language for the [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) parser generator tool.
44

5-
Athough Tree-sitter has many applications, the main intent of this parser is powering the [`nvim-treesitter-rescript`](https://github.com/nkrkv/nvim-tree-sitter-rescript/) NeoVim plugin which may be used to improve development experience in the NeoVim + ReScript combo.
6-
75
Queries for text objects are also included which help you to navigate, select, and modify ReScript code syntactically. For NeoVim, the [`nvim-treesitter-textobjects`](https://github.com/nvim-treesitter/nvim-treesitter-textobjects) plugin is required to use Tree-sitter text objects.
86

97
## Installation
108

11-
- If you want ReScript Tree-sitter in NeoVim, refer to [`nvim-treesitter-rescript`](https://github.com/nkrkv/nvim-tree-sitter-rescript/) installation notes;
9+
### Neovim
10+
11+
If you want ReScript Tree-sitter in NeoVim, you will first need to register a new parser for it like so:
12+
13+
```lua
14+
local parser_config = require("nvim-treesitter.parsers").get_parser_configs()
15+
parser_config.rescript = {
16+
install_info = {
17+
url = "https://github.com/rescript-lang/tree-sitter-rescript",
18+
branch = "main",
19+
files = { "src/scanner.c" },
20+
generate_requires_npm = false,
21+
requires_generate_from_grammar = true,
22+
use_makefile = true, -- macOS specific instruction
23+
},
24+
}
25+
```
26+
27+
This will make `TSInstall rescript` globally available. For more persistent approach you should add this parser to your Lua configuration.
28+
29+
Default configuration detects `.res` and `.resi` files. You can confirm that it's correctly installed by invoking `:InspectTree` when you are in the ReScript file.
30+
31+
- Notice that by default you will not see the highlighting! To enable highlighting, you will need to install this package either as a dependency or directly.
32+
33+
If you are using `lazy.nvim` example configuration will look like so:
34+
35+
```lua
36+
{
37+
"nvim-treesitter/nvim-treesitter",
38+
dependencies = {
39+
"rescript-lang/tree-sitter-rescript"
40+
},
41+
opts = function(_, opts) -- this is needed so you won't override your default nvim-treesitter configuration
42+
vim.list_extend(opts.ensure_installed, {
43+
"rescript",
44+
})
45+
46+
local parser_config = require("nvim-treesitter.parsers").get_parser_configs()
47+
parser_config.rescript = {
48+
install_info = {
49+
url = "https://github.com/rescript-lang/tree-sitter-rescript",
50+
branch = "main",
51+
files = { "src/scanner.c" },
52+
generate_requires_npm = false,
53+
requires_generate_from_grammar = true,
54+
use_makefile = true, -- macOS specific instruction
55+
},
56+
}
57+
end,
58+
}
59+
```
60+
1261
- If you want it for other purposes, you probably know what to do.
1362

1463
## Contributing

grammar.js

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/// <reference types="tree-sitter-cli/dsl" />
2+
13
module.exports = grammar({
24
name: 'rescript',
35

@@ -105,7 +107,9 @@ module.exports = grammar({
105107
[$._reserved_identifier, $.function],
106108
[$.exception_pattern, $.or_pattern],
107109
[$.type_binding, $._inline_type],
108-
[$._module_structure, $.parenthesized_module_expression]
110+
[$._module_structure, $.parenthesized_module_expression],
111+
[$.record_type_field, $.object_type_field],
112+
[$._record_type_member, $._object_type_member],
109113
],
110114

111115
rules: {
@@ -174,6 +178,7 @@ module.exports = grammar({
174178
)),
175179
optional(seq(
176180
'=',
181+
optional('await'),
177182
field('definition', $._module_definition),
178183
)),
179184
)),
@@ -314,6 +319,7 @@ module.exports = grammar({
314319
$.module_pack,
315320
$.unit,
316321
$.polymorphic_type,
322+
alias($._as_aliasing_non_function_inline_type, $.as_aliasing_type)
317323
),
318324

319325
polymorphic_type: $ => seq(
@@ -377,37 +383,48 @@ module.exports = grammar({
377383

378384
record_type: $ => seq(
379385
'{',
380-
commaSept($.record_type_field),
386+
commaSept($._record_type_member),
381387
'}',
382388
),
383389

384-
record_type_field: $ => seq(
385-
optional('mutable'),
386-
alias($.value_identifier, $.property_identifier),
387-
optional('?'),
388-
$.type_annotation,
390+
record_type_field: $ =>
391+
seq(
392+
optional('mutable'),
393+
alias($.value_identifier, $.property_identifier),
394+
optional('?'),
395+
$.type_annotation,
396+
),
397+
398+
type_spread: $ =>
399+
seq('...', choice($.type_identifier, $.generic_type, $.type_identifier_path)),
400+
401+
_record_type_member: $ => choice(
402+
$.record_type_field,
403+
$.type_spread
389404
),
390405

391406
object_type: $ => prec.left(seq(
392407
'{',
393408
choice(
394-
commaSep1t($._object_type_field),
395-
seq('.', commaSept($._object_type_field)),
396-
seq('..', commaSept($._object_type_field)),
409+
commaSep1t($._object_type_member),
410+
seq('.', commaSept($._object_type_member)),
411+
seq('..', commaSept($._object_type_member)),
397412
),
398413
'}',
399414
)),
400415

401-
_object_type_field: $ => alias($.object_type_field, $.field),
416+
_object_type_member: $ =>
417+
choice(
418+
alias($.object_type_field, $.field),
419+
$.type_spread
420+
),
402421

403422
object_type_field: $ => choice(
404-
seq('...', choice($.type_identifier, $.type_identifier_path)),
405423
seq(
406424
alias($.string, $.property_identifier),
407425
':',
408426
$._type,
409427
),
410-
411428
),
412429

413430
generic_type: $ => prec.left(seq(
@@ -521,6 +538,7 @@ module.exports = grammar({
521538
$.module_pack,
522539
$.extension_expression,
523540
$.lazy_expression,
541+
$._jsx_element
524542
),
525543

526544
parenthesized_expression: $ => seq(
@@ -698,6 +716,9 @@ module.exports = grammar({
698716

699717
as_aliasing_type: $ => seq($._type, 'as', $.type_identifier),
700718

719+
_as_aliasing_non_function_inline_type: $ =>
720+
prec(2, seq($._non_function_inline_type, 'as', $.type_identifier)),
721+
701722
assert_expression: $ => prec.left(seq('assert', $.expression)),
702723

703724
call_expression: $ => prec('call', seq(
@@ -726,6 +747,7 @@ module.exports = grammar({
726747
'(',
727748
optional($.uncurry),
728749
optional(commaSep1t($._call_argument)),
750+
optional($.partial_application_spread),
729751
')'
730752
),
731753

@@ -737,6 +759,8 @@ module.exports = grammar({
737759
$.labeled_argument,
738760
),
739761

762+
partial_application_spread: $ => "...",
763+
740764
labeled_argument: $ => seq(
741765
'~',
742766
field('label', $.value_identifier),
@@ -876,6 +900,7 @@ module.exports = grammar({
876900
record_pattern: $ => seq(
877901
'{',
878902
commaSep1t(seq(
903+
optional("?"),
879904
choice(
880905
$.value_identifier,
881906
$.value_identifier_path,
@@ -1331,7 +1356,7 @@ module.exports = grammar({
13311356
const bigint_literal = seq(choice(hex_literal, binary_literal, octal_literal, decimal_digits), 'n')
13321357

13331358
const decimal_integer_literal = choice(
1334-
repeat('0'),
1359+
repeat1('0'),
13351360
seq(repeat('0'), /[1-9]/, optional(seq(optional('_'), decimal_digits)))
13361361
)
13371362

package.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,19 @@
1717
"res",
1818
"resi"
1919
],
20-
"injection-regex": "rescript"
20+
"injection-regex": "rescript",
21+
"highlights": [
22+
"queries/rescript/highlights.scm"
23+
],
24+
"locals": [
25+
"queries/rescript/locals.scm"
26+
],
27+
"injections": [
28+
"queries/rescript/injections.scm"
29+
],
30+
"textobjects": [
31+
"queries/rescript/textobjects.scm"
32+
]
2133
}
2234
]
2335
}

queries/injections.scm

Lines changed: 0 additions & 21 deletions
This file was deleted.
File renamed without changes.

queries/rescript/injections.scm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
((comment) @injection.content (#set! injection.language "comment"))
2+
3+
; %re
4+
(extension_expression
5+
(extension_identifier) @_name
6+
(#eq? @_name "re")
7+
(expression_statement (_) @injection.content (#set! injection.language "regex")))
8+
9+
; %raw
10+
(extension_expression
11+
(extension_identifier) @_name
12+
(#eq? @_name "raw")
13+
(expression_statement
14+
(_ (_) @injection.content (#set! injection.language "javascript"))))
15+
16+
; %graphql
17+
(extension_expression
18+
(extension_identifier) @_name
19+
(#eq? @_name "graphql")
20+
(expression_statement
21+
(_ (_) @injection.content (#set! injection.language "graphql"))))
22+
23+
; %relay
24+
(extension_expression
25+
(extension_identifier) @_name
26+
(#eq? @_name "relay")
27+
(expression_statement
28+
(_ (_) @injection.content (#set! injection.language "graphql") )))
29+
File renamed without changes.
File renamed without changes.

src/scanner.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static bool scan_comment(TSLexer *lexer) {
113113
// Single-line comment
114114
do {
115115
advance(lexer);
116-
} while (lexer->lookahead != '\n');
116+
} while (lexer->lookahead != '\n' && !lexer->eof(lexer));
117117
return true;
118118

119119
case '*':

test/corpus/expressions.txt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ blocky(
111111
~third={3},
112112
)
113113
f(raise)
114+
f(1, ...)
114115

115116
--------------------------------------------------------------------------------
116117

@@ -191,7 +192,13 @@ f(raise)
191192
(call_expression
192193
function: (value_identifier)
193194
arguments: (arguments
194-
(value_identifier)))))
195+
(value_identifier))))
196+
(expression_statement
197+
(call_expression
198+
function: (value_identifier)
199+
arguments: (arguments
200+
(number)
201+
(partial_application_spread)))))
195202

196203
================================================================================
197204
Pipe
@@ -755,6 +762,7 @@ switch person {
755762
}) => 20
756763
| Student({status: Sick}) => 30
757764
| Student({name}) => 40
765+
| Student({?age}) => 50
758766
}
759767

760768
--------------------------------------------------------------------------------
@@ -818,7 +826,16 @@ switch person {
818826
(value_identifier))))
819827
(sequence_expression
820828
(expression_statement
821-
(number)))))))
829+
(number))))
830+
(switch_match
831+
(variant_pattern
832+
(variant_identifier)
833+
(formal_parameters
834+
(record_pattern
835+
(value_identifier))))
836+
(sequence_expression
837+
(expression_statement
838+
(number)))))))
822839

823840
================================================================================
824841
Switch of lists
@@ -1149,6 +1166,8 @@ Math operators
11491166
- 1 + 2 / 3
11501167
-. 1.0 +. 2.0 /. 3.0
11511168
2.0 ** 3.0
1169+
-0l
1170+
-ln
11521171

11531172
--------------------------------------------------------------------------------
11541173

@@ -1170,7 +1189,12 @@ Math operators
11701189
(expression_statement
11711190
(binary_expression
11721191
(number)
1173-
(number))))
1192+
(number)))
1193+
(expression_statement
1194+
(number))
1195+
(expression_statement
1196+
(unary_expression
1197+
(value_identifier))))
11741198

11751199
================================================================================
11761200
Boolean operators

0 commit comments

Comments
 (0)