From 1f81887a7863545d8b89bff6cc7d31941da0abf0 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 23:35:58 +0300 Subject: [PATCH] recover after invalid inline/extern --- lib/std/zig/ast.zig | 4 ++++ lib/std/zig/parse.zig | 17 ++++++++++------- lib/std/zig/parser_test.zig | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index afb7fce23e..26bff31bbd 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -129,6 +129,7 @@ pub const Error = union(enum) { ExpectedStatement: ExpectedStatement, ExpectedVarDeclOrFn: ExpectedVarDeclOrFn, ExpectedVarDecl: ExpectedVarDecl, + ExpectedFn: ExpectedFn, ExpectedReturnType: ExpectedReturnType, ExpectedAggregateKw: ExpectedAggregateKw, UnattachedDocComment: UnattachedDocComment, @@ -179,6 +180,7 @@ pub const Error = union(enum) { .ExpectedStatement => |*x| return x.render(tokens, stream), .ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), .ExpectedVarDecl => |*x| return x.render(tokens, stream), + .ExpectedFn => |*x| return x.render(tokens, stream), .ExpectedReturnType => |*x| return x.render(tokens, stream), .ExpectedAggregateKw => |*x| return x.render(tokens, stream), .UnattachedDocComment => |*x| return x.render(tokens, stream), @@ -231,6 +233,7 @@ pub const Error = union(enum) { .ExpectedStatement => |x| return x.token, .ExpectedVarDeclOrFn => |x| return x.token, .ExpectedVarDecl => |x| return x.token, + .ExpectedFn => |x| return x.token, .ExpectedReturnType => |x| return x.token, .ExpectedAggregateKw => |x| return x.token, .UnattachedDocComment => |x| return x.token, @@ -280,6 +283,7 @@ pub const Error = union(enum) { pub const ExpectedStatement = SingleTokenError("Expected statement, found '{}'"); pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found '{}'"); pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'"); + pub const ExpectedFn = SingleTokenError("Expected function, found '{}'"); pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'"); pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'"); pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'"); diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index d8d1d4b427..cbd5336ca2 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -360,15 +360,17 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? try tree.errors.push(.{ .ExpectedSemiOrLBrace = .{ .token = it.index }, }); - return null; + return error.ParseError; } if (extern_export_inline_token) |token| { if (tree.tokens.at(token).id == .Keyword_inline or tree.tokens.at(token).id == .Keyword_noinline) { - putBackToken(it, token); - return null; + try tree.errors.push(.{ + .ExpectedFn = .{ .token = it.index }, + }); + return error.ParseError; } } @@ -399,10 +401,11 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? } if (extern_export_inline_token) |token| { - if (lib_name) |string_literal_node| - putBackToken(it, string_literal_node.cast(Node.StringLiteral).?.token); - putBackToken(it, token); - return null; + try tree.errors.push(.{ + .ExpectedVarDeclOrFn = .{ .token = it.index }, + }); + // ignore this and try again; + return error.ParseError; } return parseUse(arena, it, tree) catch |err| switch (err) { diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 7ddf9cc9c8..d837769802 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -84,6 +84,21 @@ test "recovery: continue after invalid decl" { }); } +test "recovery: invalid extern/inline" { + try testError( + \\inline test "" { a && b; } + , &[_]Error{ + .ExpectedFn, + .InvalidAnd, + }); + try testError( + \\extern "" test "" { a && b; } + , &[_]Error{ + .ExpectedVarDeclOrFn, + .InvalidAnd, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know,