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 }