Commit ba74af2ae8

Techatrix <techatrix@mailbox.org>
2025-02-24 18:24:59
std.zig.Ast: update doc comments of `Node.Tag`
The existing comment are incomplete, outdated and sometimes incorrect.
1 parent ca6fb30
Changed files (1)
lib
std
lib/std/zig/Ast.zig
@@ -3052,480 +3052,893 @@ pub const Node = struct {
         }
     }
 
-    /// Note: The FooComma/FooSemicolon variants exist to ease the implementation of
-    /// Ast.lastToken()
+    /// The FooComma/FooSemicolon variants exist to ease the implementation of
+    /// `Ast.lastToken()`
     pub const Tag = enum {
-        /// sub_list[lhs...rhs]
+        /// The root node which is guaranteed to be at `Node.Index.root`.
+        /// The meaning of the `data` field depends on whether it is a `.zig` or
+        /// `.zon` file.
+        ///
+        /// The `main_token` field is the first token for the source file.
         root,
-        /// `usingnamespace lhs;`. rhs unused. main_token is `usingnamespace`.
+        /// `usingnamespace expr;`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `usingnamespace` token.
         @"usingnamespace",
-        /// lhs is test name token (must be string literal or identifier), if any.
-        /// rhs is the body node.
+        /// `test {}`,
+        /// `test "name" {}`,
+        /// `test identifier {}`.
+        ///
+        /// The `data` field is a `.opt_token_and_node`:
+        ///   1. a `OptionalTokenIndex` to the test name token (must be string literal or identifier), if any.
+        ///   2. a `Node.Index` to the block.
+        ///
+        /// The `main_token` field is the `test` token.
         test_decl,
-        /// lhs is the index into extra_data.
-        /// rhs is the initialization expression, if any.
-        /// main_token is `var` or `const`.
+        /// The `data` field is a `.extra_and_opt_node`:
+        ///   1. a `ExtraIndex` to `GlobalVarDecl`.
+        ///   2. a `Node.OptionalIndex` to the initialization expression.
+        ///
+        /// The `main_token` field is the `var` or `const` token.
+        ///
+        /// The initialization expression can't be `.none` unless it is part of
+        /// a `assign_destructure` node or a parsing error occured.
         global_var_decl,
-        /// `var a: x align(y) = rhs`
-        /// lhs is the index into extra_data.
-        /// main_token is `var` or `const`.
+        /// `var a: b align(c) = d`.
+        /// `const main_token: type_node align(align_node) = init_expr`.
+        ///
+        /// The `data` field is a `.extra_and_opt_node`:
+        ///   1. a `ExtraIndex` to `LocalVarDecl`.
+        ///   2. a `Node.OptionalIndex` to the initialization expression-
+        ///
+        /// The `main_token` field is the `var` or `const` token.
+        ///
+        /// The initialization expression can't be `.none` unless it is part of
+        /// a `assign_destructure` node or a parsing error occured.
         local_var_decl,
-        /// `var a: lhs = rhs`. lhs and rhs may be unused.
+        /// `var a: b = c`.
+        /// `const name_token: type_expr = init_expr`.
         /// Can be local or global.
-        /// main_token is `var` or `const`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the type expression, if any.
+        ///   2. a `Node.OptionalIndex` to the initialization expression.
+        ///
+        /// The `main_token` field is the `var` or `const` token.
+        ///
+        /// The initialization expression can't be `.none` unless it is part of
+        /// a `assign_destructure` node or a parsing error occured.
         simple_var_decl,
-        /// `var a align(lhs) = rhs`. lhs and rhs may be unused.
+        /// `var a align(b) = c`.
+        /// `const name_token align(align_expr) = init_expr`.
         /// Can be local or global.
-        /// main_token is `var` or `const`.
+        ///
+        /// The `data` field is a `.node_and_opt_node`:
+        ///   1. a `Node.Index` to the alignment expression.
+        ///   2. a `Node.OptionalIndex` to the initialization expression.
+        ///
+        /// The `main_token` field is the `var` or `const` token.
+        ///
+        /// The initialization expression can't be `.none` unless it is part of
+        /// a `assign_destructure` node or a parsing error occured.
         aligned_var_decl,
-        /// lhs is the identifier token payload if any,
-        /// rhs is the deferred expression.
+        /// `errdefer expr`,
+        /// `errdefer |payload| expr`.
+        ///
+        /// The `data` field is a `.opt_token_and_node`:
+        ///   1. a `OptionalTokenIndex` to the payload identifier, if any.
+        ///   2. a `Node.Index` to the deferred expression.
+        ///
+        /// The `main_token` field is the `errdefer` token.
         @"errdefer",
-        /// lhs is unused.
-        /// rhs is the deferred expression.
+        /// `defer expr`.
+        ///
+        /// The `data` field is a `.node` to the deferred expression.
+        ///
+        /// The `main_token` field is the `defer`.
         @"defer",
-        /// lhs catch rhs
-        /// lhs catch |err| rhs
-        /// main_token is the `catch` keyword.
-        /// payload is determined by looking at the next token after the `catch` keyword.
+        /// `lhs catch rhs`,
+        /// `lhs catch |err| rhs`.
+        ///
+        /// The `main_token` field is the `catch` token.
+        ///
+        /// The error payload is determined by looking at the next token after
+        /// the `catch` token.
         @"catch",
-        /// `lhs.a`. main_token is the dot. rhs is the identifier token index.
+        /// `lhs.a`.
+        ///
+        /// The `data` field is a `.node_and_token`:
+        ///   1. a `Node.Index` to the left side of the field access.
+        ///   2. a `TokenIndex` to the field name identifier.
+        ///
+        /// The `main_token` field is the `.` token.
         field_access,
-        /// `lhs.?`. main_token is the dot. rhs is the `?` token index.
+        /// `lhs.?`.
+        ///
+        /// The `data` field is a `.node_and_token`:
+        ///   1. a `Node.Index` to the left side of the optional unwrap.
+        ///   2. a `TokenIndex` to the `?` token.
+        ///
+        /// The `main_token` field is the `.` token.
         unwrap_optional,
-        /// `lhs == rhs`. main_token is op.
+        /// `lhs == rhs`. The `main_token` field is the `==` token.
         equal_equal,
-        /// `lhs != rhs`. main_token is op.
+        /// `lhs != rhs`. The `main_token` field is the `!=` token.
         bang_equal,
-        /// `lhs < rhs`. main_token is op.
+        /// `lhs < rhs`. The `main_token` field is the `<` token.
         less_than,
-        /// `lhs > rhs`. main_token is op.
+        /// `lhs > rhs`. The `main_token` field is the `>` token.
         greater_than,
-        /// `lhs <= rhs`. main_token is op.
+        /// `lhs <= rhs`. The `main_token` field is the `<=` token.
         less_or_equal,
-        /// `lhs >= rhs`. main_token is op.
+        /// `lhs >= rhs`. The `main_token` field is the `>=` token.
         greater_or_equal,
-        /// `lhs *= rhs`. main_token is op.
+        /// `lhs *= rhs`. The `main_token` field is the `*=` token.
         assign_mul,
-        /// `lhs /= rhs`. main_token is op.
+        /// `lhs /= rhs`. The `main_token` field is the `/=` token.
         assign_div,
-        /// `lhs %= rhs`. main_token is op.
+        /// `lhs %= rhs`. The `main_token` field is the `%=` token.
         assign_mod,
-        /// `lhs += rhs`. main_token is op.
+        /// `lhs += rhs`. The `main_token` field is the `+=` token.
         assign_add,
-        /// `lhs -= rhs`. main_token is op.
+        /// `lhs -= rhs`. The `main_token` field is the `-=` token.
         assign_sub,
-        /// `lhs <<= rhs`. main_token is op.
+        /// `lhs <<= rhs`. The `main_token` field is the `<<=` token.
         assign_shl,
-        /// `lhs <<|= rhs`. main_token is op.
+        /// `lhs <<|= rhs`. The `main_token` field is the `<<|=` token.
         assign_shl_sat,
-        /// `lhs >>= rhs`. main_token is op.
+        /// `lhs >>= rhs`. The `main_token` field is the `>>=` token.
         assign_shr,
-        /// `lhs &= rhs`. main_token is op.
+        /// `lhs &= rhs`. The `main_token` field is the `&=` token.
         assign_bit_and,
-        /// `lhs ^= rhs`. main_token is op.
+        /// `lhs ^= rhs`. The `main_token` field is the `^=` token.
         assign_bit_xor,
-        /// `lhs |= rhs`. main_token is op.
+        /// `lhs |= rhs`. The `main_token` field is the `|=` token.
         assign_bit_or,
-        /// `lhs *%= rhs`. main_token is op.
+        /// `lhs *%= rhs`. The `main_token` field is the `*%=` token.
         assign_mul_wrap,
-        /// `lhs +%= rhs`. main_token is op.
+        /// `lhs +%= rhs`. The `main_token` field is the `+%=` token.
         assign_add_wrap,
-        /// `lhs -%= rhs`. main_token is op.
+        /// `lhs -%= rhs`. The `main_token` field is the `-%=` token.
         assign_sub_wrap,
-        /// `lhs *|= rhs`. main_token is op.
+        /// `lhs *|= rhs`. The `main_token` field is the `*%=` token.
         assign_mul_sat,
-        /// `lhs +|= rhs`. main_token is op.
+        /// `lhs +|= rhs`. The `main_token` field is the `+|=` token.
         assign_add_sat,
-        /// `lhs -|= rhs`. main_token is op.
+        /// `lhs -|= rhs`. The `main_token` field is the `-|=` token.
         assign_sub_sat,
-        /// `lhs = rhs`. main_token is op.
+        /// `lhs = rhs`. The `main_token` field is the `=` token.
         assign,
-        /// `a, b, ... = rhs`. main_token is op. lhs is index into `extra_data`
-        /// of an lhs elem count followed by an array of that many `Node.Index`,
-        /// with each node having one of the following types:
-        /// * `global_var_decl`
-        /// * `local_var_decl`
-        /// * `simple_var_decl`
-        /// * `aligned_var_decl`
-        /// * Any expression node
-        /// The first 3 types correspond to a `var` or `const` lhs node (note
-        /// that their `rhs` is always 0). An expression node corresponds to a
-        /// standard assignment LHS (which must be evaluated as an lvalue).
-        /// There may be a preceding `comptime` token, which does not create a
-        /// corresponding `comptime` node so must be manually detected.
+        /// `a, b, ... = rhs`.
+        ///
+        /// The `data` field is a `.extra_and_node`:
+        ///   1. a `ExtraIndex`. Further explained below.
+        ///   2. a `Node.Index` to the initialization expression.
+        ///
+        /// The `main_token` field is the `=` token.
+        ///
+        /// The `ExtraIndex` stores the following data:
+        /// ```
+        /// elem_count: u32,
+        /// variables: [elem_count]Node.Index,
+        /// ```
+        ///
+        /// Each node in `variables` has one of the following tags:
+        ///   - `global_var_decl`
+        ///   - `local_var_decl`
+        ///   - `simple_var_decl`
+        ///   - `aligned_var_decl`
+        ///   - Any expression node
+        ///
+        /// The first 4 tags correspond to a `var` or `const` lhs node (note
+        /// that their initialization expression is always `.none`).
+        /// An expression node corresponds to a standard assignment LHS (which
+        /// must be evaluated as an lvalue). There may be a preceding
+        /// `comptime` token, which does not create a corresponding `comptime`
+        /// node so must be manually detected.
         assign_destructure,
-        /// `lhs || rhs`. main_token is the `||`.
+        /// `lhs || rhs`. The `main_token` field is the `||` token.
         merge_error_sets,
-        /// `lhs * rhs`. main_token is the `*`.
+        /// `lhs * rhs`. The `main_token` field is the `*` token.
         mul,
-        /// `lhs / rhs`. main_token is the `/`.
+        /// `lhs / rhs`. The `main_token` field is the `/` token.
         div,
-        /// `lhs % rhs`. main_token is the `%`.
+        /// `lhs % rhs`. The `main_token` field is the `%` token.
         mod,
-        /// `lhs ** rhs`. main_token is the `**`.
+        /// `lhs ** rhs`. The `main_token` field is the `**` token.
         array_mult,
-        /// `lhs *% rhs`. main_token is the `*%`.
+        /// `lhs *% rhs`. The `main_token` field is the `*%` token.
         mul_wrap,
-        /// `lhs *| rhs`. main_token is the `*|`.
+        /// `lhs *| rhs`. The `main_token` field is the `*|` token.
         mul_sat,
-        /// `lhs + rhs`. main_token is the `+`.
+        /// `lhs + rhs`. The `main_token` field is the `+` token.
         add,
-        /// `lhs - rhs`. main_token is the `-`.
+        /// `lhs - rhs`. The `main_token` field is the `-` token.
         sub,
-        /// `lhs ++ rhs`. main_token is the `++`.
+        /// `lhs ++ rhs`. The `main_token` field is the `++` token.
         array_cat,
-        /// `lhs +% rhs`. main_token is the `+%`.
+        /// `lhs +% rhs`. The `main_token` field is the `+%` token.
         add_wrap,
-        /// `lhs -% rhs`. main_token is the `-%`.
+        /// `lhs -% rhs`. The `main_token` field is the `-%` token.
         sub_wrap,
-        /// `lhs +| rhs`. main_token is the `+|`.
+        /// `lhs +| rhs`. The `main_token` field is the `+|` token.
         add_sat,
-        /// `lhs -| rhs`. main_token is the `-|`.
+        /// `lhs -| rhs`. The `main_token` field is the `-|` token.
         sub_sat,
-        /// `lhs << rhs`. main_token is the `<<`.
+        /// `lhs << rhs`. The `main_token` field is the `<<` token.
         shl,
-        /// `lhs <<| rhs`. main_token is the `<<|`.
+        /// `lhs <<| rhs`. The `main_token` field is the `<<|` token.
         shl_sat,
-        /// `lhs >> rhs`. main_token is the `>>`.
+        /// `lhs >> rhs`. The `main_token` field is the `>>` token.
         shr,
-        /// `lhs & rhs`. main_token is the `&`.
+        /// `lhs & rhs`. The `main_token` field is the `&` token.
         bit_and,
-        /// `lhs ^ rhs`. main_token is the `^`.
+        /// `lhs ^ rhs`. The `main_token` field is the `^` token.
         bit_xor,
-        /// `lhs | rhs`. main_token is the `|`.
+        /// `lhs | rhs`. The `main_token` field is the `|` token.
         bit_or,
-        /// `lhs orelse rhs`. main_token is the `orelse`.
+        /// `lhs orelse rhs`. The `main_token` field is the `orelse` token.
         @"orelse",
-        /// `lhs and rhs`. main_token is the `and`.
+        /// `lhs and rhs`. The `main_token` field is the `and` token.
         bool_and,
-        /// `lhs or rhs`. main_token is the `or`.
+        /// `lhs or rhs`. The `main_token` field is the `or` token.
         bool_or,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `!expr`. The `main_token` field is the `!` token.
         bool_not,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `-expr`. The `main_token` field is the `-` token.
         negation,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `~expr`. The `main_token` field is the `~` token.
         bit_not,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `-%expr`. The `main_token` field is the `-%` token.
         negation_wrap,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `&expr`. The `main_token` field is the `&` token.
         address_of,
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `try expr`. The `main_token` field is the `try` token.
         @"try",
-        /// `op lhs`. rhs unused. main_token is op.
+        /// `await expr`. The `main_token` field is the `await` token.
         @"await",
-        /// `?lhs`. rhs unused. main_token is the `?`.
+        /// `?expr`. The `main_token` field is the `?` token.
         optional_type,
-        /// `[lhs]rhs`.
+        /// `[lhs]rhs`. The `main_token` field is the `[` token.
         array_type,
-        /// `[lhs:a]b`. `ArrayTypeSentinel[rhs]`.
+        /// `[lhs:a]b`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the length expression.
+        ///   2. a `ExtraIndex` to `ArrayTypeSentinel`.
+        ///
+        /// The `main_token` field is the `[` token.
         array_type_sentinel,
-        /// `[*]align(lhs) rhs`. lhs can be omitted.
-        /// `*align(lhs) rhs`. lhs can be omitted.
+        /// `[*]align(lhs) rhs`,
+        /// `*align(lhs) rhs`,
         /// `[]rhs`.
-        /// main_token is the asterisk if a single item pointer or the lbracket
-        /// if a slice, many-item pointer, or C-pointer
-        /// main_token might be a ** token, which is shared with a parent/child
-        /// pointer type and may require special handling.
+        ///
+        /// The `data` field is a `.opt_node_and_node`:
+        ///   1. a `Node.OptionalIndex` to the alignment expression, if any.
+        ///   2. a `Node.Index` to the element type expression.
+        ///
+        /// The `main_token` is the asterisk if a single item pointer or the
+        /// lbracket if a slice, many-item pointer, or C-pointer.
+        /// The `main_token` might be a ** token, which is shared with a
+        /// parent/child pointer type and may require special handling.
         ptr_type_aligned,
-        /// `[*:lhs]rhs`. lhs can be omitted.
-        /// `*rhs`.
+        /// `[*:lhs]rhs`,
+        /// `*rhs`,
         /// `[:lhs]rhs`.
-        /// main_token is the asterisk if a single item pointer or the lbracket
-        /// if a slice, many-item pointer, or C-pointer
-        /// main_token might be a ** token, which is shared with a parent/child
-        /// pointer type and may require special handling.
+        ///
+        /// The `data` field is a `.opt_node_and_node`:
+        ///   1. a `Node.OptionalIndex` to the sentinel expression, if any.
+        ///   2. a `Node.Index` to the element type expression.
+        ///
+        /// The `main_token` is the asterisk if a single item pointer or the
+        /// lbracket if a slice, many-item pointer, or C-pointer.
+        /// The `main_token` might be a ** token, which is shared with a
+        /// parent/child pointer type and may require special handling.
         ptr_type_sentinel,
-        /// lhs is index into ptr_type. rhs is the element type expression.
-        /// main_token is the asterisk if a single item pointer or the lbracket
-        /// if a slice, many-item pointer, or C-pointer
-        /// main_token might be a ** token, which is shared with a parent/child
-        /// pointer type and may require special handling.
+        /// The `data` field is a `.opt_node_and_node`:
+        ///   1. a `ExtraIndex` to `PtrType`.
+        ///   2. a `Node.Index` to the element type expression.
+        ///
+        /// The `main_token` is the asterisk if a single item pointer or the
+        /// lbracket if a slice, many-item pointer, or C-pointer.
+        /// The `main_token` might be a ** token, which is shared with a
+        /// parent/child pointer type and may require special handling.
         ptr_type,
-        /// lhs is index into ptr_type_bit_range. rhs is the element type expression.
-        /// main_token is the asterisk if a single item pointer or the lbracket
-        /// if a slice, many-item pointer, or C-pointer
-        /// main_token might be a ** token, which is shared with a parent/child
-        /// pointer type and may require special handling.
+        /// The `data` field is a `.opt_node_and_node`:
+        ///   1. a `ExtraIndex` to `PtrTypeBitRange`.
+        ///   2. a `Node.Index` to the element type expression.
+        ///
+        /// The `main_token` is the asterisk if a single item pointer or the
+        /// lbracket if a slice, many-item pointer, or C-pointer.
+        /// The `main_token` might be a ** token, which is shared with a
+        /// parent/child pointer type and may require special handling.
         ptr_type_bit_range,
         /// `lhs[rhs..]`
-        /// main_token is the lbracket.
+        ///
+        /// The `main_token` field is the `[` token.
         slice_open,
-        /// `lhs[b..c]`. rhs is index into Slice
-        /// main_token is the lbracket.
+        /// `sliced[start..end]`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the sliced expression.
+        ///   2. a `ExtraIndex` to `Slice`.
+        ///
+        /// The `main_token` field is the `[` token.
         slice,
-        /// `lhs[b..c :d]`. rhs is index into SliceSentinel. Slice end "c" can be omitted.
-        /// main_token is the lbracket.
+        /// `sliced[start..end :sentinel]`,
+        /// `sliced[start.. :sentinel]`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the sliced expression.
+        ///   2. a `ExtraIndex` to `SliceSentinel`.
+        ///
+        /// The `main_token` field is the `[` token.
         slice_sentinel,
-        /// `lhs.*`. rhs is unused.
+        /// `expr.*`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `*` token.
         deref,
         /// `lhs[rhs]`.
+        ///
+        /// The `main_token` field is the `[` token.
         array_access,
-        /// `lhs{rhs}`. rhs can be omitted.
+        /// `lhs{rhs}`.
+        ///
+        /// The `main_token` field is the `{` token.
         array_init_one,
-        /// `lhs{rhs,}`. rhs can *not* be omitted
+        /// Same as `array_init_one` except there is known to be a trailing
+        /// comma before the final rbrace.
         array_init_one_comma,
-        /// `.{lhs, rhs}`. lhs and rhs can be omitted.
+        /// `.{a}`,
+        /// `.{a, b}`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first element. Never `.none`
+        ///   2. a `Node.OptionalIndex` to the second element, if any.
+        ///
+        /// The `main_token` field is the `{` token.
         array_init_dot_two,
-        /// Same as `array_init_dot_two` except there is known to be a trailing comma
-        /// before the final rbrace.
+        /// Same as `array_init_dot_two` except there is known to be a trailing
+        /// comma before the final rbrace.
         array_init_dot_two_comma,
-        /// `.{a, b}`. `sub_list[lhs..rhs]`.
+        /// `.{a, b, c}`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each element.
+        ///
+        /// The `main_token` field is the `{` token.
         array_init_dot,
-        /// Same as `array_init_dot` except there is known to be a trailing comma
-        /// before the final rbrace.
+        /// Same as `array_init_dot` except there is known to be a trailing
+        /// comma before the final rbrace.
         array_init_dot_comma,
-        /// `lhs{a, b}`. `sub_range_list[rhs]`. lhs can be omitted which means `.{a, b}`.
+        /// `a{b, c}`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the type expression.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each element.
+        ///
+        /// The `main_token` field is the `{` token.
         array_init,
         /// Same as `array_init` except there is known to be a trailing comma
         /// before the final rbrace.
         array_init_comma,
-        /// `lhs{.a = rhs}`. rhs can be omitted making it empty.
-        /// main_token is the lbrace.
+        /// `a{.x = b}`, `a{}`.
+        ///
+        /// The `data` field is a `.node_and_opt_node`:
+        ///   1. a `Node.Index` to the type expression.
+        ///   2. a `Node.OptionalIndex` to the first field initialization, if any.
+        ///
+        /// The `main_token` field is the `{` token.
+        ///
+        /// The field name is determined by looking at the tokens preceding the
+        /// field initialization.
         struct_init_one,
-        /// `lhs{.a = rhs,}`. rhs can *not* be omitted.
-        /// main_token is the lbrace.
+        /// Same as `struct_init_one` except there is known to be a trailing comma
+        /// before the final rbrace.
         struct_init_one_comma,
-        /// `.{.a = lhs, .b = rhs}`. lhs and rhs can be omitted.
-        /// main_token is the lbrace.
-        /// No trailing comma before the rbrace.
+        /// `.{.x = a, .y = b}`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first field initialization. Never `.none`
+        ///   2. a `Node.OptionalIndex` to the second field initialization, if any.
+        ///
+        /// The `main_token` field is the '{' token.
+        ///
+        /// The field name is determined by looking at the tokens preceding the
+        /// field initialization.
         struct_init_dot_two,
-        /// Same as `struct_init_dot_two` except there is known to be a trailing comma
-        /// before the final rbrace.
+        /// Same as `struct_init_dot_two` except there is known to be a trailing
+        /// comma before the final rbrace.
         struct_init_dot_two_comma,
-        /// `.{.a = b, .c = d}`. `sub_list[lhs..rhs]`.
-        /// main_token is the lbrace.
+        /// `.{.x = a, .y = b, .z = c}`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each field initialization.
+        ///
+        /// The `main_token` field is the `{` token.
+        ///
+        /// The field name is determined by looking at the tokens preceding the
+        /// field initialization.
         struct_init_dot,
-        /// Same as `struct_init_dot` except there is known to be a trailing comma
-        /// before the final rbrace.
+        /// Same as `struct_init_dot` except there is known to be a trailing
+        /// comma before the final rbrace.
         struct_init_dot_comma,
-        /// `lhs{.a = b, .c = d}`. `sub_range_list[rhs]`.
-        /// lhs can be omitted which means `.{.a = b, .c = d}`.
-        /// main_token is the lbrace.
+        /// `a{.x = b, .y = c}`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the type expression.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each field initialization.
+        ///
+        /// The `main_token` field is the `{` token.
+        ///
+        /// The field name is determined by looking at the tokens preceding the
+        /// field initialization.
         struct_init,
         /// Same as `struct_init` except there is known to be a trailing comma
         /// before the final rbrace.
         struct_init_comma,
-        /// `lhs(rhs)`. rhs can be omitted.
-        /// main_token is the lparen.
+        /// `a(b)`, `a()`.
+        ///
+        /// The `data` field is a `.node_and_opt_node`:
+        ///   1. a `Node.Index` to the function expression.
+        ///   2. a `Node.OptionalIndex` to the first argument, if any.
+        ///
+        /// The `main_token` field is the `(` token.
         call_one,
-        /// `lhs(rhs,)`. rhs can be omitted.
-        /// main_token is the lparen.
+        /// Same as `call_one` except there is known to be a trailing comma
+        /// before the final rparen.
         call_one_comma,
-        /// `async lhs(rhs)`. rhs can be omitted.
+        /// `async a(b)`, `async a()`.
+        ///
+        /// The `data` field is a `.node_and_opt_node`:
+        ///   1. a `Node.Index` to the function expression.
+        ///   2. a `Node.OptionalIndex` to the first argument, if any.
+        ///
+        /// The `main_token` field is the `(` token.
         async_call_one,
-        /// `async lhs(rhs,)`.
+        /// Same as `async_call_one` except there is known to be a trailing
+        /// comma before the final rparen.
         async_call_one_comma,
-        /// `lhs(a, b, c)`. `SubRange[rhs]`.
-        /// main_token is the `(`.
+        /// `a(b, c, d)`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the function expression.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each argument.
+        ///
+        /// The `main_token` field is the `(` token.
         call,
-        /// `lhs(a, b, c,)`. `SubRange[rhs]`.
-        /// main_token is the `(`.
+        /// Same as `call` except there is known to be a trailing comma before
+        /// the final rparen.
         call_comma,
-        /// `async lhs(a, b, c)`. `SubRange[rhs]`.
-        /// main_token is the `(`.
+        /// `async a(b, c, d)`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the function expression.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each argument.
+        ///
+        /// The `main_token` field is the `(` token.
         async_call,
-        /// `async lhs(a, b, c,)`. `SubRange[rhs]`.
-        /// main_token is the `(`.
+        /// Same as `async_call` except there is known to be a trailing comma
+        /// before the final rparen.
         async_call_comma,
-        /// `switch(lhs) {}`. `SubRange[rhs]`.
-        /// `main_token` is the identifier of a preceding label, if any; otherwise `switch`.
+        /// `switch(a) {}`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the switch operand.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each switch case.
+        ///
+        /// `The `main_token` field` is the identifier of a preceding label, if any; otherwise `switch`.
         @"switch",
-        /// Same as switch except there is known to be a trailing comma
-        /// before the final rbrace
+        /// Same as `switch` except there is known to be a trailing comma before
+        /// the final rbrace.
         switch_comma,
-        /// `lhs => rhs`. If lhs is omitted it means `else`.
-        /// main_token is the `=>`
+        /// `a => b`,
+        /// `else => b`.
+        ///
+        /// The `data` field is a `.opt_node_and_node`:
+        ///   1. a `Node.OptionalIndex` where `.none` means `else`.
+        ///   2. a `Node.Index` to the target expression.
+        ///
+        /// The `main_token` field is the `=>` token.
         switch_case_one,
-        /// Same ast `switch_case_one` but the case is inline
+        /// Same as `switch_case_one` but the case is inline.
         switch_case_inline_one,
-        /// `a, b, c => rhs`. `SubRange[lhs]`.
-        /// main_token is the `=>`
+        /// `a, b, c => d`.
+        ///
+        /// The `data` field is a `.extra_and_node`:
+        ///   1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each switch item.
+        ///   2. a `Node.Index` to the target expression.
+        ///
+        /// The `main_token` field is the `=>` token.
         switch_case,
-        /// Same ast `switch_case` but the case is inline
+        /// Same as `switch_case` but the case is inline.
         switch_case_inline,
         /// `lhs...rhs`.
+        ///
+        /// The `main_token` field is the `...` token.
         switch_range,
-        /// `while (lhs) rhs`.
-        /// `while (lhs) |x| rhs`.
+        /// `while (a) b`,
+        /// `while (a) |x| b`.
         while_simple,
-        /// `while (lhs) : (a) b`. `WhileCont[rhs]`.
-        /// `while (lhs) : (a) b`. `WhileCont[rhs]`.
+        /// `while (a) : (b) c`,
+        /// `while (a) |x| : (b) c`.
         while_cont,
-        /// `while (lhs) : (a) b else c`. `While[rhs]`.
-        /// `while (lhs) |x| : (a) b else c`. `While[rhs]`.
-        /// `while (lhs) |x| : (a) b else |y| c`. `While[rhs]`.
-        /// The cont expression part `: (a)` may be omitted.
+        /// `while (a) : (b) c else d`,
+        /// `while (a) |x| : (b) c else d`,
+        /// `while (a) |x| : (b) c else |y| d`.
+        /// The continue expression part `: (b)` may be omitted.
         @"while",
-        /// `for (lhs) rhs`.
+        /// `for (a) b`.
         for_simple,
         /// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`.
         @"for",
-        /// `lhs..rhs`. rhs can be omitted.
+        /// `lhs..rhs`, `lhs..`.
         for_range,
-        /// `if (lhs) rhs`.
-        /// `if (lhs) |a| rhs`.
+        /// `if (a) b`.
+        /// `if (b) |x| b`.
         if_simple,
-        /// `if (lhs) a else b`. `If[rhs]`.
-        /// `if (lhs) |x| a else b`. `If[rhs]`.
-        /// `if (lhs) |x| a else |y| b`. `If[rhs]`.
+        /// `if (a) b else c`.
+        /// `if (a) |x| b else c`.
+        /// `if (a) |x| b else |y| d`.
         @"if",
-        /// `suspend lhs`. lhs can be omitted. rhs is unused.
+        /// `suspend expr`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `suspend` token.
         @"suspend",
-        /// `resume lhs`. rhs is unused.
+        /// `resume expr`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `resume` token.
         @"resume",
-        /// `continue :lhs rhs`
-        /// both lhs and rhs may be omitted.
+        /// `continue :label expr`,
+        /// `continue expr`,
+        /// `continue :label`,
+        /// `continue`.
+        ///
+        /// The `data` field is a `.opt_token_and_opt_node`:
+        ///   1. a `OptionalTokenIndex` to the label identifier, if any.
+        ///   2. a `Node.OptionalIndex` to the target expression, if any.
+        ///
+        /// The `main_token` field is the `continue` token.
         @"continue",
-        /// `break :lhs rhs`
-        /// both lhs and rhs may be omitted.
+        /// `break :label expr`,
+        /// `break expr`,
+        /// `break :label`,
+        /// `break`.
+        ///
+        /// The `data` field is a `.opt_token_and_opt_node`:
+        ///   1. a `OptionalTokenIndex` to the label identifier, if any.
+        ///   2. a `Node.OptionalIndex` to the target expression, if any.
+        ///
+        /// The `main_token` field is the `break` token.
         @"break",
-        /// `return lhs`. lhs can be omitted. rhs is unused.
+        /// `return expr`, `return`.
+        ///
+        /// The `data` field is a `.opt_node` to the return value, if any.
+        ///
+        /// The `main_token` field is the `return` token.
         @"return",
-        /// `fn (a: lhs) rhs`. lhs can be omitted.
-        /// anytype and ... parameters are omitted from the AST tree.
-        /// main_token is the `fn` keyword.
-        /// extern function declarations use this tag.
+        /// `fn (a: type_expr) return_type`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first parameter type expression, if any.
+        ///   2. a `Node.OptionalIndex` to the return type expression. Can't be
+        ///      `.none` unless a parsing error occured.
+        ///
+        /// The `main_token` field is the `fn` token.
+        ///
+        /// `anytype` and `...` parameters are omitted from the AST tree.
+        /// Extern function declarations use this tag.
         fn_proto_simple,
-        /// `fn (a: b, c: d) rhs`. `sub_range_list[lhs]`.
-        /// anytype and ... parameters are omitted from the AST tree.
-        /// main_token is the `fn` keyword.
-        /// extern function declarations use this tag.
+        /// `fn (a: b, c: d) return_type`.
+        ///
+        /// The `data` field is a `.extra_and_opt_node`:
+        ///   1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each parameter type expression.
+        ///   2. a `Node.OptionalIndex` to the return type expression. Can't be
+        ///      `.none` unless a parsing error occured.
+        ///
+        /// The `main_token` field is the `fn` token.
+        ///
+        /// `anytype` and `...` parameters are omitted from the AST tree.
+        /// Extern function declarations use this tag.
         fn_proto_multi,
-        /// `fn (a: b) addrspace(e) linksection(f) callconv(g) rhs`. `FnProtoOne[lhs]`.
+        /// `fn (a: b) addrspace(e) linksection(f) callconv(g) return_type`.
         /// zero or one parameters.
-        /// anytype and ... parameters are omitted from the AST tree.
-        /// main_token is the `fn` keyword.
-        /// extern function declarations use this tag.
+        ///
+        /// The `data` field is a `.extra_and_opt_node`:
+        ///   1. a `Node.ExtraIndex` to `FnProtoOne`.
+        ///   2. a `Node.OptionalIndex` to the return type expression. Can't be
+        ///      `.none` unless a parsing error occured.
+        ///
+        /// The `main_token` field is the `fn` token.
+        ///
+        /// `anytype` and `...` parameters are omitted from the AST tree.
+        /// Extern function declarations use this tag.
         fn_proto_one,
-        /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) rhs`. `FnProto[lhs]`.
-        /// anytype and ... parameters are omitted from the AST tree.
-        /// main_token is the `fn` keyword.
-        /// extern function declarations use this tag.
+        /// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) return_type`.
+        ///
+        /// The `data` field is a `.extra_and_opt_node`:
+        ///   1. a `Node.ExtraIndex` to `FnProto`.
+        ///   2. a `Node.OptionalIndex` to the return type expression. Can't be
+        ///      `.none` unless a parsing error occured.
+        ///
+        /// The `main_token` field is the `fn` token.
+        ///
+        /// `anytype` and `...` parameters are omitted from the AST tree.
+        /// Extern function declarations use this tag.
         fn_proto,
