zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob d36bf55e (126076B) - Raw


      1 // SPDX-License-Identifier: MIT
      2 // Copyright (c) 2015-2020 Zig Contributors
      3 // This file is part of [zig](https://ziglang.org/), which is MIT licensed.
      4 // The MIT license requires this copyright notice to be included in all copies
      5 // and substantial portions of the software.
      6 const std = @import("../std.zig");
      7 const assert = std.debug.assert;
      8 const Allocator = std.mem.Allocator;
      9 const ast = std.zig.ast;
     10 const Node = ast.Node;
     11 const Tree = ast.Tree;
     12 const AstError = ast.Error;
     13 const TokenIndex = ast.TokenIndex;
     14 const NodeIndex = ast.NodeIndex;
     15 const Token = std.zig.Token;
     16 
     17 pub const Error = error{ParseError} || Allocator.Error;
     18 
     19 /// Result should be freed with tree.deinit() when there are
     20 /// no more references to any of the tokens or nodes.
     21 pub fn parse(gpa: *Allocator, source: []const u8) Allocator.Error!*Tree {
     22     var token_ids = std.ArrayList(Token.Id).init(gpa);
     23     defer token_ids.deinit();
     24     var token_locs = std.ArrayList(Token.Loc).init(gpa);
     25     defer token_locs.deinit();
     26 
     27     // Empirically, the zig std lib has an 8:1 ratio of source bytes to token count.
     28     const estimated_token_count = source.len / 8;
     29     try token_ids.ensureCapacity(estimated_token_count);
     30     try token_locs.ensureCapacity(estimated_token_count);
     31 
     32     var tokenizer = std.zig.Tokenizer.init(source);
     33     while (true) {
     34         const token = tokenizer.next();
     35         try token_ids.append(token.id);
     36         try token_locs.append(token.loc);
     37         if (token.id == .Eof) break;
     38     }
     39 
     40     var parser: Parser = .{
     41         .source = source,
     42         .arena = std.heap.ArenaAllocator.init(gpa),
     43         .gpa = gpa,
     44         .token_ids = token_ids.items,
     45         .token_locs = token_locs.items,
     46         .errors = .{},
     47         .tok_i = 0,
     48     };
     49     defer parser.errors.deinit(gpa);
     50     errdefer parser.arena.deinit();
     51 
     52     while (token_ids.items[parser.tok_i] == .LineComment) parser.tok_i += 1;
     53 
     54     const root_node = try parser.parseRoot();
     55 
     56     const tree = try parser.arena.allocator.create(Tree);
     57     tree.* = .{
     58         .gpa = gpa,
     59         .source = source,
     60         .token_ids = token_ids.toOwnedSlice(),
     61         .token_locs = token_locs.toOwnedSlice(),
     62         .errors = parser.errors.toOwnedSlice(gpa),
     63         .root_node = root_node,
     64         .arena = parser.arena.state,
     65     };
     66     return tree;
     67 }
     68 
     69 /// Represents in-progress parsing, will be converted to an ast.Tree after completion.
     70 const Parser = struct {
     71     arena: std.heap.ArenaAllocator,
     72     gpa: *Allocator,
     73     source: []const u8,
     74     token_ids: []const Token.Id,
     75     token_locs: []const Token.Loc,
     76     tok_i: TokenIndex,
     77     errors: std.ArrayListUnmanaged(AstError),
     78 
     79     /// Root <- skip ContainerMembers eof
     80     fn parseRoot(p: *Parser) Allocator.Error!*Node.Root {
     81         const decls = try parseContainerMembers(p, true);
     82         defer p.gpa.free(decls);
     83 
     84         // parseContainerMembers will try to skip as much
     85         // invalid tokens as it can so this can only be the EOF
     86         const eof_token = p.eatToken(.Eof).?;
     87 
     88         const decls_len = @intCast(NodeIndex, decls.len);
     89         const node = try Node.Root.create(&p.arena.allocator, decls_len, eof_token);
     90         std.mem.copy(*Node, node.decls(), decls);
     91 
     92         return node;
     93     }
     94 
     95     /// ContainerMembers
     96     ///     <- TestDecl ContainerMembers
     97     ///      / TopLevelComptime ContainerMembers
     98     ///      / KEYWORD_pub? TopLevelDecl ContainerMembers
     99     ///      / ContainerField COMMA ContainerMembers
    100     ///      / ContainerField
    101     ///      /
    102     fn parseContainerMembers(p: *Parser, top_level: bool) ![]*Node {
    103         var list = std.ArrayList(*Node).init(p.gpa);
    104         defer list.deinit();
    105 
    106         var field_state: union(enum) {
    107             /// no fields have been seen
    108             none,
    109             /// currently parsing fields
    110             seen,
    111             /// saw fields and then a declaration after them.
    112             /// payload is first token of previous declaration.
    113             end: TokenIndex,
    114             /// ther was a declaration between fields, don't report more errors
    115             err,
    116         } = .none;
    117 
    118         while (true) {
    119             if (try p.parseContainerDocComments()) |node| {
    120                 try list.append(node);
    121                 continue;
    122             }
    123 
    124             const doc_comments = try p.parseDocComment();
    125 
    126             if (p.parseTestDecl() catch |err| switch (err) {
    127                 error.OutOfMemory => return error.OutOfMemory,
    128                 error.ParseError => {
    129                     p.findNextContainerMember();
    130                     continue;
    131                 },
    132             }) |node| {
    133                 if (field_state == .seen) {
    134                     field_state = .{ .end = node.firstToken() };
    135                 }
    136                 node.cast(Node.TestDecl).?.doc_comments = doc_comments;
    137                 try list.append(node);
    138                 continue;
    139             }
    140 
    141             if (p.parseTopLevelComptime() catch |err| switch (err) {
    142                 error.OutOfMemory => return error.OutOfMemory,
    143                 error.ParseError => {
    144                     p.findNextContainerMember();
    145                     continue;
    146                 },
    147             }) |node| {
    148                 if (field_state == .seen) {
    149                     field_state = .{ .end = node.firstToken() };
    150                 }
    151                 node.cast(Node.Comptime).?.doc_comments = doc_comments;
    152                 try list.append(node);
    153                 continue;
    154             }
    155 
    156             const visib_token = p.eatToken(.Keyword_pub);
    157 
    158             if (p.parseTopLevelDecl(doc_comments, visib_token) catch |err| switch (err) {
    159                 error.OutOfMemory => return error.OutOfMemory,
    160                 error.ParseError => {
    161                     p.findNextContainerMember();
    162                     continue;
    163                 },
    164             }) |node| {
    165                 if (field_state == .seen) {
    166                     field_state = .{ .end = visib_token orelse node.firstToken() };
    167                 }
    168                 try list.append(node);
    169                 continue;
    170             }
    171 
    172             if (visib_token != null) {
    173                 try p.errors.append(p.gpa, .{
    174                     .ExpectedPubItem = .{ .token = p.tok_i },
    175                 });
    176                 // ignore this pub
    177                 continue;
    178             }
    179 
    180             if (p.parseContainerField() catch |err| switch (err) {
    181                 error.OutOfMemory => return error.OutOfMemory,
    182                 error.ParseError => {
    183                     // attempt to recover
    184                     p.findNextContainerMember();
    185                     continue;
    186                 },
    187             }) |node| {
    188                 switch (field_state) {
    189                     .none => field_state = .seen,
    190                     .err, .seen => {},
    191                     .end => |tok| {
    192                         try p.errors.append(p.gpa, .{
    193                             .DeclBetweenFields = .{ .token = tok },
    194                         });
    195                         // continue parsing, error will be reported later
    196                         field_state = .err;
    197                     },
    198                 }
    199 
    200                 const field = node.cast(Node.ContainerField).?;
    201                 field.doc_comments = doc_comments;
    202                 try list.append(node);
    203                 const comma = p.eatToken(.Comma) orelse {
    204                     // try to continue parsing
    205                     const index = p.tok_i;
    206                     p.findNextContainerMember();
    207                     const next = p.token_ids[p.tok_i];
    208                     switch (next) {
    209                         .Eof => {
    210                             // no invalid tokens were found
    211                             if (index == p.tok_i) break;
    212 
    213                             // Invalid tokens, add error and exit
    214                             try p.errors.append(p.gpa, .{
    215                                 .ExpectedToken = .{ .token = index, .expected_id = .Comma },
    216                             });
    217                             break;
    218                         },
    219                         else => {
    220                             if (next == .RBrace) {
    221                                 if (!top_level) break;
    222                                 _ = p.nextToken();
    223                             }
    224 
    225                             // add error and continue
    226                             try p.errors.append(p.gpa, .{
    227                                 .ExpectedToken = .{ .token = index, .expected_id = .Comma },
    228                             });
    229                             continue;
    230                         },
    231                     }
    232                 };
    233                 if (try p.parseAppendedDocComment(comma)) |appended_comment|
    234                     field.doc_comments = appended_comment;
    235                 continue;
    236             }
    237 
    238             // Dangling doc comment
    239             if (doc_comments != null) {
    240                 try p.errors.append(p.gpa, .{
    241                     .UnattachedDocComment = .{ .token = doc_comments.?.firstToken() },
    242                 });
    243             }
    244 
    245             const next = p.token_ids[p.tok_i];
    246             switch (next) {
    247                 .Eof => break,
    248                 .Keyword_comptime => {
    249                     _ = p.nextToken();
    250                     try p.errors.append(p.gpa, .{
    251                         .ExpectedBlockOrField = .{ .token = p.tok_i },
    252                     });
    253                 },
    254                 else => {
    255                     const index = p.tok_i;
    256                     if (next == .RBrace) {
    257                         if (!top_level) break;
    258                         _ = p.nextToken();
    259                     }
    260 
    261                     // this was likely not supposed to end yet,
    262                     // try to find the next declaration
    263                     p.findNextContainerMember();
    264                     try p.errors.append(p.gpa, .{
    265                         .ExpectedContainerMembers = .{ .token = index },
    266                     });
    267                 },
    268             }
    269         }
    270 
    271         return list.toOwnedSlice();
    272     }
    273 
    274     /// Attempts to find next container member by searching for certain tokens
    275     fn findNextContainerMember(p: *Parser) void {
    276         var level: u32 = 0;
    277         while (true) {
    278             const tok = p.nextToken();
    279             switch (p.token_ids[tok]) {
    280                 // any of these can start a new top level declaration
    281                 .Keyword_test,
    282                 .Keyword_comptime,
    283                 .Keyword_pub,
    284                 .Keyword_export,
    285                 .Keyword_extern,
    286                 .Keyword_inline,
    287                 .Keyword_noinline,
    288                 .Keyword_usingnamespace,
    289                 .Keyword_threadlocal,
    290                 .Keyword_const,
    291                 .Keyword_var,
    292                 .Keyword_fn,
    293                 .Identifier,
    294                 => {
    295                     if (level == 0) {
    296                         p.putBackToken(tok);
    297                         return;
    298                     }
    299                 },
    300                 .Comma, .Semicolon => {
    301                     // this decl was likely meant to end here
    302                     if (level == 0) {
    303                         return;
    304                     }
    305                 },
    306                 .LParen, .LBracket, .LBrace => level += 1,
    307                 .RParen, .RBracket => {
    308                     if (level != 0) level -= 1;
    309                 },
    310                 .RBrace => {
    311                     if (level == 0) {
    312                         // end of container, exit
    313                         p.putBackToken(tok);
    314                         return;
    315                     }
    316                     level -= 1;
    317                 },
    318                 .Eof => {
    319                     p.putBackToken(tok);
    320                     return;
    321                 },
    322                 else => {},
    323             }
    324         }
    325     }
    326 
    327     /// Attempts to find the next statement by searching for a semicolon
    328     fn findNextStmt(p: *Parser) void {
    329         var level: u32 = 0;
    330         while (true) {
    331             const tok = p.nextToken();
    332             switch (p.token_ids[tok]) {
    333                 .LBrace => level += 1,
    334                 .RBrace => {
    335                     if (level == 0) {
    336                         p.putBackToken(tok);
    337                         return;
    338                     }
    339                     level -= 1;
    340                 },
    341                 .Semicolon => {
    342                     if (level == 0) {
    343                         return;
    344                     }
    345                 },
    346                 .Eof => {
    347                     p.putBackToken(tok);
    348                     return;
    349                 },
    350                 else => {},
    351             }
    352         }
    353     }
    354 
    355     /// Eat a multiline container doc comment
    356     fn parseContainerDocComments(p: *Parser) !?*Node {
    357         if (p.eatToken(.ContainerDocComment)) |first_line| {
    358             while (p.eatToken(.ContainerDocComment)) |_| {}
    359             const node = try p.arena.allocator.create(Node.DocComment);
    360             node.* = .{ .first_line = first_line };
    361             return &node.base;
    362         }
    363         return null;
    364     }
    365 
    366     /// TestDecl <- KEYWORD_test STRINGLITERALSINGLE Block
    367     fn parseTestDecl(p: *Parser) !?*Node {
    368         const test_token = p.eatToken(.Keyword_test) orelse return null;
    369         const name_node = try p.expectNode(parseStringLiteralSingle, .{
    370             .ExpectedStringLiteral = .{ .token = p.tok_i },
    371         });
    372         const block_node = (try p.parseBlock(null)) orelse {
    373             try p.errors.append(p.gpa, .{ .ExpectedLBrace = .{ .token = p.tok_i } });
    374             return error.ParseError;
    375         };
    376 
    377         const test_node = try p.arena.allocator.create(Node.TestDecl);
    378         test_node.* = .{
    379             .doc_comments = null,
    380             .test_token = test_token,
    381             .name = name_node,
    382             .body_node = block_node,
    383         };
    384         return &test_node.base;
    385     }
    386 
    387     /// TopLevelComptime <- KEYWORD_comptime BlockExpr
    388     fn parseTopLevelComptime(p: *Parser) !?*Node {
    389         const tok = p.eatToken(.Keyword_comptime) orelse return null;
    390         const lbrace = p.eatToken(.LBrace) orelse {
    391             p.putBackToken(tok);
    392             return null;
    393         };
    394         p.putBackToken(lbrace);
    395         const block_node = try p.expectNode(parseBlockExpr, .{
    396             .ExpectedLabelOrLBrace = .{ .token = p.tok_i },
    397         });
    398 
    399         const comptime_node = try p.arena.allocator.create(Node.Comptime);
    400         comptime_node.* = .{
    401             .doc_comments = null,
    402             .comptime_token = tok,
    403             .expr = block_node,
    404         };
    405         return &comptime_node.base;
    406     }
    407 
    408     /// TopLevelDecl
    409     ///     <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
    410     ///      / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
    411     ///      / KEYWORD_usingnamespace Expr SEMICOLON
    412     fn parseTopLevelDecl(p: *Parser, doc_comments: ?*Node.DocComment, visib_token: ?TokenIndex) !?*Node {
    413         var lib_name: ?*Node = null;
    414         const extern_export_inline_token = blk: {
    415             if (p.eatToken(.Keyword_export)) |token| break :blk token;
    416             if (p.eatToken(.Keyword_extern)) |token| {
    417                 lib_name = try p.parseStringLiteralSingle();
    418                 break :blk token;
    419             }
    420             if (p.eatToken(.Keyword_inline)) |token| break :blk token;
    421             if (p.eatToken(.Keyword_noinline)) |token| break :blk token;
    422             break :blk null;
    423         };
    424 
    425         if (try p.parseFnProto(.top_level, .{
    426             .doc_comments = doc_comments,
    427             .visib_token = visib_token,
    428             .extern_export_inline_token = extern_export_inline_token,
    429             .lib_name = lib_name,
    430         })) |node| {
    431             return node;
    432         }
    433 
    434         if (extern_export_inline_token) |token| {
    435             if (p.token_ids[token] == .Keyword_inline or
    436                 p.token_ids[token] == .Keyword_noinline)
    437             {
    438                 try p.errors.append(p.gpa, .{
    439                     .ExpectedFn = .{ .token = p.tok_i },
    440                 });
    441                 return error.ParseError;
    442             }
    443         }
    444 
    445         const thread_local_token = p.eatToken(.Keyword_threadlocal);
    446 
    447         if (try p.parseVarDecl(.{
    448             .doc_comments = doc_comments,
    449             .visib_token = visib_token,
    450             .thread_local_token = thread_local_token,
    451             .extern_export_token = extern_export_inline_token,
    452             .lib_name = lib_name,
    453         })) |node| {
    454             return node;
    455         }
    456 
    457         if (thread_local_token != null) {
    458             try p.errors.append(p.gpa, .{
    459                 .ExpectedVarDecl = .{ .token = p.tok_i },
    460             });
    461             // ignore this and try again;
    462             return error.ParseError;
    463         }
    464 
    465         if (extern_export_inline_token) |token| {
    466             try p.errors.append(p.gpa, .{
    467                 .ExpectedVarDeclOrFn = .{ .token = p.tok_i },
    468             });
    469             // ignore this and try again;
    470             return error.ParseError;
    471         }
    472 
    473         const use_token = p.eatToken(.Keyword_usingnamespace) orelse return null;
    474         const expr = try p.expectNode(parseExpr, .{
    475             .ExpectedExpr = .{ .token = p.tok_i },
    476         });
    477         const semicolon_token = try p.expectToken(.Semicolon);
    478 
    479         const node = try p.arena.allocator.create(Node.Use);
    480         node.* = .{
    481             .doc_comments = doc_comments orelse try p.parseAppendedDocComment(semicolon_token),
    482             .visib_token = visib_token,
    483             .use_token = use_token,
    484             .expr = expr,
    485             .semicolon_token = semicolon_token,
    486         };
    487 
    488         return &node.base;
    489     }
    490 
    491     /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (Keyword_anytype / TypeExpr)
    492     fn parseFnProto(p: *Parser, level: enum { top_level, as_type }, fields: struct {
    493         doc_comments: ?*Node.DocComment = null,
    494         visib_token: ?TokenIndex = null,
    495         extern_export_inline_token: ?TokenIndex = null,
    496         lib_name: ?*Node = null,
    497     }) !?*Node {
    498         // TODO: Remove once extern/async fn rewriting is
    499         var is_async: ?void = null;
    500         var is_extern_prototype: ?void = null;
    501         const cc_token: ?TokenIndex = blk: {
    502             if (p.eatToken(.Keyword_extern)) |token| {
    503                 is_extern_prototype = {};
    504                 break :blk token;
    505             }
    506             if (p.eatToken(.Keyword_async)) |token| {
    507                 is_async = {};
    508                 break :blk token;
    509             }
    510             break :blk null;
    511         };
    512         const fn_token = p.eatToken(.Keyword_fn) orelse {
    513             if (cc_token) |token|
    514                 p.putBackToken(token);
    515             return null;
    516         };
    517         const name_token = p.eatToken(.Identifier);
    518         const lparen = try p.expectToken(.LParen);
    519         const params = try p.parseParamDeclList();
    520         defer p.gpa.free(params);
    521         const var_args_token = p.eatToken(.Ellipsis3);
    522         const rparen = try p.expectToken(.RParen);
    523         const align_expr = try p.parseByteAlign();
    524         const section_expr = try p.parseLinkSection();
    525         const callconv_expr = try p.parseCallconv();
    526         const exclamation_token = p.eatToken(.Bang);
    527 
    528         const return_type_expr = (try p.parseAnyType()) orelse
    529             try p.expectNodeRecoverable(parseTypeExpr, .{
    530             // most likely the user forgot to specify the return type.
    531             // Mark return type as invalid and try to continue.
    532             .ExpectedReturnType = .{ .token = p.tok_i },
    533         });
    534 
    535         // TODO https://github.com/ziglang/zig/issues/3750
    536         const R = Node.FnProto.ReturnType;
    537         const return_type = if (return_type_expr == null)
    538             R{ .Invalid = rparen }
    539         else if (exclamation_token != null)
    540             R{ .InferErrorSet = return_type_expr.? }
    541         else
    542             R{ .Explicit = return_type_expr.? };
    543 
    544         const body_node: ?*Node = switch (level) {
    545             .top_level => blk: {
    546                 if (p.eatToken(.Semicolon)) |_| {
    547                     break :blk null;
    548                 }
    549                 const body_block = (try p.parseBlock(null)) orelse {
    550                     // Since parseBlock only return error.ParseError on
    551                     // a missing '}' we can assume this function was
    552                     // supposed to end here.
    553                     try p.errors.append(p.gpa, .{ .ExpectedSemiOrLBrace = .{ .token = p.tok_i } });
    554                     break :blk null;
    555                 };
    556                 break :blk body_block;
    557             },
    558             .as_type => null,
    559         };
    560 
    561         const fn_proto_node = try Node.FnProto.create(&p.arena.allocator, .{
    562             .params_len = params.len,
    563             .fn_token = fn_token,
    564             .return_type = return_type,
    565         }, .{
    566             .doc_comments = fields.doc_comments,
    567             .visib_token = fields.visib_token,
    568             .name_token = name_token,
    569             .var_args_token = var_args_token,
    570             .extern_export_inline_token = fields.extern_export_inline_token,
    571             .body_node = body_node,
    572             .lib_name = fields.lib_name,
    573             .align_expr = align_expr,
    574             .section_expr = section_expr,
    575             .callconv_expr = callconv_expr,
    576             .is_extern_prototype = is_extern_prototype,
    577             .is_async = is_async,
    578         });
    579         std.mem.copy(Node.FnProto.ParamDecl, fn_proto_node.params(), params);
    580 
    581         return &fn_proto_node.base;
    582     }
    583 
    584     /// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
    585     fn parseVarDecl(p: *Parser, fields: struct {
    586         doc_comments: ?*Node.DocComment = null,
    587         visib_token: ?TokenIndex = null,
    588         thread_local_token: ?TokenIndex = null,
    589         extern_export_token: ?TokenIndex = null,
    590         lib_name: ?*Node = null,
    591         comptime_token: ?TokenIndex = null,
    592     }) !?*Node {
    593         const mut_token = p.eatToken(.Keyword_const) orelse
    594             p.eatToken(.Keyword_var) orelse
    595             return null;
    596 
    597         const name_token = try p.expectToken(.Identifier);
    598         const type_node = if (p.eatToken(.Colon) != null)
    599             try p.expectNode(parseTypeExpr, .{
    600                 .ExpectedTypeExpr = .{ .token = p.tok_i },
    601             })
    602         else
    603             null;
    604         const align_node = try p.parseByteAlign();
    605         const section_node = try p.parseLinkSection();
    606         const eq_token = p.eatToken(.Equal);
    607         const init_node = if (eq_token != null) blk: {
    608             break :blk try p.expectNode(parseExpr, .{
    609                 .ExpectedExpr = .{ .token = p.tok_i },
    610             });
    611         } else null;
    612         const semicolon_token = try p.expectToken(.Semicolon);
    613 
    614         const doc_comments = fields.doc_comments orelse try p.parseAppendedDocComment(semicolon_token);
    615 
    616         const node = try Node.VarDecl.create(&p.arena.allocator, .{
    617             .mut_token = mut_token,
    618             .name_token = name_token,
    619             .semicolon_token = semicolon_token,
    620         }, .{
    621             .doc_comments = doc_comments,
    622             .visib_token = fields.visib_token,
    623             .thread_local_token = fields.thread_local_token,
    624             .eq_token = eq_token,
    625             .comptime_token = fields.comptime_token,
    626             .extern_export_token = fields.extern_export_token,
    627             .lib_name = fields.lib_name,
    628             .type_node = type_node,
    629             .align_node = align_node,
    630             .section_node = section_node,
    631             .init_node = init_node,
    632         });
    633         return &node.base;
    634     }
    635 
    636     /// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
    637     fn parseContainerField(p: *Parser) !?*Node {
    638         const comptime_token = p.eatToken(.Keyword_comptime);
    639         const name_token = p.eatToken(.Identifier) orelse {
    640             if (comptime_token) |t| p.putBackToken(t);
    641             return null;
    642         };
    643 
    644         var align_expr: ?*Node = null;
    645         var type_expr: ?*Node = null;
    646         if (p.eatToken(.Colon)) |_| {
    647             if (p.eatToken(.Keyword_anytype) orelse p.eatToken(.Keyword_var)) |anytype_tok| {
    648                 const node = try p.arena.allocator.create(Node.OneToken);
    649                 node.* = .{
    650                     .base = .{ .tag = .AnyType },
    651                     .token = anytype_tok,
    652                 };
    653                 type_expr = &node.base;
    654             } else {
    655                 type_expr = try p.expectNode(parseTypeExpr, .{
    656                     .ExpectedTypeExpr = .{ .token = p.tok_i },
    657                 });
    658                 align_expr = try p.parseByteAlign();
    659             }
    660         }
    661 
    662         const value_expr = if (p.eatToken(.Equal)) |_|
    663             try p.expectNode(parseExpr, .{
    664                 .ExpectedExpr = .{ .token = p.tok_i },
    665             })
    666         else
    667             null;
    668 
    669         const node = try p.arena.allocator.create(Node.ContainerField);
    670         node.* = .{
    671             .doc_comments = null,
    672             .comptime_token = comptime_token,
    673             .name_token = name_token,
    674             .type_expr = type_expr,
    675             .value_expr = value_expr,
    676             .align_expr = align_expr,
    677         };
    678         return &node.base;
    679     }
    680 
    681     /// Statement
    682     ///     <- KEYWORD_comptime? VarDecl
    683     ///      / KEYWORD_comptime BlockExprStatement
    684     ///      / KEYWORD_nosuspend BlockExprStatement
    685     ///      / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
    686     ///      / KEYWORD_defer BlockExprStatement
    687     ///      / KEYWORD_errdefer Payload? BlockExprStatement
    688     ///      / IfStatement
    689     ///      / LabeledStatement
    690     ///      / SwitchExpr
    691     ///      / AssignExpr SEMICOLON
    692     fn parseStatement(p: *Parser) Error!?*Node {
    693         const comptime_token = p.eatToken(.Keyword_comptime);
    694 
    695         if (try p.parseVarDecl(.{
    696             .comptime_token = comptime_token,
    697         })) |node| {
    698             return node;
    699         }
    700 
    701         if (comptime_token) |token| {
    702             const block_expr = try p.expectNode(parseBlockExprStatement, .{
    703                 .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
    704             });
    705 
    706             const node = try p.arena.allocator.create(Node.Comptime);
    707             node.* = .{
    708                 .doc_comments = null,
    709                 .comptime_token = token,
    710                 .expr = block_expr,
    711             };
    712             return &node.base;
    713         }
    714 
    715         if (p.eatToken(.Keyword_nosuspend)) |nosuspend_token| {
    716             const block_expr = try p.expectNode(parseBlockExprStatement, .{
    717                 .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
    718             });
    719 
    720             const node = try p.arena.allocator.create(Node.Nosuspend);
    721             node.* = .{
    722                 .nosuspend_token = nosuspend_token,
    723                 .expr = block_expr,
    724             };
    725             return &node.base;
    726         }
    727 
    728         if (p.eatToken(.Keyword_suspend)) |suspend_token| {
    729             const semicolon = p.eatToken(.Semicolon);
    730 
    731             const body_node = if (semicolon == null) blk: {
    732                 break :blk try p.expectNode(parseBlockExprStatement, .{
    733                     .ExpectedBlockOrExpression = .{ .token = p.tok_i },
    734                 });
    735             } else null;
    736 
    737             const node = try p.arena.allocator.create(Node.Suspend);
    738             node.* = .{
    739                 .suspend_token = suspend_token,
    740                 .body = body_node,
    741             };
    742             return &node.base;
    743         }
    744 
    745         const defer_token = p.eatToken(.Keyword_defer) orelse p.eatToken(.Keyword_errdefer);
    746         if (defer_token) |token| {
    747             const payload = if (p.token_ids[token] == .Keyword_errdefer)
    748                 try p.parsePayload()
    749             else
    750                 null;
    751             const expr_node = try p.expectNode(parseBlockExprStatement, .{
    752                 .ExpectedBlockOrExpression = .{ .token = p.tok_i },
    753             });
    754             const node = try p.arena.allocator.create(Node.Defer);
    755             node.* = .{
    756                 .defer_token = token,
    757                 .expr = expr_node,
    758                 .payload = payload,
    759             };
    760             return &node.base;
    761         }
    762 
    763         if (try p.parseIfStatement()) |node| return node;
    764         if (try p.parseLabeledStatement()) |node| return node;
    765         if (try p.parseSwitchExpr()) |node| return node;
    766         if (try p.parseAssignExpr()) |node| {
    767             _ = try p.expectTokenRecoverable(.Semicolon);
    768             return node;
    769         }
    770 
    771         return null;
    772     }
    773 
    774     /// IfStatement
    775     ///     <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
    776     ///      / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
    777     fn parseIfStatement(p: *Parser) !?*Node {
    778         const if_node = (try p.parseIfPrefix()) orelse return null;
    779         const if_prefix = if_node.cast(Node.If).?;
    780 
    781         const block_expr = (try p.parseBlockExpr());
    782         const assign_expr = if (block_expr == null)
    783             try p.expectNode(parseAssignExpr, .{
    784                 .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
    785             })
    786         else
    787             null;
    788 
    789         const semicolon = if (assign_expr != null) p.eatToken(.Semicolon) else null;
    790 
    791         const else_node = if (semicolon == null) blk: {
    792             const else_token = p.eatToken(.Keyword_else) orelse break :blk null;
    793             const payload = try p.parsePayload();
    794             const else_body = try p.expectNode(parseStatement, .{
    795                 .InvalidToken = .{ .token = p.tok_i },
    796             });
    797 
    798             const node = try p.arena.allocator.create(Node.Else);
    799             node.* = .{
    800                 .else_token = else_token,
    801                 .payload = payload,
    802                 .body = else_body,
    803             };
    804 
    805             break :blk node;
    806         } else null;
    807 
    808         if (block_expr) |body| {
    809             if_prefix.body = body;
    810             if_prefix.@"else" = else_node;
    811             return if_node;
    812         }
    813 
    814         if (assign_expr) |body| {
    815             if_prefix.body = body;
    816             if (semicolon != null) return if_node;
    817             if (else_node != null) {
    818                 if_prefix.@"else" = else_node;
    819                 return if_node;
    820             }
    821             try p.errors.append(p.gpa, .{
    822                 .ExpectedSemiOrElse = .{ .token = p.tok_i },
    823             });
    824         }
    825 
    826         return if_node;
    827     }
    828 
    829     /// LabeledStatement <- BlockLabel? (Block / LoopStatement)
    830     fn parseLabeledStatement(p: *Parser) !?*Node {
    831         var colon: TokenIndex = undefined;
    832         const label_token = p.parseBlockLabel(&colon);
    833 
    834         if (try p.parseBlock(label_token)) |node| return node;
    835 
    836         if (try p.parseLoopStatement()) |node| {
    837             if (node.cast(Node.For)) |for_node| {
    838                 for_node.label = label_token;
    839             } else if (node.cast(Node.While)) |while_node| {
    840                 while_node.label = label_token;
    841             } else unreachable;
    842             return node;
    843         }
    844 
    845         if (label_token != null) {
    846             try p.errors.append(p.gpa, .{
    847                 .ExpectedLabelable = .{ .token = p.tok_i },
    848             });
    849             return error.ParseError;
    850         }
    851 
    852         return null;
    853     }
    854 
    855     /// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
    856     fn parseLoopStatement(p: *Parser) !?*Node {
    857         const inline_token = p.eatToken(.Keyword_inline);
    858 
    859         if (try p.parseForStatement()) |node| {
    860             node.cast(Node.For).?.inline_token = inline_token;
    861             return node;
    862         }
    863 
    864         if (try p.parseWhileStatement()) |node| {
    865             node.cast(Node.While).?.inline_token = inline_token;
    866             return node;
    867         }
    868         if (inline_token == null) return null;
    869 
    870         // If we've seen "inline", there should have been a "for" or "while"
    871         try p.errors.append(p.gpa, .{
    872             .ExpectedInlinable = .{ .token = p.tok_i },
    873         });
    874         return error.ParseError;
    875     }
    876 
    877     /// ForStatement
    878     ///     <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
    879     ///      / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
    880     fn parseForStatement(p: *Parser) !?*Node {
    881         const node = (try p.parseForPrefix()) orelse return null;
    882         const for_prefix = node.cast(Node.For).?;
    883 
    884         if (try p.parseBlockExpr()) |block_expr_node| {
    885             for_prefix.body = block_expr_node;
    886 
    887             if (p.eatToken(.Keyword_else)) |else_token| {
    888                 const statement_node = try p.expectNode(parseStatement, .{
    889                     .InvalidToken = .{ .token = p.tok_i },
    890                 });
    891 
    892                 const else_node = try p.arena.allocator.create(Node.Else);
    893                 else_node.* = .{
    894                     .else_token = else_token,
    895                     .payload = null,
    896                     .body = statement_node,
    897                 };
    898                 for_prefix.@"else" = else_node;
    899 
    900                 return node;
    901             }
    902 
    903             return node;
    904         }
    905 
    906         for_prefix.body = try p.expectNode(parseAssignExpr, .{
    907             .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
    908         });
    909 
    910         if (p.eatToken(.Semicolon) != null) return node;
    911 
    912         if (p.eatToken(.Keyword_else)) |else_token| {
    913             const statement_node = try p.expectNode(parseStatement, .{
    914                 .ExpectedStatement = .{ .token = p.tok_i },
    915             });
    916 
    917             const else_node = try p.arena.allocator.create(Node.Else);
    918             else_node.* = .{
    919                 .else_token = else_token,
    920                 .payload = null,
    921                 .body = statement_node,
    922             };
    923             for_prefix.@"else" = else_node;
    924             return node;
    925         }
    926 
    927         try p.errors.append(p.gpa, .{
    928             .ExpectedSemiOrElse = .{ .token = p.tok_i },
    929         });
    930 
    931         return node;
    932     }
    933 
    934     /// WhileStatement
    935     ///     <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
    936     ///      / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
    937     fn parseWhileStatement(p: *Parser) !?*Node {
    938         const node = (try p.parseWhilePrefix()) orelse return null;
    939         const while_prefix = node.cast(Node.While).?;
    940 
    941         if (try p.parseBlockExpr()) |block_expr_node| {
    942             while_prefix.body = block_expr_node;
    943 
    944             if (p.eatToken(.Keyword_else)) |else_token| {
    945                 const payload = try p.parsePayload();
    946 
    947                 const statement_node = try p.expectNode(parseStatement, .{
    948                     .InvalidToken = .{ .token = p.tok_i },
    949                 });
    950 
    951                 const else_node = try p.arena.allocator.create(Node.Else);
    952                 else_node.* = .{
    953                     .else_token = else_token,
    954                     .payload = payload,
    955                     .body = statement_node,
    956                 };
    957                 while_prefix.@"else" = else_node;
    958 
    959                 return node;
    960             }
    961 
    962             return node;
    963         }
    964 
    965         while_prefix.body = try p.expectNode(parseAssignExpr, .{
    966             .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
    967         });
    968 
    969         if (p.eatToken(.Semicolon) != null) return node;
    970 
    971         if (p.eatToken(.Keyword_else)) |else_token| {
    972             const payload = try p.parsePayload();
    973 
    974             const statement_node = try p.expectNode(parseStatement, .{
    975                 .ExpectedStatement = .{ .token = p.tok_i },
    976             });
    977 
    978             const else_node = try p.arena.allocator.create(Node.Else);
    979             else_node.* = .{
    980                 .else_token = else_token,
    981                 .payload = payload,
    982                 .body = statement_node,
    983             };
    984             while_prefix.@"else" = else_node;
    985             return node;
    986         }
    987 
    988         try p.errors.append(p.gpa, .{
    989             .ExpectedSemiOrElse = .{ .token = p.tok_i },
    990         });
    991 
    992         return node;
    993     }
    994 
    995     /// BlockExprStatement
    996     ///     <- BlockExpr
    997     ///      / AssignExpr SEMICOLON
    998     fn parseBlockExprStatement(p: *Parser) !?*Node {
    999         if (try p.parseBlockExpr()) |node| return node;
   1000         if (try p.parseAssignExpr()) |node| {
   1001             _ = try p.expectTokenRecoverable(.Semicolon);
   1002             return node;
   1003         }
   1004         return null;
   1005     }
   1006 
   1007     /// BlockExpr <- BlockLabel? Block
   1008     fn parseBlockExpr(p: *Parser) Error!?*Node {
   1009         var colon: TokenIndex = undefined;
   1010         const label_token = p.parseBlockLabel(&colon);
   1011         const block_node = (try p.parseBlock(label_token)) orelse {
   1012             if (label_token) |label| {
   1013                 p.putBackToken(label + 1); // ":"
   1014                 p.putBackToken(label); // IDENTIFIER
   1015             }
   1016             return null;
   1017         };
   1018         return block_node;
   1019     }
   1020 
   1021     /// AssignExpr <- Expr (AssignOp Expr)?
   1022     fn parseAssignExpr(p: *Parser) !?*Node {
   1023         return p.parseBinOpExpr(parseAssignOp, parseExpr, .Once);
   1024     }
   1025 
   1026     /// Expr <- KEYWORD_try* BoolOrExpr
   1027     fn parseExpr(p: *Parser) Error!?*Node {
   1028         return p.parsePrefixOpExpr(parseTry, parseBoolOrExpr);
   1029     }
   1030 
   1031     /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
   1032     fn parseBoolOrExpr(p: *Parser) !?*Node {
   1033         return p.parseBinOpExpr(
   1034             SimpleBinOpParseFn(.Keyword_or, .BoolOr),
   1035             parseBoolAndExpr,
   1036             .Infinitely,
   1037         );
   1038     }
   1039 
   1040     /// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
   1041     fn parseBoolAndExpr(p: *Parser) !?*Node {
   1042         return p.parseBinOpExpr(
   1043             SimpleBinOpParseFn(.Keyword_and, .BoolAnd),
   1044             parseCompareExpr,
   1045             .Infinitely,
   1046         );
   1047     }
   1048 
   1049     /// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
   1050     fn parseCompareExpr(p: *Parser) !?*Node {
   1051         return p.parseBinOpExpr(parseCompareOp, parseBitwiseExpr, .Once);
   1052     }
   1053 
   1054     /// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
   1055     fn parseBitwiseExpr(p: *Parser) !?*Node {
   1056         return p.parseBinOpExpr(parseBitwiseOp, parseBitShiftExpr, .Infinitely);
   1057     }
   1058 
   1059     /// BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
   1060     fn parseBitShiftExpr(p: *Parser) !?*Node {
   1061         return p.parseBinOpExpr(parseBitShiftOp, parseAdditionExpr, .Infinitely);
   1062     }
   1063 
   1064     /// AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
   1065     fn parseAdditionExpr(p: *Parser) !?*Node {
   1066         return p.parseBinOpExpr(parseAdditionOp, parseMultiplyExpr, .Infinitely);
   1067     }
   1068 
   1069     /// MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
   1070     fn parseMultiplyExpr(p: *Parser) !?*Node {
   1071         return p.parseBinOpExpr(parseMultiplyOp, parsePrefixExpr, .Infinitely);
   1072     }
   1073 
   1074     /// PrefixExpr <- PrefixOp* PrimaryExpr
   1075     fn parsePrefixExpr(p: *Parser) !?*Node {
   1076         return p.parsePrefixOpExpr(parsePrefixOp, parsePrimaryExpr);
   1077     }
   1078 
   1079     /// PrimaryExpr
   1080     ///     <- AsmExpr
   1081     ///      / IfExpr
   1082     ///      / KEYWORD_break BreakLabel? Expr?
   1083     ///      / KEYWORD_comptime Expr
   1084     ///      / KEYWORD_nosuspend Expr
   1085     ///      / KEYWORD_continue BreakLabel?
   1086     ///      / KEYWORD_resume Expr
   1087     ///      / KEYWORD_return Expr?
   1088     ///      / BlockLabel? LoopExpr
   1089     ///      / Block
   1090     ///      / CurlySuffixExpr
   1091     fn parsePrimaryExpr(p: *Parser) !?*Node {
   1092         if (try p.parseAsmExpr()) |node| return node;
   1093         if (try p.parseIfExpr()) |node| return node;
   1094 
   1095         if (p.eatToken(.Keyword_break)) |token| {
   1096             const label = try p.parseBreakLabel();
   1097             const expr_node = try p.parseExpr();
   1098             const node = try Node.ControlFlowExpression.create(&p.arena.allocator, .{
   1099                 .tag = .Break,
   1100                 .ltoken = token,
   1101             }, .{
   1102                 .label = label,
   1103                 .rhs = expr_node,
   1104             });
   1105             return &node.base;
   1106         }
   1107 
   1108         if (p.eatToken(.Keyword_comptime)) |token| {
   1109             const expr_node = try p.expectNode(parseExpr, .{
   1110                 .ExpectedExpr = .{ .token = p.tok_i },
   1111             });
   1112             const node = try p.arena.allocator.create(Node.Comptime);
   1113             node.* = .{
   1114                 .doc_comments = null,
   1115                 .comptime_token = token,
   1116                 .expr = expr_node,
   1117             };
   1118             return &node.base;
   1119         }
   1120 
   1121         if (p.eatToken(.Keyword_nosuspend)) |token| {
   1122             const expr_node = try p.expectNode(parseExpr, .{
   1123                 .ExpectedExpr = .{ .token = p.tok_i },
   1124             });
   1125             const node = try p.arena.allocator.create(Node.Nosuspend);
   1126             node.* = .{
   1127                 .nosuspend_token = token,
   1128                 .expr = expr_node,
   1129             };
   1130             return &node.base;
   1131         }
   1132 
   1133         if (p.eatToken(.Keyword_continue)) |token| {
   1134             const label = try p.parseBreakLabel();
   1135             const node = try Node.ControlFlowExpression.create(&p.arena.allocator, .{
   1136                 .tag = .Continue,
   1137                 .ltoken = token,
   1138             }, .{
   1139                 .label = label,
   1140                 .rhs = null,
   1141             });
   1142             return &node.base;
   1143         }
   1144 
   1145         if (p.eatToken(.Keyword_resume)) |token| {
   1146             const expr_node = try p.expectNode(parseExpr, .{
   1147                 .ExpectedExpr = .{ .token = p.tok_i },
   1148             });
   1149             const node = try p.arena.allocator.create(Node.SimplePrefixOp);
   1150             node.* = .{
   1151                 .base = .{ .tag = .Resume },
   1152                 .op_token = token,
   1153                 .rhs = expr_node,
   1154             };
   1155             return &node.base;
   1156         }
   1157 
   1158         if (p.eatToken(.Keyword_return)) |token| {
   1159             const expr_node = try p.parseExpr();
   1160             const node = try Node.ControlFlowExpression.create(&p.arena.allocator, .{
   1161                 .tag = .Return,
   1162                 .ltoken = token,
   1163             }, .{
   1164                 .rhs = expr_node,
   1165             });
   1166             return &node.base;
   1167         }
   1168 
   1169         var colon: TokenIndex = undefined;
   1170         const label = p.parseBlockLabel(&colon);
   1171         if (try p.parseLoopExpr()) |node| {
   1172             if (node.cast(Node.For)) |for_node| {
   1173                 for_node.label = label;
   1174             } else if (node.cast(Node.While)) |while_node| {
   1175                 while_node.label = label;
   1176             } else unreachable;
   1177             return node;
   1178         }
   1179         if (label) |token| {
   1180             p.putBackToken(token + 1); // ":"
   1181             p.putBackToken(token); // IDENTIFIER
   1182         }
   1183 
   1184         if (try p.parseBlock(null)) |node| return node;
   1185         if (try p.parseCurlySuffixExpr()) |node| return node;
   1186 
   1187         return null;
   1188     }
   1189 
   1190     /// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
   1191     fn parseIfExpr(p: *Parser) !?*Node {
   1192         return p.parseIf(parseExpr);
   1193     }
   1194 
   1195     /// Block <- LBRACE Statement* RBRACE
   1196     fn parseBlock(p: *Parser, label_token: ?TokenIndex) !?*Node {
   1197         const lbrace = p.eatToken(.LBrace) orelse return null;
   1198 
   1199         var statements = std.ArrayList(*Node).init(p.gpa);
   1200         defer statements.deinit();
   1201 
   1202         while (true) {
   1203             const statement = (p.parseStatement() catch |err| switch (err) {
   1204                 error.OutOfMemory => return error.OutOfMemory,
   1205                 error.ParseError => {
   1206                     // try to skip to the next statement
   1207                     p.findNextStmt();
   1208                     continue;
   1209                 },
   1210             }) orelse break;
   1211             try statements.append(statement);
   1212         }
   1213 
   1214         const rbrace = try p.expectToken(.RBrace);
   1215 
   1216         const statements_len = @intCast(NodeIndex, statements.items.len);
   1217 
   1218         if (label_token) |label| {
   1219             const block_node = try Node.LabeledBlock.alloc(&p.arena.allocator, statements_len);
   1220             block_node.* = .{
   1221                 .label = label,
   1222                 .lbrace = lbrace,
   1223                 .statements_len = statements_len,
   1224                 .rbrace = rbrace,
   1225             };
   1226             std.mem.copy(*Node, block_node.statements(), statements.items);
   1227             return &block_node.base;
   1228         } else {
   1229             const block_node = try Node.Block.alloc(&p.arena.allocator, statements_len);
   1230             block_node.* = .{
   1231                 .lbrace = lbrace,
   1232                 .statements_len = statements_len,
   1233                 .rbrace = rbrace,
   1234             };
   1235             std.mem.copy(*Node, block_node.statements(), statements.items);
   1236             return &block_node.base;
   1237         }
   1238     }
   1239 
   1240     /// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
   1241     fn parseLoopExpr(p: *Parser) !?*Node {
   1242         const inline_token = p.eatToken(.Keyword_inline);
   1243 
   1244         if (try p.parseForExpr()) |node| {
   1245             node.cast(Node.For).?.inline_token = inline_token;
   1246             return node;
   1247         }
   1248 
   1249         if (try p.parseWhileExpr()) |node| {
   1250             node.cast(Node.While).?.inline_token = inline_token;
   1251             return node;
   1252         }
   1253 
   1254         if (inline_token == null) return null;
   1255 
   1256         // If we've seen "inline", there should have been a "for" or "while"
   1257         try p.errors.append(p.gpa, .{
   1258             .ExpectedInlinable = .{ .token = p.tok_i },
   1259         });
   1260         return error.ParseError;
   1261     }
   1262 
   1263     /// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
   1264     fn parseForExpr(p: *Parser) !?*Node {
   1265         const node = (try p.parseForPrefix()) orelse return null;
   1266         const for_prefix = node.cast(Node.For).?;
   1267 
   1268         const body_node = try p.expectNode(parseExpr, .{
   1269             .ExpectedExpr = .{ .token = p.tok_i },
   1270         });
   1271         for_prefix.body = body_node;
   1272 
   1273         if (p.eatToken(.Keyword_else)) |else_token| {
   1274             const body = try p.expectNode(parseExpr, .{
   1275                 .ExpectedExpr = .{ .token = p.tok_i },
   1276             });
   1277 
   1278             const else_node = try p.arena.allocator.create(Node.Else);
   1279             else_node.* = .{
   1280                 .else_token = else_token,
   1281                 .payload = null,
   1282                 .body = body,
   1283             };
   1284 
   1285             for_prefix.@"else" = else_node;
   1286         }
   1287 
   1288         return node;
   1289     }
   1290 
   1291     /// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
   1292     fn parseWhileExpr(p: *Parser) !?*Node {
   1293         const node = (try p.parseWhilePrefix()) orelse return null;
   1294         const while_prefix = node.cast(Node.While).?;
   1295 
   1296         const body_node = try p.expectNode(parseExpr, .{
   1297             .ExpectedExpr = .{ .token = p.tok_i },
   1298         });
   1299         while_prefix.body = body_node;
   1300 
   1301         if (p.eatToken(.Keyword_else)) |else_token| {
   1302             const payload = try p.parsePayload();
   1303             const body = try p.expectNode(parseExpr, .{
   1304                 .ExpectedExpr = .{ .token = p.tok_i },
   1305             });
   1306 
   1307             const else_node = try p.arena.allocator.create(Node.Else);
   1308             else_node.* = .{
   1309                 .else_token = else_token,
   1310                 .payload = payload,
   1311                 .body = body,
   1312             };
   1313 
   1314             while_prefix.@"else" = else_node;
   1315         }
   1316 
   1317         return node;
   1318     }
   1319 
   1320     /// CurlySuffixExpr <- TypeExpr InitList?
   1321     fn parseCurlySuffixExpr(p: *Parser) !?*Node {
   1322         const lhs = (try p.parseTypeExpr()) orelse return null;
   1323         const suffix_op = (try p.parseInitList(lhs)) orelse return lhs;
   1324         return suffix_op;
   1325     }
   1326 
   1327     /// InitList
   1328     ///     <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
   1329     ///      / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
   1330     ///      / LBRACE RBRACE
   1331     fn parseInitList(p: *Parser, lhs: *Node) !?*Node {
   1332         const lbrace = p.eatToken(.LBrace) orelse return null;
   1333         var init_list = std.ArrayList(*Node).init(p.gpa);
   1334         defer init_list.deinit();
   1335 
   1336         if (try p.parseFieldInit()) |field_init| {
   1337             try init_list.append(field_init);
   1338             while (p.eatToken(.Comma)) |_| {
   1339                 const next = (try p.parseFieldInit()) orelse break;
   1340                 try init_list.append(next);
   1341             }
   1342             const node = try Node.StructInitializer.alloc(&p.arena.allocator, init_list.items.len);
   1343             node.* = .{
   1344                 .lhs = lhs,
   1345                 .rtoken = try p.expectToken(.RBrace),
   1346                 .list_len = init_list.items.len,
   1347             };
   1348             std.mem.copy(*Node, node.list(), init_list.items);
   1349             return &node.base;
   1350         }
   1351 
   1352         if (try p.parseExpr()) |expr| {
   1353             try init_list.append(expr);
   1354             while (p.eatToken(.Comma)) |_| {
   1355                 const next = (try p.parseExpr()) orelse break;
   1356                 try init_list.append(next);
   1357             }
   1358             const node = try Node.ArrayInitializer.alloc(&p.arena.allocator, init_list.items.len);
   1359             node.* = .{
   1360                 .lhs = lhs,
   1361                 .rtoken = try p.expectToken(.RBrace),
   1362                 .list_len = init_list.items.len,
   1363             };
   1364             std.mem.copy(*Node, node.list(), init_list.items);
   1365             return &node.base;
   1366         }
   1367 
   1368         const node = try p.arena.allocator.create(Node.StructInitializer);
   1369         node.* = .{
   1370             .lhs = lhs,
   1371             .rtoken = try p.expectToken(.RBrace),
   1372             .list_len = 0,
   1373         };
   1374         return &node.base;
   1375     }
   1376 
   1377     /// InitList
   1378     ///     <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
   1379     ///      / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
   1380     ///      / LBRACE RBRACE
   1381     fn parseAnonInitList(p: *Parser, dot: TokenIndex) !?*Node {
   1382         const lbrace = p.eatToken(.LBrace) orelse return null;
   1383         var init_list = std.ArrayList(*Node).init(p.gpa);
   1384         defer init_list.deinit();
   1385 
   1386         if (try p.parseFieldInit()) |field_init| {
   1387             try init_list.append(field_init);
   1388             while (p.eatToken(.Comma)) |_| {
   1389                 const next = (try p.parseFieldInit()) orelse break;
   1390                 try init_list.append(next);
   1391             }
   1392             const node = try Node.StructInitializerDot.alloc(&p.arena.allocator, init_list.items.len);
   1393             node.* = .{
   1394                 .dot = dot,
   1395                 .rtoken = try p.expectToken(.RBrace),
   1396                 .list_len = init_list.items.len,
   1397             };
   1398             std.mem.copy(*Node, node.list(), init_list.items);
   1399             return &node.base;
   1400         }
   1401 
   1402         if (try p.parseExpr()) |expr| {
   1403             try init_list.append(expr);
   1404             while (p.eatToken(.Comma)) |_| {
   1405                 const next = (try p.parseExpr()) orelse break;
   1406                 try init_list.append(next);
   1407             }
   1408             const node = try Node.ArrayInitializerDot.alloc(&p.arena.allocator, init_list.items.len);
   1409             node.* = .{
   1410                 .dot = dot,
   1411                 .rtoken = try p.expectToken(.RBrace),
   1412                 .list_len = init_list.items.len,
   1413             };
   1414             std.mem.copy(*Node, node.list(), init_list.items);
   1415             return &node.base;
   1416         }
   1417 
   1418         const node = try p.arena.allocator.create(Node.StructInitializerDot);
   1419         node.* = .{
   1420             .dot = dot,
   1421             .rtoken = try p.expectToken(.RBrace),
   1422             .list_len = 0,
   1423         };
   1424         return &node.base;
   1425     }
   1426 
   1427     /// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
   1428     fn parseTypeExpr(p: *Parser) Error!?*Node {
   1429         return p.parsePrefixOpExpr(parsePrefixTypeOp, parseErrorUnionExpr);
   1430     }
   1431 
   1432     /// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
   1433     fn parseErrorUnionExpr(p: *Parser) !?*Node {
   1434         const suffix_expr = (try p.parseSuffixExpr()) orelse return null;
   1435 
   1436         if (try SimpleBinOpParseFn(.Bang, .ErrorUnion)(p)) |node| {
   1437             const error_union = node.castTag(.ErrorUnion).?;
   1438             const type_expr = try p.expectNode(parseTypeExpr, .{
   1439                 .ExpectedTypeExpr = .{ .token = p.tok_i },
   1440             });
   1441             error_union.lhs = suffix_expr;
   1442             error_union.rhs = type_expr;
   1443             return node;
   1444         }
   1445 
   1446         return suffix_expr;
   1447     }
   1448 
   1449     /// SuffixExpr
   1450     ///     <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
   1451     ///      / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
   1452     fn parseSuffixExpr(p: *Parser) !?*Node {
   1453         const maybe_async = p.eatToken(.Keyword_async);
   1454         if (maybe_async) |async_token| {
   1455             const token_fn = p.eatToken(.Keyword_fn);
   1456             if (token_fn != null) {
   1457                 // TODO: remove this hack when async fn rewriting is
   1458                 // HACK: If we see the keyword `fn`, then we assume that
   1459                 //       we are parsing an async fn proto, and not a call.
   1460                 //       We therefore put back all tokens consumed by the async
   1461                 //       prefix...
   1462                 p.putBackToken(token_fn.?);
   1463                 p.putBackToken(async_token);
   1464                 return p.parsePrimaryTypeExpr();
   1465             }
   1466             var res = try p.expectNode(parsePrimaryTypeExpr, .{
   1467                 .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i },
   1468             });
   1469 
   1470             while (try p.parseSuffixOp(res)) |node| {
   1471                 res = node;
   1472             }
   1473 
   1474             const params = (try p.parseFnCallArguments()) orelse {
   1475                 try p.errors.append(p.gpa, .{
   1476                     .ExpectedParamList = .{ .token = p.tok_i },
   1477                 });
   1478                 // ignore this, continue parsing
   1479                 return res;
   1480             };
   1481             defer p.gpa.free(params.list);
   1482             const node = try Node.Call.alloc(&p.arena.allocator, params.list.len);
   1483             node.* = .{
   1484                 .lhs = res,
   1485                 .params_len = params.list.len,
   1486                 .async_token = async_token,
   1487                 .rtoken = params.rparen,
   1488             };
   1489             std.mem.copy(*Node, node.params(), params.list);
   1490             return &node.base;
   1491         }
   1492         if (try p.parsePrimaryTypeExpr()) |expr| {
   1493             var res = expr;
   1494 
   1495             while (true) {
   1496                 if (try p.parseSuffixOp(res)) |node| {
   1497                     res = node;
   1498                     continue;
   1499                 }
   1500                 if (try p.parseFnCallArguments()) |params| {
   1501                     defer p.gpa.free(params.list);
   1502                     const call = try Node.Call.alloc(&p.arena.allocator, params.list.len);
   1503                     call.* = .{
   1504                         .lhs = res,
   1505                         .params_len = params.list.len,
   1506                         .async_token = null,
   1507                         .rtoken = params.rparen,
   1508                     };
   1509                     std.mem.copy(*Node, call.params(), params.list);
   1510                     res = &call.base;
   1511                     continue;
   1512                 }
   1513                 break;
   1514             }
   1515             return res;
   1516         }
   1517 
   1518         return null;
   1519     }
   1520 
   1521     /// PrimaryTypeExpr
   1522     ///     <- BUILTINIDENTIFIER FnCallArguments
   1523     ///      / CHAR_LITERAL
   1524     ///      / ContainerDecl
   1525     ///      / DOT IDENTIFIER
   1526     ///      / ErrorSetDecl
   1527     ///      / FLOAT
   1528     ///      / FnProto
   1529     ///      / GroupedExpr
   1530     ///      / LabeledTypeExpr
   1531     ///      / IDENTIFIER
   1532     ///      / IfTypeExpr
   1533     ///      / INTEGER
   1534     ///      / KEYWORD_comptime TypeExpr
   1535     ///      / KEYWORD_error DOT IDENTIFIER
   1536     ///      / KEYWORD_false
   1537     ///      / KEYWORD_null
   1538     ///      / KEYWORD_anyframe
   1539     ///      / KEYWORD_true
   1540     ///      / KEYWORD_undefined
   1541     ///      / KEYWORD_unreachable
   1542     ///      / STRINGLITERAL
   1543     ///      / SwitchExpr
   1544     fn parsePrimaryTypeExpr(p: *Parser) !?*Node {
   1545         if (try p.parseBuiltinCall()) |node| return node;
   1546         if (p.eatToken(.CharLiteral)) |token| {
   1547             const node = try p.arena.allocator.create(Node.OneToken);
   1548             node.* = .{
   1549                 .base = .{ .tag = .CharLiteral },
   1550                 .token = token,
   1551             };
   1552             return &node.base;
   1553         }
   1554         if (try p.parseContainerDecl()) |node| return node;
   1555         if (try p.parseAnonLiteral()) |node| return node;
   1556         if (try p.parseErrorSetDecl()) |node| return node;
   1557         if (try p.parseFloatLiteral()) |node| return node;
   1558         if (try p.parseFnProto(.as_type, .{})) |node| return node;
   1559         if (try p.parseGroupedExpr()) |node| return node;
   1560         if (try p.parseLabeledTypeExpr()) |node| return node;
   1561         if (try p.parseIdentifier()) |node| return node;
   1562         if (try p.parseIfTypeExpr()) |node| return node;
   1563         if (try p.parseIntegerLiteral()) |node| return node;
   1564         if (p.eatToken(.Keyword_comptime)) |token| {
   1565             const expr = (try p.parseTypeExpr()) orelse return null;
   1566             const node = try p.arena.allocator.create(Node.Comptime);
   1567             node.* = .{
   1568                 .doc_comments = null,
   1569                 .comptime_token = token,
   1570                 .expr = expr,
   1571             };
   1572             return &node.base;
   1573         }
   1574         if (p.eatToken(.Keyword_error)) |token| {
   1575             const period = try p.expectTokenRecoverable(.Period);
   1576             const identifier = try p.expectNodeRecoverable(parseIdentifier, .{
   1577                 .ExpectedIdentifier = .{ .token = p.tok_i },
   1578             });
   1579             const global_error_set = try p.createLiteral(.ErrorType, token);
   1580             if (period == null or identifier == null) return global_error_set;
   1581 
   1582             const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   1583             node.* = .{
   1584                 .base = Node{ .tag = .Period },
   1585                 .op_token = period.?,
   1586                 .lhs = global_error_set,
   1587                 .rhs = identifier.?,
   1588             };
   1589             return &node.base;
   1590         }
   1591         if (p.eatToken(.Keyword_false)) |token| return p.createLiteral(.BoolLiteral, token);
   1592         if (p.eatToken(.Keyword_null)) |token| return p.createLiteral(.NullLiteral, token);
   1593         if (p.eatToken(.Keyword_anyframe)) |token| {
   1594             const node = try p.arena.allocator.create(Node.AnyFrameType);
   1595             node.* = .{
   1596                 .anyframe_token = token,
   1597                 .result = null,
   1598             };
   1599             return &node.base;
   1600         }
   1601         if (p.eatToken(.Keyword_true)) |token| return p.createLiteral(.BoolLiteral, token);
   1602         if (p.eatToken(.Keyword_undefined)) |token| return p.createLiteral(.UndefinedLiteral, token);
   1603         if (p.eatToken(.Keyword_unreachable)) |token| return p.createLiteral(.Unreachable, token);
   1604         if (try p.parseStringLiteral()) |node| return node;
   1605         if (try p.parseSwitchExpr()) |node| return node;
   1606 
   1607         return null;
   1608     }
   1609 
   1610     /// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
   1611     fn parseContainerDecl(p: *Parser) !?*Node {
   1612         const layout_token = p.eatToken(.Keyword_extern) orelse
   1613             p.eatToken(.Keyword_packed);
   1614 
   1615         const node = (try p.parseContainerDeclAuto()) orelse {
   1616             if (layout_token) |token|
   1617                 p.putBackToken(token);
   1618             return null;
   1619         };
   1620         node.cast(Node.ContainerDecl).?.*.layout_token = layout_token;
   1621         return node;
   1622     }
   1623 
   1624     /// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
   1625     fn parseErrorSetDecl(p: *Parser) !?*Node {
   1626         const error_token = p.eatToken(.Keyword_error) orelse return null;
   1627         if (p.eatToken(.LBrace) == null) {
   1628             // Might parse as `KEYWORD_error DOT IDENTIFIER` later in PrimaryTypeExpr, so don't error
   1629             p.putBackToken(error_token);
   1630             return null;
   1631         }
   1632         const decls = try p.parseErrorTagList();
   1633         defer p.gpa.free(decls);
   1634         const rbrace = try p.expectToken(.RBrace);
   1635 
   1636         const node = try Node.ErrorSetDecl.alloc(&p.arena.allocator, decls.len);
   1637         node.* = .{
   1638             .error_token = error_token,
   1639             .decls_len = decls.len,
   1640             .rbrace_token = rbrace,
   1641         };
   1642         std.mem.copy(*Node, node.decls(), decls);
   1643         return &node.base;
   1644     }
   1645 
   1646     /// GroupedExpr <- LPAREN Expr RPAREN
   1647     fn parseGroupedExpr(p: *Parser) !?*Node {
   1648         const lparen = p.eatToken(.LParen) orelse return null;
   1649         const expr = try p.expectNode(parseExpr, .{
   1650             .ExpectedExpr = .{ .token = p.tok_i },
   1651         });
   1652         const rparen = try p.expectToken(.RParen);
   1653 
   1654         const node = try p.arena.allocator.create(Node.GroupedExpression);
   1655         node.* = .{
   1656             .lparen = lparen,
   1657             .expr = expr,
   1658             .rparen = rparen,
   1659         };
   1660         return &node.base;
   1661     }
   1662 
   1663     /// IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
   1664     fn parseIfTypeExpr(p: *Parser) !?*Node {
   1665         return p.parseIf(parseTypeExpr);
   1666     }
   1667 
   1668     /// LabeledTypeExpr
   1669     ///     <- BlockLabel Block
   1670     ///      / BlockLabel? LoopTypeExpr
   1671     fn parseLabeledTypeExpr(p: *Parser) !?*Node {
   1672         var colon: TokenIndex = undefined;
   1673         const label = p.parseBlockLabel(&colon);
   1674 
   1675         if (label) |label_token| {
   1676             if (try p.parseBlock(label_token)) |node| return node;
   1677         }
   1678 
   1679         if (try p.parseLoopTypeExpr()) |node| {
   1680             switch (node.tag) {
   1681                 .For => node.cast(Node.For).?.label = label,
   1682                 .While => node.cast(Node.While).?.label = label,
   1683                 else => unreachable,
   1684             }
   1685             return node;
   1686         }
   1687 
   1688         if (label) |token| {
   1689             p.putBackToken(colon);
   1690             p.putBackToken(token);
   1691         }
   1692         return null;
   1693     }
   1694 
   1695     /// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
   1696     fn parseLoopTypeExpr(p: *Parser) !?*Node {
   1697         const inline_token = p.eatToken(.Keyword_inline);
   1698 
   1699         if (try p.parseForTypeExpr()) |node| {
   1700             node.cast(Node.For).?.inline_token = inline_token;
   1701             return node;
   1702         }
   1703 
   1704         if (try p.parseWhileTypeExpr()) |node| {
   1705             node.cast(Node.While).?.inline_token = inline_token;
   1706             return node;
   1707         }
   1708 
   1709         if (inline_token == null) return null;
   1710 
   1711         // If we've seen "inline", there should have been a "for" or "while"
   1712         try p.errors.append(p.gpa, .{
   1713             .ExpectedInlinable = .{ .token = p.tok_i },
   1714         });
   1715         return error.ParseError;
   1716     }
   1717 
   1718     /// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
   1719     fn parseForTypeExpr(p: *Parser) !?*Node {
   1720         const node = (try p.parseForPrefix()) orelse return null;
   1721         const for_prefix = node.cast(Node.For).?;
   1722 
   1723         const type_expr = try p.expectNode(parseTypeExpr, .{
   1724             .ExpectedTypeExpr = .{ .token = p.tok_i },
   1725         });
   1726         for_prefix.body = type_expr;
   1727 
   1728         if (p.eatToken(.Keyword_else)) |else_token| {
   1729             const else_expr = try p.expectNode(parseTypeExpr, .{
   1730                 .ExpectedTypeExpr = .{ .token = p.tok_i },
   1731             });
   1732 
   1733             const else_node = try p.arena.allocator.create(Node.Else);
   1734             else_node.* = .{
   1735                 .else_token = else_token,
   1736                 .payload = null,
   1737                 .body = else_expr,
   1738             };
   1739 
   1740             for_prefix.@"else" = else_node;
   1741         }
   1742 
   1743         return node;
   1744     }
   1745 
   1746     /// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
   1747     fn parseWhileTypeExpr(p: *Parser) !?*Node {
   1748         const node = (try p.parseWhilePrefix()) orelse return null;
   1749         const while_prefix = node.cast(Node.While).?;
   1750 
   1751         const type_expr = try p.expectNode(parseTypeExpr, .{
   1752             .ExpectedTypeExpr = .{ .token = p.tok_i },
   1753         });
   1754         while_prefix.body = type_expr;
   1755 
   1756         if (p.eatToken(.Keyword_else)) |else_token| {
   1757             const payload = try p.parsePayload();
   1758 
   1759             const else_expr = try p.expectNode(parseTypeExpr, .{
   1760                 .ExpectedTypeExpr = .{ .token = p.tok_i },
   1761             });
   1762 
   1763             const else_node = try p.arena.allocator.create(Node.Else);
   1764             else_node.* = .{
   1765                 .else_token = else_token,
   1766                 .payload = null,
   1767                 .body = else_expr,
   1768             };
   1769 
   1770             while_prefix.@"else" = else_node;
   1771         }
   1772 
   1773         return node;
   1774     }
   1775 
   1776     /// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
   1777     fn parseSwitchExpr(p: *Parser) !?*Node {
   1778         const switch_token = p.eatToken(.Keyword_switch) orelse return null;
   1779         _ = try p.expectToken(.LParen);
   1780         const expr_node = try p.expectNode(parseExpr, .{
   1781             .ExpectedExpr = .{ .token = p.tok_i },
   1782         });
   1783         _ = try p.expectToken(.RParen);
   1784         _ = try p.expectToken(.LBrace);
   1785         const cases = try p.parseSwitchProngList();
   1786         defer p.gpa.free(cases);
   1787         const rbrace = try p.expectToken(.RBrace);
   1788 
   1789         const node = try Node.Switch.alloc(&p.arena.allocator, cases.len);
   1790         node.* = .{
   1791             .switch_token = switch_token,
   1792             .expr = expr_node,
   1793             .cases_len = cases.len,
   1794             .rbrace = rbrace,
   1795         };
   1796         std.mem.copy(*Node, node.cases(), cases);
   1797         return &node.base;
   1798     }
   1799 
   1800     /// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN
   1801     /// AsmOutput <- COLON AsmOutputList AsmInput?
   1802     /// AsmInput <- COLON AsmInputList AsmClobbers?
   1803     /// AsmClobbers <- COLON StringList
   1804     /// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL?
   1805     fn parseAsmExpr(p: *Parser) !?*Node {
   1806         const asm_token = p.eatToken(.Keyword_asm) orelse return null;
   1807         const volatile_token = p.eatToken(.Keyword_volatile);
   1808         _ = try p.expectToken(.LParen);
   1809         const template = try p.expectNode(parseExpr, .{
   1810             .ExpectedExpr = .{ .token = p.tok_i },
   1811         });
   1812 
   1813         var arena_outputs: []Node.Asm.Output = &[0]Node.Asm.Output{};
   1814         var arena_inputs: []Node.Asm.Input = &[0]Node.Asm.Input{};
   1815         var arena_clobbers: []*Node = &[0]*Node{};
   1816 
   1817         if (p.eatToken(.Colon) != null) {
   1818             const outputs = try p.parseAsmOutputList();
   1819             defer p.gpa.free(outputs);
   1820             arena_outputs = try p.arena.allocator.dupe(Node.Asm.Output, outputs);
   1821 
   1822             if (p.eatToken(.Colon) != null) {
   1823                 const inputs = try p.parseAsmInputList();
   1824                 defer p.gpa.free(inputs);
   1825                 arena_inputs = try p.arena.allocator.dupe(Node.Asm.Input, inputs);
   1826 
   1827                 if (p.eatToken(.Colon) != null) {
   1828                     const clobbers = try ListParseFn(*Node, parseStringLiteral)(p);
   1829                     defer p.gpa.free(clobbers);
   1830                     arena_clobbers = try p.arena.allocator.dupe(*Node, clobbers);
   1831                 }
   1832             }
   1833         }
   1834 
   1835         const node = try p.arena.allocator.create(Node.Asm);
   1836         node.* = .{
   1837             .asm_token = asm_token,
   1838             .volatile_token = volatile_token,
   1839             .template = template,
   1840             .outputs = arena_outputs,
   1841             .inputs = arena_inputs,
   1842             .clobbers = arena_clobbers,
   1843             .rparen = try p.expectToken(.RParen),
   1844         };
   1845 
   1846         return &node.base;
   1847     }
   1848 
   1849     /// DOT IDENTIFIER
   1850     fn parseAnonLiteral(p: *Parser) !?*Node {
   1851         const dot = p.eatToken(.Period) orelse return null;
   1852 
   1853         // anon enum literal
   1854         if (p.eatToken(.Identifier)) |name| {
   1855             const node = try p.arena.allocator.create(Node.EnumLiteral);
   1856             node.* = .{
   1857                 .dot = dot,
   1858                 .name = name,
   1859             };
   1860             return &node.base;
   1861         }
   1862 
   1863         if (try p.parseAnonInitList(dot)) |node| {
   1864             return node;
   1865         }
   1866 
   1867         p.putBackToken(dot);
   1868         return null;
   1869     }
   1870 
   1871     /// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
   1872     fn parseAsmOutputItem(p: *Parser) !?Node.Asm.Output {
   1873         const lbracket = p.eatToken(.LBracket) orelse return null;
   1874         const name = try p.expectNode(parseIdentifier, .{
   1875             .ExpectedIdentifier = .{ .token = p.tok_i },
   1876         });
   1877         _ = try p.expectToken(.RBracket);
   1878 
   1879         const constraint = try p.expectNode(parseStringLiteral, .{
   1880             .ExpectedStringLiteral = .{ .token = p.tok_i },
   1881         });
   1882 
   1883         _ = try p.expectToken(.LParen);
   1884         const kind: Node.Asm.Output.Kind = blk: {
   1885             if (p.eatToken(.Arrow) != null) {
   1886                 const return_ident = try p.expectNode(parseTypeExpr, .{
   1887                     .ExpectedTypeExpr = .{ .token = p.tok_i },
   1888                 });
   1889                 break :blk .{ .Return = return_ident };
   1890             }
   1891             const variable = try p.expectNode(parseIdentifier, .{
   1892                 .ExpectedIdentifier = .{ .token = p.tok_i },
   1893             });
   1894             break :blk .{ .Variable = variable.castTag(.Identifier).? };
   1895         };
   1896         const rparen = try p.expectToken(.RParen);
   1897 
   1898         return Node.Asm.Output{
   1899             .lbracket = lbracket,
   1900             .symbolic_name = name,
   1901             .constraint = constraint,
   1902             .kind = kind,
   1903             .rparen = rparen,
   1904         };
   1905     }
   1906 
   1907     /// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
   1908     fn parseAsmInputItem(p: *Parser) !?Node.Asm.Input {
   1909         const lbracket = p.eatToken(.LBracket) orelse return null;
   1910         const name = try p.expectNode(parseIdentifier, .{
   1911             .ExpectedIdentifier = .{ .token = p.tok_i },
   1912         });
   1913         _ = try p.expectToken(.RBracket);
   1914 
   1915         const constraint = try p.expectNode(parseStringLiteral, .{
   1916             .ExpectedStringLiteral = .{ .token = p.tok_i },
   1917         });
   1918 
   1919         _ = try p.expectToken(.LParen);
   1920         const expr = try p.expectNode(parseExpr, .{
   1921             .ExpectedExpr = .{ .token = p.tok_i },
   1922         });
   1923         const rparen = try p.expectToken(.RParen);
   1924 
   1925         return Node.Asm.Input{
   1926             .lbracket = lbracket,
   1927             .symbolic_name = name,
   1928             .constraint = constraint,
   1929             .expr = expr,
   1930             .rparen = rparen,
   1931         };
   1932     }
   1933 
   1934     /// BreakLabel <- COLON IDENTIFIER
   1935     fn parseBreakLabel(p: *Parser) !?TokenIndex {
   1936         _ = p.eatToken(.Colon) orelse return null;
   1937         const ident = try p.expectToken(.Identifier);
   1938         return ident;
   1939     }
   1940 
   1941     /// BlockLabel <- IDENTIFIER COLON
   1942     fn parseBlockLabel(p: *Parser, colon_token: *TokenIndex) ?TokenIndex {
   1943         const identifier = p.eatToken(.Identifier) orelse return null;
   1944         if (p.eatToken(.Colon)) |colon| {
   1945             colon_token.* = colon;
   1946             return identifier;
   1947         }
   1948         p.putBackToken(identifier);
   1949         return null;
   1950     }
   1951 
   1952     /// FieldInit <- DOT IDENTIFIER EQUAL Expr
   1953     fn parseFieldInit(p: *Parser) !?*Node {
   1954         const period_token = p.eatToken(.Period) orelse return null;
   1955         const name_token = p.eatToken(.Identifier) orelse {
   1956             // Because of anon literals `.{` is also valid.
   1957             p.putBackToken(period_token);
   1958             return null;
   1959         };
   1960         const eq_token = p.eatToken(.Equal) orelse {
   1961             // `.Name` may also be an enum literal, which is a later rule.
   1962             p.putBackToken(name_token);
   1963             p.putBackToken(period_token);
   1964             return null;
   1965         };
   1966         const expr_node = try p.expectNode(parseExpr, .{
   1967             .ExpectedExpr = .{ .token = p.tok_i },
   1968         });
   1969 
   1970         const node = try p.arena.allocator.create(Node.FieldInitializer);
   1971         node.* = .{
   1972             .period_token = period_token,
   1973             .name_token = name_token,
   1974             .expr = expr_node,
   1975         };
   1976         return &node.base;
   1977     }
   1978 
   1979     /// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
   1980     fn parseWhileContinueExpr(p: *Parser) !?*Node {
   1981         _ = p.eatToken(.Colon) orelse return null;
   1982         _ = try p.expectToken(.LParen);
   1983         const node = try p.expectNode(parseAssignExpr, .{
   1984             .ExpectedExprOrAssignment = .{ .token = p.tok_i },
   1985         });
   1986         _ = try p.expectToken(.RParen);
   1987         return node;
   1988     }
   1989 
   1990     /// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
   1991     fn parseLinkSection(p: *Parser) !?*Node {
   1992         _ = p.eatToken(.Keyword_linksection) orelse return null;
   1993         _ = try p.expectToken(.LParen);
   1994         const expr_node = try p.expectNode(parseExpr, .{
   1995             .ExpectedExpr = .{ .token = p.tok_i },
   1996         });
   1997         _ = try p.expectToken(.RParen);
   1998         return expr_node;
   1999     }
   2000 
   2001     /// CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
   2002     fn parseCallconv(p: *Parser) !?*Node {
   2003         _ = p.eatToken(.Keyword_callconv) orelse return null;
   2004         _ = try p.expectToken(.LParen);
   2005         const expr_node = try p.expectNode(parseExpr, .{
   2006             .ExpectedExpr = .{ .token = p.tok_i },
   2007         });
   2008         _ = try p.expectToken(.RParen);
   2009         return expr_node;
   2010     }
   2011 
   2012     /// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
   2013     fn parseParamDecl(p: *Parser) !?Node.FnProto.ParamDecl {
   2014         const doc_comments = try p.parseDocComment();
   2015         const noalias_token = p.eatToken(.Keyword_noalias);
   2016         const comptime_token = if (noalias_token == null) p.eatToken(.Keyword_comptime) else null;
   2017         const name_token = blk: {
   2018             const identifier = p.eatToken(.Identifier) orelse break :blk null;
   2019             if (p.eatToken(.Colon) != null) break :blk identifier;
   2020             p.putBackToken(identifier); // ParamType may also be an identifier
   2021             break :blk null;
   2022         };
   2023         const param_type = (try p.parseParamType()) orelse {
   2024             // Only return cleanly if no keyword, identifier, or doc comment was found
   2025             if (noalias_token == null and
   2026                 comptime_token == null and
   2027                 name_token == null and
   2028                 doc_comments == null)
   2029             {
   2030                 return null;
   2031             }
   2032             try p.errors.append(p.gpa, .{
   2033                 .ExpectedParamType = .{ .token = p.tok_i },
   2034             });
   2035             return error.ParseError;
   2036         };
   2037 
   2038         return Node.FnProto.ParamDecl{
   2039             .doc_comments = doc_comments,
   2040             .comptime_token = comptime_token,
   2041             .noalias_token = noalias_token,
   2042             .name_token = name_token,
   2043             .param_type = param_type,
   2044         };
   2045     }
   2046 
   2047     /// ParamType
   2048     ///     <- Keyword_anytype
   2049     ///      / DOT3
   2050     ///      / TypeExpr
   2051     fn parseParamType(p: *Parser) !?Node.FnProto.ParamDecl.ParamType {
   2052         // TODO cast from tuple to error union is broken
   2053         const P = Node.FnProto.ParamDecl.ParamType;
   2054         if (try p.parseAnyType()) |node| return P{ .any_type = node };
   2055         if (try p.parseTypeExpr()) |node| return P{ .type_expr = node };
   2056         return null;
   2057     }
   2058 
   2059     /// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
   2060     fn parseIfPrefix(p: *Parser) !?*Node {
   2061         const if_token = p.eatToken(.Keyword_if) orelse return null;
   2062         _ = try p.expectToken(.LParen);
   2063         const condition = try p.expectNode(parseExpr, .{
   2064             .ExpectedExpr = .{ .token = p.tok_i },
   2065         });
   2066         _ = try p.expectToken(.RParen);
   2067         const payload = try p.parsePtrPayload();
   2068 
   2069         const node = try p.arena.allocator.create(Node.If);
   2070         node.* = .{
   2071             .if_token = if_token,
   2072             .condition = condition,
   2073             .payload = payload,
   2074             .body = undefined, // set by caller
   2075             .@"else" = null,
   2076         };
   2077         return &node.base;
   2078     }
   2079 
   2080     /// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
   2081     fn parseWhilePrefix(p: *Parser) !?*Node {
   2082         const while_token = p.eatToken(.Keyword_while) orelse return null;
   2083 
   2084         _ = try p.expectToken(.LParen);
   2085         const condition = try p.expectNode(parseExpr, .{
   2086             .ExpectedExpr = .{ .token = p.tok_i },
   2087         });
   2088         _ = try p.expectToken(.RParen);
   2089 
   2090         const payload = try p.parsePtrPayload();
   2091         const continue_expr = try p.parseWhileContinueExpr();
   2092 
   2093         const node = try p.arena.allocator.create(Node.While);
   2094         node.* = .{
   2095             .label = null,
   2096             .inline_token = null,
   2097             .while_token = while_token,
   2098             .condition = condition,
   2099             .payload = payload,
   2100             .continue_expr = continue_expr,
   2101             .body = undefined, // set by caller
   2102             .@"else" = null,
   2103         };
   2104         return &node.base;
   2105     }
   2106 
   2107     /// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
   2108     fn parseForPrefix(p: *Parser) !?*Node {
   2109         const for_token = p.eatToken(.Keyword_for) orelse return null;
   2110 
   2111         _ = try p.expectToken(.LParen);
   2112         const array_expr = try p.expectNode(parseExpr, .{
   2113             .ExpectedExpr = .{ .token = p.tok_i },
   2114         });
   2115         _ = try p.expectToken(.RParen);
   2116 
   2117         const payload = try p.expectNode(parsePtrIndexPayload, .{
   2118             .ExpectedPayload = .{ .token = p.tok_i },
   2119         });
   2120 
   2121         const node = try p.arena.allocator.create(Node.For);
   2122         node.* = .{
   2123             .label = null,
   2124             .inline_token = null,
   2125             .for_token = for_token,
   2126             .array_expr = array_expr,
   2127             .payload = payload,
   2128             .body = undefined, // set by caller
   2129             .@"else" = null,
   2130         };
   2131         return &node.base;
   2132     }
   2133 
   2134     /// Payload <- PIPE IDENTIFIER PIPE
   2135     fn parsePayload(p: *Parser) !?*Node {
   2136         const lpipe = p.eatToken(.Pipe) orelse return null;
   2137         const identifier = try p.expectNode(parseIdentifier, .{
   2138             .ExpectedIdentifier = .{ .token = p.tok_i },
   2139         });
   2140         const rpipe = try p.expectToken(.Pipe);
   2141 
   2142         const node = try p.arena.allocator.create(Node.Payload);
   2143         node.* = .{
   2144             .lpipe = lpipe,
   2145             .error_symbol = identifier,
   2146             .rpipe = rpipe,
   2147         };
   2148         return &node.base;
   2149     }
   2150 
   2151     /// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
   2152     fn parsePtrPayload(p: *Parser) !?*Node {
   2153         const lpipe = p.eatToken(.Pipe) orelse return null;
   2154         const asterisk = p.eatToken(.Asterisk);
   2155         const identifier = try p.expectNode(parseIdentifier, .{
   2156             .ExpectedIdentifier = .{ .token = p.tok_i },
   2157         });
   2158         const rpipe = try p.expectToken(.Pipe);
   2159 
   2160         const node = try p.arena.allocator.create(Node.PointerPayload);
   2161         node.* = .{
   2162             .lpipe = lpipe,
   2163             .ptr_token = asterisk,
   2164             .value_symbol = identifier,
   2165             .rpipe = rpipe,
   2166         };
   2167         return &node.base;
   2168     }
   2169 
   2170     /// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
   2171     fn parsePtrIndexPayload(p: *Parser) !?*Node {
   2172         const lpipe = p.eatToken(.Pipe) orelse return null;
   2173         const asterisk = p.eatToken(.Asterisk);
   2174         const identifier = try p.expectNode(parseIdentifier, .{
   2175             .ExpectedIdentifier = .{ .token = p.tok_i },
   2176         });
   2177 
   2178         const index = if (p.eatToken(.Comma) == null)
   2179             null
   2180         else
   2181             try p.expectNode(parseIdentifier, .{
   2182                 .ExpectedIdentifier = .{ .token = p.tok_i },
   2183             });
   2184 
   2185         const rpipe = try p.expectToken(.Pipe);
   2186 
   2187         const node = try p.arena.allocator.create(Node.PointerIndexPayload);
   2188         node.* = .{
   2189             .lpipe = lpipe,
   2190             .ptr_token = asterisk,
   2191             .value_symbol = identifier,
   2192             .index_symbol = index,
   2193             .rpipe = rpipe,
   2194         };
   2195         return &node.base;
   2196     }
   2197 
   2198     /// SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
   2199     fn parseSwitchProng(p: *Parser) !?*Node {
   2200         const node = (try p.parseSwitchCase()) orelse return null;
   2201         const arrow = try p.expectToken(.EqualAngleBracketRight);
   2202         const payload = try p.parsePtrPayload();
   2203         const expr = try p.expectNode(parseAssignExpr, .{
   2204             .ExpectedExprOrAssignment = .{ .token = p.tok_i },
   2205         });
   2206 
   2207         const switch_case = node.cast(Node.SwitchCase).?;
   2208         switch_case.arrow_token = arrow;
   2209         switch_case.payload = payload;
   2210         switch_case.expr = expr;
   2211 
   2212         return node;
   2213     }
   2214 
   2215     /// SwitchCase
   2216     ///     <- SwitchItem (COMMA SwitchItem)* COMMA?
   2217     ///      / KEYWORD_else
   2218     fn parseSwitchCase(p: *Parser) !?*Node {
   2219         var list = std.ArrayList(*Node).init(p.gpa);
   2220         defer list.deinit();
   2221 
   2222         if (try p.parseSwitchItem()) |first_item| {
   2223             try list.append(first_item);
   2224             while (p.eatToken(.Comma) != null) {
   2225                 const next_item = (try p.parseSwitchItem()) orelse break;
   2226                 try list.append(next_item);
   2227             }
   2228         } else if (p.eatToken(.Keyword_else)) |else_token| {
   2229             const else_node = try p.arena.allocator.create(Node.SwitchElse);
   2230             else_node.* = .{
   2231                 .token = else_token,
   2232             };
   2233             try list.append(&else_node.base);
   2234         } else return null;
   2235 
   2236         const node = try Node.SwitchCase.alloc(&p.arena.allocator, list.items.len);
   2237         node.* = .{
   2238             .items_len = list.items.len,
   2239             .arrow_token = undefined, // set by caller
   2240             .payload = null,
   2241             .expr = undefined, // set by caller
   2242         };
   2243         std.mem.copy(*Node, node.items(), list.items);
   2244         return &node.base;
   2245     }
   2246 
   2247     /// SwitchItem <- Expr (DOT3 Expr)?
   2248     fn parseSwitchItem(p: *Parser) !?*Node {
   2249         const expr = (try p.parseExpr()) orelse return null;
   2250         if (p.eatToken(.Ellipsis3)) |token| {
   2251             const range_end = try p.expectNode(parseExpr, .{
   2252                 .ExpectedExpr = .{ .token = p.tok_i },
   2253             });
   2254 
   2255             const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   2256             node.* = .{
   2257                 .base = Node{ .tag = .Range },
   2258                 .op_token = token,
   2259                 .lhs = expr,
   2260                 .rhs = range_end,
   2261             };
   2262             return &node.base;
   2263         }
   2264         return expr;
   2265     }
   2266 
   2267     /// AssignOp
   2268     ///     <- ASTERISKEQUAL
   2269     ///      / SLASHEQUAL
   2270     ///      / PERCENTEQUAL
   2271     ///      / PLUSEQUAL
   2272     ///      / MINUSEQUAL
   2273     ///      / LARROW2EQUAL
   2274     ///      / RARROW2EQUAL
   2275     ///      / AMPERSANDEQUAL
   2276     ///      / CARETEQUAL
   2277     ///      / PIPEEQUAL
   2278     ///      / ASTERISKPERCENTEQUAL
   2279     ///      / PLUSPERCENTEQUAL
   2280     ///      / MINUSPERCENTEQUAL
   2281     ///      / EQUAL
   2282     fn parseAssignOp(p: *Parser) !?*Node {
   2283         const token = p.nextToken();
   2284         const op: Node.Tag = switch (p.token_ids[token]) {
   2285             .AsteriskEqual => .AssignMul,
   2286             .SlashEqual => .AssignDiv,
   2287             .PercentEqual => .AssignMod,
   2288             .PlusEqual => .AssignAdd,
   2289             .MinusEqual => .AssignSub,
   2290             .AngleBracketAngleBracketLeftEqual => .AssignBitShiftLeft,
   2291             .AngleBracketAngleBracketRightEqual => .AssignBitShiftRight,
   2292             .AmpersandEqual => .AssignBitAnd,
   2293             .CaretEqual => .AssignBitXor,
   2294             .PipeEqual => .AssignBitOr,
   2295             .AsteriskPercentEqual => .AssignMulWrap,
   2296             .PlusPercentEqual => .AssignAddWrap,
   2297             .MinusPercentEqual => .AssignSubWrap,
   2298             .Equal => .Assign,
   2299             else => {
   2300                 p.putBackToken(token);
   2301                 return null;
   2302             },
   2303         };
   2304 
   2305         const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   2306         node.* = .{
   2307             .base = .{ .tag = op },
   2308             .op_token = token,
   2309             .lhs = undefined, // set by caller
   2310             .rhs = undefined, // set by caller
   2311         };
   2312         return &node.base;
   2313     }
   2314 
   2315     /// CompareOp
   2316     ///     <- EQUALEQUAL
   2317     ///      / EXCLAMATIONMARKEQUAL
   2318     ///      / LARROW
   2319     ///      / RARROW
   2320     ///      / LARROWEQUAL
   2321     ///      / RARROWEQUAL
   2322     fn parseCompareOp(p: *Parser) !?*Node {
   2323         const token = p.nextToken();
   2324         const op: Node.Tag = switch (p.token_ids[token]) {
   2325             .EqualEqual => .EqualEqual,
   2326             .BangEqual => .BangEqual,
   2327             .AngleBracketLeft => .LessThan,
   2328             .AngleBracketRight => .GreaterThan,
   2329             .AngleBracketLeftEqual => .LessOrEqual,
   2330             .AngleBracketRightEqual => .GreaterOrEqual,
   2331             else => {
   2332                 p.putBackToken(token);
   2333                 return null;
   2334             },
   2335         };
   2336 
   2337         return p.createInfixOp(token, op);
   2338     }
   2339 
   2340     /// BitwiseOp
   2341     ///     <- AMPERSAND
   2342     ///      / CARET
   2343     ///      / PIPE
   2344     ///      / KEYWORD_orelse
   2345     ///      / KEYWORD_catch Payload?
   2346     fn parseBitwiseOp(p: *Parser) !?*Node {
   2347         const token = p.nextToken();
   2348         const op: Node.Tag = switch (p.token_ids[token]) {
   2349             .Ampersand => .BitAnd,
   2350             .Caret => .BitXor,
   2351             .Pipe => .BitOr,
   2352             .Keyword_orelse => .OrElse,
   2353             .Keyword_catch => {
   2354                 const payload = try p.parsePayload();
   2355                 const node = try p.arena.allocator.create(Node.Catch);
   2356                 node.* = .{
   2357                     .op_token = token,
   2358                     .lhs = undefined, // set by caller
   2359                     .rhs = undefined, // set by caller
   2360                     .payload = payload,
   2361                 };
   2362                 return &node.base;
   2363             },
   2364             else => {
   2365                 p.putBackToken(token);
   2366                 return null;
   2367             },
   2368         };
   2369 
   2370         return p.createInfixOp(token, op);
   2371     }
   2372 
   2373     /// BitShiftOp
   2374     ///     <- LARROW2
   2375     ///      / RARROW2
   2376     fn parseBitShiftOp(p: *Parser) !?*Node {
   2377         const token = p.nextToken();
   2378         const op: Node.Tag = switch (p.token_ids[token]) {
   2379             .AngleBracketAngleBracketLeft => .BitShiftLeft,
   2380             .AngleBracketAngleBracketRight => .BitShiftRight,
   2381             else => {
   2382                 p.putBackToken(token);
   2383                 return null;
   2384             },
   2385         };
   2386 
   2387         return p.createInfixOp(token, op);
   2388     }
   2389 
   2390     /// AdditionOp
   2391     ///     <- PLUS
   2392     ///      / MINUS
   2393     ///      / PLUS2
   2394     ///      / PLUSPERCENT
   2395     ///      / MINUSPERCENT
   2396     fn parseAdditionOp(p: *Parser) !?*Node {
   2397         const token = p.nextToken();
   2398         const op: Node.Tag = switch (p.token_ids[token]) {
   2399             .Plus => .Add,
   2400             .Minus => .Sub,
   2401             .PlusPlus => .ArrayCat,
   2402             .PlusPercent => .AddWrap,
   2403             .MinusPercent => .SubWrap,
   2404             else => {
   2405                 p.putBackToken(token);
   2406                 return null;
   2407             },
   2408         };
   2409 
   2410         return p.createInfixOp(token, op);
   2411     }
   2412 
   2413     /// MultiplyOp
   2414     ///     <- PIPE2
   2415     ///      / ASTERISK
   2416     ///      / SLASH
   2417     ///      / PERCENT
   2418     ///      / ASTERISK2
   2419     ///      / ASTERISKPERCENT
   2420     fn parseMultiplyOp(p: *Parser) !?*Node {
   2421         const token = p.nextToken();
   2422         const op: Node.Tag = switch (p.token_ids[token]) {
   2423             .PipePipe => .MergeErrorSets,
   2424             .Asterisk => .Mul,
   2425             .Slash => .Div,
   2426             .Percent => .Mod,
   2427             .AsteriskAsterisk => .ArrayMult,
   2428             .AsteriskPercent => .MulWrap,
   2429             else => {
   2430                 p.putBackToken(token);
   2431                 return null;
   2432             },
   2433         };
   2434 
   2435         return p.createInfixOp(token, op);
   2436     }
   2437 
   2438     /// PrefixOp
   2439     ///     <- EXCLAMATIONMARK
   2440     ///      / MINUS
   2441     ///      / TILDE
   2442     ///      / MINUSPERCENT
   2443     ///      / AMPERSAND
   2444     ///      / KEYWORD_try
   2445     ///      / KEYWORD_await
   2446     fn parsePrefixOp(p: *Parser) !?*Node {
   2447         const token = p.nextToken();
   2448         switch (p.token_ids[token]) {
   2449             .Bang => return p.allocSimplePrefixOp(.BoolNot, token),
   2450             .Minus => return p.allocSimplePrefixOp(.Negation, token),
   2451             .Tilde => return p.allocSimplePrefixOp(.BitNot, token),
   2452             .MinusPercent => return p.allocSimplePrefixOp(.NegationWrap, token),
   2453             .Ampersand => return p.allocSimplePrefixOp(.AddressOf, token),
   2454             .Keyword_try => return p.allocSimplePrefixOp(.Try, token),
   2455             .Keyword_await => return p.allocSimplePrefixOp(.Await, token),
   2456             else => {
   2457                 p.putBackToken(token);
   2458                 return null;
   2459             },
   2460         }
   2461     }
   2462 
   2463     fn allocSimplePrefixOp(p: *Parser, comptime tag: Node.Tag, token: TokenIndex) !?*Node {
   2464         const node = try p.arena.allocator.create(Node.SimplePrefixOp);
   2465         node.* = .{
   2466             .base = .{ .tag = tag },
   2467             .op_token = token,
   2468             .rhs = undefined, // set by caller
   2469         };
   2470         return &node.base;
   2471     }
   2472 
   2473     // TODO: ArrayTypeStart is either an array or a slice, but const/allowzero only work on
   2474     //       pointers. Consider updating this rule:
   2475     //       ...
   2476     //       / ArrayTypeStart
   2477     //       / SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
   2478     //       / PtrTypeStart ...
   2479 
   2480     /// PrefixTypeOp
   2481     ///     <- QUESTIONMARK
   2482     ///      / KEYWORD_anyframe MINUSRARROW
   2483     ///      / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
   2484     ///      / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
   2485     fn parsePrefixTypeOp(p: *Parser) !?*Node {
   2486         if (p.eatToken(.QuestionMark)) |token| {
   2487             const node = try p.arena.allocator.create(Node.SimplePrefixOp);
   2488             node.* = .{
   2489                 .base = .{ .tag = .OptionalType },
   2490                 .op_token = token,
   2491                 .rhs = undefined, // set by caller
   2492             };
   2493             return &node.base;
   2494         }
   2495 
   2496         if (p.eatToken(.Keyword_anyframe)) |token| {
   2497             const arrow = p.eatToken(.Arrow) orelse {
   2498                 p.putBackToken(token);
   2499                 return null;
   2500             };
   2501             const node = try p.arena.allocator.create(Node.AnyFrameType);
   2502             node.* = .{
   2503                 .anyframe_token = token,
   2504                 .result = .{
   2505                     .arrow_token = arrow,
   2506                     .return_type = undefined, // set by caller
   2507                 },
   2508             };
   2509             return &node.base;
   2510         }
   2511 
   2512         if (try p.parsePtrTypeStart()) |node| {
   2513             // If the token encountered was **, there will be two nodes instead of one.
   2514             // The attributes should be applied to the rightmost operator.
   2515             var ptr_info = if (node.cast(Node.PtrType)) |ptr_type|
   2516                 if (p.token_ids[ptr_type.op_token] == .AsteriskAsterisk)
   2517                     &ptr_type.rhs.cast(Node.PtrType).?.ptr_info
   2518                 else
   2519                     &ptr_type.ptr_info
   2520             else if (node.cast(Node.SliceType)) |slice_type|
   2521                 &slice_type.ptr_info
   2522             else
   2523                 unreachable;
   2524 
   2525             while (true) {
   2526                 if (p.eatToken(.Keyword_align)) |align_token| {
   2527                     const lparen = try p.expectToken(.LParen);
   2528                     const expr_node = try p.expectNode(parseExpr, .{
   2529                         .ExpectedExpr = .{ .token = p.tok_i },
   2530                     });
   2531 
   2532                     // Optional bit range
   2533                     const bit_range = if (p.eatToken(.Colon)) |_| bit_range_value: {
   2534                         const range_start = try p.expectNode(parseIntegerLiteral, .{
   2535                             .ExpectedIntegerLiteral = .{ .token = p.tok_i },
   2536                         });
   2537                         _ = try p.expectToken(.Colon);
   2538                         const range_end = try p.expectNode(parseIntegerLiteral, .{
   2539                             .ExpectedIntegerLiteral = .{ .token = p.tok_i },
   2540                         });
   2541 
   2542                         break :bit_range_value ast.PtrInfo.Align.BitRange{
   2543                             .start = range_start,
   2544                             .end = range_end,
   2545                         };
   2546                     } else null;
   2547                     _ = try p.expectToken(.RParen);
   2548 
   2549                     if (ptr_info.align_info != null) {
   2550                         try p.errors.append(p.gpa, .{
   2551                             .ExtraAlignQualifier = .{ .token = p.tok_i - 1 },
   2552                         });
   2553                         continue;
   2554                     }
   2555 
   2556                     ptr_info.align_info = ast.PtrInfo.Align{
   2557                         .node = expr_node,
   2558                         .bit_range = bit_range,
   2559                     };
   2560 
   2561                     continue;
   2562                 }
   2563                 if (p.eatToken(.Keyword_const)) |const_token| {
   2564                     if (ptr_info.const_token != null) {
   2565                         try p.errors.append(p.gpa, .{
   2566                             .ExtraConstQualifier = .{ .token = p.tok_i - 1 },
   2567                         });
   2568                         continue;
   2569                     }
   2570                     ptr_info.const_token = const_token;
   2571                     continue;
   2572                 }
   2573                 if (p.eatToken(.Keyword_volatile)) |volatile_token| {
   2574                     if (ptr_info.volatile_token != null) {
   2575                         try p.errors.append(p.gpa, .{
   2576                             .ExtraVolatileQualifier = .{ .token = p.tok_i - 1 },
   2577                         });
   2578                         continue;
   2579                     }
   2580                     ptr_info.volatile_token = volatile_token;
   2581                     continue;
   2582                 }
   2583                 if (p.eatToken(.Keyword_allowzero)) |allowzero_token| {
   2584                     if (ptr_info.allowzero_token != null) {
   2585                         try p.errors.append(p.gpa, .{
   2586                             .ExtraAllowZeroQualifier = .{ .token = p.tok_i - 1 },
   2587                         });
   2588                         continue;
   2589                     }
   2590                     ptr_info.allowzero_token = allowzero_token;
   2591                     continue;
   2592                 }
   2593                 break;
   2594             }
   2595 
   2596             return node;
   2597         }
   2598 
   2599         if (try p.parseArrayTypeStart()) |node| {
   2600             if (node.cast(Node.SliceType)) |slice_type| {
   2601                 // Collect pointer qualifiers in any order, but disallow duplicates
   2602                 while (true) {
   2603                     if (try p.parseByteAlign()) |align_expr| {
   2604                         if (slice_type.ptr_info.align_info != null) {
   2605                             try p.errors.append(p.gpa, .{
   2606                                 .ExtraAlignQualifier = .{ .token = p.tok_i - 1 },
   2607                             });
   2608                             continue;
   2609                         }
   2610                         slice_type.ptr_info.align_info = ast.PtrInfo.Align{
   2611                             .node = align_expr,
   2612                             .bit_range = null,
   2613                         };
   2614                         continue;
   2615                     }
   2616                     if (p.eatToken(.Keyword_const)) |const_token| {
   2617                         if (slice_type.ptr_info.const_token != null) {
   2618                             try p.errors.append(p.gpa, .{
   2619                                 .ExtraConstQualifier = .{ .token = p.tok_i - 1 },
   2620                             });
   2621                             continue;
   2622                         }
   2623                         slice_type.ptr_info.const_token = const_token;
   2624                         continue;
   2625                     }
   2626                     if (p.eatToken(.Keyword_volatile)) |volatile_token| {
   2627                         if (slice_type.ptr_info.volatile_token != null) {
   2628                             try p.errors.append(p.gpa, .{
   2629                                 .ExtraVolatileQualifier = .{ .token = p.tok_i - 1 },
   2630                             });
   2631                             continue;
   2632                         }
   2633                         slice_type.ptr_info.volatile_token = volatile_token;
   2634                         continue;
   2635                     }
   2636                     if (p.eatToken(.Keyword_allowzero)) |allowzero_token| {
   2637                         if (slice_type.ptr_info.allowzero_token != null) {
   2638                             try p.errors.append(p.gpa, .{
   2639                                 .ExtraAllowZeroQualifier = .{ .token = p.tok_i - 1 },
   2640                             });
   2641                             continue;
   2642                         }
   2643                         slice_type.ptr_info.allowzero_token = allowzero_token;
   2644                         continue;
   2645                     }
   2646                     break;
   2647                 }
   2648             }
   2649             return node;
   2650         }
   2651 
   2652         return null;
   2653     }
   2654 
   2655     /// SuffixOp
   2656     ///     <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET
   2657     ///      / DOT IDENTIFIER
   2658     ///      / DOTASTERISK
   2659     ///      / DOTQUESTIONMARK
   2660     fn parseSuffixOp(p: *Parser, lhs: *Node) !?*Node {
   2661         if (p.eatToken(.LBracket)) |_| {
   2662             const index_expr = try p.expectNode(parseExpr, .{
   2663                 .ExpectedExpr = .{ .token = p.tok_i },
   2664             });
   2665 
   2666             if (p.eatToken(.Ellipsis2) != null) {
   2667                 const end_expr = try p.parseExpr();
   2668                 const sentinel: ?*Node = if (p.eatToken(.Colon) != null)
   2669                     try p.parseExpr()
   2670                 else
   2671                     null;
   2672                 const rtoken = try p.expectToken(.RBracket);
   2673                 const node = try p.arena.allocator.create(Node.Slice);
   2674                 node.* = .{
   2675                     .lhs = lhs,
   2676                     .rtoken = rtoken,
   2677                     .start = index_expr,
   2678                     .end = end_expr,
   2679                     .sentinel = sentinel,
   2680                 };
   2681                 return &node.base;
   2682             }
   2683 
   2684             const rtoken = try p.expectToken(.RBracket);
   2685             const node = try p.arena.allocator.create(Node.ArrayAccess);
   2686             node.* = .{
   2687                 .lhs = lhs,
   2688                 .rtoken = rtoken,
   2689                 .index_expr = index_expr,
   2690             };
   2691             return &node.base;
   2692         }
   2693 
   2694         if (p.eatToken(.PeriodAsterisk)) |period_asterisk| {
   2695             const node = try p.arena.allocator.create(Node.SimpleSuffixOp);
   2696             node.* = .{
   2697                 .base = .{ .tag = .Deref },
   2698                 .lhs = lhs,
   2699                 .rtoken = period_asterisk,
   2700             };
   2701             return &node.base;
   2702         }
   2703 
   2704         if (p.eatToken(.Invalid_periodasterisks)) |period_asterisk| {
   2705             try p.errors.append(p.gpa, .{
   2706                 .AsteriskAfterPointerDereference = .{ .token = period_asterisk },
   2707             });
   2708             const node = try p.arena.allocator.create(Node.SimpleSuffixOp);
   2709             node.* = .{
   2710                 .base = .{ .tag = .Deref },
   2711                 .lhs = lhs,
   2712                 .rtoken = period_asterisk,
   2713             };
   2714             return &node.base;
   2715         }
   2716 
   2717         if (p.eatToken(.Period)) |period| {
   2718             if (try p.parseIdentifier()) |identifier| {
   2719                 const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   2720                 node.* = .{
   2721                     .base = Node{ .tag = .Period },
   2722                     .op_token = period,
   2723                     .lhs = lhs,
   2724                     .rhs = identifier,
   2725                 };
   2726                 return &node.base;
   2727             }
   2728             if (p.eatToken(.QuestionMark)) |question_mark| {
   2729                 const node = try p.arena.allocator.create(Node.SimpleSuffixOp);
   2730                 node.* = .{
   2731                     .base = .{ .tag = .UnwrapOptional },
   2732                     .lhs = lhs,
   2733                     .rtoken = question_mark,
   2734                 };
   2735                 return &node.base;
   2736             }
   2737             try p.errors.append(p.gpa, .{
   2738                 .ExpectedSuffixOp = .{ .token = p.tok_i },
   2739             });
   2740             return null;
   2741         }
   2742 
   2743         return null;
   2744     }
   2745 
   2746     /// FnCallArguments <- LPAREN ExprList RPAREN
   2747     /// ExprList <- (Expr COMMA)* Expr?
   2748     fn parseFnCallArguments(p: *Parser) !?AnnotatedParamList {
   2749         if (p.eatToken(.LParen) == null) return null;
   2750         const list = try ListParseFn(*Node, parseExpr)(p);
   2751         errdefer p.gpa.free(list);
   2752         const rparen = try p.expectToken(.RParen);
   2753         return AnnotatedParamList{ .list = list, .rparen = rparen };
   2754     }
   2755 
   2756     const AnnotatedParamList = struct {
   2757         list: []*Node,
   2758         rparen: TokenIndex,
   2759     };
   2760 
   2761     /// ArrayTypeStart <- LBRACKET Expr? RBRACKET
   2762     fn parseArrayTypeStart(p: *Parser) !?*Node {
   2763         const lbracket = p.eatToken(.LBracket) orelse return null;
   2764         const expr = try p.parseExpr();
   2765         const sentinel = if (p.eatToken(.Colon)) |_|
   2766             try p.expectNode(parseExpr, .{
   2767                 .ExpectedExpr = .{ .token = p.tok_i },
   2768             })
   2769         else
   2770             null;
   2771         const rbracket = try p.expectToken(.RBracket);
   2772 
   2773         if (expr) |len_expr| {
   2774             if (sentinel) |s| {
   2775                 const node = try p.arena.allocator.create(Node.ArrayTypeSentinel);
   2776                 node.* = .{
   2777                     .op_token = lbracket,
   2778                     .rhs = undefined, // set by caller
   2779                     .len_expr = len_expr,
   2780                     .sentinel = s,
   2781                 };
   2782                 return &node.base;
   2783             } else {
   2784                 const node = try p.arena.allocator.create(Node.ArrayType);
   2785                 node.* = .{
   2786                     .op_token = lbracket,
   2787                     .rhs = undefined, // set by caller
   2788                     .len_expr = len_expr,
   2789                 };
   2790                 return &node.base;
   2791             }
   2792         }
   2793 
   2794         const node = try p.arena.allocator.create(Node.SliceType);
   2795         node.* = .{
   2796             .op_token = lbracket,
   2797             .rhs = undefined, // set by caller
   2798             .ptr_info = .{ .sentinel = sentinel },
   2799         };
   2800         return &node.base;
   2801     }
   2802 
   2803     /// PtrTypeStart
   2804     ///     <- ASTERISK
   2805     ///      / ASTERISK2
   2806     ///      / PTRUNKNOWN
   2807     ///      / PTRC
   2808     fn parsePtrTypeStart(p: *Parser) !?*Node {
   2809         if (p.eatToken(.Asterisk)) |asterisk| {
   2810             const sentinel = if (p.eatToken(.Colon)) |_|
   2811                 try p.expectNode(parseExpr, .{
   2812                     .ExpectedExpr = .{ .token = p.tok_i },
   2813                 })
   2814             else
   2815                 null;
   2816             const node = try p.arena.allocator.create(Node.PtrType);
   2817             node.* = .{
   2818                 .op_token = asterisk,
   2819                 .rhs = undefined, // set by caller
   2820                 .ptr_info = .{ .sentinel = sentinel },
   2821             };
   2822             return &node.base;
   2823         }
   2824 
   2825         if (p.eatToken(.AsteriskAsterisk)) |double_asterisk| {
   2826             const node = try p.arena.allocator.create(Node.PtrType);
   2827             node.* = .{
   2828                 .op_token = double_asterisk,
   2829                 .rhs = undefined, // set by caller
   2830             };
   2831 
   2832             // Special case for **, which is its own token
   2833             const child = try p.arena.allocator.create(Node.PtrType);
   2834             child.* = .{
   2835                 .op_token = double_asterisk,
   2836                 .rhs = undefined, // set by caller
   2837             };
   2838             node.rhs = &child.base;
   2839 
   2840             return &node.base;
   2841         }
   2842         if (p.eatToken(.LBracket)) |lbracket| {
   2843             const asterisk = p.eatToken(.Asterisk) orelse {
   2844                 p.putBackToken(lbracket);
   2845                 return null;
   2846             };
   2847             if (p.eatToken(.Identifier)) |ident| {
   2848                 const token_loc = p.token_locs[ident];
   2849                 const token_slice = p.source[token_loc.start..token_loc.end];
   2850                 if (!std.mem.eql(u8, token_slice, "c")) {
   2851                     p.putBackToken(ident);
   2852                 } else {
   2853                     _ = try p.expectToken(.RBracket);
   2854                     const node = try p.arena.allocator.create(Node.PtrType);
   2855                     node.* = .{
   2856                         .op_token = lbracket,
   2857                         .rhs = undefined, // set by caller
   2858                     };
   2859                     return &node.base;
   2860                 }
   2861             }
   2862             const sentinel = if (p.eatToken(.Colon)) |_|
   2863                 try p.expectNode(parseExpr, .{
   2864                     .ExpectedExpr = .{ .token = p.tok_i },
   2865                 })
   2866             else
   2867                 null;
   2868             _ = try p.expectToken(.RBracket);
   2869             const node = try p.arena.allocator.create(Node.PtrType);
   2870             node.* = .{
   2871                 .op_token = lbracket,
   2872                 .rhs = undefined, // set by caller
   2873                 .ptr_info = .{ .sentinel = sentinel },
   2874             };
   2875             return &node.base;
   2876         }
   2877         return null;
   2878     }
   2879 
   2880     /// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
   2881     fn parseContainerDeclAuto(p: *Parser) !?*Node {
   2882         const container_decl_type = (try p.parseContainerDeclType()) orelse return null;
   2883         const lbrace = try p.expectToken(.LBrace);
   2884         const members = try p.parseContainerMembers(false);
   2885         defer p.gpa.free(members);
   2886         const rbrace = try p.expectToken(.RBrace);
   2887 
   2888         const members_len = @intCast(NodeIndex, members.len);
   2889         const node = try Node.ContainerDecl.alloc(&p.arena.allocator, members_len);
   2890         node.* = .{
   2891             .layout_token = null,
   2892             .kind_token = container_decl_type.kind_token,
   2893             .init_arg_expr = container_decl_type.init_arg_expr,
   2894             .fields_and_decls_len = members_len,
   2895             .lbrace_token = lbrace,
   2896             .rbrace_token = rbrace,
   2897         };
   2898         std.mem.copy(*Node, node.fieldsAndDecls(), members);
   2899         return &node.base;
   2900     }
   2901 
   2902     /// Holds temporary data until we are ready to construct the full ContainerDecl AST node.
   2903     const ContainerDeclType = struct {
   2904         kind_token: TokenIndex,
   2905         init_arg_expr: Node.ContainerDecl.InitArg,
   2906     };
   2907 
   2908     /// ContainerDeclType
   2909     ///     <- KEYWORD_struct
   2910     ///      / KEYWORD_enum (LPAREN Expr RPAREN)?
   2911     ///      / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
   2912     ///      / KEYWORD_opaque
   2913     fn parseContainerDeclType(p: *Parser) !?ContainerDeclType {
   2914         const kind_token = p.nextToken();
   2915 
   2916         const init_arg_expr = switch (p.token_ids[kind_token]) {
   2917             .Keyword_struct, .Keyword_opaque => Node.ContainerDecl.InitArg{ .None = {} },
   2918             .Keyword_enum => blk: {
   2919                 if (p.eatToken(.LParen) != null) {
   2920                     const expr = try p.expectNode(parseExpr, .{
   2921                         .ExpectedExpr = .{ .token = p.tok_i },
   2922                     });
   2923                     _ = try p.expectToken(.RParen);
   2924                     break :blk Node.ContainerDecl.InitArg{ .Type = expr };
   2925                 }
   2926                 break :blk Node.ContainerDecl.InitArg{ .None = {} };
   2927             },
   2928             .Keyword_union => blk: {
   2929                 if (p.eatToken(.LParen) != null) {
   2930                     if (p.eatToken(.Keyword_enum) != null) {
   2931                         if (p.eatToken(.LParen) != null) {
   2932                             const expr = try p.expectNode(parseExpr, .{
   2933                                 .ExpectedExpr = .{ .token = p.tok_i },
   2934                             });
   2935                             _ = try p.expectToken(.RParen);
   2936                             _ = try p.expectToken(.RParen);
   2937                             break :blk Node.ContainerDecl.InitArg{ .Enum = expr };
   2938                         }
   2939                         _ = try p.expectToken(.RParen);
   2940                         break :blk Node.ContainerDecl.InitArg{ .Enum = null };
   2941                     }
   2942                     const expr = try p.expectNode(parseExpr, .{
   2943                         .ExpectedExpr = .{ .token = p.tok_i },
   2944                     });
   2945                     _ = try p.expectToken(.RParen);
   2946                     break :blk Node.ContainerDecl.InitArg{ .Type = expr };
   2947                 }
   2948                 break :blk Node.ContainerDecl.InitArg{ .None = {} };
   2949             },
   2950             else => {
   2951                 p.putBackToken(kind_token);
   2952                 return null;
   2953             },
   2954         };
   2955 
   2956         return ContainerDeclType{
   2957             .kind_token = kind_token,
   2958             .init_arg_expr = init_arg_expr,
   2959         };
   2960     }
   2961 
   2962     /// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
   2963     fn parseByteAlign(p: *Parser) !?*Node {
   2964         _ = p.eatToken(.Keyword_align) orelse return null;
   2965         _ = try p.expectToken(.LParen);
   2966         const expr = try p.expectNode(parseExpr, .{
   2967             .ExpectedExpr = .{ .token = p.tok_i },
   2968         });
   2969         _ = try p.expectToken(.RParen);
   2970         return expr;
   2971     }
   2972 
   2973     /// IdentifierList <- (IDENTIFIER COMMA)* IDENTIFIER?
   2974     /// Only ErrorSetDecl parses an IdentifierList
   2975     fn parseErrorTagList(p: *Parser) ![]*Node {
   2976         return ListParseFn(*Node, parseErrorTag)(p);
   2977     }
   2978 
   2979     /// SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
   2980     fn parseSwitchProngList(p: *Parser) ![]*Node {
   2981         return ListParseFn(*Node, parseSwitchProng)(p);
   2982     }
   2983 
   2984     /// AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem?
   2985     fn parseAsmOutputList(p: *Parser) Error![]Node.Asm.Output {
   2986         return ListParseFn(Node.Asm.Output, parseAsmOutputItem)(p);
   2987     }
   2988 
   2989     /// AsmInputList <- (AsmInputItem COMMA)* AsmInputItem?
   2990     fn parseAsmInputList(p: *Parser) Error![]Node.Asm.Input {
   2991         return ListParseFn(Node.Asm.Input, parseAsmInputItem)(p);
   2992     }
   2993 
   2994     /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
   2995     fn parseParamDeclList(p: *Parser) ![]Node.FnProto.ParamDecl {
   2996         return ListParseFn(Node.FnProto.ParamDecl, parseParamDecl)(p);
   2997     }
   2998 
   2999     const NodeParseFn = fn (p: *Parser) Error!?*Node;
   3000 
   3001     fn ListParseFn(comptime E: type, comptime nodeParseFn: anytype) ParseFn([]E) {
   3002         return struct {
   3003             pub fn parse(p: *Parser) ![]E {
   3004                 var list = std.ArrayList(E).init(p.gpa);
   3005                 defer list.deinit();
   3006 
   3007                 while (try nodeParseFn(p)) |item| {
   3008                     try list.append(item);
   3009 
   3010                     switch (p.token_ids[p.tok_i]) {
   3011                         .Comma => _ = p.nextToken(),
   3012                         // all possible delimiters
   3013                         .Colon, .RParen, .RBrace, .RBracket => break,
   3014                         else => {
   3015                             // this is likely just a missing comma,
   3016                             // continue parsing this list and give an error
   3017                             try p.errors.append(p.gpa, .{
   3018                                 .ExpectedToken = .{ .token = p.tok_i, .expected_id = .Comma },
   3019                             });
   3020                         },
   3021                     }
   3022                 }
   3023                 return list.toOwnedSlice();
   3024             }
   3025         }.parse;
   3026     }
   3027 
   3028     fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.Tag) NodeParseFn {
   3029         return struct {
   3030             pub fn parse(p: *Parser) Error!?*Node {
   3031                 const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) {
   3032                     .Keyword_and => p.nextToken(),
   3033                     .Invalid_ampersands => blk: {
   3034                         try p.errors.append(p.gpa, .{
   3035                             .InvalidAnd = .{ .token = p.tok_i },
   3036                         });
   3037                         break :blk p.nextToken();
   3038                     },
   3039                     else => return null,
   3040                 } else p.eatToken(token) orelse return null;
   3041 
   3042                 const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   3043                 node.* = .{
   3044                     .base = .{ .tag = op },
   3045                     .op_token = op_token,
   3046                     .lhs = undefined, // set by caller
   3047                     .rhs = undefined, // set by caller
   3048                 };
   3049                 return &node.base;
   3050             }
   3051         }.parse;
   3052     }
   3053 
   3054     // Helper parsers not included in the grammar
   3055 
   3056     fn parseBuiltinCall(p: *Parser) !?*Node {
   3057         const token = p.eatToken(.Builtin) orelse return null;
   3058         const params = (try p.parseFnCallArguments()) orelse {
   3059             try p.errors.append(p.gpa, .{
   3060                 .ExpectedParamList = .{ .token = p.tok_i },
   3061             });
   3062 
   3063             // lets pretend this was an identifier so we can continue parsing
   3064             const node = try p.arena.allocator.create(Node.OneToken);
   3065             node.* = .{
   3066                 .base = .{ .tag = .Identifier },
   3067                 .token = token,
   3068             };
   3069             return &node.base;
   3070         };
   3071         defer p.gpa.free(params.list);
   3072 
   3073         const node = try Node.BuiltinCall.alloc(&p.arena.allocator, params.list.len);
   3074         node.* = .{
   3075             .builtin_token = token,
   3076             .params_len = params.list.len,
   3077             .rparen_token = params.rparen,
   3078         };
   3079         std.mem.copy(*Node, node.params(), params.list);
   3080         return &node.base;
   3081     }
   3082 
   3083     fn parseErrorTag(p: *Parser) !?*Node {
   3084         const doc_comments = try p.parseDocComment(); // no need to rewind on failure
   3085         const token = p.eatToken(.Identifier) orelse return null;
   3086 
   3087         const node = try p.arena.allocator.create(Node.ErrorTag);
   3088         node.* = .{
   3089             .doc_comments = doc_comments,
   3090             .name_token = token,
   3091         };
   3092         return &node.base;
   3093     }
   3094 
   3095     fn parseIdentifier(p: *Parser) !?*Node {
   3096         const token = p.eatToken(.Identifier) orelse return null;
   3097         const node = try p.arena.allocator.create(Node.OneToken);
   3098         node.* = .{
   3099             .base = .{ .tag = .Identifier },
   3100             .token = token,
   3101         };
   3102         return &node.base;
   3103     }
   3104 
   3105     fn parseAnyType(p: *Parser) !?*Node {
   3106         const token = p.eatToken(.Keyword_anytype) orelse
   3107             p.eatToken(.Keyword_var) orelse return null; // TODO remove in next release cycle
   3108         const node = try p.arena.allocator.create(Node.OneToken);
   3109         node.* = .{
   3110             .base = .{ .tag = .AnyType },
   3111             .token = token,
   3112         };
   3113         return &node.base;
   3114     }
   3115 
   3116     fn createLiteral(p: *Parser, tag: ast.Node.Tag, token: TokenIndex) !*Node {
   3117         const result = try p.arena.allocator.create(Node.OneToken);
   3118         result.* = .{
   3119             .base = .{ .tag = tag },
   3120             .token = token,
   3121         };
   3122         return &result.base;
   3123     }
   3124 
   3125     fn parseStringLiteralSingle(p: *Parser) !?*Node {
   3126         if (p.eatToken(.StringLiteral)) |token| {
   3127             const node = try p.arena.allocator.create(Node.OneToken);
   3128             node.* = .{
   3129                 .base = .{ .tag = .StringLiteral },
   3130                 .token = token,
   3131             };
   3132             return &node.base;
   3133         }
   3134         return null;
   3135     }
   3136 
   3137     // string literal or multiline string literal
   3138     fn parseStringLiteral(p: *Parser) !?*Node {
   3139         if (try p.parseStringLiteralSingle()) |node| return node;
   3140 
   3141         if (p.eatToken(.MultilineStringLiteralLine)) |first_line| {
   3142             const start_tok_i = p.tok_i;
   3143             var tok_i = start_tok_i;
   3144             var count: usize = 1; // including first_line
   3145             while (true) : (tok_i += 1) {
   3146                 switch (p.token_ids[tok_i]) {
   3147                     .LineComment => continue,
   3148                     .MultilineStringLiteralLine => count += 1,
   3149                     else => break,
   3150                 }
   3151             }
   3152 
   3153             const node = try Node.MultilineStringLiteral.alloc(&p.arena.allocator, count);
   3154             node.* = .{ .lines_len = count };
   3155             const lines = node.lines();
   3156             tok_i = start_tok_i;
   3157             lines[0] = first_line;
   3158             count = 1;
   3159             while (true) : (tok_i += 1) {
   3160                 switch (p.token_ids[tok_i]) {
   3161                     .LineComment => continue,
   3162                     .MultilineStringLiteralLine => {
   3163                         lines[count] = tok_i;
   3164                         count += 1;
   3165                     },
   3166                     else => break,
   3167                 }
   3168             }
   3169             p.tok_i = tok_i;
   3170             return &node.base;
   3171         }
   3172 
   3173         return null;
   3174     }
   3175 
   3176     fn parseIntegerLiteral(p: *Parser) !?*Node {
   3177         const token = p.eatToken(.IntegerLiteral) orelse return null;
   3178         const node = try p.arena.allocator.create(Node.OneToken);
   3179         node.* = .{
   3180             .base = .{ .tag = .IntegerLiteral },
   3181             .token = token,
   3182         };
   3183         return &node.base;
   3184     }
   3185 
   3186     fn parseFloatLiteral(p: *Parser) !?*Node {
   3187         const token = p.eatToken(.FloatLiteral) orelse return null;
   3188         const node = try p.arena.allocator.create(Node.OneToken);
   3189         node.* = .{
   3190             .base = .{ .tag = .FloatLiteral },
   3191             .token = token,
   3192         };
   3193         return &node.base;
   3194     }
   3195 
   3196     fn parseTry(p: *Parser) !?*Node {
   3197         const token = p.eatToken(.Keyword_try) orelse return null;
   3198         const node = try p.arena.allocator.create(Node.SimplePrefixOp);
   3199         node.* = .{
   3200             .base = .{ .tag = .Try },
   3201             .op_token = token,
   3202             .rhs = undefined, // set by caller
   3203         };
   3204         return &node.base;
   3205     }
   3206 
   3207     /// IfPrefix Body (KEYWORD_else Payload? Body)?
   3208     fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !?*Node {
   3209         const node = (try p.parseIfPrefix()) orelse return null;
   3210         const if_prefix = node.cast(Node.If).?;
   3211 
   3212         if_prefix.body = try p.expectNode(bodyParseFn, .{
   3213             .InvalidToken = .{ .token = p.tok_i },
   3214         });
   3215 
   3216         const else_token = p.eatToken(.Keyword_else) orelse return node;
   3217         const payload = try p.parsePayload();
   3218         const else_expr = try p.expectNode(bodyParseFn, .{
   3219             .InvalidToken = .{ .token = p.tok_i },
   3220         });
   3221         const else_node = try p.arena.allocator.create(Node.Else);
   3222         else_node.* = .{
   3223             .else_token = else_token,
   3224             .payload = payload,
   3225             .body = else_expr,
   3226         };
   3227         if_prefix.@"else" = else_node;
   3228 
   3229         return node;
   3230     }
   3231 
   3232     /// Eat a multiline doc comment
   3233     fn parseDocComment(p: *Parser) !?*Node.DocComment {
   3234         if (p.eatToken(.DocComment)) |first_line| {
   3235             while (p.eatToken(.DocComment)) |_| {}
   3236             const node = try p.arena.allocator.create(Node.DocComment);
   3237             node.* = .{ .first_line = first_line };
   3238             return node;
   3239         }
   3240         return null;
   3241     }
   3242 
   3243     fn tokensOnSameLine(p: *Parser, token1: TokenIndex, token2: TokenIndex) bool {
   3244         return std.mem.indexOfScalar(u8, p.source[p.token_locs[token1].end..p.token_locs[token2].start], '\n') == null;
   3245     }
   3246 
   3247     /// Eat a single-line doc comment on the same line as another node
   3248     fn parseAppendedDocComment(p: *Parser, after_token: TokenIndex) !?*Node.DocComment {
   3249         const comment_token = p.eatToken(.DocComment) orelse return null;
   3250         if (p.tokensOnSameLine(after_token, comment_token)) {
   3251             const node = try p.arena.allocator.create(Node.DocComment);
   3252             node.* = .{ .first_line = comment_token };
   3253             return node;
   3254         }
   3255         p.putBackToken(comment_token);
   3256         return null;
   3257     }
   3258 
   3259     /// Op* Child
   3260     fn parsePrefixOpExpr(p: *Parser, comptime opParseFn: NodeParseFn, comptime childParseFn: NodeParseFn) Error!?*Node {
   3261         if (try opParseFn(p)) |first_op| {
   3262             var rightmost_op = first_op;
   3263             while (true) {
   3264                 switch (rightmost_op.tag) {
   3265                     .AddressOf,
   3266                     .Await,
   3267                     .BitNot,
   3268                     .BoolNot,
   3269                     .OptionalType,
   3270                     .Negation,
   3271                     .NegationWrap,
   3272                     .Resume,
   3273                     .Try,
   3274                     => {
   3275                         if (try opParseFn(p)) |rhs| {
   3276                             rightmost_op.cast(Node.SimplePrefixOp).?.rhs = rhs;
   3277                             rightmost_op = rhs;
   3278                         } else break;
   3279                     },
   3280                     .ArrayType => {
   3281                         if (try opParseFn(p)) |rhs| {
   3282                             rightmost_op.cast(Node.ArrayType).?.rhs = rhs;
   3283                             rightmost_op = rhs;
   3284                         } else break;
   3285                     },
   3286                     .ArrayTypeSentinel => {
   3287                         if (try opParseFn(p)) |rhs| {
   3288                             rightmost_op.cast(Node.ArrayTypeSentinel).?.rhs = rhs;
   3289                             rightmost_op = rhs;
   3290                         } else break;
   3291                     },
   3292                     .SliceType => {
   3293                         if (try opParseFn(p)) |rhs| {
   3294                             rightmost_op.cast(Node.SliceType).?.rhs = rhs;
   3295                             rightmost_op = rhs;
   3296                         } else break;
   3297                     },
   3298                     .PtrType => {
   3299                         var ptr_type = rightmost_op.cast(Node.PtrType).?;
   3300                         // If the token encountered was **, there will be two nodes
   3301                         if (p.token_ids[ptr_type.op_token] == .AsteriskAsterisk) {
   3302                             rightmost_op = ptr_type.rhs;
   3303                             ptr_type = rightmost_op.cast(Node.PtrType).?;
   3304                         }
   3305                         if (try opParseFn(p)) |rhs| {
   3306                             ptr_type.rhs = rhs;
   3307                             rightmost_op = rhs;
   3308                         } else break;
   3309                     },
   3310                     .AnyFrameType => {
   3311                         const prom = rightmost_op.cast(Node.AnyFrameType).?;
   3312                         if (try opParseFn(p)) |rhs| {
   3313                             prom.result.?.return_type = rhs;
   3314                             rightmost_op = rhs;
   3315                         } else break;
   3316                     },
   3317                     else => unreachable,
   3318                 }
   3319             }
   3320 
   3321             // If any prefix op existed, a child node on the RHS is required
   3322             switch (rightmost_op.tag) {
   3323                 .AddressOf,
   3324                 .Await,
   3325                 .BitNot,
   3326                 .BoolNot,
   3327                 .OptionalType,
   3328                 .Negation,
   3329                 .NegationWrap,
   3330                 .Resume,
   3331                 .Try,
   3332                 => {
   3333                     const prefix_op = rightmost_op.cast(Node.SimplePrefixOp).?;
   3334                     prefix_op.rhs = try p.expectNode(childParseFn, .{
   3335                         .InvalidToken = .{ .token = p.tok_i },
   3336                     });
   3337                 },
   3338                 .ArrayType => {
   3339                     const prefix_op = rightmost_op.cast(Node.ArrayType).?;
   3340                     prefix_op.rhs = try p.expectNode(childParseFn, .{
   3341                         .InvalidToken = .{ .token = p.tok_i },
   3342                     });
   3343                 },
   3344                 .ArrayTypeSentinel => {
   3345                     const prefix_op = rightmost_op.cast(Node.ArrayTypeSentinel).?;
   3346                     prefix_op.rhs = try p.expectNode(childParseFn, .{
   3347                         .InvalidToken = .{ .token = p.tok_i },
   3348                     });
   3349                 },
   3350                 .PtrType => {
   3351                     const prefix_op = rightmost_op.cast(Node.PtrType).?;
   3352                     prefix_op.rhs = try p.expectNode(childParseFn, .{
   3353                         .InvalidToken = .{ .token = p.tok_i },
   3354                     });
   3355                 },
   3356                 .SliceType => {
   3357                     const prefix_op = rightmost_op.cast(Node.SliceType).?;
   3358                     prefix_op.rhs = try p.expectNode(childParseFn, .{
   3359                         .InvalidToken = .{ .token = p.tok_i },
   3360                     });
   3361                 },
   3362                 .AnyFrameType => {
   3363                     const prom = rightmost_op.cast(Node.AnyFrameType).?;
   3364                     prom.result.?.return_type = try p.expectNode(childParseFn, .{
   3365                         .InvalidToken = .{ .token = p.tok_i },
   3366                     });
   3367                 },
   3368                 else => unreachable,
   3369             }
   3370 
   3371             return first_op;
   3372         }
   3373 
   3374         // Otherwise, the child node is optional
   3375         return childParseFn(p);
   3376     }
   3377 
   3378     /// Child (Op Child)*
   3379     /// Child (Op Child)?
   3380     fn parseBinOpExpr(
   3381         p: *Parser,
   3382         opParseFn: NodeParseFn,
   3383         childParseFn: NodeParseFn,
   3384         chain: enum {
   3385             Once,
   3386             Infinitely,
   3387         },
   3388     ) Error!?*Node {
   3389         var res = (try childParseFn(p)) orelse return null;
   3390 
   3391         while (try opParseFn(p)) |node| {
   3392             const right = try p.expectNode(childParseFn, .{
   3393                 .InvalidToken = .{ .token = p.tok_i },
   3394             });
   3395             const left = res;
   3396             res = node;
   3397 
   3398             if (node.castTag(.Catch)) |op| {
   3399                 op.lhs = left;
   3400                 op.rhs = right;
   3401             } else if (node.cast(Node.SimpleInfixOp)) |op| {
   3402                 op.lhs = left;
   3403                 op.rhs = right;
   3404             }
   3405 
   3406             switch (chain) {
   3407                 .Once => break,
   3408                 .Infinitely => continue,
   3409             }
   3410         }
   3411 
   3412         return res;
   3413     }
   3414 
   3415     fn createInfixOp(p: *Parser, op_token: TokenIndex, tag: Node.Tag) !*Node {
   3416         const node = try p.arena.allocator.create(Node.SimpleInfixOp);
   3417         node.* = .{
   3418             .base = Node{ .tag = tag },
   3419             .op_token = op_token,
   3420             .lhs = undefined, // set by caller
   3421             .rhs = undefined, // set by caller
   3422         };
   3423         return &node.base;
   3424     }
   3425 
   3426     fn eatToken(p: *Parser, id: Token.Id) ?TokenIndex {
   3427         return if (p.token_ids[p.tok_i] == id) p.nextToken() else null;
   3428     }
   3429 
   3430     fn expectToken(p: *Parser, id: Token.Id) Error!TokenIndex {
   3431         return (try p.expectTokenRecoverable(id)) orelse error.ParseError;
   3432     }
   3433 
   3434     fn expectTokenRecoverable(p: *Parser, id: Token.Id) !?TokenIndex {
   3435         const token = p.nextToken();
   3436         if (p.token_ids[token] != id) {
   3437             try p.errors.append(p.gpa, .{
   3438                 .ExpectedToken = .{ .token = token, .expected_id = id },
   3439             });
   3440             // go back so that we can recover properly
   3441             p.putBackToken(token);
   3442             return null;
   3443         }
   3444         return token;
   3445     }
   3446 
   3447     fn nextToken(p: *Parser) TokenIndex {
   3448         const result = p.tok_i;
   3449         p.tok_i += 1;
   3450         assert(p.token_ids[result] != .LineComment);
   3451         if (p.tok_i >= p.token_ids.len) return result;
   3452 
   3453         while (true) {
   3454             if (p.token_ids[p.tok_i] != .LineComment) return result;
   3455             p.tok_i += 1;
   3456         }
   3457     }
   3458 
   3459     fn putBackToken(p: *Parser, putting_back: TokenIndex) void {
   3460         while (p.tok_i > 0) {
   3461             p.tok_i -= 1;
   3462             if (p.token_ids[p.tok_i] == .LineComment) continue;
   3463             assert(putting_back == p.tok_i);
   3464             return;
   3465         }
   3466     }
   3467 
   3468     /// TODO Delete this function. I don't like the inversion of control.
   3469     fn expectNode(
   3470         p: *Parser,
   3471         parseFn: NodeParseFn,
   3472         /// if parsing fails
   3473         err: AstError,
   3474     ) Error!*Node {
   3475         return (try p.expectNodeRecoverable(parseFn, err)) orelse return error.ParseError;
   3476     }
   3477 
   3478     /// TODO Delete this function. I don't like the inversion of control.
   3479     fn expectNodeRecoverable(
   3480         p: *Parser,
   3481         parseFn: NodeParseFn,
   3482         /// if parsing fails
   3483         err: AstError,
   3484     ) !?*Node {
   3485         return (try parseFn(p)) orelse {
   3486             try p.errors.append(p.gpa, err);
   3487             return null;
   3488         };
   3489     }
   3490 };
   3491 
   3492 fn ParseFn(comptime T: type) type {
   3493     return fn (p: *Parser) Error!T;
   3494 }
   3495 
   3496 test "std.zig.parser" {
   3497     _ = @import("parser_test.zig");
   3498 }