add error message to zig side of tokenizing/parsing

master
Travis 2020-10-29 11:04:50 -05:00
parent 960b5b518f
commit d7f9128b5d
4 changed files with 27 additions and 3 deletions

View File

@ -171,6 +171,7 @@ pub const Error = union(enum) {
ExpectedBlockOrField: ExpectedBlockOrField, ExpectedBlockOrField: ExpectedBlockOrField,
DeclBetweenFields: DeclBetweenFields, DeclBetweenFields: DeclBetweenFields,
InvalidAnd: InvalidAnd, InvalidAnd: InvalidAnd,
AsteriskAfterPointerDereference: AsteriskAfterPointerDereference,
pub fn render(self: *const Error, tokens: []const Token.Id, stream: anytype) !void { pub fn render(self: *const Error, tokens: []const Token.Id, stream: anytype) !void {
switch (self.*) { switch (self.*) {
@ -222,6 +223,7 @@ pub const Error = union(enum) {
.ExpectedBlockOrField => |*x| return x.render(tokens, stream), .ExpectedBlockOrField => |*x| return x.render(tokens, stream),
.DeclBetweenFields => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream),
.InvalidAnd => |*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, .ExpectedBlockOrField => |x| return x.token,
.DeclBetweenFields => |x| return x.token, .DeclBetweenFields => |x| return x.token,
.InvalidAnd => |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 ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier");
pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); 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 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 { pub const ExpectedCall = struct {
node: *Node, node: *Node,

View File

@ -2701,6 +2701,13 @@ const Parser = struct {
return &node.base; 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 (p.eatToken(.Period)) |period| {
if (try p.parseIdentifier()) |identifier| { if (try p.parseIdentifier()) |identifier| {
const node = try p.arena.allocator.create(Node.SimpleInfixOp); const node = try p.arena.allocator.create(Node.SimpleInfixOp);

View File

@ -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" { test "recovery: missing semicolon after if, for, while stmt" {
try testError( try testError(
\\test "" { \\test "" {

View File

@ -78,6 +78,7 @@ pub const Token = struct {
pub const Id = enum { pub const Id = enum {
Invalid, Invalid,
Invalid_ampersands, Invalid_ampersands,
Invalid_periodasterisks,
Identifier, Identifier,
StringLiteral, StringLiteral,
MultilineStringLiteralLine, MultilineStringLiteralLine,
@ -201,6 +202,7 @@ pub const Token = struct {
return switch (id) { return switch (id) {
.Invalid => "Invalid", .Invalid => "Invalid",
.Invalid_ampersands => "&&", .Invalid_ampersands => "&&",
.Invalid_periodasterisks => ".**",
.Identifier => "Identifier", .Identifier => "Identifier",
.StringLiteral => "StringLiteral", .StringLiteral => "StringLiteral",
.MultilineStringLiteralLine => "MultilineStringLiteralLine", .MultilineStringLiteralLine => "MultilineStringLiteralLine",
@ -1002,13 +1004,13 @@ pub const Tokenizer = struct {
.period_asterisk => switch (c) { .period_asterisk => switch (c) {
'*' => { '*' => {
result.id = .Invalid; result.id = .Invalid_periodasterisks;
break; break;
}, },
else => { else => {
result.id = .PeriodAsterisk; result.id = .PeriodAsterisk;
break; break;
} },
}, },
.slash => switch (c) { .slash => switch (c) {
@ -1794,7 +1796,7 @@ test "correctly parse pointer dereference followed by asterisk" {
testTokenize("\"b\".*** 10", &[_]Token.Id{ testTokenize("\"b\".*** 10", &[_]Token.Id{
.StringLiteral, .StringLiteral,
.Invalid, .Invalid_periodasterisks,
.AsteriskAsterisk, .AsteriskAsterisk,
.IntegerLiteral, .IntegerLiteral,
}); });