-        /// lhs is the fn_proto.
-        /// rhs is the function body block.
-        /// Note that extern function declarations use the fn_proto tags rather
-        /// than this one.
+        /// Extern function declarations use the fn_proto tags rather than this one.
+        ///
+        /// The `data` field is a `.node_and_node`:
+        ///   1. a `Node.Index` to `fn_proto_*`.
+        ///   2. a `Node.Index` to function body block.
+        ///
+        /// The `main_token` field is the `fn` token.
         fn_decl,
-        /// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index.
+        /// `anyframe->return_type`.
+        ///
+        /// The `data` field is a `.token_and_node`:
+        ///   1. a `TokenIndex` to the `->` token.
+        ///   2. a `Node.Index` to the function frame return type expression.
+        ///
+        /// The `main_token` field is the `anyframe` token.
         anyframe_type,
-        /// Both lhs and rhs unused.
+        /// The `data` field is unused.
         anyframe_literal,
-        /// Both lhs and rhs unused.
+        /// The `data` field is unused.
         char_literal,
-        /// Both lhs and rhs unused.
+        /// The `data` field is unused.
         number_literal,
-        /// Both lhs and rhs unused.
+        /// The `data` field is unused.
         unreachable_literal,
-        /// Both lhs and rhs unused.
-        /// Most identifiers will not have explicit AST nodes, however for expressions
-        /// which could be one of many different kinds of AST nodes, there will be an
-        /// identifier AST node for it.
+        /// The `data` field is unused.
+        ///
+        /// Most identifiers will not have explicit AST nodes, however for
+        /// expressions which could be one of many different kinds of AST nodes,
+        /// there will be an identifier AST node for it.
         identifier,
