Commit d7f9128b5d

Travis <tssund93@gmail.com>
2020-10-29 17:04:50
add error message to zig side of tokenizing/parsing
1 parent 960b5b5
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,
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);
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 "" {
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,
     });