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.

parseWhileStatement

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

File

lib/std/zig/Parse.zig:1298

Code

fn parseWhileStatement(p: *Parse) !?Node.Index {
    const while_token = p.eatToken(.keyword_while) orelse return null;
    _ = try p.expectToken(.l_paren);
    const condition = try p.expectExpr();
    _ = try p.expectToken(.r_paren);
    _ = try p.parsePtrPayload();
    const cont_expr = try p.parseWhileContinueExpr();

    // TODO propose to change the syntax so that semicolons are always required
    // inside while statements, even if there is an `else`.
    var else_required = false;
    const then_expr = blk: {
        const block_expr = try p.parseBlockExpr();
        if (block_expr) |block| break :blk block;
        const assign_expr = try p.parseAssignExpr() orelse {
            return p.fail(.expected_block_or_assignment);
        };
        if (p.eatToken(.semicolon)) |_| {
            if (cont_expr == null) {
                return try p.addNode(.{
                    .tag = .while_simple,
                    .main_token = while_token,
                    .data = .{ .node_and_node = .{
                        condition,
                        assign_expr,
                    } },
                });
            } else {
                return try p.addNode(.{
                    .tag = .while_cont,
                    .main_token = while_token,
                    .data = .{ .node_and_extra = .{
                        condition,
                        try p.addExtra(Node.WhileCont{
                            .cont_expr = cont_expr.?,
                            .then_expr = assign_expr,
                        }),
                    } },
                });
            }
        }
        else_required = true;
        break :blk assign_expr;
    };
    _ = p.eatToken(.keyword_else) orelse {
        if (else_required) {
            try p.warn(.expected_semi_or_else);
        }
        if (cont_expr == null) {
            return try p.addNode(.{
                .tag = .while_simple,
                .main_token = while_token,
                .data = .{ .node_and_node = .{
                    condition,
                    then_expr,
                } },
            });
        } else {
            return try p.addNode(.{
                .tag = .while_cont,
                .main_token = while_token,
                .data = .{ .node_and_extra = .{
                    condition,
                    try p.addExtra(Node.WhileCont{
                        .cont_expr = cont_expr.?,
                        .then_expr = then_expr,
                    }),
                } },
            });
        }
    };
    _ = try p.parsePayload();
    const else_expr = try p.expectStatement(false);
    return try p.addNode(.{
        .tag = .@"while",
        .main_token = while_token,
        .data = .{ .node_and_extra = .{
            condition,
            try p.addExtra(Node.While{
                .cont_expr = .fromOptional(cont_expr),
                .then_expr = then_expr,
                .else_expr = else_expr,
            }),
        } },
    });
}