-        /// lhs is the dot token index, rhs unused, main_token is the identifier.
+        /// `.foo`.
+        ///
+        /// The `data` field is a `.token` to the `.`.
+        ///
+        /// The `main_token` field is the identifier.
         enum_literal,
-        /// main_token is the string literal token
-        /// Both lhs and rhs unused.
+        /// The `data` field is unused.
+        ///
+        /// The `main_token` field is the string literal token.
         string_literal,
-        /// main_token is the first token index (redundant with lhs)
-        /// lhs is the first token index; rhs is the last token index.
-        /// Could be a series of multiline_string_literal_line tokens, or a single
-        /// string_literal token.
+        /// The `data` field is a `.token_and_token`:
+        ///   1. a `TokenIndex` to the first `.multiline_string_literal_line` token.
+        ///   2. a `TokenIndex` to the last `.multiline_string_literal_line` token.
+        ///
+        /// The `main_token` field is the first token index (redundant with `data`).
         multiline_string_literal,
-        /// `(lhs)`. main_token is the `(`; rhs is the token index of the `)`.
+        /// `(expr)`.
+        ///
+        /// The `data` field is a `.node_and_token`:
+        ///   1. a `Node.Index` to the sub-expression
+        ///   2. a `TokenIndex` to the `)` token.
+        ///
+        /// The `main_token` field is the `(` token.
         grouped_expression,
