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.

parsePrimaryTypeExpr

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

File

lib/std/zig/Parse.zig:2197

Code

fn parsePrimaryTypeExpr(p: *Parse) !?Node.Index {
    switch (p.tokenTag(p.tok_i)) {
        .char_literal => return try p.addNode(.{
            .tag = .char_literal,
            .main_token = p.nextToken(),
            .data = undefined,
        }),
        .number_literal => return try p.addNode(.{
            .tag = .number_literal,
            .main_token = p.nextToken(),
            .data = undefined,
        }),
        .keyword_unreachable => return try p.addNode(.{
            .tag = .unreachable_literal,
            .main_token = p.nextToken(),
            .data = undefined,
        }),
        .keyword_anyframe => return try p.addNode(.{
            .tag = .anyframe_literal,
            .main_token = p.nextToken(),
            .data = undefined,
        }),
        .string_literal => {
            const main_token = p.nextToken();
            return try p.addNode(.{
                .tag = .string_literal,
                .main_token = main_token,
                .data = undefined,
            });
        },

        .builtin => return try p.expectBuiltinCall(),
        .keyword_fn => return (try p.parseFnProto()).?,
        .keyword_if => return try p.expectIf(expectTypeExpr),
        .keyword_switch => return try p.expectSwitchExpr(false),

        .keyword_extern,
        .keyword_packed,
        => {
            p.tok_i += 1;
            return try p.expectContainerDeclAuto();
        },

        .keyword_struct,
        .keyword_opaque,
        .keyword_enum,
        .keyword_union,
        => return try p.expectContainerDeclAuto(),

        .keyword_comptime => return try p.addNode(.{
            .tag = .@"comptime",
            .main_token = p.nextToken(),
            .data = .{ .node = try p.expectTypeExpr() },
        }),
        .multiline_string_literal_line => {
            const first_line = p.nextToken();
            while (p.tokenTag(p.tok_i) == .multiline_string_literal_line) {
                p.tok_i += 1;
            }
            return try p.addNode(.{
                .tag = .multiline_string_literal,
                .main_token = first_line,
                .data = .{ .token_and_token = .{
                    first_line,
                    p.tok_i - 1,
                } },
            });
        },
        .identifier => switch (p.tokenTag(p.tok_i + 1)) {
            .colon => switch (p.tokenTag(p.tok_i + 2)) {
                .keyword_inline => {
                    p.tok_i += 3;
                    switch (p.tokenTag(p.tok_i)) {
                        .keyword_for => return try p.expectFor(expectTypeExpr),
                        .keyword_while => return try p.expectWhileTypeExpr(),
                        else => return p.fail(.expected_inlinable),
                    }
                },
                .keyword_for => {
                    p.tok_i += 2;
                    return try p.expectFor(expectTypeExpr);
                },
                .keyword_while => {
                    p.tok_i += 2;
                    return try p.expectWhileTypeExpr();
                },
                .keyword_switch => {
                    p.tok_i += 2;
                    return try p.expectSwitchExpr(true);
                },
                .l_brace => {
                    p.tok_i += 2;
                    return (try p.parseBlock()).?;
                },
                else => return try p.addNode(.{
                    .tag = .identifier,
                    .main_token = p.nextToken(),
                    .data = undefined,
                }),
            },
            else => return try p.addNode(.{
                .tag = .identifier,
                .main_token = p.nextToken(),
                .data = undefined,
            }),
        },
        .keyword_inline => {
            p.tok_i += 1;
            switch (p.tokenTag(p.tok_i)) {
                .keyword_for => return try p.expectFor(expectTypeExpr),
                .keyword_while => return try p.expectWhileTypeExpr(),
                else => return p.fail(.expected_inlinable),
            }
        },
        .keyword_for => return try p.expectFor(expectTypeExpr),
        .keyword_while => return try p.expectWhileTypeExpr(),
        .period => switch (p.tokenTag(p.tok_i + 1)) {
            .identifier => {
                p.tok_i += 1;
                return try p.addNode(.{
                    .tag = .enum_literal,
                    .main_token = p.nextToken(), // identifier
                    .data = undefined,
                });
            },
            .l_brace => {
                const lbrace = p.tok_i + 1;
                p.tok_i = lbrace + 1;

                // If there are 0, 1, or 2 items, we can use ArrayInitDotTwo/StructInitDotTwo;
                // otherwise we use the full ArrayInitDot/StructInitDot.

                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 <= 2) {
                        return try p.addNode(.{
                            .tag = if (comma) .struct_init_dot_two_comma else .struct_init_dot_two,
                            .main_token = lbrace,
                            .data = .{ .opt_node_and_opt_node = .{
                                if (inits.len >= 1) .fromOptional(inits[0]) else .none,
                                if (inits.len >= 2) .fromOptional(inits[1]) else .none,
                            } },
                        });
                    } else {
                        return try p.addNode(.{
                            .tag = if (comma) .struct_init_dot_comma else .struct_init_dot,
                            .main_token = lbrace,
                            .data = .{ .extra_range = 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..];
                if (inits.len <= 2) {
                    return try p.addNode(.{
                        .tag = if (inits.len == 0)
                            .struct_init_dot_two
                        else if (comma) .array_init_dot_two_comma else .array_init_dot_two,
                        .main_token = lbrace,
                        .data = .{ .opt_node_and_opt_node = .{
                            if (inits.len >= 1) inits[0].toOptional() else .none,
                            if (inits.len >= 2) inits[1].toOptional() else .none,
                        } },
                    });
                } else {
                    return try p.addNode(.{
                        .tag = if (comma) .array_init_dot_comma else .array_init_dot,
                        .main_token = lbrace,
                        .data = .{ .extra_range = try p.listToSpan(inits) },
                    });
                }
            },
            else => return null,
        },
        .keyword_error => switch (p.tokenTag(p.tok_i + 1)) {
            .l_brace => {
                const error_token = p.tok_i;
                p.tok_i += 2;
                while (true) {
                    if (p.eatToken(.r_brace)) |_| break;
                    _ = try p.eatDocComments();
                    _ = try p.expectToken(.identifier);
                    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_field),
                    }
                }
                return try p.addNode(.{
                    .tag = .error_set_decl,
                    .main_token = error_token,
                    .data = .{
                        .token_and_token = .{
                            error_token + 1, // lbrace
                            p.tok_i - 1, // rbrace
                        },
                    },
                });
            },
            else => {
                const main_token = p.nextToken();
                _ = try p.expectToken(.period);
                _ = try p.expectToken(.identifier);
                return try p.addNode(.{
                    .tag = .error_value,
                    .main_token = main_token,
                    .data = undefined,
                });
            },
        },
        .l_paren => return try p.addNode(.{
            .tag = .grouped_expression,
            .main_token = p.nextToken(),
            .data = .{ .node_and_token = .{
                try p.expectExpr(),
                try p.expectToken(.r_paren),
            } },
        }),
        else => return null,
    }
}