| author | |
| committer | |
| log | d7f9128b5d3c8c8f6a0a617c45717cdc7e3543fd |
| tree | 8da94ed09600cfcebe599c531d7aa887531e5514 |
| parent | 960b5b518fa7ff7c6760d3e5f3c1256e553e6ba8 |
4 files changed, 27 insertions(+), 3 deletions(-)
lib/std/zig/ast.zig+4| ... | @@ -171,6 +171,7 @@ pub const Error = union(enum) { | ... | @@ -171,6 +171,7 @@ pub const Error = union(enum) { |
| 171 | ExpectedBlockOrField: ExpectedBlockOrField, | 171 | ExpectedBlockOrField: ExpectedBlockOrField, |
| 172 | DeclBetweenFields: DeclBetweenFields, | 172 | DeclBetweenFields: DeclBetweenFields, |
| 173 | InvalidAnd: InvalidAnd, | 173 | InvalidAnd: InvalidAnd, |
| 174 | AsteriskAfterPointerDereference: AsteriskAfterPointerDereference, | ||
| 174 | 175 | ||
| 175 | pub fn render(self: *const Error, tokens: []const Token.Id, stream: anytype) !void { | 176 | pub fn render(self: *const Error, tokens: []const Token.Id, stream: anytype) !void { |
| 176 | switch (self.*) { | 177 | switch (self.*) { |
| ... | @@ -222,6 +223,7 @@ pub const Error = union(enum) { | ... | @@ -222,6 +223,7 @@ pub const Error = union(enum) { |
| 222 | .ExpectedBlockOrField => |*x| return x.render(tokens, stream), | 223 | .ExpectedBlockOrField => |*x| return x.render(tokens, stream), |
| 223 | .DeclBetweenFields => |*x| return x.render(tokens, stream), | 224 | .DeclBetweenFields => |*x| return x.render(tokens, stream), |
| 224 | .InvalidAnd => |*x| return x.render(tokens, stream), | 225 | .InvalidAnd => |*x| return x.render(tokens, stream), |
| 226 | .AsteriskAfterPointerDereference => |*x| return x.render(tokens, stream), | ||
| 225 | } | 227 | } |
| 226 | } | 228 | } |
| 227 | 229 | ||
| ... | @@ -275,6 +277,7 @@ pub const Error = union(enum) { | ... | @@ -275,6 +277,7 @@ pub const Error = union(enum) { |
| 275 | .ExpectedBlockOrField => |x| return x.token, | 277 | .ExpectedBlockOrField => |x| return x.token, |
| 276 | .DeclBetweenFields => |x| return x.token, | 278 | .DeclBetweenFields => |x| return x.token, |
| 277 | .InvalidAnd => |x| return x.token, | 279 | .InvalidAnd => |x| return x.token, |
| 280 | .AsteriskAfterPointerDereference => |x| return x.token, | ||
| 278 | } | 281 | } |
| 279 | } | 282 | } |
| 280 | 283 | ||
| ... | @@ -323,6 +326,7 @@ pub const Error = union(enum) { | ... | @@ -323,6 +326,7 @@ pub const Error = union(enum) { |
| 323 | pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); | 326 | pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); |
| 324 | pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); | 327 | pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); |
| 325 | pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); | 328 | pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); |
| 329 | pub const AsteriskAfterPointerDereference = SimpleError("`.*` can't be followed by `*`. Are you missing a space?"); | ||
| 326 | 330 | ||
| 327 | pub const ExpectedCall = struct { | 331 | pub const ExpectedCall = struct { |
| 328 | node: *Node, | 332 | node: *Node, |
lib/std/zig/parse.zig+7| ... | @@ -2701,6 +2701,13 @@ const Parser = struct { | ... | @@ -2701,6 +2701,13 @@ const Parser = struct { |
| 2701 | return &node.base; | 2701 | return &node.base; |
| 2702 | } | 2702 | } |
| 2703 | 2703 | ||
| 2704 | if (p.token_ids[p.tok_i] == .Invalid_periodasterisks) { | ||
| 2705 | try p.errors.append(p.gpa, .{ | ||
| 2706 | .AsteriskAfterPointerDereference = .{ .token = p.tok_i }, | ||
| 2707 | }); | ||
| 2708 | return null; | ||
| 2709 | } | ||
| 2710 | |||
| 2704 | if (p.eatToken(.Period)) |period| { | 2711 | if (p.eatToken(.Period)) |period| { |
| 2705 | if (try p.parseIdentifier()) |identifier| { | 2712 | if (try p.parseIdentifier()) |identifier| { |
| 2706 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); | 2713 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
lib/std/zig/parser_test.zig+11| ... | @@ -219,6 +219,17 @@ test "recovery: invalid global error set access" { | ... | @@ -219,6 +219,17 @@ test "recovery: invalid global error set access" { |
| 219 | }); | 219 | }); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | test "recovery: invalid asterisk after pointer dereference" { | ||
| 223 | try testError( | ||
| 224 | \\test "" { | ||
| 225 | \\ var sequence = "repeat".*** 10; | ||
| 226 | \\} | ||
| 227 | , &[_]Error{ | ||
| 228 | .AsteriskAfterPointerDereference, | ||
| 229 | .ExpectedToken, | ||
| 230 | }); | ||
| 231 | } | ||
| 232 | |||
| 222 | test "recovery: missing semicolon after if, for, while stmt" { | 233 | test "recovery: missing semicolon after if, for, while stmt" { |
| 223 | try testError( | 234 | try testError( |
| 224 | \\test "" { | 235 | \\test "" { |
lib/std/zig/tokenizer.zig+5-3| ... | @@ -78,6 +78,7 @@ pub const Token = struct { | ... | @@ -78,6 +78,7 @@ pub const Token = struct { |
| 78 | pub const Id = enum { | 78 | pub const Id = enum { |
| 79 | Invalid, | 79 | Invalid, |
| 80 | Invalid_ampersands, | 80 | Invalid_ampersands, |
| 81 | Invalid_periodasterisks, | ||
| 81 | Identifier, | 82 | Identifier, |
| 82 | StringLiteral, | 83 | StringLiteral, |
| 83 | MultilineStringLiteralLine, | 84 | MultilineStringLiteralLine, |
| ... | @@ -201,6 +202,7 @@ pub const Token = struct { | ... | @@ -201,6 +202,7 @@ pub const Token = struct { |
| 201 | return switch (id) { | 202 | return switch (id) { |
| 202 | .Invalid => "Invalid", | 203 | .Invalid => "Invalid", |
| 203 | .Invalid_ampersands => "&&", | 204 | .Invalid_ampersands => "&&", |
| 205 | .Invalid_periodasterisks => ".**", | ||
| 204 | .Identifier => "Identifier", | 206 | .Identifier => "Identifier", |
| 205 | .StringLiteral => "StringLiteral", | 207 | .StringLiteral => "StringLiteral", |
| 206 | .MultilineStringLiteralLine => "MultilineStringLiteralLine", | 208 | .MultilineStringLiteralLine => "MultilineStringLiteralLine", |
| ... | @@ -1002,13 +1004,13 @@ pub const Tokenizer = struct { | ... | @@ -1002,13 +1004,13 @@ pub const Tokenizer = struct { |
| 1002 | 1004 | ||
| 1003 | .period_asterisk => switch (c) { | 1005 | .period_asterisk => switch (c) { |
| 1004 | '*' => { | 1006 | '*' => { |
| 1005 | result.id = .Invalid; | 1007 | result.id = .Invalid_periodasterisks; |
| 1006 | break; | 1008 | break; |
| 1007 | }, | 1009 | }, |
| 1008 | else => { | 1010 | else => { |
| 1009 | result.id = .PeriodAsterisk; | 1011 | result.id = .PeriodAsterisk; |
| 1010 | break; | 1012 | break; |
| 1011 | } | 1013 | }, |
| 1012 | }, | 1014 | }, |
| 1013 | 1015 | ||
| 1014 | .slash => switch (c) { | 1016 | .slash => switch (c) { |
| ... | @@ -1794,7 +1796,7 @@ test "correctly parse pointer dereference followed by asterisk" { | ... | @@ -1794,7 +1796,7 @@ test "correctly parse pointer dereference followed by asterisk" { |
| 1794 | 1796 | ||
| 1795 | testTokenize("\"b\".*** 10", &[_]Token.Id{ | 1797 | testTokenize("\"b\".*** 10", &[_]Token.Id{ |
| 1796 | .StringLiteral, | 1798 | .StringLiteral, |
| 1797 | .Invalid, | 1799 | .Invalid_periodasterisks, |
| 1798 | .AsteriskAsterisk, | 1800 | .AsteriskAsterisk, |
| 1799 | .IntegerLiteral, | 1801 | .IntegerLiteral, |
| 1800 | }); | 1802 | }); |