-        /// `@a(lhs, rhs)`. lhs and rhs may be omitted.
-        /// main_token is the builtin token.
+        /// `@a(b, c)`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first argument, if any.
+        ///   2. a `Node.OptionalIndex` to the second argument, if any.
+        ///
+        /// The `main_token` field is the builtin token.
         builtin_call_two,
-        /// Same as builtin_call_two but there is known to be a trailing comma before the rparen.
+        /// Same as `builtin_call_two` except there is known to be a trailing comma
+        /// before the final rparen.
         builtin_call_two_comma,
-        /// `@a(b, c)`. `sub_list[lhs..rhs]`.
-        /// main_token is the builtin token.
+        /// `@a(b, c, d)`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each argument.
+        ///
+        /// The `main_token` field is the builtin token.
         builtin_call,
-        /// Same as builtin_call but there is known to be a trailing comma before the rparen.
+        /// Same as `builtin_call` except there is known to be a trailing comma
+        /// before the final rparen.
         builtin_call_comma,
         /// `error{a, b}`.
-        /// rhs is the rbrace, lhs is unused.
+        ///
+        /// The `data` field is a `.token` to the '}'.
+        ///
+        /// The `main_token` field is the `error`.
         error_set_decl,
-        /// `struct {}`, `union {}`, `opaque {}`, `enum {}`. `extra_data[lhs..rhs]`.
-        /// main_token is `struct`, `union`, `opaque`, `enum` keyword.
+        /// `struct {}`, `union {}`, `opaque {}`, `enum {}`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each container member.
+        ///
+        /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
         container_decl,
