Line data Source code
1 : // wok_trivia -- comments, attached to the tree so the formatter can put them
2 : // back (design section 5).
3 : //
4 : // The scanner already collects comments into a side list. This pass decides
5 : // which ITEM each one belongs to: declaration, statement, handler clause,
6 : // case alternative -- the same granularity error recovery resynchronises to,
7 : // which is not a coincidence, it is the unit a reader thinks in.
8 : //
9 : // COMMENTS ARE NOT PART OF A PROGRAM'S IDENTITY. Two files differing only in
10 : // their comments are the same program, so a comment is never a slot, never in
11 : // the dump, and never in the hash the safety interlock compares. Putting one
12 : // there would make the interlock assert something false. Preservation is its
13 : // own property instead:
14 : //
15 : // comments(Format(t)) == comments(t) -- same texts, same order
16 : //
17 : // The storage costs nothing: WokNode already had four bytes of padding
18 : // between `nslots` and its 8-byte-aligned slot array, and that is exactly a
19 : // uint32 index into the side table below. A tree with no comments is byte for
20 : // byte the tree that existed before this file.
21 :
22 : #pragma once
23 :
24 : // The prelude comes FIRST: it carries the POSIX feature-test macros, which
25 : // have no effect once a system header has been read. wok_base.h hard-errors
26 : // if it is reached too late.
27 : #include "wok_base.h"
28 :
29 : #include <stddef.h>
30 : #include <stdint.h>
31 :
32 : #include "wok_arena.h"
33 : #include "wok_ast.h"
34 : #include "wok_token.h"
35 :
36 : // `lead_*` and `trail_*` are ranges into WokTrivia::comment. `blank_before` is
37 : // the author's paragraph break, capped at one: everything above one blank line
38 : // collapses, and the comment block counts as part of the item, so a blank line
39 : // ABOVE a leading comment is what is recorded.
40 : typedef struct {
41 : u32 lead_first, lead_n;
42 : u32 trail_first, trail_n;
43 : u8 blank_before;
44 : } WokTriviaEntry;
45 :
46 : typedef struct {
47 : WokTriviaEntry *entry; // entry[0] is a reserved empty sentinel, so a
48 : // node's `trivia == 0` can mean "none"
49 : u32 nentries;
50 : WokComment *comment;
51 : u32 ncomments;
52 : } WokTrivia;
53 :
54 : // Attaches `comments` to `file` and returns the table its `trivia` indices
55 : // index into. The table is also BOUND to `file`, so wok_print can find it
56 : // from the tree alone; see wok_trivia_of.
57 : const WokTrivia *wok_trivia_attach(WokNode *file, const char *src,
58 : usize src_len, const WokComment *comments,
59 : usize ncomments, WokArena *arena);
60 :
61 : // The table bound to `file`, or nullptr for a tree that never went through
62 : // wok_trivia_attach. A tree parsed with wok_parse (no scan result, so no
63 : // comments) answers nullptr and prints exactly as it did before.
64 : const WokTrivia *wok_trivia_of(const WokNode *file);
65 :
66 : // True when a node's TRAILING range holds the comments that close a block it
67 : // owns (rule 3) rather than a comment written after the item itself. The two
68 : // can never both apply to one node, and a printer that wrote the range in
69 : // both places would emit every such comment twice.
70 : bool wok_trivia_trail_closes_block(const WokNode *);
71 :
72 : // The entry for one node, or nullptr when it carries no trivia.
73 138315 : static inline const WokTriviaEntry *wok_trivia_lookup(const WokTrivia *t,
74 : const WokNode *n) {
75 138315 : if (t == nullptr || n->trivia == 0 || n->trivia >= t->nentries)
76 : return nullptr;
77 6845 : return &t->entry[n->trivia];
78 : }
79 :
|