| ... | ... | @@ -160,6 +160,12 @@ const Parser = struct { |
| 160 | 160 | .extra = .{ .expected_tag = expected_token }, |
| 161 | 161 | }); |
| 162 | 162 | } |
| 163 | |
| 164 | fn warnExpectedAfter(p: *Parser, error_tag: AstError.Tag) error{OutOfMemory}!void { |
| 165 | @setCold(true); |
| 166 | try p.warnMsg(.{ .tag = error_tag, .token = p.tok_i - 1 }); |
| 167 | } |
| 168 | |
| 163 | 169 | fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void { |
| 164 | 170 | @setCold(true); |
| 165 | 171 | try p.errors.append(p.gpa, msg); |
| ... | ... | @@ -258,7 +264,7 @@ const Parser = struct { |
| 258 | 264 | } |
| 259 | 265 | // There is not allowed to be a decl after a field with no comma. |
| 260 | 266 | // Report error but recover parser. |
| 261 | | try p.warnExpected(.comma); |
| 267 | try p.warnExpectedAfter(.expected_comma_after_field); |
| 262 | 268 | p.findNextContainerMember(); |
| 263 | 269 | } |
| 264 | 270 | }, |
| ... | ... | @@ -361,7 +367,7 @@ const Parser = struct { |
| 361 | 367 | } |
| 362 | 368 | // There is not allowed to be a decl after a field with no comma. |
| 363 | 369 | // Report error but recover parser. |
| 364 | | try p.warnExpected(.comma); |
| 370 | try p.warnExpectedAfter(.expected_comma_after_field); |
| 365 | 371 | p.findNextContainerMember(); |
| 366 | 372 | } |
| 367 | 373 | }, |
| ... | ... | @@ -573,7 +579,7 @@ const Parser = struct { |
| 573 | 579 | // Since parseBlock only return error.ParseError on |
| 574 | 580 | // a missing '}' we can assume this function was |
| 575 | 581 | // supposed to end here. |
| 576 | | try p.warn(.expected_semi_or_lbrace); |
| 582 | try p.warnExpectedAfter(.expected_semi_or_lbrace); |
| 577 | 583 | return null_node; |
| 578 | 584 | }, |
| 579 | 585 | } |
| ... | ... | @@ -984,7 +990,7 @@ const Parser = struct { |
| 984 | 990 | }; |
| 985 | 991 | _ = p.eatToken(.keyword_else) orelse { |
| 986 | 992 | if (else_required) { |
| 987 | | try p.warn(.expected_semi_or_else); |
| 993 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 988 | 994 | } |
| 989 | 995 | return p.addNode(.{ |
| 990 | 996 | .tag = .if_simple, |
| ... | ... | @@ -1079,7 +1085,7 @@ const Parser = struct { |
| 1079 | 1085 | }; |
| 1080 | 1086 | _ = p.eatToken(.keyword_else) orelse { |
| 1081 | 1087 | if (else_required) { |
| 1082 | | try p.warn(.expected_semi_or_else); |
| 1088 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 1083 | 1089 | } |
| 1084 | 1090 | return p.addNode(.{ |
| 1085 | 1091 | .tag = .for_simple, |
| ... | ... | @@ -1154,7 +1160,7 @@ const Parser = struct { |
| 1154 | 1160 | }; |
| 1155 | 1161 | _ = p.eatToken(.keyword_else) orelse { |
| 1156 | 1162 | if (else_required) { |
| 1157 | | try p.warn(.expected_semi_or_else); |
| 1163 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 1158 | 1164 | } |
| 1159 | 1165 | if (cont_expr == 0) { |
| 1160 | 1166 | return p.addNode(.{ |
| ... | ... | @@ -2038,7 +2044,7 @@ const Parser = struct { |
| 2038 | 2044 | }, |
| 2039 | 2045 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2040 | 2046 | // Likely just a missing comma; give error but continue parsing. |
| 2041 | | else => try p.warnExpected(.comma), |
| 2047 | else => try p.warnExpectedAfter(.expected_comma_after_initializer), |
| 2042 | 2048 | } |
| 2043 | 2049 | if (p.eatToken(.r_brace)) |_| break; |
| 2044 | 2050 | const next = try p.expectFieldInit(); |
| ... | ... | @@ -2079,7 +2085,7 @@ const Parser = struct { |
| 2079 | 2085 | }, |
| 2080 | 2086 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2081 | 2087 | // Likely just a missing comma; give error but continue parsing. |
| 2082 | | else => try p.warnExpected(.comma), |
| 2088 | else => try p.warnExpectedAfter(.expected_comma_after_initializer), |
| 2083 | 2089 | } |
| 2084 | 2090 | } |
| 2085 | 2091 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | ... | @@ -2158,7 +2164,7 @@ const Parser = struct { |
| 2158 | 2164 | }, |
| 2159 | 2165 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 2160 | 2166 | // Likely just a missing comma; give error but continue parsing. |
| 2161 | | else => try p.warnExpected(.comma), |
| 2167 | else => try p.warnExpectedAfter(.expected_comma_after_arg), |
| 2162 | 2168 | } |
| 2163 | 2169 | } |
| 2164 | 2170 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | ... | @@ -2214,7 +2220,7 @@ const Parser = struct { |
| 2214 | 2220 | }, |
| 2215 | 2221 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 2216 | 2222 | // Likely just a missing comma; give error but continue parsing. |
| 2217 | | else => try p.warnExpected(.comma), |
| 2223 | else => try p.warnExpectedAfter(.expected_comma_after_arg), |
| 2218 | 2224 | } |
| 2219 | 2225 | } |
| 2220 | 2226 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | ... | @@ -2455,7 +2461,7 @@ const Parser = struct { |
| 2455 | 2461 | }, |
| 2456 | 2462 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2457 | 2463 | // Likely just a missing comma; give error but continue parsing. |
| 2458 | | else => try p.warnExpected(.comma), |
| 2464 | else => try p.warnExpectedAfter(.expected_comma_after_initializer), |
| 2459 | 2465 | } |
| 2460 | 2466 | if (p.eatToken(.r_brace)) |_| break; |
| 2461 | 2467 | const next = try p.expectFieldInit(); |
| ... | ... | @@ -2507,7 +2513,7 @@ const Parser = struct { |
| 2507 | 2513 | }, |
| 2508 | 2514 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2509 | 2515 | // Likely just a missing comma; give error but continue parsing. |
| 2510 | | else => try p.warnExpected(.comma), |
| 2516 | else => try p.warnExpectedAfter(.expected_comma_after_initializer), |
| 2511 | 2517 | } |
| 2512 | 2518 | } |
| 2513 | 2519 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | ... | @@ -2568,7 +2574,7 @@ const Parser = struct { |
| 2568 | 2574 | }, |
| 2569 | 2575 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2570 | 2576 | // Likely just a missing comma; give error but continue parsing. |
| 2571 | | else => try p.warnExpected(.comma), |
| 2577 | else => try p.warnExpectedAfter(.expected_comma_after_field), |
| 2572 | 2578 | } |
| 2573 | 2579 | } |
| 2574 | 2580 | return p.addNode(.{ |
| ... | ... | @@ -3383,7 +3389,24 @@ const Parser = struct { |
| 3383 | 3389 | |
| 3384 | 3390 | /// SwitchProngList <- (SwitchProng COMMA)* SwitchProng? |
| 3385 | 3391 | fn parseSwitchProngList(p: *Parser) !Node.SubRange { |
| 3386 | | return ListParseFn(parseSwitchProng)(p); |
| 3392 | const scratch_top = p.scratch.items.len; |
| 3393 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3394 | |
| 3395 | while (true) { |
| 3396 | const item = try parseSwitchProng(p); |
| 3397 | if (item == 0) break; |
| 3398 | |
| 3399 | try p.scratch.append(p.gpa, item); |
| 3400 | |
| 3401 | switch (p.token_tags[p.tok_i]) { |
| 3402 | .comma => p.tok_i += 1, |
| 3403 | // All possible delimiters. |
| 3404 | .colon, .r_paren, .r_brace, .r_bracket => break, |
| 3405 | // Likely just a missing comma; give error but continue parsing. |
| 3406 | else => try p.warnExpectedAfter(.expected_comma_after_switch_prong), |
| 3407 | } |
| 3408 | } |
| 3409 | return p.listToSpan(p.scratch.items[scratch_top..]); |
| 3387 | 3410 | } |
| 3388 | 3411 | |
| 3389 | 3412 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? |
| ... | ... | @@ -3409,7 +3432,7 @@ const Parser = struct { |
| 3409 | 3432 | }, |
| 3410 | 3433 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 3411 | 3434 | // Likely just a missing comma; give error but continue parsing. |
| 3412 | | else => try p.warnExpected(.comma), |
| 3435 | else => try p.warnExpectedAfter(.expected_comma_after_param), |
| 3413 | 3436 | } |
| 3414 | 3437 | } |
| 3415 | 3438 | if (varargs == .nonfinal) { |
| ... | ... | @@ -3423,33 +3446,6 @@ const Parser = struct { |
| 3423 | 3446 | }; |
| 3424 | 3447 | } |
| 3425 | 3448 | |
| 3426 | | const NodeParseFn = fn (p: *Parser) Error!Node.Index; |
| 3427 | | |
| 3428 | | fn ListParseFn(comptime nodeParseFn: anytype) (fn (p: *Parser) Error!Node.SubRange) { |
| 3429 | | return struct { |
| 3430 | | pub fn parse(p: *Parser) Error!Node.SubRange { |
| 3431 | | const scratch_top = p.scratch.items.len; |
| 3432 | | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3433 | | |
| 3434 | | while (true) { |
| 3435 | | const item = try nodeParseFn(p); |
| 3436 | | if (item == 0) break; |
| 3437 | | |
| 3438 | | try p.scratch.append(p.gpa, item); |
| 3439 | | |
| 3440 | | switch (p.token_tags[p.tok_i]) { |
| 3441 | | .comma => p.tok_i += 1, |
| 3442 | | // All possible delimiters. |
| 3443 | | .colon, .r_paren, .r_brace, .r_bracket => break, |
| 3444 | | // Likely just a missing comma; give error but continue parsing. |
| 3445 | | else => try p.warnExpected(.comma), |
| 3446 | | } |
| 3447 | | } |
| 3448 | | return p.listToSpan(p.scratch.items[scratch_top..]); |
| 3449 | | } |
| 3450 | | }.parse; |
| 3451 | | } |
| 3452 | | |
| 3453 | 3449 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 3454 | 3450 | /// ExprList <- (Expr COMMA)* Expr? |
| 3455 | 3451 | fn parseBuiltinCall(p: *Parser) !Node.Index { |
| ... | ... | @@ -3480,7 +3476,7 @@ const Parser = struct { |
| 3480 | 3476 | break; |
| 3481 | 3477 | }, |
| 3482 | 3478 | // Likely just a missing comma; give error but continue parsing. |
| 3483 | | else => try p.warnExpected(.comma), |
| 3479 | else => try p.warnExpectedAfter(.expected_comma_after_arg), |
| 3484 | 3480 | } |
| 3485 | 3481 | } |
| 3486 | 3482 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | ... | @@ -3576,7 +3572,7 @@ const Parser = struct { |
| 3576 | 3572 | } |
| 3577 | 3573 | |
| 3578 | 3574 | /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)? |
| 3579 | | fn parseIf(p: *Parser, bodyParseFn: NodeParseFn) !Node.Index { |
| 3575 | fn parseIf(p: *Parser, bodyParseFn: fn (p: *Parser) Error!Node.Index) !Node.Index { |
| 3580 | 3576 | const if_token = p.eatToken(.keyword_if) orelse return null_node; |
| 3581 | 3577 | _ = try p.expectToken(.l_paren); |
| 3582 | 3578 | const condition = try p.expectExpr(); |
| ... | ... | @@ -3664,12 +3660,12 @@ const Parser = struct { |
| 3664 | 3660 | } |
| 3665 | 3661 | } |
| 3666 | 3662 | |
| 3667 | | fn expectSemicolon(p: *Parser, tag: AstError.Tag, recoverable: bool) Error!void { |
| 3663 | fn expectSemicolon(p: *Parser, error_tag: AstError.Tag, recoverable: bool) Error!void { |
| 3668 | 3664 | if (p.token_tags[p.tok_i] == .semicolon) { |
| 3669 | 3665 | _ = p.nextToken(); |
| 3670 | 3666 | return; |
| 3671 | 3667 | } |
| 3672 | | try p.warnMsg(.{ .tag = tag, .token = p.tok_i - 1 }); |
| 3668 | try p.warnExpectedAfter(error_tag); |
| 3673 | 3669 | if (!recoverable) return error.ParseError; |
| 3674 | 3670 | } |
| 3675 | 3671 | |