-        /// Same as ContainerDecl but there is known to be a trailing comma
-        /// or semicolon before the rbrace.
+        /// Same as `container_decl` except there is known to be a trailing
+        /// comma before the final rbrace.
         container_decl_trailing,
         /// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`.
-        /// lhs or rhs can be omitted.
-        /// main_token is `struct`, `union`, `opaque`, `enum` keyword.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first container member, if any.
+        ///   2. a `Node.OptionalIndex` to the second container member, if any.
+        ///
+        /// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
         container_decl_two,
-        /// Same as ContainerDeclTwo except there is known to be a trailing comma
-        /// or semicolon before the rbrace.
+        /// Same as `container_decl_two` except there is known to be a trailing
+        /// comma before the final rbrace.
         container_decl_two_trailing,
-        /// `struct(lhs)` / `union(lhs)` / `enum(lhs)`. `SubRange[rhs]`.
+        /// `struct(arg)`, `union(arg)`, `enum(arg)`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to arg.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each container member.
+        ///
+        /// The `main_token` field is the `struct`, `union` or `enum` token.
         container_decl_arg,
-        /// Same as container_decl_arg but there is known to be a trailing
-        /// comma or semicolon before the rbrace.
+        /// Same as `container_decl_arg` except there is known to be a trailing
+        /// comma before the final rbrace.
         container_decl_arg_trailing,
