From d7f9128b5d3c8c8f6a0a617c45717cdc7e3543fd Mon Sep 17 00:00:00 2001 From: Travis Date: Thu, 29 Oct 2020 11:04:50 -0500 Subject: [PATCH] add error message to zig side of tokenizing/parsing --- lib/std/zig/ast.zig | 4 ++++ lib/std/zig/parse.zig | 7 +++++++ lib/std/zig/parser_test.zig | 11 +++++++++++ lib/std/zig/tokenizer.zig | 8 +++++--- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 0973877aa..eb878fb88 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -171,6 +171,7 @@ pub const Error = union(enum) { ExpectedBlockOrField: ExpectedBlockOrField, DeclBetweenFields: DeclBetweenFields, InvalidAnd: InvalidAnd, + AsteriskAfterPointerDereference: AsteriskAfterPointerDereference, pub fn render(self: *const Error, tokens: []const Token.Id, stream: anytype) !void { switch (self.*) { @@ -222,6 +223,7 @@ pub const Error = union(enum) { .ExpectedBlockOrField => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream), .InvalidAnd => |*x| return x.render(tokens, stream), + .AsteriskAfterPointerDereference => |*x| return x.render(tokens, stream), } } @@ -275,6 +277,7 @@ pub const Error = union(enum) { .ExpectedBlockOrField => |x| return x.token, .DeclBetweenFields => |x| return x.token, .InvalidAnd => |x| return x.token, + .AsteriskAfterPointerDereference => |x| return x.token, } } @@ -323,6 +326,7 @@ pub const Error = union(enum) { pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); + pub const AsteriskAfterPointerDereference = SimpleError("`.*` can't be followed by `*`. Are you missing a space?"); pub const ExpectedCall = struct { node: *Node, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 467b06a5c..5e745dd42 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -2701,6 +2701,13 @@ const Parser = struct { return &node.base; } + if (p.token_ids[p.tok_i] == .Invalid_periodasterisks) { + try p.errors.append(p.gpa, .{ + .AsteriskAfterPointerDereference = .{ .token = p.tok_i }, + }); + return null; + } + if (p.eatToken(.Period)) |period| { if (try p.parseIdentifier()) |identifier| { const node = try p.arena.allocator.create(Node.SimpleInfixOp); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 994ad6d5d..9495f536d 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -219,6 +219,17 @@ test "recovery: invalid global error set access" { }); } +test "recovery: invalid asterisk after pointer dereference" { + try testError( + \\test "" { + \\ var sequence = "repeat".*** 10; + \\} + , &[_]Error{ + .AsteriskAfterPointerDereference, + .ExpectedToken, + }); +} + test "recovery: missing semicolon after if, for, while stmt" { try testError( \\test "" { diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index 280ae5c1f..a0e2806e9 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -78,6 +78,7 @@ pub const Token = struct { pub const Id = enum { Invalid, Invalid_ampersands, + Invalid_periodasterisks, Identifier, StringLiteral, MultilineStringLiteralLine, @@ -201,6 +202,7 @@ pub const Token = struct { return switch (id) { .Invalid => "Invalid", .Invalid_ampersands => "&&", + .Invalid_periodasterisks => ".**", .Identifier => "Identifier", .StringLiteral => "StringLiteral", .MultilineStringLiteralLine => "MultilineStringLiteralLine", @@ -1002,13 +1004,13 @@ pub const Tokenizer = struct { .period_asterisk => switch (c) { '*' => { - result.id = .Invalid; + result.id = .Invalid_periodasterisks; break; }, else => { result.id = .PeriodAsterisk; break; - } + }, }, .slash => switch (c) { @@ -1794,7 +1796,7 @@ test "correctly parse pointer dereference followed by asterisk" { testTokenize("\"b\".*** 10", &[_]Token.Id{ .StringLiteral, - .Invalid, + .Invalid_periodasterisks, .AsteriskAsterisk, .IntegerLiteral, });