add error message to zig side of tokenizing/parsing
parent
960b5b518f
commit
d7f9128b5d
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 "" {
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue