Skip to content

Commit a326186

Browse files
committed
create terminals for explicit layout braces
1 parent f9f5e9b commit a326186

File tree

8 files changed

+263248
-259620
lines changed

8 files changed

+263248
-259620
lines changed

grammar.js

+15
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,25 @@ module.exports = grammar({
8686
$._cmd_layout_start_if,
8787
$._cmd_layout_start_let,
8888
$._cmd_layout_start_quote,
89+
// This variant is used in a `choice` with the others, and serves only to create a terminal node for explicit
90+
// braces.
91+
// If the scanner emitted the same symbol for virtual and explicit braces, we would either get an anonymous node
92+
// ranging over the brace, or a terminal brace node even for virtual starts if we were to alias the symbol to '{'
93+
// unconditionally.
94+
// So we use separate symbols and alias only this one.
95+
// The same reasoning applies to `_cond_layout_end_explicit`.
96+
// The terminal could be ensured in different ways – adding an `optional('{')` after the start symbol, using
97+
// `seq($._cmd_layout_start_explicit, '{')` instead of including the brace in the scanner range, or branching the
98+
// entire layout on the start token to unconditionally use `_cmd_brace_close` instead of
99+
// `_cond_layout_end_explicit`.
100+
// However, these solutions are all very expensive, adding between 500 and 1000kB to the shared object size, and up
101+
// to a second in generation time.
102+
$._cmd_layout_start_explicit,
89103

90104
// Emitted when a new line's indent mandates ending the current layout (depending on the layout sort), or when a
91105
// special inline layout-ending token is encountered, like an `in`.
92106
$._cond_layout_end,
107+
$._cond_layout_end_explicit,
93108

94109
// Instruct the scanner to push or pop a brace context.
95110
$._cmd_brace_open,

grammar/module.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,16 @@ module.exports = {
6262
declarations: $ => seq(semis($, $._topdecl), semi_opt($)),
6363

6464
_body: $ => seq(
65-
$._cmd_layout_start,
65+
choice($._cmd_layout_start, alias($._cmd_layout_start_explicit, '{')),
6666
semi_opt($),
6767
field('imports', optional($.imports)),
6868
field('declarations', optional($.declarations)),
69+
$._layout_end,
70+
),
71+
72+
_layout_end: $ => choice(
6973
$._cond_layout_end,
74+
alias($._cond_layout_end_explicit, '}'),
7075
),
7176

7277
}

grammar/util.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ semis = ($, rule) => sep1(semi($), rule),
3333
/**
3434
* Wrap a repeated rule in a layout.
3535
* This is used for `where`, `let`, `of`, `if` and `do`, and the toplevel module.
36-
* The `start` rule must be one of the externals starting with `_cond_layout_<type>`, which instruct the scanner to push
36+
* The `start` rule must be one of the externals starting with `_cmd_layout_<type>`, which instruct the scanner to push
3737
* a layout context with the current column as its indentation.
3838
* When a `_cond_layout_end` or `_cond_layout_semicolon` is encountered by the scanner, the recorded indent is compared
3939
* to the current one to make a decision.
4040
*/
4141
layout_sort = ($, start, rule) => seq(
42-
start,
42+
choice(start, alias($._cmd_layout_start_explicit, '{')),
4343
optional(seq(
4444
semi_opt($),
4545
semis($, rule),
4646
semi_opt($),
4747
)),
48-
$._cond_layout_end,
48+
$._layout_end,
4949
),
5050

5151
/**
52-
* Alias of `layout_sort` using the common layout type for the start token, which corresponds to declarations and GADT
52+
* Alias for `layout_sort` using the common layout type for the start token, which corresponds to declarations and GADT
5353
* constructors.
5454
*/
5555
layout = ($, rule) => layout_sort($, $._cmd_layout_start, rule)

0 commit comments

Comments
 (0)