recover after invalid inline/extern

This commit is contained in:
Vexu
2020-05-13 23:35:58 +03:00
parent ad71d959d7
commit 1f81887a78
3 changed files with 29 additions and 7 deletions

View File

@@ -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 '{}'");

View File

@@ -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) {

View File

@@ -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,