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.

parseCPostfixExprInner

MacroTranslator.parseCPostfixExprInner
fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNode) ParseError!ZigNode

File

lib/compiler/translate-c/MacroTranslator.zig:1212

Code

fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNode) ParseError!ZigNode {
    const gpa = mt.t.gpa;
    const arena = mt.t.arena;
    var node = type_name orelse try mt.parseCPrimaryExpr(scope);
    while (true) {
        switch (mt.peek()) {
            .period => {
                mt.i += 1;
                const tok = mt.tokens[mt.i];
                if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
                    const param = mt.macro.params[tok.end];
                    mt.i += 1;

                    const mangled_name = scope.getAlias(param) orelse param;
                    const field_name = try ZigTag.identifier.create(arena, mangled_name);
                    node = try ZigTag.field_builtin.create(arena, .{ .lhs = node, .rhs = field_name });
                    continue;
                }
                const field_name = mt.tokSlice();
                try mt.expect(.identifier);

                node = try ZigTag.field_access.create(arena, .{ .lhs = node, .field_name = field_name });
            },
            .arrow => {
                mt.i += 1;
                const tok = mt.tokens[mt.i];
                if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
                    const param = mt.macro.params[tok.end];
                    mt.i += 1;

                    const mangled_name = scope.getAlias(param) orelse param;
                    const field_name = try ZigTag.identifier.create(arena, mangled_name);
                    node = try ZigTag.field_builtin.create(arena, .{ .lhs = node, .rhs = field_name });
                    continue;
                }
                const field_name = mt.tokSlice();
                try mt.expect(.identifier);

                const deref = try ZigTag.deref.create(arena, node);
                node = try ZigTag.field_access.create(arena, .{ .lhs = deref, .field_name = field_name });
            },
            .l_bracket => {
                mt.i += 1;

                const index_val = try mt.macroIntFromBool(try mt.parseCExpr(scope));
                const index = try ZigTag.as.create(arena, .{
                    .lhs = try ZigTag.type.create(arena, "usize"),
                    .rhs = try ZigTag.int_cast.create(arena, index_val),
                });
                node = try ZigTag.array_access.create(arena, .{ .lhs = node, .rhs = index });
                try mt.expect(.r_bracket);
            },
            .l_paren => {
                mt.i += 1;

                if (mt.eat(.r_paren)) {
                    node = try ZigTag.call.create(arena, .{ .lhs = node, .args = &.{} });
                } else {
                    var args: std.ArrayList(ZigNode) = .empty;
                    defer args.deinit(gpa);

                    while (true) {
                        const arg = try mt.parseCCondExpr(scope);
                        try args.append(gpa, arg);

                        const next_id = mt.peek();
                        switch (next_id) {
                            .comma => {
                                mt.i += 1;
                            },
                            .r_paren => {
                                mt.i += 1;
                                break;
                            },
                            else => {
                                try mt.fail("unable to translate C expr: expected ',' or ')' instead got '{s}'", .{next_id.symbol()});
                                return error.ParseError;
                            },
                        }
                    }
                    node = try ZigTag.call.create(arena, .{ .lhs = node, .args = try arena.dupe(ZigNode, args.items) });
                }
            },
            .l_brace => {
                mt.i += 1;

                // Check for designated field initializers
                if (mt.peek() == .period) {
                    var init_vals: std.ArrayList(ast.Payload.ContainerInitDot.Initializer) = .empty;
                    defer init_vals.deinit(gpa);

                    while (true) {
                        try mt.expect(.period);
                        const name = mt.tokSlice();
                        try mt.expect(.identifier);
                        try mt.expect(.equal);

                        const val = try mt.parseCCondExpr(scope);
                        try init_vals.append(gpa, .{ .name = name, .value = val });

                        const next_id = mt.peek();
                        switch (next_id) {
                            .comma => {
                                mt.i += 1;
                            },
                            .r_brace => {
                                mt.i += 1;
                                break;
                            },
                            else => {
                                try mt.fail("unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()});
                                return error.ParseError;
                            },
                        }
                    }
                    const tuple_node = try ZigTag.container_init_dot.create(arena, try arena.dupe(ast.Payload.ContainerInitDot.Initializer, init_vals.items));
                    node = try ZigTag.std_mem_zeroinit.create(arena, .{ .lhs = node, .rhs = tuple_node });
                    continue;
                }

                var init_vals: std.ArrayList(ZigNode) = .empty;
                defer init_vals.deinit(gpa);

                while (true) {
                    const val = try mt.parseCCondExpr(scope);
                    try init_vals.append(gpa, val);

                    const next_id = mt.peek();
                    switch (next_id) {
                        .comma => {
                            mt.i += 1;
                        },
                        .r_brace => {
                            mt.i += 1;
                            break;
                        },
                        else => {
                            try mt.fail("unable to translate C expr: expected ',' or '}}' instead got '{s}'", .{next_id.symbol()});
                            return error.ParseError;
                        },
                    }
                }
                const tuple_node = try ZigTag.tuple.create(arena, try arena.dupe(ZigNode, init_vals.items));
                node = try ZigTag.std_mem_zeroinit.create(arena, .{ .lhs = node, .rhs = tuple_node });
            },
            .plus_plus, .minus_minus => {
                try mt.fail("TODO postfix inc/dec expr", .{});
                return error.ParseError;
            },
            else => return node,
        }
    }
}