| ... | ... | @@ -232,6 +232,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top |
| 232 | 232 | switch (next) { |
| 233 | 233 | .Eof => break, |
| 234 | 234 | else => { |
| 235 | const index = it.index; |
| 235 | 236 | if (next == .RBrace) { |
| 236 | 237 | if (!top_level) break; |
| 237 | 238 | _ = nextToken(it); |
| ... | ... | @@ -239,7 +240,6 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top |
| 239 | 240 | |
| 240 | 241 | // this was likely not supposed to end yet, |
| 241 | 242 | // try to find the next declaration |
| 242 | | const index = it.index; |
| 243 | 243 | findNextContainerMember(it); |
| 244 | 244 | try tree.errors.push(.{ |
| 245 | 245 | .ExpectedContainerMembers = .{ .token = index }, |
| ... | ... | @@ -411,20 +411,16 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 411 | 411 | fn_node.*.extern_export_inline_token = extern_export_inline_token; |
| 412 | 412 | fn_node.*.lib_name = lib_name; |
| 413 | 413 | if (eatToken(it, .Semicolon)) |_| return node; |
| 414 | | if (parseBlock(arena, it, tree) catch |err| switch (err) { |
| 415 | | error.OutOfMemory => return error.OutOfMemory, |
| 414 | |
| 415 | if (try expectNodeRecoverable(arena, it, tree, parseBlock, .{ |
| 416 | 416 | // since parseBlock only return error.ParseError on |
| 417 | 417 | // a missing '}' we can assume this function was |
| 418 | 418 | // supposed to end here. |
| 419 | | error.ParseError => return node, |
| 420 | | }) |body_node| { |
| 419 | .ExpectedSemiOrLBrace = .{ .token = it.index }, |
| 420 | })) |body_node| { |
| 421 | 421 | fn_node.body_node = body_node; |
| 422 | | return node; |
| 423 | 422 | } |
| 424 | | try tree.errors.push(.{ |
| 425 | | .ExpectedSemiOrLBrace = .{ .token = it.index }, |
| 426 | | }); |
| 427 | | return error.ParseError; |
| 423 | return node; |
| 428 | 424 | } |
| 429 | 425 | |
| 430 | 426 | if (extern_export_inline_token) |token| { |
| ... | ... | @@ -499,14 +495,11 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 499 | 495 | const exclamation_token = eatToken(it, .Bang); |
| 500 | 496 | |
| 501 | 497 | const return_type_expr = (try parseVarType(arena, it, tree)) orelse |
| 502 | | (try parseTypeExpr(arena, it, tree)) orelse blk: { |
| 503 | | try tree.errors.push(.{ |
| 504 | | .ExpectedReturnType = .{ .token = it.index }, |
| 505 | | }); |
| 498 | try expectNodeRecoverable(arena, it, tree, parseTypeExpr, .{ |
| 506 | 499 | // most likely the user forgot to specify the return type. |
| 507 | 500 | // Mark return type as invalid and try to continue. |
| 508 | | break :blk null; |
| 509 | | }; |
| 501 | .ExpectedReturnType = .{ .token = it.index }, |
| 502 | }); |
| 510 | 503 | |
| 511 | 504 | // TODO https://github.com/ziglang/zig/issues/3750 |
| 512 | 505 | const R = Node.FnProto.ReturnType; |
| ... | ... | @@ -716,12 +709,7 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No |
| 716 | 709 | if (try parseLabeledStatement(arena, it, tree)) |node| return node; |
| 717 | 710 | if (try parseSwitchExpr(arena, it, tree)) |node| return node; |
| 718 | 711 | if (try parseAssignExpr(arena, it, tree)) |node| { |
| 719 | | _ = eatToken(it, .Semicolon) orelse { |
| 720 | | try tree.errors.push(.{ |
| 721 | | .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, |
| 722 | | }); |
| 723 | | // pretend we saw a semicolon and continue parsing |
| 724 | | }; |
| 712 | _ = try expectTokenRecoverable(it, tree, .Semicolon); |
| 725 | 713 | return node; |
| 726 | 714 | } |
| 727 | 715 | |
| ... | ... | @@ -965,12 +953,7 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No |
| 965 | 953 | fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 966 | 954 | if (try parseBlockExpr(arena, it, tree)) |node| return node; |
| 967 | 955 | if (try parseAssignExpr(arena, it, tree)) |node| { |
| 968 | | _ = eatToken(it, .Semicolon) orelse { |
| 969 | | try tree.errors.push(.{ |
| 970 | | .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, |
| 971 | | }); |
| 972 | | // pretend we saw a semicolon and continue parsing |
| 973 | | }; |
| 956 | _ = try expectTokenRecoverable(it, tree, .Semicolon); |
| 974 | 957 | return node; |
| 975 | 958 | } |
| 976 | 959 | return null; |
| ... | ... | @@ -1487,17 +1470,19 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N |
| 1487 | 1470 | return &node.base; |
| 1488 | 1471 | } |
| 1489 | 1472 | if (eatToken(it, .Keyword_error)) |token| { |
| 1490 | | const period = try expectToken(it, tree, .Period); |
| 1491 | | const identifier = try expectNode(arena, it, tree, parseIdentifier, .{ |
| 1473 | const period = try expectTokenRecoverable(it, tree, .Period); |
| 1474 | const identifier = try expectNodeRecoverable(arena, it, tree, parseIdentifier, .{ |
| 1492 | 1475 | .ExpectedIdentifier = .{ .token = it.index }, |
| 1493 | 1476 | }); |
| 1494 | 1477 | const global_error_set = try createLiteral(arena, Node.ErrorType, token); |
| 1478 | if (period == null or identifier == null) return global_error_set; |
| 1479 | |
| 1495 | 1480 | const node = try arena.create(Node.InfixOp); |
| 1496 | 1481 | node.* = .{ |
| 1497 | | .op_token = period, |
| 1482 | .op_token = period.?, |
| 1498 | 1483 | .lhs = global_error_set, |
| 1499 | 1484 | .op = .Period, |
| 1500 | | .rhs = identifier, |
| 1485 | .rhs = identifier.?, |
| 1501 | 1486 | }; |
| 1502 | 1487 | return &node.base; |
| 1503 | 1488 | } |
| ... | ... | @@ -3259,6 +3244,11 @@ fn eatAnnotatedToken(it: *TokenIterator, id: Token.Id) ?AnnotatedToken { |
| 3259 | 3244 | } |
| 3260 | 3245 | |
| 3261 | 3246 | fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex { |
| 3247 | return (try expectTokenRecoverable(it, tree, id)) orelse |
| 3248 | error.ParseError; |
| 3249 | } |
| 3250 | |
| 3251 | fn expectTokenRecoverable(it: *TokenIterator, tree: *Tree, id: Token.Id) !?TokenIndex { |
| 3262 | 3252 | const token = nextToken(it); |
| 3263 | 3253 | if (token.ptr.id != id) { |
| 3264 | 3254 | try tree.errors.push(.{ |
| ... | ... | @@ -3266,7 +3256,7 @@ fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex { |
| 3266 | 3256 | }); |
| 3267 | 3257 | // go back so that we can recover properly |
| 3268 | 3258 | putBackToken(it, token.index); |
| 3269 | | return error.ParseError; |
| 3259 | return null; |
| 3270 | 3260 | } |
| 3271 | 3261 | return token.index; |
| 3272 | 3262 | } |
| ... | ... | @@ -3306,9 +3296,20 @@ fn expectNode( |
| 3306 | 3296 | parseFn: NodeParseFn, |
| 3307 | 3297 | err: AstError, // if parsing fails |
| 3308 | 3298 | ) Error!*Node { |
| 3299 | return (try expectNodeRecoverable(arena, it, tree, parseFn, err)) orelse |
| 3300 | return error.ParseError; |
| 3301 | } |
| 3302 | |
| 3303 | fn expectNodeRecoverable( |
| 3304 | arena: *Allocator, |
| 3305 | it: *TokenIterator, |
| 3306 | tree: *Tree, |
| 3307 | parseFn: NodeParseFn, |
| 3308 | err: AstError, // if parsing fails |
| 3309 | ) !?*Node { |
| 3309 | 3310 | return (try parseFn(arena, it, tree)) orelse { |
| 3310 | 3311 | try tree.errors.push(err); |
| 3311 | | return error.ParseError; |
| 3312 | return null; |
| 3312 | 3313 | }; |
| 3313 | 3314 | } |
| 3314 | 3315 | |