-        /// `union(enum) {}`. `sub_list[lhs..rhs]`.
-        /// Note that tagged unions with explicitly provided enums are represented
-        /// by `container_decl_arg`.
+        /// `union(enum) {}`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each container member.
+        ///
+        /// The `main_token` field is the `union` token.
+        ///
+        /// A tagged union with explicitly provided enums will instead be
+        /// represented by `container_decl_arg`.
         tagged_union,
-        /// Same as tagged_union but there is known to be a trailing comma
-        /// or semicolon before the rbrace.
+        /// Same as `tagged_union` except there is known to be a trailing comma
+        /// before the final rbrace.
         tagged_union_trailing,
-        /// `union(enum) {lhs, rhs}`. lhs or rhs may be omitted.
-        /// Note that tagged unions with explicitly provided enums are represented
-        /// by `container_decl_arg`.
+        /// `union(enum) {lhs, rhs}`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first container member, if any.
+        ///   2. a `Node.OptionalIndex` to the second container member, if any.
+        ///
+        /// The `main_token` field is the `union` token.
+        ///
+        /// A tagged union with explicitly provided enums will instead be
+        /// represented by `container_decl_arg`.
         tagged_union_two,
-        /// Same as tagged_union_two but there is known to be a trailing comma
-        /// or semicolon before the rbrace.
+        /// Same as `tagged_union_two` except there is known to be a trailing
+        /// comma before the final rbrace.
         tagged_union_two_trailing,
