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