@algosail/tree-sitter 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/grammar.js +145 -101
- package/package.json +3 -2
- package/src/grammar.json +420 -142
- package/src/node-types.json +297 -108
- package/src/parser.c +3406 -1664
- package/tree-sitter-sail.wasm +0 -0
package/grammar.js
CHANGED
|
@@ -1,92 +1,179 @@
|
|
|
1
1
|
/// <reference types="tree-sitter-cli/dsl" />
|
|
2
2
|
// @ts-check
|
|
3
3
|
|
|
4
|
+
const UPPERNAME = /[A-Z][a-zA-Z0-9_]*/
|
|
5
|
+
const LOWERNAME = /[a-z][a-zA-Z0-9_]*/
|
|
6
|
+
|
|
4
7
|
module.exports = grammar({
|
|
5
8
|
name: 'sail',
|
|
6
9
|
|
|
7
10
|
extras: ($) => [/\s+/],
|
|
8
11
|
|
|
9
12
|
conflicts: ($) => [
|
|
10
|
-
// '(' can start a comment OR a signature — tree-sitter resolves by
|
|
11
|
-
// looking for '--' inside.
|
|
12
13
|
[$.comment, $.signature],
|
|
13
14
|
[$.comment, $.sig_quotation],
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[$.
|
|
17
|
-
|
|
18
|
-
[$.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
[$.
|
|
15
|
+
|
|
16
|
+
[$.module_def, $.module_ref],
|
|
17
|
+
[$.group_def, $.group_ref],
|
|
18
|
+
[$.tag_def, $.tag_ref],
|
|
19
|
+
[$.map_def, $.map_ref],
|
|
20
|
+
[$.field_def, $.field_ref],
|
|
21
|
+
|
|
22
|
+
[$.group],
|
|
23
|
+
[$.tag],
|
|
24
|
+
[$.map],
|
|
25
|
+
[$.field],
|
|
26
|
+
[$.word],
|
|
27
|
+
|
|
28
|
+
[$.group_def],
|
|
29
|
+
[$.tag, $.group],
|
|
30
|
+
[$.word, $._expr],
|
|
23
31
|
],
|
|
24
32
|
|
|
25
33
|
rules: {
|
|
26
34
|
source_file: ($) => repeat($._top_level),
|
|
35
|
+
_top_level: ($) => choice($.comment, $.import, $.group, $.map, $.word),
|
|
36
|
+
|
|
37
|
+
// ~Module
|
|
38
|
+
module_def: ($) => /~[A-Z][a-zA-Z0-9_]*/,
|
|
39
|
+
// ~Module
|
|
40
|
+
module_ref: ($) => /~[A-Z][a-zA-Z0-9_]*/,
|
|
41
|
+
// &Group
|
|
42
|
+
group_def: ($) => /&[A-Z][a-zA-Z0-9_]*/,
|
|
43
|
+
// &Group
|
|
44
|
+
group_ref: ($) => /&[A-Z][a-zA-Z0-9_]*/,
|
|
45
|
+
// #Tag
|
|
46
|
+
tag_def: ($) => /#[A-Z][a-zA-Z0-9_]*/,
|
|
47
|
+
// #Tag
|
|
48
|
+
tag_ref: ($) => /#[A-Z][a-zA-Z0-9_]*/,
|
|
49
|
+
// _Tag
|
|
50
|
+
tag_pattern: ($) => /\_[A-Z][a-zA-Z0-9_]*/,
|
|
51
|
+
// _
|
|
52
|
+
default_pattern: ($) => token('_'),
|
|
53
|
+
// $Map
|
|
54
|
+
map_def: ($) => /\$[A-Z][a-zA-Z0-9_]*/,
|
|
55
|
+
// $Map
|
|
56
|
+
map_ref: ($) => /\$[A-Z][a-zA-Z0-9_]*/,
|
|
57
|
+
// .field
|
|
58
|
+
field_def: ($) => /\.[a-z][a-zA-Z0-9_]*/,
|
|
59
|
+
// $Map.field
|
|
60
|
+
field_ref: ($) => /\$[A-Z][a-zA-Z0-9_]*\.[a-z][a-zA-Z0-9_]*/,
|
|
61
|
+
// @word
|
|
62
|
+
word_def: ($) => /@[a-z][a-zA-Z0-9_]*/,
|
|
63
|
+
// /word
|
|
64
|
+
word_ref: ($) => /\/[a-z][a-zA-Z0-9_]*/,
|
|
65
|
+
|
|
66
|
+
// ~Module&Group
|
|
67
|
+
module_group_ref: ($) => /~[A-Z][a-zA-Z0-9_]*&[A-Z][a-zA-Z0-9_]*/,
|
|
68
|
+
// ~Module#Tag
|
|
69
|
+
module_tag_ref: ($) => /~[A-Z][a-zA-Z0-9_]*#[A-Z][a-zA-Z0-9_]*/,
|
|
70
|
+
// ~Module$Map
|
|
71
|
+
module_map_ref: ($) => /~[A-Z][a-zA-Z0-9_]*\$[A-Z][a-zA-Z0-9_]*/,
|
|
72
|
+
// ~Module$Map.field
|
|
73
|
+
module_field_ref: ($) => /~[A-Z][a-zA-Z0-9_]*\$[A-Z][a-zA-Z0-9_]*\.[a-z][a-zA-Z0-9_]*/,
|
|
74
|
+
// ~Module/word
|
|
75
|
+
module_word_ref: ($) => /~[A-Z][a-zA-Z0-9_]*\/[a-z][a-zA-Z0-9_]*/,
|
|
27
76
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
comment_content: ($) => /[^()]+/,
|
|
35
|
-
|
|
36
|
-
// Module definition: !ModuleName
|
|
37
|
-
module_def: ($) => field('name', $.module_name),
|
|
38
|
-
module_name: ($) => /![A-Z][a-zA-Z0-9_]*/,
|
|
39
|
-
|
|
40
|
-
// Import: |path/or/npm:pkg Alias
|
|
41
|
-
import_decl: ($) => seq(field('path', $.import_path), field('alias', $.module_alias)),
|
|
42
|
-
|
|
43
|
-
import_path: ($) => /\|[^\s]+/,
|
|
44
|
-
|
|
45
|
-
module_alias: ($) => /~[A-Z][a-zA-Z0-9_]*/,
|
|
46
|
-
|
|
47
|
-
// Tag group: &Name typeParam* (>TagCase typeParam*)*
|
|
48
|
-
tag_group: ($) =>
|
|
49
|
-
seq(field('name', $.tag_group_name), repeat($.type_variable), repeat($.tag_def)),
|
|
50
|
-
|
|
51
|
-
tag_group_name: ($) => /&[A-Z][a-zA-Z0-9_]*/,
|
|
77
|
+
// Uppercase type: Int, Str, Maybe, List, etc.
|
|
78
|
+
type: ($) => /[A-Z][a-zA-Z0-9_]*/,
|
|
79
|
+
// Lowercase type variable: a, b, elem, etc.
|
|
80
|
+
type_var: ($) => /[a-z][a-zA-Z0-9_]*/,
|
|
81
|
+
// Lowercase type variable: a, b, elem, etc.
|
|
82
|
+
spread: ($) => /\.\.[a-z][a-zA-Z0-9_]*/,
|
|
52
83
|
|
|
53
|
-
|
|
84
|
+
// +Effect
|
|
85
|
+
effect_add: ($) => /\+[A-Z][a-zA-Z0-9_]*/,
|
|
86
|
+
// -Effect
|
|
87
|
+
effect_remove: ($) => /\-[A-Z][a-zA-Z0-9_]*/,
|
|
54
88
|
|
|
55
|
-
|
|
89
|
+
// :name
|
|
90
|
+
slot_push: ($) => /:[a-z][a-zA-Z0-9_]*/,
|
|
56
91
|
|
|
57
|
-
//
|
|
58
|
-
|
|
92
|
+
// ;name
|
|
93
|
+
slot_pop: ($) => /;[a-z][a-zA-Z0-9_]*/,
|
|
59
94
|
|
|
60
|
-
|
|
95
|
+
// 'raw string literal'
|
|
96
|
+
raw_string: ($) => /\'[^\']*\'/,
|
|
61
97
|
|
|
62
|
-
|
|
98
|
+
// Catch-all: any non-whitespace sequence that doesn't match a more specific
|
|
99
|
+
// rule. prec(-1) gives it the lowest priority so every other token wins
|
|
100
|
+
// when there is a tie. Structural characters ( ) [ ] are excluded because
|
|
101
|
+
// they are needed by the parser to delimit blocks and comments.
|
|
102
|
+
raw_value: ($) => token(prec(-1, /[^\s\[\]()']+/)),
|
|
63
103
|
|
|
64
|
-
|
|
104
|
+
// Comment / doc block: ( any text )
|
|
105
|
+
// comment_content is recursive: it can contain plain text and/or nested
|
|
106
|
+
// parenthesised groups, so ( use f(x) here ) parses correctly.
|
|
107
|
+
comment: ($) => seq('(', optional($.comment_content), ')'),
|
|
108
|
+
comment_content: ($) => repeat1(choice(/[^()]+/, $.comment)),
|
|
109
|
+
|
|
110
|
+
// Import: +path/or/+pkg Alias
|
|
111
|
+
import: ($) => seq(field('path', $.path), field('module', $.module_def)),
|
|
112
|
+
path: ($) => /\+[^\s]+/,
|
|
113
|
+
// seq('+', field('url', alias(/[^\s]+/, $.url))),
|
|
114
|
+
|
|
115
|
+
// Tag group: &Name typeParam* (#TagCase typeParam*)*
|
|
116
|
+
group: ($) =>
|
|
117
|
+
seq(
|
|
118
|
+
field('def', $.group_def),
|
|
119
|
+
repeat($.type_var),
|
|
120
|
+
optional(field('doc', $.comment)),
|
|
121
|
+
repeat($.tag),
|
|
122
|
+
),
|
|
123
|
+
tag: ($) =>
|
|
124
|
+
seq(
|
|
125
|
+
field('def', $.tag_def),
|
|
126
|
+
optional(field('type_param', $.type_var)),
|
|
127
|
+
optional(field('doc', $.comment)),
|
|
128
|
+
),
|
|
129
|
+
group_type: ($) =>
|
|
130
|
+
seq(
|
|
131
|
+
field('group', choice($.group_ref, $.module_group_ref)),
|
|
132
|
+
optional(field('params', $._generic)),
|
|
133
|
+
),
|
|
134
|
+
_generic: ($) => seq('{', repeat($._generic_content), '}'),
|
|
135
|
+
_generic_content: ($) => choice($.type, $.group_type, $.map_ref, $.module_map_ref),
|
|
136
|
+
|
|
137
|
+
// Map definition: %Name (.field Type)*
|
|
138
|
+
map: ($) => seq(field('def', $.map_def), optional(field('doc', $.comment)), repeat($.field)),
|
|
139
|
+
field: ($) =>
|
|
140
|
+
seq(
|
|
141
|
+
field('key', $.field_def),
|
|
142
|
+
field('type', $._field_types),
|
|
143
|
+
optional(field('doc', $.comment)),
|
|
144
|
+
),
|
|
145
|
+
_field_types: ($) => choice($.type, $.group_type, $.map_ref, $.module_map_ref),
|
|
65
146
|
|
|
66
147
|
// Word definition: @name ( sig ) expr*
|
|
67
148
|
// Signature is required per the spec ("Word definition must have a signature").
|
|
68
149
|
// prec.right makes the body's repeat greedy: prefer consuming '(' as a body
|
|
69
150
|
// comment rather than ending the word_def early.
|
|
70
|
-
|
|
71
|
-
prec.right(
|
|
72
|
-
|
|
73
|
-
|
|
151
|
+
word: ($) =>
|
|
152
|
+
prec.right(
|
|
153
|
+
seq(
|
|
154
|
+
field('name_def', $.word_def),
|
|
155
|
+
field('sig', $.signature),
|
|
156
|
+
optional(field('doc', $.comment)),
|
|
157
|
+
repeat($._expr),
|
|
158
|
+
),
|
|
159
|
+
),
|
|
74
160
|
|
|
75
161
|
// Signature: ( inputs -- outputs +effects )
|
|
76
162
|
// The required '--' token is what makes it unambiguous vs a comment.
|
|
77
163
|
signature: ($) => seq('(', repeat($._sig_item), $.sig_arrow, repeat($._sig_item), ')'),
|
|
78
|
-
|
|
79
164
|
sig_arrow: ($) => token('--'),
|
|
80
|
-
|
|
81
165
|
_sig_item: ($) =>
|
|
82
166
|
choice(
|
|
83
167
|
$.effect_add,
|
|
84
168
|
$.effect_remove,
|
|
85
169
|
$.spread,
|
|
86
|
-
$.
|
|
87
|
-
$.
|
|
170
|
+
$.type,
|
|
171
|
+
$.type_var,
|
|
88
172
|
$.sig_list,
|
|
89
173
|
$.sig_quotation,
|
|
174
|
+
$.group_type,
|
|
175
|
+
$.map_ref,
|
|
176
|
+
$.module_map_ref,
|
|
90
177
|
),
|
|
91
178
|
|
|
92
179
|
// [ Type Type ... ] — list / tuple type in a signature
|
|
@@ -95,37 +182,24 @@ module.exports = grammar({
|
|
|
95
182
|
// ( a b -- c d ) — higher-order function type nested inside a signature
|
|
96
183
|
sig_quotation: ($) => seq('(', repeat($._sig_item), $.sig_arrow, repeat($._sig_item), ')'),
|
|
97
184
|
|
|
98
|
-
// +IO, +FAIL, etc.
|
|
99
|
-
effect_add: ($) => /\+[A-Z][a-zA-Z0-9_]*/,
|
|
100
|
-
|
|
101
|
-
// -IO, -FAIL, etc. (uppercase after dash avoids matching negative numbers)
|
|
102
|
-
effect_remove: ($) => /-[A-Z][a-zA-Z0-9_]*/,
|
|
103
|
-
|
|
104
|
-
// ..a, ..row — spread / row-variable in a signature
|
|
105
|
-
spread: ($) => /\.\.[a-zA-Z][a-zA-Z0-9_]*/,
|
|
106
|
-
|
|
107
|
-
// Uppercase type: Int, Str, Maybe, List, etc.
|
|
108
|
-
type_name: ($) => /[A-Z][a-zA-Z0-9_]*/,
|
|
109
|
-
|
|
110
|
-
// Lowercase type variable: a, b, elem, etc.
|
|
111
|
-
type_variable: ($) => /[a-z][a-zA-Z0-9_]*/,
|
|
112
|
-
|
|
113
185
|
// Expressions inside word bodies
|
|
114
186
|
_expr: ($) =>
|
|
115
187
|
choice(
|
|
116
188
|
$.comment, // doc / inline comment block
|
|
117
189
|
$.quotation,
|
|
118
190
|
$.builtin_word,
|
|
119
|
-
$.
|
|
120
|
-
$.
|
|
121
|
-
$.
|
|
122
|
-
$.
|
|
191
|
+
$.word_ref,
|
|
192
|
+
$.module_word_ref,
|
|
193
|
+
$.tag_ref,
|
|
194
|
+
$.module_tag_ref,
|
|
123
195
|
$.tag_pattern,
|
|
196
|
+
$.default_pattern,
|
|
197
|
+
$.field_ref,
|
|
198
|
+
$.module_field_ref,
|
|
124
199
|
$.slot_push,
|
|
125
200
|
$.slot_pop,
|
|
126
201
|
$.raw_string,
|
|
127
|
-
$.
|
|
128
|
-
$.identifier,
|
|
202
|
+
$.raw_value,
|
|
129
203
|
),
|
|
130
204
|
|
|
131
205
|
// [ expr* ] — quotation (anonymous code block or list literal)
|
|
@@ -159,35 +233,5 @@ module.exports = grammar({
|
|
|
159
233
|
'ERROR',
|
|
160
234
|
),
|
|
161
235
|
),
|
|
162
|
-
|
|
163
|
-
// /wordName — call a locally defined word
|
|
164
|
-
word_call: ($) => /\/[a-z][a-zA-Z0-9_]*/,
|
|
165
|
-
|
|
166
|
-
// ~Module/word or ~Module — module-qualified word call
|
|
167
|
-
module_call: ($) => /~[A-Z][a-zA-Z0-9_]*(\/[a-zA-Z][a-zA-Z0-9_]*)?/,
|
|
168
|
-
|
|
169
|
-
// *Map/field — map field accessor / lens
|
|
170
|
-
map_access: ($) => /\*[A-Z][a-zA-Z0-9_]*\/[a-z][a-zA-Z0-9_]*/,
|
|
171
|
-
|
|
172
|
-
// #TagName — construct a tagged union value
|
|
173
|
-
tag_constructor: ($) => /#[A-Z][a-zA-Z0-9_]*/,
|
|
174
|
-
|
|
175
|
-
// _TagName — match/destructure a tag in MATCH
|
|
176
|
-
tag_pattern: ($) => /_[A-Z][a-zA-Z0-9_]*/,
|
|
177
|
-
|
|
178
|
-
// .name — pop the top of the stack into a named local slot
|
|
179
|
-
slot_push: ($) => /\.[a-z][a-zA-Z0-9_]*/,
|
|
180
|
-
|
|
181
|
-
// ,name — push a named local slot back onto the stack
|
|
182
|
-
slot_pop: ($) => /,[a-z][a-zA-Z0-9_]*/,
|
|
183
|
-
|
|
184
|
-
// 'raw string literal'
|
|
185
|
-
raw_string: ($) => /\'[^\']*\'/,
|
|
186
|
-
|
|
187
|
-
// Numeric literal: integer or decimal
|
|
188
|
-
number: ($) => /[0-9]+(\.[0-9]+)?/,
|
|
189
|
-
|
|
190
|
-
// Generic bare identifier (raw data tokens, unrecognised lowercase words)
|
|
191
|
-
identifier: ($) => /[a-zA-Z_][a-zA-Z0-9_]*/,
|
|
192
236
|
},
|
|
193
237
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algosail/tree-sitter",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Tree-sitter grammar for the Sail language",
|
|
5
5
|
"main": "bindings/node",
|
|
6
6
|
"types": "bindings/node",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"build:wasm": "tree-sitter build --wasm",
|
|
9
9
|
"build:native": "node-gyp rebuild",
|
|
10
10
|
"generate": "tree-sitter generate",
|
|
11
|
-
"install": "echo 'Skipping native build. Run npm run build:native manually if needed.'"
|
|
11
|
+
"install": "echo 'Skipping native build. Run npm run build:native manually if needed.'",
|
|
12
|
+
"playground": "tree-sitter playground"
|
|
12
13
|
},
|
|
13
14
|
"devDependencies": {
|
|
14
15
|
"node-addon-api": "^8.6.0",
|