-        /// `union(enum(lhs)) {}`. `SubRange[rhs]`.
+        /// `union(enum(arg)) {}`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to arg.
+        ///   2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
+        ///      each container member.
+        ///
+        /// The `main_token` field is the `union` token.
         tagged_union_enum_tag,
-        /// Same as tagged_union_enum_tag but there is known to be a trailing comma
-        /// or semicolon before the rbrace.
+        /// Same as `tagged_union_enum_tag` except there is known to be a
+        /// trailing comma before the final rbrace.
         tagged_union_enum_tag_trailing,
-        /// `a: lhs = rhs,`. lhs and rhs can be omitted.
-        /// main_token is the field name identifier.
-        /// lastToken() does not include the possible trailing comma.
+        /// `a: lhs = rhs,`,
+        /// `a: lhs,`.
+        ///
+        /// The `data` field is a `.node_and_opt_node`:
+        ///   1. a `Node.Index` to the field type expression.
+        ///   2. a `Node.OptionalIndex` to the default value expression, if any.
+        ///
+        /// The `main_token` field is the field name identifier.
+        ///
+        /// `lastToken()` does not include the possible trailing comma.
         container_field_init,
-        /// `a: lhs align(rhs),`. rhs can be omitted.
-        /// main_token is the field name identifier.
-        /// lastToken() does not include the possible trailing comma.
+        /// `a: lhs align(rhs),`.
+        ///
+        /// The `data` field is a `.node_and_node`:
+        ///   1. a `Node.Index` to the field type expression.
+        ///   2. a `Node.Index` to the alignment expression.
+        ///
+        /// The `main_token` field is the field name identifier.
+        ///
+        /// `lastToken()` does not include the possible trailing comma.
         container_field_align,
