aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-02-13 12:34:41 +0200
committerVeikka Tuominen <git@vexu.eu>2022-02-13 13:45:35 +0200
commitddd6de86f7eb71814d3605d3e0ea9ed01d075613 (patch)
tree4d6373402a99ed70eba6aa66dbcc3624036dbe30 /lib/std
parent0b7347fd18eee7dd829cd9aaed3683123d84859b (diff)
downloadzig-ddd6de86f7eb71814d3605d3e0ea9ed01d075613.tar.gz
zig-ddd6de86f7eb71814d3605d3e0ea9ed01d075613.zip
parser: make missing semicolon error point to the end of the previous token
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/zig/Ast.zig22
-rw-r--r--lib/std/zig/parse.zig19
2 files changed, 36 insertions, 5 deletions
diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig
index 17da4f5315..16430fe9d4 100644
--- a/lib/std/zig/Ast.zig
+++ b/lib/std/zig/Ast.zig
@@ -64,6 +64,17 @@ pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8)) RenderError!void
return @import("./render.zig").renderTree(buffer, tree);
}
+/// Returns an extra offset for column and byte offset of errors that
+/// should point after the token in the error message.
+pub fn errorOffset(tree:Ast, error_tag: Error.Tag, token: TokenIndex) u32 {
+ return switch (error_tag) {
+ .expected_semi_after_decl,
+ .expected_semi_after_stmt,
+ => @intCast(u32, tree.tokenSlice(token).len),
+ else => 0,
+ };
+}
+
pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {
var loc = Location{
.line = 0,
@@ -306,6 +317,13 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
return stream.writeAll("function prototype has parameter after varargs");
},
+ .expected_semi_after_decl => {
+ return stream.writeAll("expected ';' after declaration");
+ },
+ .expected_semi_after_stmt => {
+ return stream.writeAll("expected ';' after statement");
+ },
+
.expected_token => {
const found_tag = token_tags[parse_error.token];
const expected_symbol = parse_error.extra.expected_tag.symbol();
@@ -2495,6 +2513,10 @@ pub const Error = struct {
unattached_doc_comment,
varargs_nonfinal,
+ // these have `token` set to token after which a semicolon was expected
+ expected_semi_after_decl,
+ expected_semi_after_stmt,
+
/// `expected_tag` is populated.
expected_token,
};
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index a70d0309e3..e818046ac5 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -586,7 +586,7 @@ const Parser = struct {
const thread_local_token = p.eatToken(.keyword_threadlocal);
const var_decl = try p.parseVarDecl();
if (var_decl != 0) {
- _ = try p.expectToken(.semicolon);
+ try p.expectSemicolon(.expected_semi_after_decl, false);
return var_decl;
}
if (thread_local_token != null) {
@@ -614,7 +614,7 @@ const Parser = struct {
fn expectUsingNamespace(p: *Parser) !Node.Index {
const usingnamespace_token = p.assertToken(.keyword_usingnamespace);
const expr = try p.expectExpr();
- _ = try p.expectToken(.semicolon);
+ try p.expectSemicolon(.expected_semi_after_decl, false);
return p.addNode(.{
.tag = .@"usingnamespace",
.main_token = usingnamespace_token,
@@ -851,7 +851,7 @@ const Parser = struct {
const var_decl = try p.parseVarDecl();
if (var_decl != 0) {
- _ = try p.expectTokenRecoverable(.semicolon);
+ try p.expectSemicolon(.expected_semi_after_decl, true);
return var_decl;
}
@@ -915,7 +915,7 @@ const Parser = struct {
const assign_expr = try p.parseAssignExpr();
if (assign_expr != 0) {
- _ = try p.expectTokenRecoverable(.semicolon);
+ try p.expectSemicolon(.expected_semi_after_stmt, true);
return assign_expr;
}
@@ -1205,7 +1205,7 @@ const Parser = struct {
}
const assign_expr = try p.parseAssignExpr();
if (assign_expr != 0) {
- _ = try p.expectTokenRecoverable(.semicolon);
+ try p.expectSemicolon(.expected_semi_after_stmt, true);
return assign_expr;
}
return null_node;
@@ -3664,6 +3664,15 @@ const Parser = struct {
}
}
+ fn expectSemicolon(p: *Parser, tag: AstError.Tag, recoverable: bool) Error!void {
+ if (p.token_tags[p.tok_i] == .semicolon) {
+ _ = p.nextToken();
+ return;
+ }
+ try p.warnMsg(.{ .tag = tag, .token = p.tok_i - 1 });
+ if (!recoverable) return error.ParseError;
+ }
+
fn nextToken(p: *Parser) TokenIndex {
const result = p.tok_i;
p.tok_i += 1;