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.

parseSuffixOp

Parse.parseSuffixOp
fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index

File

lib/std/zig/Parse.zig:2872

Code

fn parseSuffixOp(p: *Parse, lhs: Node.Index) !?Node.Index {
    switch (p.tokenTag(p.tok_i)) {
        .l_bracket => {
            const lbracket = p.nextToken();
            const index_expr = try p.expectExpr();

            if (p.eatToken(.ellipsis2)) |_| {
                const opt_end_expr = try p.parseExpr();
                if (p.eatToken(.colon)) |_| {
                    const sentinel = try p.expectExpr();
                    _ = try p.expectToken(.r_bracket);
                    return try p.addNode(.{
                        .tag = .slice_sentinel,
                        .main_token = lbracket,
                        .data = .{ .node_and_extra = .{
                            lhs,
                            try p.addExtra(Node.SliceSentinel{
                                .start = index_expr,
                                .end = .fromOptional(opt_end_expr),
                                .sentinel = sentinel,
                            }),
                        } },
                    });
                }
                _ = try p.expectToken(.r_bracket);
                const end_expr = opt_end_expr orelse {
                    return try p.addNode(.{
                        .tag = .slice_open,
                        .main_token = lbracket,
                        .data = .{ .node_and_node = .{
                            lhs,
                            index_expr,
                        } },
                    });
                };
                return try p.addNode(.{
                    .tag = .slice,
                    .main_token = lbracket,
                    .data = .{ .node_and_extra = .{
                        lhs,
                        try p.addExtra(Node.Slice{
                            .start = index_expr,
                            .end = end_expr,
                        }),
                    } },
                });
            }
            _ = try p.expectToken(.r_bracket);
            return try p.addNode(.{
                .tag = .array_access,
                .main_token = lbracket,
                .data = .{ .node_and_node = .{
                    lhs,
                    index_expr,
                } },
            });
        },
        .period_asterisk => return try p.addNode(.{
            .tag = .deref,
            .main_token = p.nextToken(),
            .data = .{ .node = lhs },
        }),
        .period => switch (p.tokenTag(p.tok_i + 1)) {
            .identifier => return try p.addNode(.{
                .tag = .field_access,
                .main_token = p.nextToken(),
                .data = .{ .node_and_token = .{
                    lhs,
                    p.nextToken(),
                } },
            }),
            .question_mark => return try p.addNode(.{
                .tag = .unwrap_optional,
                .main_token = p.nextToken(),
                .data = .{ .node_and_token = .{
                    lhs,
                    p.nextToken(),
                } },
            }),
            .l_brace => {
                // this a misplaced `.{`, handle the error somewhere else
                return null;
            },
            else => {
                p.tok_i += 1;
                try p.warn(.expected_suffix_op);
                return null;
            },
        },
        .l_paren => {
            const lparen = p.nextToken();
            const scratch_top = p.scratch.items.len;
            defer p.scratch.shrinkRetainingCapacity(scratch_top);
            while (true) {
                if (p.eatToken(.r_paren)) |_| break;
                const param = try p.expectExpr();
                try p.scratch.append(p.gpa, param);
                switch (p.tokenTag(p.tok_i)) {
                    .comma => p.tok_i += 1,
                    .r_paren => {
                        p.tok_i += 1;
                        break;
                    },
                    .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren),
                    // Likely just a missing comma; give error but continue parsing.
                    else => try p.warn(.expected_comma_after_arg),
                }
            }
            const comma = (p.tokenTag(p.tok_i - 2)) == .comma;
            const params = p.scratch.items[scratch_top..];
            switch (params.len) {
                0, 1 => return try p.addNode(.{
                    .tag = if (comma) .call_one_comma else .call_one,
                    .main_token = lparen,
                    .data = .{ .node_and_opt_node = .{
                        lhs,
                        if (params.len >= 1) .fromOptional(params[0]) else .none,
                    } },
                }),
                else => return try p.addNode(.{
                    .tag = if (comma) .call_comma else .call,
                    .main_token = lparen,
                    .data = .{ .node_and_extra = .{
                        lhs,
                        try p.addExtra(try p.listToSpan(params)),
                    } },
                }),
            }
        },
        else => return null,
    }
}