@willbooster/tree-sitter-haskell 0.0.0-stage → 1.0.0
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/LICENSE +21 -0
- package/README.md +155 -2
- package/grammar/class.js +130 -0
- package/grammar/conflicts.js +116 -0
- package/grammar/context.js +69 -0
- package/grammar/data.js +241 -0
- package/grammar/decl.js +184 -0
- package/grammar/exp.js +413 -0
- package/grammar/externals.js +177 -0
- package/grammar/general.js +54 -0
- package/grammar/id.js +132 -0
- package/grammar/inline.js +99 -0
- package/grammar/lexeme.js +59 -0
- package/grammar/literal.js +102 -0
- package/grammar/module.js +150 -0
- package/grammar/operator.js +75 -0
- package/grammar/pat.js +149 -0
- package/grammar/patsyn.js +42 -0
- package/grammar/precedences.js +109 -0
- package/grammar/th.js +82 -0
- package/grammar/type.js +451 -0
- package/grammar/util.js +162 -0
- package/grammar.js +102 -0
- package/package.json +74 -4
- package/queries/highlights.scm +448 -0
- package/queries/injections.scm +76 -0
- package/queries/locals.scm +4 -0
- package/src/node-types.json +6412 -0
- package/tree-sitter-haskell.wasm +0 -0
- package/tree-sitter.json +40 -0
package/grammar/exp.js
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
const {
|
|
2
|
+
sep1,
|
|
3
|
+
sep,
|
|
4
|
+
parens,
|
|
5
|
+
braces,
|
|
6
|
+
brackets,
|
|
7
|
+
layout_sort,
|
|
8
|
+
layout,
|
|
9
|
+
unboxed_tuple_nonempty,
|
|
10
|
+
unboxed_sum_single,
|
|
11
|
+
qualified,
|
|
12
|
+
} = require('./util.js')
|
|
13
|
+
|
|
14
|
+
module.exports = {
|
|
15
|
+
|
|
16
|
+
// ------------------------------------------------------------------------
|
|
17
|
+
// names
|
|
18
|
+
// ------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
_exp_name: $ => choice(
|
|
21
|
+
$._cons,
|
|
22
|
+
$._vars,
|
|
23
|
+
$.variable,
|
|
24
|
+
$.implicit_variable,
|
|
25
|
+
$.label,
|
|
26
|
+
),
|
|
27
|
+
|
|
28
|
+
_exp_th_quoted_name: $ => choice(
|
|
29
|
+
seq('\'', field('name', choice($._vars, $._cons))),
|
|
30
|
+
prec('prefix', seq('\'\'', field('type', $.type))),
|
|
31
|
+
),
|
|
32
|
+
|
|
33
|
+
// ------------------------------------------------------------------------
|
|
34
|
+
// tuples and parens
|
|
35
|
+
// ------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
_exp_parens: $ => parens($, field('expression', $._exp)),
|
|
38
|
+
|
|
39
|
+
// Having this separate reduces size by ~15kB
|
|
40
|
+
_exp_tuple_elems: $ => seq(
|
|
41
|
+
choice(
|
|
42
|
+
seq(repeat1(','), field('element', $._exp)),
|
|
43
|
+
seq(field('element', $._exp), ',', optional(field('element', $._exp))),
|
|
44
|
+
),
|
|
45
|
+
repeat(seq(',', optional(field('element', $._exp))))
|
|
46
|
+
),
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* This needs to be disambiguated from `prefix_tuple`, which is a constructor with _only_ commas.
|
|
50
|
+
* Tuple sections aren't allowed in patterns.
|
|
51
|
+
*
|
|
52
|
+
* Since tuple expressions can contain singular expressions in sections like `(a,)` and `(,a)`, it has to be ensured
|
|
53
|
+
* that there is _at least_ each one comma and one expression in there, but the comma may be on either side and be
|
|
54
|
+
* preceded by any number of further commas, like `(,,,a)`.
|
|
55
|
+
*
|
|
56
|
+
* The final `repeat` is simpler, it just has to ensure that no two `_exp`s can be successive, but this encoding
|
|
57
|
+
* means that the optional `_exp` after `(5,)` needs to be included in the `choice`, otherwise a simple pair
|
|
58
|
+
* would be impossible.
|
|
59
|
+
*/
|
|
60
|
+
_exp_tuple: $ => parens($, $._exp_tuple_elems),
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Unlike their boxed variants, unboxed tuples may be nullary and unary, making it simpler to parse them.
|
|
64
|
+
*/
|
|
65
|
+
_exp_unboxed_tuple: $ => unboxed_tuple_nonempty($, $._exp),
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Unboxed sums must have at least one separating `|`, otherwise the expression would be a unary or nullary tuple.
|
|
69
|
+
* This is a lenient parser that allows multiple variants to be filled in, for simplicity.
|
|
70
|
+
*/
|
|
71
|
+
_exp_unboxed_sum: $ => unboxed_sum_single($, $._exp),
|
|
72
|
+
|
|
73
|
+
// ------------------------------------------------------------------------
|
|
74
|
+
// lists
|
|
75
|
+
// ------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
_exp_list: $ => brackets($, sep1(',', field('element', $._exp)), optional(',')),
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* An expression like `[1,2..20]`.
|
|
81
|
+
*/
|
|
82
|
+
_exp_arithmetic_sequence: $ => brackets(
|
|
83
|
+
$,
|
|
84
|
+
field('from', $._exp),
|
|
85
|
+
optional(seq(',', field('step', $._exp))),
|
|
86
|
+
$._dotdot,
|
|
87
|
+
optional(field('to', $._exp)),
|
|
88
|
+
),
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* `TransformListComp`, group style.
|
|
92
|
+
*
|
|
93
|
+
* Inlining `_exp` here is necessary to avoid a conflict.
|
|
94
|
+
*/
|
|
95
|
+
group: $ => seq(
|
|
96
|
+
'then',
|
|
97
|
+
'group',
|
|
98
|
+
optional(seq('by', field('key', choice(alias($._exp_signature, $.signature), $.expression)))),
|
|
99
|
+
'using',
|
|
100
|
+
field('classifier', $._exp),
|
|
101
|
+
),
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* `TransformListComp`, simple transformation style.
|
|
105
|
+
*/
|
|
106
|
+
transform: $ => seq(
|
|
107
|
+
'then',
|
|
108
|
+
field('transformation', $._exp),
|
|
109
|
+
optional(seq('by', field('key', $._exp))),
|
|
110
|
+
),
|
|
111
|
+
|
|
112
|
+
qualifier: $ => choice(
|
|
113
|
+
$.generator,
|
|
114
|
+
$.let,
|
|
115
|
+
$.transform,
|
|
116
|
+
$.group,
|
|
117
|
+
alias($._exp, $.boolean),
|
|
118
|
+
),
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* This is a supertype.
|
|
122
|
+
*/
|
|
123
|
+
qualifiers: $ => seq(sep1(',', field('qualifier', $.qualifier))),
|
|
124
|
+
|
|
125
|
+
_exp_list_comprehension: $ => brackets(
|
|
126
|
+
$,
|
|
127
|
+
field('expression', $._exp),
|
|
128
|
+
repeat1(seq('|', field('qualifiers', $.qualifiers))),
|
|
129
|
+
),
|
|
130
|
+
|
|
131
|
+
// ------------------------------------------------------------------------
|
|
132
|
+
// greedy block args
|
|
133
|
+
// ------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
_exp_lambda: $ => seq(
|
|
136
|
+
'\\',
|
|
137
|
+
field('patterns', $.patterns),
|
|
138
|
+
$._arrow,
|
|
139
|
+
field('expression', $._exp),
|
|
140
|
+
),
|
|
141
|
+
|
|
142
|
+
_exp_let_in: $ => seq($._let, optional($._phantom_in), 'in', field('expression', $._exp)),
|
|
143
|
+
|
|
144
|
+
_exp_conditional: $ => seq(
|
|
145
|
+
'if',
|
|
146
|
+
field('if', $._exp),
|
|
147
|
+
repeat(';'),
|
|
148
|
+
'then',
|
|
149
|
+
field('then', $._exp),
|
|
150
|
+
repeat(';'),
|
|
151
|
+
'else',
|
|
152
|
+
field('else', $._exp),
|
|
153
|
+
),
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* These block arguments don't end in a layout, so they all range over all following block arguments and will
|
|
157
|
+
* therefore always be the last argument in an application or infix chain.
|
|
158
|
+
* They also pull a trailing type annotation into their body.
|
|
159
|
+
*/
|
|
160
|
+
_exp_greedy: $ => choice(
|
|
161
|
+
alias($._exp_lambda, $.lambda),
|
|
162
|
+
alias($._exp_let_in, $.let_in),
|
|
163
|
+
alias($._exp_conditional, $.conditional),
|
|
164
|
+
),
|
|
165
|
+
|
|
166
|
+
// ------------------------------------------------------------------------
|
|
167
|
+
// do
|
|
168
|
+
// ------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
_exp_statement: $ => $._exp,
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* This is a supertype.
|
|
174
|
+
*/
|
|
175
|
+
statement: $ => choice(
|
|
176
|
+
alias($._exp_statement, $.exp),
|
|
177
|
+
alias($.generator, $.bind),
|
|
178
|
+
$.let,
|
|
179
|
+
$.rec,
|
|
180
|
+
),
|
|
181
|
+
|
|
182
|
+
_statements: $ => layout_sort($, $._cmd_layout_start_do, field('statement', $.statement)),
|
|
183
|
+
|
|
184
|
+
rec: $ => seq('rec', $._statements),
|
|
185
|
+
|
|
186
|
+
_do_keyword: _ => choice('mdo', 'do'),
|
|
187
|
+
|
|
188
|
+
do_module: $ => field('qualified_do', qualified($, $._do_keyword)),
|
|
189
|
+
|
|
190
|
+
_do: $ => choice(
|
|
191
|
+
$.do_module,
|
|
192
|
+
$._do_keyword
|
|
193
|
+
),
|
|
194
|
+
|
|
195
|
+
_exp_do: $ => seq($._do, $._statements),
|
|
196
|
+
|
|
197
|
+
// ------------------------------------------------------------------------
|
|
198
|
+
// case
|
|
199
|
+
// ------------------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
match: $ => seq(
|
|
202
|
+
$._guards,
|
|
203
|
+
optional($._phantom_arrow),
|
|
204
|
+
$._arrow,
|
|
205
|
+
$._cmd_texp_end,
|
|
206
|
+
field('expression', $._exp),
|
|
207
|
+
),
|
|
208
|
+
|
|
209
|
+
_simple_match: $ => seq($._arrow, field('expression', $._exp)),
|
|
210
|
+
|
|
211
|
+
_matches: $ => field('match', choice(
|
|
212
|
+
alias($._simple_match, $.match),
|
|
213
|
+
repeat1($.match),
|
|
214
|
+
)),
|
|
215
|
+
|
|
216
|
+
alternative: $ => seq(
|
|
217
|
+
field('pattern', $._pat),
|
|
218
|
+
$._matches,
|
|
219
|
+
optional($._where_binds),
|
|
220
|
+
),
|
|
221
|
+
|
|
222
|
+
_nalt: $ => seq(
|
|
223
|
+
field('patterns', $.patterns),
|
|
224
|
+
$._matches,
|
|
225
|
+
optional($._where_binds),
|
|
226
|
+
),
|
|
227
|
+
|
|
228
|
+
alternatives: $ => layout_sort($, $._cmd_layout_start_case, field('alternative', $.alternative)),
|
|
229
|
+
_nalts: $ => layout_sort($, $._cmd_layout_start_case, field('alternative', alias($._nalt, $.alternative))),
|
|
230
|
+
|
|
231
|
+
_exp_case: $ => seq('case', $._exp, 'of', optional(field('alternatives', $.alternatives))),
|
|
232
|
+
|
|
233
|
+
_exp_lambda_case: $ => seq(
|
|
234
|
+
'\\',
|
|
235
|
+
'case',
|
|
236
|
+
optional(field('alternatives', $.alternatives)),
|
|
237
|
+
),
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* alternatives are not optional in a `\cases` expression, but we're lenient.
|
|
241
|
+
*/
|
|
242
|
+
_exp_lambda_cases: $ => seq(
|
|
243
|
+
'\\',
|
|
244
|
+
'cases',
|
|
245
|
+
optional(field('alternatives', alias($._nalts, $.alternatives))),
|
|
246
|
+
),
|
|
247
|
+
|
|
248
|
+
_exp_multi_way_if: $ => seq(
|
|
249
|
+
'if',
|
|
250
|
+
$._cmd_layout_start_if,
|
|
251
|
+
repeat(field('match', $.match)),
|
|
252
|
+
$._cond_layout_end,
|
|
253
|
+
),
|
|
254
|
+
|
|
255
|
+
// ------------------------------------------------------------------------
|
|
256
|
+
// record
|
|
257
|
+
// ------------------------------------------------------------------------
|
|
258
|
+
|
|
259
|
+
field_update: $ => choice(
|
|
260
|
+
alias('..', $.wildcard),
|
|
261
|
+
seq(
|
|
262
|
+
field('field', $._field_spec),
|
|
263
|
+
optional(seq('=', field('expression', $._exp)))
|
|
264
|
+
),
|
|
265
|
+
),
|
|
266
|
+
|
|
267
|
+
_exp_record: $ => prec('record', seq(
|
|
268
|
+
field('expression', $.expression),
|
|
269
|
+
braces($, sep(',', field('field', $.field_update)))),
|
|
270
|
+
),
|
|
271
|
+
|
|
272
|
+
_exp_projection_selector: $ => parens(
|
|
273
|
+
$,
|
|
274
|
+
$._any_prefix_dot,
|
|
275
|
+
field('field', $.variable),
|
|
276
|
+
repeat(seq($._tight_dot, field('field', $.variable))),
|
|
277
|
+
),
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* A dot-syntax field projection like `var.name.othername`.
|
|
281
|
+
*/
|
|
282
|
+
_exp_projection: $ => seq(
|
|
283
|
+
prec('projection', seq(
|
|
284
|
+
field('expression', $.expression),
|
|
285
|
+
$._tight_dot,
|
|
286
|
+
)),
|
|
287
|
+
field('field', $.field_name),
|
|
288
|
+
),
|
|
289
|
+
|
|
290
|
+
// ------------------------------------------------------------------------
|
|
291
|
+
// application
|
|
292
|
+
// ------------------------------------------------------------------------
|
|
293
|
+
|
|
294
|
+
explicit_type: $ => parens($, 'type', field('type', $.type)),
|
|
295
|
+
|
|
296
|
+
_exp_apply: $ => prec.left('apply', seq(
|
|
297
|
+
field('function', $.expression),
|
|
298
|
+
field('argument', choice(
|
|
299
|
+
$.expression,
|
|
300
|
+
alias($._at_type, $.type_application),
|
|
301
|
+
$.explicit_type,
|
|
302
|
+
)),
|
|
303
|
+
)),
|
|
304
|
+
|
|
305
|
+
// ------------------------------------------------------------------------
|
|
306
|
+
// operators
|
|
307
|
+
// ------------------------------------------------------------------------
|
|
308
|
+
|
|
309
|
+
_exp_op: $ => choice(
|
|
310
|
+
$._sym,
|
|
311
|
+
$._op_ticked,
|
|
312
|
+
alias($._prefix_dot, $.operator),
|
|
313
|
+
),
|
|
314
|
+
|
|
315
|
+
_exp_section_left: $ => parens(
|
|
316
|
+
$,
|
|
317
|
+
field('left_operand', $.expression),
|
|
318
|
+
$._cond_left_section_op,
|
|
319
|
+
field('operator', choice(
|
|
320
|
+
$._exp_op,
|
|
321
|
+
$._operator_minus,
|
|
322
|
+
$._qsym,
|
|
323
|
+
)),
|
|
324
|
+
),
|
|
325
|
+
|
|
326
|
+
_exp_section_right: $ => parens(
|
|
327
|
+
$,
|
|
328
|
+
choice(
|
|
329
|
+
alias($._operator_qual_dot_head, $.operator),
|
|
330
|
+
$._ops,
|
|
331
|
+
),
|
|
332
|
+
field('right_operand', $.expression),
|
|
333
|
+
),
|
|
334
|
+
|
|
335
|
+
_exp_negation: $ => seq(
|
|
336
|
+
field('minus', '-'),
|
|
337
|
+
prec('negation', field('expression', $.expression)),
|
|
338
|
+
),
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Infix expressions have severe conflicts with several structures:
|
|
342
|
+
*
|
|
343
|
+
* - Negation is supposed to bind less tight than application and tighter than infix, which requires an unsolvable
|
|
344
|
+
* precedence configuration
|
|
345
|
+
* - Qualified operators cannot be identified with single-token lookahead, which causes ambiguity with function
|
|
346
|
+
* application
|
|
347
|
+
* - Left operator sections require infix expressions in their operand to reduce before the section operator, but
|
|
348
|
+
* single-token lookahead also makes this decision impossible
|
|
349
|
+
*
|
|
350
|
+
* All of these are solved with external symbols.
|
|
351
|
+
* Consult `grammar/externals.js` for more information.
|
|
352
|
+
*/
|
|
353
|
+
_exp_infix: $ => prec.right('infix', seq(
|
|
354
|
+
field('left_operand', $.expression),
|
|
355
|
+
optional($._cond_no_section_op),
|
|
356
|
+
field('operator', choice(
|
|
357
|
+
seq($._cond_minus, $._operator_minus),
|
|
358
|
+
$._exp_op,
|
|
359
|
+
seq($._cond_qualified_op, $._qsym),
|
|
360
|
+
)),
|
|
361
|
+
field('right_operand', $.expression),
|
|
362
|
+
)),
|
|
363
|
+
|
|
364
|
+
// ------------------------------------------------------------------------
|
|
365
|
+
// top level
|
|
366
|
+
// ------------------------------------------------------------------------
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* This is a supertype.
|
|
370
|
+
*/
|
|
371
|
+
expression: $ => choice(
|
|
372
|
+
alias($._exp_infix, $.infix),
|
|
373
|
+
alias($._exp_negation, $.negation),
|
|
374
|
+
alias($._exp_apply, $.apply),
|
|
375
|
+
alias($._exp_record, $.record),
|
|
376
|
+
alias($._exp_projection, $.projection),
|
|
377
|
+
alias($._exp_arithmetic_sequence, $.arithmetic_sequence),
|
|
378
|
+
alias($._exp_list_comprehension, $.list_comprehension),
|
|
379
|
+
alias($._exp_unboxed_tuple, $.unboxed_tuple),
|
|
380
|
+
alias($._exp_unboxed_sum, $.unboxed_sum),
|
|
381
|
+
alias($._exp_projection_selector, $.projection_selector),
|
|
382
|
+
alias($._exp_quote, $.quote),
|
|
383
|
+
alias($._exp_typed_quote, $.typed_quote),
|
|
384
|
+
alias($._exp_th_quoted_name, $.th_quoted_name),
|
|
385
|
+
alias($._exp_lambda_case, $.lambda_case),
|
|
386
|
+
alias($._exp_lambda_cases, $.lambda_cases),
|
|
387
|
+
alias($._exp_do, $.do),
|
|
388
|
+
alias($._exp_parens, $.parens),
|
|
389
|
+
alias($._exp_tuple, $.tuple),
|
|
390
|
+
alias($._exp_list, $.list),
|
|
391
|
+
// Not using a name like "empty list" here because it's only really special in types.
|
|
392
|
+
alias($._plist, $.list),
|
|
393
|
+
alias($._exp_section_left, $.left_section),
|
|
394
|
+
alias($._exp_section_right, $.right_section),
|
|
395
|
+
$._exp_greedy,
|
|
396
|
+
alias($._exp_case, $.case),
|
|
397
|
+
alias($._exp_multi_way_if, $.multi_way_if),
|
|
398
|
+
$._exp_name,
|
|
399
|
+
$._universal,
|
|
400
|
+
),
|
|
401
|
+
|
|
402
|
+
_exp_signature: $ => prec.right('annotated', seq(
|
|
403
|
+
field('expression', $.expression),
|
|
404
|
+
$._type_annotation,
|
|
405
|
+
)),
|
|
406
|
+
|
|
407
|
+
_exp: $ => choice(
|
|
408
|
+
alias($._exp_signature, $.signature),
|
|
409
|
+
// Right-associative means that the reduction of `expression` to `_exp` loses against any shift.
|
|
410
|
+
prec.right($.expression),
|
|
411
|
+
),
|
|
412
|
+
|
|
413
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* These rules are handled manually by the custom lexer in `src/scanner.c`.
|
|
5
|
+
* Whenever the symbols are used in the rule tree, the parser executes the scanner.
|
|
6
|
+
* Since several symbols are present both here and in `extras`, the scanner will be invoked before every single
|
|
7
|
+
* natively lexed symbol, repeatedly, until it fails.
|
|
8
|
+
* This makes indentation/layout tracking simpler.
|
|
9
|
+
*
|
|
10
|
+
* There are three special behavioral classes of symbols in this grammar, indicated by their name prefix:
|
|
11
|
+
*
|
|
12
|
+
* `cmd`: Commands are sequenced after key tokens like opening braces that unconditionally trigger a state change in
|
|
13
|
+
* the scanner.
|
|
14
|
+
* They don't require the scanner to _decide_ that a symbol is valid – the native parser has already committed
|
|
15
|
+
* to a symbol, and the command relays that information to the scanner so it can update its state and return.
|
|
16
|
+
* For example, after having parsed an opening brace, the scanner adds a brace context to the stack in reaction
|
|
17
|
+
* to `_cond_brace_open`, which will influence its future behavior.
|
|
18
|
+
* These symbols do not produce nodes in the parse tree.
|
|
19
|
+
*
|
|
20
|
+
* `cond`: Conditions are hard requirements in the grammar that are decided by the scanner based on its state and the
|
|
21
|
+
* lookahead.
|
|
22
|
+
* For example, whitespace-sensitive operators (tight infix /prefix ops) like the `@` in a type application or
|
|
23
|
+
* the `.` in a record projection are lexed when the following characters have certain properties.
|
|
24
|
+
* When the scanner decides that such a symbol is valid, the parser cannot attempt to use an alternative
|
|
25
|
+
* interpretation like it can with conflicts.
|
|
26
|
+
* This is often difficult, but also especially useful to force declarations and other layout items to be
|
|
27
|
+
* terminated when a new line has smaller or equal indent, preventing incorrect interpretations as top level
|
|
28
|
+
* expression splices spanning multiple lines.
|
|
29
|
+
*
|
|
30
|
+
* `phantom`: Phantom symbols are used to signal to the scanner that certain constructs are valid without requiring
|
|
31
|
+
* the scanner to actually parse them and produce text nodes for them.
|
|
32
|
+
* In the grammar, they are always optional, and the scanner never emits the phantom symbol itself, but
|
|
33
|
+
* decides whether to emit _other_ symbols when the phantom symbol is _not_ valid.
|
|
34
|
+
* This is used to implement GHC's tactic of allowing layouts to end _whenever a parse error occurs_, but
|
|
35
|
+
* using specialized heuristics.
|
|
36
|
+
*
|
|
37
|
+
* Most other symbols produce nodes, except for newline and the error sentinel.
|
|
38
|
+
*/
|
|
39
|
+
externals: $ => [
|
|
40
|
+
|
|
41
|
+
// This is an unused symbol that indicates to the scanner that a parse error has occurred.
|
|
42
|
+
// Tree-sitter marks _all_ symbols as valid when calling the scanner after an error, so a symbol that's not used in
|
|
43
|
+
// the grammar is only valid if that is the case.
|
|
44
|
+
$.error_sentinel,
|
|
45
|
+
|
|
46
|
+
// Emitted after every newline with equal or less indent to terminate layout-based rules, with a few exceptions.
|
|
47
|
+
$._cond_layout_semicolon,
|
|
48
|
+
|
|
49
|
+
// Instruct the scanner to push a layout context.
|
|
50
|
+
// The first one is for declarations and miscellaneous other layouts.
|
|
51
|
+
// The others are for the specific syntax construct.
|
|
52
|
+
// The quote layout is for declaration quotes (`[d|data A ...|]`).
|
|
53
|
+
$._cmd_layout_start,
|
|
54
|
+
$._cmd_layout_start_do,
|
|
55
|
+
$._cmd_layout_start_case,
|
|
56
|
+
$._cmd_layout_start_if,
|
|
57
|
+
$._cmd_layout_start_let,
|
|
58
|
+
$._cmd_layout_start_quote,
|
|
59
|
+
// This variant is used in a `choice` with the others, and serves only to create a terminal node for explicit
|
|
60
|
+
// braces.
|
|
61
|
+
// If the scanner emitted the same symbol for virtual and explicit braces, we would either get an anonymous node
|
|
62
|
+
// ranging over the brace, or a terminal brace node even for virtual starts if we were to alias the symbol to '{'
|
|
63
|
+
// unconditionally.
|
|
64
|
+
// So we use separate symbols and alias only this one.
|
|
65
|
+
// The same reasoning applies to `_cond_layout_end_explicit`.
|
|
66
|
+
// The terminal could be ensured in different ways – adding an `optional('{')` after the start symbol, using
|
|
67
|
+
// `seq($._cmd_layout_start_explicit, '{')` instead of including the brace in the scanner range, or branching the
|
|
68
|
+
// entire layout on the start token to unconditionally use `_cmd_brace_close` instead of
|
|
69
|
+
// `_cond_layout_end_explicit`.
|
|
70
|
+
// However, these solutions are all very expensive, adding between 500 and 1000kB to the shared object size, and up
|
|
71
|
+
// to a second in generation time.
|
|
72
|
+
$._cmd_layout_start_explicit,
|
|
73
|
+
|
|
74
|
+
// Emitted when a new line's indent mandates ending the current layout (depending on the layout sort), or when a
|
|
75
|
+
// special inline layout-ending token is encountered, like an `in`.
|
|
76
|
+
$._cond_layout_end,
|
|
77
|
+
$._cond_layout_end_explicit,
|
|
78
|
+
|
|
79
|
+
// Instruct the scanner to push or pop a brace context.
|
|
80
|
+
$._cmd_brace_open,
|
|
81
|
+
$._cmd_brace_close,
|
|
82
|
+
|
|
83
|
+
// Instruct the scanner to push or pop a tuple expression context.
|
|
84
|
+
// In parenthesized or bracketed expressions, certain tokens (like commas, bars, and closing brackets), can end
|
|
85
|
+
// layouts, so the scanner must be aware of them.
|
|
86
|
+
$._cmd_texp_start,
|
|
87
|
+
$._cmd_texp_end,
|
|
88
|
+
|
|
89
|
+
// Signal to the scanner that these symbols are valid.
|
|
90
|
+
// See the explanation of phantom symbols above.
|
|
91
|
+
$._phantom_where,
|
|
92
|
+
$._phantom_in,
|
|
93
|
+
$._phantom_arrow,
|
|
94
|
+
$._phantom_bar,
|
|
95
|
+
$._phantom_deriving,
|
|
96
|
+
|
|
97
|
+
// Detect and emit text nodes for comments and CPP.
|
|
98
|
+
// In particular, #else branches of CPP conditionals a fully contained in the resulting node, since their nonlinear
|
|
99
|
+
// nature means they cannot be parsed.
|
|
100
|
+
$.comment,
|
|
101
|
+
$.haddock,
|
|
102
|
+
$.cpp,
|
|
103
|
+
$.pragma,
|
|
104
|
+
|
|
105
|
+
// Starting quote brackets are a bit messy, so it's easier to let the scanner signal that it encountered one.
|
|
106
|
+
// The body produces a text node until the ending bracket.
|
|
107
|
+
$._cond_quote_start,
|
|
108
|
+
$.quasiquote_body,
|
|
109
|
+
|
|
110
|
+
// Whitespace-sensitive operators for splices (`$`, `$$`), projection and module dots (`a.b`, `A.b`), arithmetic
|
|
111
|
+
// sequence dots `[1..10]`, as-pattern (`a@(Just b)`), type application (`@Int`), strictness and laziness
|
|
112
|
+
// annotations (`!pat`, `~Int`), and modifiers (`Int %1 -> Int`).
|
|
113
|
+
$._cond_splice,
|
|
114
|
+
$._cond_qual_dot,
|
|
115
|
+
$._cond_tight_dot,
|
|
116
|
+
$._cond_prefix_dot,
|
|
117
|
+
$._cond_dotdot,
|
|
118
|
+
$._cond_tight_at,
|
|
119
|
+
$._cond_prefix_at,
|
|
120
|
+
$._cond_tight_bang,
|
|
121
|
+
$._cond_prefix_bang,
|
|
122
|
+
$._cond_tight_tilde,
|
|
123
|
+
$._cond_prefix_tilde,
|
|
124
|
+
$._cond_prefix_percent,
|
|
125
|
+
|
|
126
|
+
// GHC lexes all qualified names as atomic tokens, but we can't do that because we need nodes for their
|
|
127
|
+
// substructures.
|
|
128
|
+
// However, infix expressions need single-token lookahead for the operator to resolve conflicts, which is
|
|
129
|
+
// impossible without an external.
|
|
130
|
+
// This symbol detects a qualified symbolic operator.
|
|
131
|
+
$._cond_qualified_op,
|
|
132
|
+
// This one performs an additional lookahead check for a following closing parenthesis, to disambiguate left
|
|
133
|
+
// sections from infix ops in `(a - b +)`.
|
|
134
|
+
$._cond_left_section_op,
|
|
135
|
+
// This is an auxiliary for `_cond_left_section_op` that allows restarting the scanner without that symbol being
|
|
136
|
+
// valid again when whitespace was skipped after a symop to discover that there's no parenthesis.
|
|
137
|
+
// Without this, we would get wrong token ranges for the operator.
|
|
138
|
+
$._cond_no_section_op,
|
|
139
|
+
|
|
140
|
+
// This symbol always succeeds when a minus is ahead.
|
|
141
|
+
// Infix expressions with minus as the operator conflict with function application.
|
|
142
|
+
// `a - b` can be parsed as `a (- b)`, which would normally be solved by a simple precedence entry, but is
|
|
143
|
+
// impossible to express because it contradicts another conflict: Negation in the left operand, `- a + b`, which
|
|
144
|
+
// must be parsed as `(- a) + b`.
|
|
145
|
+
// Simply sequencing this external before the operator solves this conflict, because a minus following an expression
|
|
146
|
+
// can never be negation; it can only occur at the beginning of an expression.
|
|
147
|
+
$._cond_minus,
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The following symbols perform lookahead for various type constructs to resolve conflicts between infix types,
|
|
151
|
+
* contexts, and type/datacon heads, because using GLR conflicts for these is very brittle and frequently leads to
|
|
152
|
+
* misparsed trees.
|
|
153
|
+
*
|
|
154
|
+
* See the documentation under 'Constraints' in `src/scanner.c` for more.
|
|
155
|
+
*/
|
|
156
|
+
$._cond_context,
|
|
157
|
+
$._cond_infix,
|
|
158
|
+
$._cond_data_infix,
|
|
159
|
+
$._cond_assoc_tyinst,
|
|
160
|
+
|
|
161
|
+
// Symbolic operators, producing text nodes.
|
|
162
|
+
// These are very difficult to parse in the grammar, because unlike most languages, Haskell's operators are not a
|
|
163
|
+
// finite set, and therefore cannot be lexically disambiguated from special operators like `->`.
|
|
164
|
+
// In the presence of runtime conflicts, this can easily lead to the invalid interpretation of reserved operators as
|
|
165
|
+
// identifiers.
|
|
166
|
+
// Furthermore, the regexes for all the unicode categories produce very large ternary operator trees if specified
|
|
167
|
+
// in the grammar.
|
|
168
|
+
$._varsym,
|
|
169
|
+
$._consym,
|
|
170
|
+
|
|
171
|
+
// The newline is used as a dummy symbol that is emitted whenever the scanner has to update its state even though
|
|
172
|
+
// the current position must be parsed by the grammar.
|
|
173
|
+
token(prec(0, /\n/)),
|
|
174
|
+
|
|
175
|
+
],
|
|
176
|
+
|
|
177
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const {
|
|
2
|
+
sep1,
|
|
3
|
+
layout_sort,
|
|
4
|
+
} = require('./util.js')
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
|
|
8
|
+
// ------------------------------------------------------------------------
|
|
9
|
+
// guard
|
|
10
|
+
// ------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
generator: $ => seq(
|
|
13
|
+
field('pattern', $._pat),
|
|
14
|
+
field('arrow', $._larrow),
|
|
15
|
+
field('expression', $._exp),
|
|
16
|
+
),
|
|
17
|
+
|
|
18
|
+
_let_binds: $ => layout_sort($, $._cmd_layout_start_let, field('decl', $.decl)),
|
|
19
|
+
|
|
20
|
+
_let: $ => seq('let', optional(field('binds', alias($._let_binds, $.local_binds)))),
|
|
21
|
+
|
|
22
|
+
let: $ => $._let,
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This is a supertype.
|
|
26
|
+
*/
|
|
27
|
+
guard: $ => choice(
|
|
28
|
+
// Cannot be named `pattern` because name clash.
|
|
29
|
+
alias($.generator, $.pattern_guard),
|
|
30
|
+
$.let,
|
|
31
|
+
alias($._exp, $.boolean),
|
|
32
|
+
),
|
|
33
|
+
|
|
34
|
+
guards: $ => sep1(',', field('guard', $.guard)),
|
|
35
|
+
|
|
36
|
+
_guards: $ => seq(
|
|
37
|
+
$._bar,
|
|
38
|
+
$._cmd_texp_start,
|
|
39
|
+
field('guards', $.guards),
|
|
40
|
+
),
|
|
41
|
+
|
|
42
|
+
// ------------------------------------------------------------------------
|
|
43
|
+
// rules shared by expression, pattern, type
|
|
44
|
+
// ------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
_universal: $ => choice(
|
|
47
|
+
$.splice,
|
|
48
|
+
$.quasiquote,
|
|
49
|
+
$.literal,
|
|
50
|
+
$._unit_cons,
|
|
51
|
+
$._tuple_cons,
|
|
52
|
+
),
|
|
53
|
+
|
|
54
|
+
}
|