-        /// `a: lhs align(c) = d,`. `container_field_list[rhs]`.
-        /// main_token is the field name identifier.
-        /// lastToken() does not include the possible trailing comma.
+        /// `a: lhs align(c) = d,`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to the field type expression.
+        ///   2. a `ExtraIndex` to `ContainerField`.
+        ///
+        /// The `main_token` field is the field name identifier.
+        ///
+        /// `lastToken()` does not include the possible trailing comma.
         container_field,
-        /// `comptime lhs`. rhs unused.
+        /// `comptime expr`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `comptime` token.
         @"comptime",
-        /// `nosuspend lhs`. rhs unused.
+        /// `nosuspend expr`.
+        ///
+        /// The `data` field is a `.node` to expr.
+        ///
+        /// The `main_token` field is the `nosuspend` token.
         @"nosuspend",
-        /// `{lhs rhs}`. rhs or lhs can be omitted.
-        /// main_token points at the lbrace.
+        /// `{lhs rhs}`.
+        ///
+        /// The `data` field is a `.opt_node_and_opt_node`:
+        ///   1. a `Node.OptionalIndex` to the first statement, if any.
+        ///   2. a `Node.OptionalIndex` to the second statement, if any.
+        ///
+        /// The `main_token` field is the `{` token.
         block_two,
-        /// Same as block_two but there is known to be a semicolon before the rbrace.
+        /// Same as `block_two_semicolon` except there is known to be a trailing
+        /// comma before the final rbrace.
         block_two_semicolon,
-        /// `{}`. `sub_list[lhs..rhs]`.
-        /// main_token points at the lbrace.
+        /// `{a b}`.
+        ///
+        /// The `data` field is a `.extra_range` that stores a `Node.Index` for
+        /// each statement.
+        ///
+        /// The `main_token` field is the `{` token.
         block,
-        /// Same as block but there is known to be a semicolon before the rbrace.
+        /// Same as `block` except there is known to be a trailing comma before
+        /// the final rbrace.
         block_semicolon,
-        /// `asm(lhs)`. rhs is the token index of the rparen.
+        /// `asm(lhs)`.
+        ///
+        /// rhs is a `Token.Index` to the `)` token.
+        /// The `main_token` field is the `asm` token.
         asm_simple,
-        /// `asm(lhs, a)`. `Asm[rhs]`.
+        /// `asm(lhs, a)`.
+        ///
+        /// The `data` field is a `.node_and_extra`:
+        ///   1. a `Node.Index` to lhs.
+        ///   2. a `ExtraIndex` to `Asm`.
+        ///
+        /// The `main_token` field is the `asm` token.
         @"asm",
-        /// `[a] "b" (c)`. lhs is 0, rhs is token index of the rparen.
-        /// `[a] "b" (-> lhs)`. rhs is token index of the rparen.
-        /// main_token is `a`.
+        /// `[a] "b" (c)`.
+        /// `[a] "b" (-> lhs)`.
+        ///
+        /// The `data` field is a `.opt_node_and_token`:
+        ///   1. a `Node.OptionalIndex` to lhs, if any.
+        ///   2. a `TokenIndex` to the `)` token.
+        ///
+        /// The `main_token` field is `a`.
         asm_output,
-        /// `[a] "b" (lhs)`. rhs is token index of the rparen.
-        /// main_token is `a`.
+        /// `[a] "b" (lhs)`.
+        ///
+        /// The `data` field is a `.node_and_token`:
+        ///   1. a `Node.Index` to lhs.
+        ///   2. a `TokenIndex` to the `)` token.
+        ///
+        /// The `main_token` field is `a`.
         asm_input,
-        /// `error.a`. lhs is token index of `.`. rhs is token index of `a`.
+        /// `error.a`.
+        ///
+        /// The `data` field is a `.opt_token_and_opt_token`:
+        ///   1. a `OptionalTokenIndex` of `.`. Can't be `.none` unless a parsing error occured.
+        ///   2. a `OptionalTokenIndex` of `a`. Can't be `.none` unless a parsing error occured.
+        ///
+        /// The `main_token` field is `error` token.
         error_value,
-        /// `lhs!rhs`. main_token is the `!`.
+        /// `lhs!rhs`.
+        ///
+        /// The `main_token` field is the `!` token.
         error_union,
 
         pub fn isContainerField(tag: Tag) bool {