| ... | @@ -160,6 +160,12 @@ const Parser = struct { | ... | @@ -160,6 +160,12 @@ const Parser = struct { |
| 160 | .extra = .{ .expected_tag = expected_token }, | 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 | fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void { | 169 | fn warnMsg(p: *Parser, msg: Ast.Error) error{OutOfMemory}!void { |
| 164 | @setCold(true); | 170 | @setCold(true); |
| 165 | try p.errors.append(p.gpa, msg); | 171 | try p.errors.append(p.gpa, msg); |
| ... | @@ -258,7 +264,7 @@ const Parser = struct { | ... | @@ -258,7 +264,7 @@ const Parser = struct { |
| 258 | } | 264 | } |
| 259 | // There is not allowed to be a decl after a field with no comma. | 265 | // There is not allowed to be a decl after a field with no comma. |
| 260 | // Report error but recover parser. | 266 | // Report error but recover parser. |
| 261 | try p.warnExpected(.comma); | 267 | try p.warnExpectedAfter(.expected_comma_after_field); |
| 262 | p.findNextContainerMember(); | 268 | p.findNextContainerMember(); |
| 263 | } | 269 | } |
| 264 | }, | 270 | }, |
| ... | @@ -361,7 +367,7 @@ const Parser = struct { | ... | @@ -361,7 +367,7 @@ const Parser = struct { |
| 361 | } | 367 | } |
| 362 | // There is not allowed to be a decl after a field with no comma. | 368 | // There is not allowed to be a decl after a field with no comma. |
| 363 | // Report error but recover parser. | 369 | // Report error but recover parser. |
| 364 | try p.warnExpected(.comma); | 370 | try p.warnExpectedAfter(.expected_comma_after_field); |
| 365 | p.findNextContainerMember(); | 371 | p.findNextContainerMember(); |
| 366 | } | 372 | } |
| 367 | }, | 373 | }, |
| ... | @@ -573,7 +579,7 @@ const Parser = struct { | ... | @@ -573,7 +579,7 @@ const Parser = struct { |
| 573 | // Since parseBlock only return error.ParseError on | 579 | // Since parseBlock only return error.ParseError on |
| 574 | // a missing '}' we can assume this function was | 580 | // a missing '}' we can assume this function was |
| 575 | // supposed to end here. | 581 | // supposed to end here. |
| 576 | try p.warn(.expected_semi_or_lbrace); | 582 | try p.warnExpectedAfter(.expected_semi_or_lbrace); |
| 577 | return null_node; | 583 | return null_node; |
| 578 | }, | 584 | }, |
| 579 | } | 585 | } |
| ... | @@ -984,7 +990,7 @@ const Parser = struct { | ... | @@ -984,7 +990,7 @@ const Parser = struct { |
| 984 | }; | 990 | }; |
| 985 | _ = p.eatToken(.keyword_else) orelse { | 991 | _ = p.eatToken(.keyword_else) orelse { |
| 986 | if (else_required) { | 992 | if (else_required) { |
| 987 | try p.warn(.expected_semi_or_else); | 993 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 988 | } | 994 | } |
| 989 | return p.addNode(.{ | 995 | return p.addNode(.{ |
| 990 | .tag = .if_simple, | 996 | .tag = .if_simple, |
| ... | @@ -1079,7 +1085,7 @@ const Parser = struct { | ... | @@ -1079,7 +1085,7 @@ const Parser = struct { |
| 1079 | }; | 1085 | }; |
| 1080 | _ = p.eatToken(.keyword_else) orelse { | 1086 | _ = p.eatToken(.keyword_else) orelse { |
| 1081 | if (else_required) { | 1087 | if (else_required) { |
| 1082 | try p.warn(.expected_semi_or_else); | 1088 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 1083 | } | 1089 | } |
| 1084 | return p.addNode(.{ | 1090 | return p.addNode(.{ |
| 1085 | .tag = .for_simple, | 1091 | .tag = .for_simple, |
| ... | @@ -1154,7 +1160,7 @@ const Parser = struct { | ... | @@ -1154,7 +1160,7 @@ const Parser = struct { |
| 1154 | }; | 1160 | }; |
| 1155 | _ = p.eatToken(.keyword_else) orelse { | 1161 | _ = p.eatToken(.keyword_else) orelse { |
| 1156 | if (else_required) { | 1162 | if (else_required) { |
| 1157 | try p.warn(.expected_semi_or_else); | 1163 | try p.warnExpectedAfter(.expected_semi_or_else); |
| 1158 | } | 1164 | } |
| 1159 | if (cont_expr == 0) { | 1165 | if (cont_expr == 0) { |
| 1160 | return p.addNode(.{ | 1166 | return p.addNode(.{ |
| ... | @@ -2038,7 +2044,7 @@ const Parser = struct { | ... | @@ -2038,7 +2044,7 @@ const Parser = struct { |
| 2038 | }, | 2044 | }, |
| 2039 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), | 2045 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2040 | // Likely just a missing comma; give error but continue parsing. | 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 | if (p.eatToken(.r_brace)) |_| break; | 2049 | if (p.eatToken(.r_brace)) |_| break; |
| 2044 | const next = try p.expectFieldInit(); | 2050 | const next = try p.expectFieldInit(); |
| ... | @@ -2079,7 +2085,7 @@ const Parser = struct { | ... | @@ -2079,7 +2085,7 @@ const Parser = struct { |
| 2079 | }, | 2085 | }, |
| 2080 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), | 2086 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2081 | // Likely just a missing comma; give error but continue parsing. | 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 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | 2091 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | @@ -2158,7 +2164,7 @@ const Parser = struct { | ... | @@ -2158,7 +2164,7 @@ const Parser = struct { |
| 2158 | }, | 2164 | }, |
| 2159 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), | 2165 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 2160 | // Likely just a missing comma; give error but continue parsing. | 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 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | 2170 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | @@ -2214,7 +2220,7 @@ const Parser = struct { | ... | @@ -2214,7 +2220,7 @@ const Parser = struct { |
| 2214 | }, | 2220 | }, |
| 2215 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), | 2221 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 2216 | // Likely just a missing comma; give error but continue parsing. | 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 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | 2226 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | @@ -2455,7 +2461,7 @@ const Parser = struct { | ... | @@ -2455,7 +2461,7 @@ const Parser = struct { |
| 2455 | }, | 2461 | }, |
| 2456 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), | 2462 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2457 | // Likely just a missing comma; give error but continue parsing. | 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 | if (p.eatToken(.r_brace)) |_| break; | 2466 | if (p.eatToken(.r_brace)) |_| break; |
| 2461 | const next = try p.expectFieldInit(); | 2467 | const next = try p.expectFieldInit(); |
| ... | @@ -2507,7 +2513,7 @@ const Parser = struct { | ... | @@ -2507,7 +2513,7 @@ const Parser = struct { |
| 2507 | }, | 2513 | }, |
| 2508 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), | 2514 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2509 | // Likely just a missing comma; give error but continue parsing. | 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 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | 2519 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | @@ -2568,7 +2574,7 @@ const Parser = struct { | ... | @@ -2568,7 +2574,7 @@ const Parser = struct { |
| 2568 | }, | 2574 | }, |
| 2569 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), | 2575 | .colon, .r_paren, .r_bracket => return p.failExpected(.r_brace), |
| 2570 | // Likely just a missing comma; give error but continue parsing. | 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 | return p.addNode(.{ | 2580 | return p.addNode(.{ |
| ... | @@ -3383,7 +3389,24 @@ const Parser = struct { | ... | @@ -3383,7 +3389,24 @@ const Parser = struct { |
| 3383 | | 3389 | |
| 3384 | /// SwitchProngList <- (SwitchProng COMMA)* SwitchProng? | 3390 | /// SwitchProngList <- (SwitchProng COMMA)* SwitchProng? |
| 3385 | fn parseSwitchProngList(p: *Parser) !Node.SubRange { | 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 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? | 3412 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? |
| ... | @@ -3409,7 +3432,7 @@ const Parser = struct { | ... | @@ -3409,7 +3432,7 @@ const Parser = struct { |
| 3409 | }, | 3432 | }, |
| 3410 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), | 3433 | .colon, .r_brace, .r_bracket => return p.failExpected(.r_paren), |
| 3411 | // Likely just a missing comma; give error but continue parsing. | 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 | if (varargs == .nonfinal) { | 3438 | if (varargs == .nonfinal) { |
| ... | @@ -3423,33 +3446,6 @@ const Parser = struct { | ... | @@ -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 | /// FnCallArguments <- LPAREN ExprList RPAREN | 3449 | /// FnCallArguments <- LPAREN ExprList RPAREN |
| 3454 | /// ExprList <- (Expr COMMA)* Expr? | 3450 | /// ExprList <- (Expr COMMA)* Expr? |
| 3455 | fn parseBuiltinCall(p: *Parser) !Node.Index { | 3451 | fn parseBuiltinCall(p: *Parser) !Node.Index { |
| ... | @@ -3480,7 +3476,7 @@ const Parser = struct { | ... | @@ -3480,7 +3476,7 @@ const Parser = struct { |
| 3480 | break; | 3476 | break; |
| 3481 | }, | 3477 | }, |
| 3482 | // Likely just a missing comma; give error but continue parsing. | 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 | const comma = (p.token_tags[p.tok_i - 2] == .comma); | 3482 | const comma = (p.token_tags[p.tok_i - 2] == .comma); |
| ... | @@ -3576,7 +3572,7 @@ const Parser = struct { | ... | @@ -3576,7 +3572,7 @@ const Parser = struct { |
| 3576 | } | 3572 | } |
| 3577 | | 3573 | |
| 3578 | /// KEYWORD_if LPAREN Expr RPAREN PtrPayload? Body (KEYWORD_else Payload? Body)? | 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 | const if_token = p.eatToken(.keyword_if) orelse return null_node; | 3576 | const if_token = p.eatToken(.keyword_if) orelse return null_node; |
| 3581 | _ = try p.expectToken(.l_paren); | 3577 | _ = try p.expectToken(.l_paren); |
| 3582 | const condition = try p.expectExpr(); | 3578 | const condition = try p.expectExpr(); |
| ... | @@ -3664,12 +3660,12 @@ const Parser = struct { | ... | @@ -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 | if (p.token_tags[p.tok_i] == .semicolon) { | 3664 | if (p.token_tags[p.tok_i] == .semicolon) { |
| 3669 | _ = p.nextToken(); | 3665 | _ = p.nextToken(); |
| 3670 | return; | 3666 | return; |
| 3671 | } | 3667 | } |
| 3672 | try p.warnMsg(.{ .tag = tag, .token = p.tok_i - 1 }); | 3668 | try p.warnExpectedAfter(error_tag); |
| 3673 | if (!recoverable) return error.ParseError; | 3669 | if (!recoverable) return error.ParseError; |
| 3674 | } | 3670 | } |
| 3675 | | 3671 | |