@willbooster/tree-sitter-haskell 0.0.0-placeholder.0 → 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/grammar/pat.js ADDED
@@ -0,0 +1,149 @@
1
+ const {
2
+ sep1,
3
+ sep2,
4
+ sep,
5
+ parens,
6
+ braces,
7
+ brackets,
8
+ unboxed_tuple_full,
9
+ unboxed_sum_single,
10
+ } = require('./util.js')
11
+
12
+ module.exports = {
13
+
14
+ // ------------------------------------------------------------------------
15
+ // tuples and parens
16
+ // ------------------------------------------------------------------------
17
+
18
+ _pat_parens: $ => parens($, field('pattern', $._pat_texp)),
19
+
20
+ _pat_tuple_elems: $ => sep2(',', field('element', $._pat_texp)),
21
+
22
+ _pat_tuple: $ => parens($, $._pat_tuple_elems),
23
+
24
+ _pat_unboxed_tuple: $ => unboxed_tuple_full($, $._pat_texp),
25
+
26
+ _pat_unboxed_sum: $ => unboxed_sum_single($, $._pat_texp),
27
+
28
+ _pat_list: $ => brackets($, sep1(',', field('element', $._pat_texp)), optional(',')),
29
+
30
+ // ------------------------------------------------------------------------
31
+ // record
32
+ // ------------------------------------------------------------------------
33
+
34
+ field_pattern: $ => choice(
35
+ alias('..', $.wildcard),
36
+ seq(field('field', $._field_names), optional(seq('=', field('pattern', $._pat_texp)))),
37
+ ),
38
+
39
+ _pat_record: $ => prec('record', seq(
40
+ field('constructor', $.pattern),
41
+ braces($, sep(',', field('field', $.field_pattern))),
42
+ )),
43
+
44
+ // ------------------------------------------------------------------------
45
+ // misc
46
+ // ------------------------------------------------------------------------
47
+
48
+ /**
49
+ * This dynamic precedence penalty is relevant for the conflict between `function` and `bind`.
50
+ * Consider:
51
+ *
52
+ * > f (A a) = exp
53
+ *
54
+ * Because of the "single choice disambiguated with named precedences" approach used for `pattern`, the left node in
55
+ * `pat_apply` can be a variable, even though it's not valid Haskell.
56
+ * While the static prec 'pat-name' covers this at generation time, Haskell's ambiguity requires us to use a runtime
57
+ * conflict for `function`/`bind`, where static prec is ineffective.
58
+ * Giving the reduction of `_var` to `pattern` a strong negative dynamic prec ensures that the runtime branch for
59
+ * `bind` has lower precedence because of `f`, so `function` always wins.
60
+ *
61
+ * While `bind` usually has a lower score than `function` anyway in this situation because it is slightly more
62
+ * complex, there are never any guarantees for runtime conflicts.
63
+ * In particular, the presence of minor parse errors later in the declaration can tip the scales randomly.
64
+ */
65
+ _pat_name: $ => choice(
66
+ prec('pat-name', prec.dynamic(-1000, $._var)),
67
+ $._cons,
68
+ ),
69
+
70
+ _pat_as: $ => prec('prefix', seq(field('bind', $.variable), $._tight_at, field('pattern', $.pattern))),
71
+
72
+ _pat_wildcard: _ => '_',
73
+
74
+ _pat_strict: $ => prec('prefix', seq($._any_prefix_bang, field('pattern', $.pattern))),
75
+
76
+ _pat_irrefutable: $ => prec('prefix', seq($._any_prefix_tilde, field('pattern', $.pattern))),
77
+
78
+ // ------------------------------------------------------------------------
79
+ // application
80
+ // ------------------------------------------------------------------------
81
+
82
+ _pat_apply_arg: $ => choice(
83
+ $.pattern,
84
+ alias($._at_type, $.type_binder),
85
+ $.explicit_type,
86
+ ),
87
+
88
+ _pat_apply: $ => prec.left('apply', seq(
89
+ field('function', $.pattern),
90
+ field('argument', $._pat_apply_arg),
91
+ )),
92
+
93
+ // ------------------------------------------------------------------------
94
+ // operators
95
+ // ------------------------------------------------------------------------
96
+
97
+ _pat_negation: $ => seq('-', field('number', $._number)),
98
+
99
+ _pat_infix: $ => prec.right('infix', seq(
100
+ field('left_operand', $.pattern),
101
+ optional($._cond_no_section_op),
102
+ field('operator', choice(
103
+ $.constructor_operator,
104
+ $._conids_ticked,
105
+ seq($._cond_qualified_op, $._qconsym),
106
+ )),
107
+ field('right_operand', $.pattern),
108
+ )),
109
+
110
+ // ------------------------------------------------------------------------
111
+ // top level
112
+ // ------------------------------------------------------------------------
113
+
114
+ pattern: $ => choice(
115
+ alias($._pat_infix, $.infix),
116
+ alias($._pat_negation, $.negation),
117
+ alias($._pat_apply, $.apply),
118
+ $._pat_name,
119
+ alias($._pat_as, $.as),
120
+ alias($._pat_record, $.record),
121
+ alias($._pat_wildcard, $.wildcard),
122
+ alias($._pat_parens, $.parens),
123
+ alias($._pat_tuple, $.tuple),
124
+ alias($._pat_unboxed_tuple, $.unboxed_tuple),
125
+ alias($._pat_unboxed_sum, $.unboxed_sum),
126
+ alias($._pat_list, $.list),
127
+ alias($._plist, $.list),
128
+ alias($._pat_strict, $.strict),
129
+ alias($._pat_irrefutable, $.irrefutable),
130
+ $._universal,
131
+ ),
132
+
133
+ patterns: $ => repeat1(prec('patterns', $._pat_apply_arg)),
134
+
135
+ _pat_signature: $ => prec.right('annotated', seq(
136
+ field('pattern', $.pattern),
137
+ $._type_annotation,
138
+ )),
139
+
140
+ _pat: $ => choice(
141
+ alias($._pat_signature, $.signature),
142
+ prec.right($.pattern),
143
+ ),
144
+
145
+ view_pattern: $ => seq(field('expression', $._exp), $._arrow, field('pattern', $._pat_texp)),
146
+
147
+ _pat_texp: $ => choice($.view_pattern, $._pat),
148
+
149
+ }
@@ -0,0 +1,42 @@
1
+ const {
2
+ layout,
3
+ optional_where,
4
+ } = require('./util.js')
5
+
6
+ module.exports = {
7
+ // ------------------------------------------------------------------------
8
+ // pattern synonym
9
+ // ------------------------------------------------------------------------
10
+
11
+ _patsyn_signature: $ => seq(
12
+ field('synonym', choice($._con, alias($._con_binding_list, $.binding_list))),
13
+ $._colon2,
14
+ field('type', $.quantified_type),
15
+ ),
16
+
17
+ _patsyn_cons: $ => layout($, alias($.bind, $.constructor_synonym)),
18
+
19
+ /**
20
+ * This allows a `where` after any equation for parsing resilience, even though it's only valid for the arrow variant
21
+ * (explicitly bidirectional patterns).
22
+ * The `where` may also be empty.
23
+ */
24
+ _patsyn_equation: $ => seq(
25
+ field('synonym', $.pattern),
26
+ choice(
27
+ '=',
28
+ $._larrow,
29
+ ),
30
+ field('pattern', $._pat),
31
+ optional_where($, field('constructors', alias($._patsyn_cons, $.constructor_synonyms))),
32
+ ),
33
+
34
+ pattern_synonym: $ => seq(
35
+ 'pattern',
36
+ choice(
37
+ alias($._patsyn_signature, $.signature),
38
+ alias($._patsyn_equation, $.equation),
39
+ ),
40
+ ),
41
+
42
+ }
@@ -0,0 +1,109 @@
1
+ module.exports = {
2
+
3
+ precedences: $ => [
4
+
5
+ // ------------------------------------------------
6
+ // associativity of expressions, patterns and types
7
+ // ------------------------------------------------
8
+
9
+ [
10
+ 'projection',
11
+ 'record',
12
+ 'prefix',
13
+ 'apply',
14
+ 'negation',
15
+ 'infix',
16
+ 'implicit',
17
+ 'fun',
18
+ 'annotated',
19
+ $.quantified_type,
20
+ ],
21
+
22
+ // ------------------------------------------------
23
+ // negation
24
+ // ------------------------------------------------
25
+
26
+ [
27
+ $._pat_negation,
28
+ $.literal,
29
+ ],
30
+
31
+ // ------------------------------------------------
32
+ // function vs bind
33
+ // ------------------------------------------------
34
+
35
+ [
36
+ 'bind',
37
+ 'pat-name',
38
+ ],
39
+
40
+ // ------------------------------------------------
41
+ // qualified names
42
+ // ------------------------------------------------
43
+
44
+ /**
45
+ * Prioritize shifting over a tight infix dot over reducing to a qualified constructor or module.
46
+ */
47
+ [
48
+ 'qualifying-module',
49
+ 'qualified-id',
50
+ ],
51
+
52
+ /**
53
+ * Prioritize qualified variables over record field projection on constructors.
54
+ */
55
+ [
56
+ 'qualifying-module',
57
+ 'con',
58
+ ],
59
+
60
+ /**
61
+ * Prioritize qualified names over the infix operator dot in types.
62
+ */
63
+ [
64
+ 'qualifying-module',
65
+ 'type-name',
66
+ ],
67
+
68
+ // ------------------------------------------------
69
+ // types and constraints
70
+ // ------------------------------------------------
71
+
72
+ [
73
+ $.operator,
74
+ $._type_star,
75
+ ],
76
+
77
+ [
78
+ $._type_wildcard,
79
+ $._type_param_wildcard,
80
+ ],
81
+
82
+ [
83
+ $._constructor_ticked,
84
+ $._tycon_ticked,
85
+ ],
86
+
87
+ [
88
+ 'qtype-single',
89
+ 'qtype-curried',
90
+ ],
91
+
92
+ // ------------------------------------------------
93
+ // misc
94
+ // ------------------------------------------------
95
+
96
+ /**
97
+ * > f A a a = a
98
+ * > data A = A Int Int
99
+ *
100
+ * This should not be parsed as constructor application, but separate patterns.
101
+ */
102
+ [
103
+ 'patterns',
104
+ 'apply',
105
+ ],
106
+
107
+ ],
108
+
109
+ }
package/grammar/th.js ADDED
@@ -0,0 +1,82 @@
1
+ const {
2
+ layout_sort,
3
+ } = require('./util.js')
4
+
5
+ const quote_bracket = ($, quoter) => seq(
6
+ $._cond_quote_start,
7
+ '[',
8
+ field('quoter', quoter),
9
+ '|',
10
+ )
11
+
12
+ module.exports = {
13
+
14
+ // ------------------------------------------------------------------------
15
+ // splice
16
+ // ------------------------------------------------------------------------
17
+
18
+ /**
19
+ * Even though the doc states "arbitrary expression", it's very rare for any others than names and parenthesized
20
+ * expressions to occur, and it's very expensive to allow them.
21
+ * Even only allowing list and quotes adds a full megabyte to the parser size.
22
+ */
23
+ _splice_exp: $ => choice(
24
+ $._exp_name,
25
+ alias($._exp_parens, $.parens),
26
+ $.literal,
27
+ ),
28
+
29
+ _splice_dollars: $ => seq(
30
+ $._cond_splice,
31
+ choice('$', '$$'),
32
+ ),
33
+
34
+ splice: $ => seq($._splice_dollars, field('expression', $._splice_exp)),
35
+
36
+ /**
37
+ * Since `expression` includes `splice`, this allows for a top level dollar splice as well.
38
+ */
39
+ top_splice: $ => $.expression,
40
+
41
+ quoter: $ => $._varids,
42
+
43
+ /**
44
+ * `_cond_quote_start` (in `quote_bracket`) is a zero-width token emitted by the scanner.
45
+ * While the quoter and the bar may not be preceded by whitespace, this is not necessary to ensure here with
46
+ * `token.immediate` since the scanner already verifies it.
47
+ */
48
+ quasiquote: $ => seq(
49
+ quote_bracket($, $.quoter),
50
+ optional(field('body', $.quasiquote_body)),
51
+ choice(token('|]'), '⟧'),
52
+ ),
53
+
54
+ quoted_decls: $ => layout_sort($, $._cmd_layout_start_quote, field('declaration', $.declaration)),
55
+
56
+ /**
57
+ * An "expression quotation" is valid in an expression, and its body may contain an expression, type, pattern or
58
+ * declaration layout.
59
+ *
60
+ * Which of these are valid is decided by the quoter: `e`, `t`, `p` or `d`.
61
+ * If the quoter is empty, or the special oxford bracket character is used, the body is parsed as an expression.
62
+ */
63
+ _exp_quote: $ => seq(
64
+ choice(
65
+ seq(choice('⟦', quote_bracket($, optional('e'))), optional(alias($._exp, $.quoted_expression))),
66
+ seq(quote_bracket($, 't'), optional(alias($._ktype, $.quoted_type))),
67
+ seq(quote_bracket($, 'p'), optional(alias($._pat, $.quoted_pattern))),
68
+ seq(quote_bracket($, 'd'), optional($.quoted_decls)),
69
+ ),
70
+ choice(token('|]'), '⟧'),
71
+ ),
72
+
73
+ _exp_typed_quote: $ => seq(
74
+ $._cond_quote_start,
75
+ '[',
76
+ optional('e'),
77
+ '||',
78
+ optional(alias($._exp, $.quoted_expression)),
79
+ token('||]'),
80
+ ),
81
+
82
+ }