Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

parseCurlySuffixExpr

Parse.parseCurlySuffixExpr
fn parseCurlySuffixExpr(p: *Parse) !?Node.Index

File

lib/std/zig/Parse.zig:2080

Code

fn parseCurlySuffixExpr(p: *Parse) !?Node.Index {
    const lhs = try p.parseTypeExpr() orelse return null;
    const lbrace = p.eatToken(.l_brace) orelse return lhs;

    // If there are 0 or 1 items, we can use ArrayInitOne/StructInitOne;
    // otherwise we use the full ArrayInit/StructInit.

    const scratch_top = p.scratch.items.len;
    defer p.scratch.shrinkRetainingCapacity(scratch_top);
    const opt_field_init = try p.parseFieldInit();
    if (opt_field_init) |field_init| {
        try p.scratch.append(p.gpa, field_init);
        while (true) {
            switch (p.tokenTag(p.tok_i)) {
                .comma => p.tok_i += 1,
                .r_brace => {
                    p.tok_i += 1;
                    break;
                },
                .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
                // Likely just a missing comma; give error but continue parsing.
                else => try p.warn(.expected_comma_after_initializer),
            }
            if (p.eatToken(.r_brace)) |_| break;
            const next = try p.expectFieldInit();
            try p.scratch.append(p.gpa, next);
        }
        const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
        const inits = p.scratch.items[scratch_top..];
        std.debug.assert(inits.len != 0);
        if (inits.len <= 1) {
            return try p.addNode(.{
                .tag = if (comma) .struct_init_one_comma else .struct_init_one,
                .main_token = lbrace,
                .data = .{ .node_and_opt_node = .{
                    lhs,
                    inits[0].toOptional(),
                } },
            });
        } else {
            return try p.addNode(.{
                .tag = if (comma) .struct_init_comma else .struct_init,
                .main_token = lbrace,
                .data = .{ .node_and_extra = .{
                    lhs,
                    try p.addExtra(try p.listToSpan(inits)),
                } },
            });
        }
    }

    while (true) {
        if (p.eatToken(.r_brace)) |_| break;
        const elem_init = try p.expectExpr();
        try p.scratch.append(p.gpa, elem_init);
        switch (p.tokenTag(p.tok_i)) {
            .comma => p.tok_i += 1,
            .r_brace => {
                p.tok_i += 1;
                break;
            },
            .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace),
            // Likely just a missing comma; give error but continue parsing.
            else => try p.warn(.expected_comma_after_initializer),
        }
    }
    const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
    const inits = p.scratch.items[scratch_top..];
    switch (inits.len) {
        0 => return try p.addNode(.{
            .tag = .struct_init_one,
            .main_token = lbrace,
            .data = .{ .node_and_opt_node = .{
                lhs,
                .none,
            } },
        }),
        1 => return try p.addNode(.{
            .tag = if (comma) .array_init_one_comma else .array_init_one,
            .main_token = lbrace,
            .data = .{ .node_and_node = .{
                lhs,
                inits[0],
            } },
        }),
        else => return try p.addNode(.{
            .tag = if (comma) .array_init_comma else .array_init,
            .main_token = lbrace,
            .data = .{ .node_and_extra = .{
                lhs,
                try p.addExtra(try p.listToSpan(inits)),
            } },
        }),
    }
}