stage2: AST: clean up parse errors

* struct instead of tagged union
 * delete dead code
 * simplify parser code
 * remove unnecessary metaprogramming
This commit is contained in:
Andrew Kelley 2021-02-19 18:04:52 -07:00
parent 74878565e5
commit 8fee41b1d5
5 changed files with 389 additions and 607 deletions

View File

@ -132,113 +132,160 @@ pub const Tree = struct {
}
pub fn renderError(tree: Tree, parse_error: Error, stream: anytype) !void {
const tokens = tree.tokens.items(.tag);
switch (parse_error) {
.InvalidToken => |*x| return x.render(tokens, stream),
.ExpectedContainerMembers => |*x| return x.render(tokens, stream),
.ExpectedStringLiteral => |*x| return x.render(tokens, stream),
.ExpectedIntegerLiteral => |*x| return x.render(tokens, stream),
.ExpectedPubItem => |*x| return x.render(tokens, stream),
.ExpectedIdentifier => |*x| return x.render(tokens, stream),
.ExpectedStatement => |*x| return x.render(tokens, stream),
.ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
.ExpectedVarDecl => |*x| return x.render(tokens, stream),
.ExpectedFn => |*x| return x.render(tokens, stream),
.ExpectedReturnType => |*x| return x.render(tokens, stream),
.ExpectedAggregateKw => |*x| return x.render(tokens, stream),
.SameLineDocComment => |*x| return x.render(tokens, stream),
.UnattachedDocComment => |*x| return x.render(tokens, stream),
.ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
.ExpectedSemiOrLBrace => |*x| return x.render(tokens, stream),
.ExpectedSemiOrElse => |*x| return x.render(tokens, stream),
.ExpectedLabelOrLBrace => |*x| return x.render(tokens, stream),
.ExpectedLBrace => |*x| return x.render(tokens, stream),
.ExpectedColonOrRParen => |*x| return x.render(tokens, stream),
.ExpectedLabelable => |*x| return x.render(tokens, stream),
.ExpectedInlinable => |*x| return x.render(tokens, stream),
.ExpectedAsmOutputReturnOrType => |*x| return x.render(tokens, stream),
.ExpectedCall => |x| return x.render(tree, stream),
.ExpectedCallOrFnProto => |x| return x.render(tree, stream),
.ExpectedSliceOrRBracket => |*x| return x.render(tokens, stream),
.ExtraAlignQualifier => |*x| return x.render(tokens, stream),
.ExtraConstQualifier => |*x| return x.render(tokens, stream),
.ExtraVolatileQualifier => |*x| return x.render(tokens, stream),
.ExtraAllowZeroQualifier => |*x| return x.render(tokens, stream),
.ExpectedTypeExpr => |*x| return x.render(tokens, stream),
.ExpectedPrimaryTypeExpr => |*x| return x.render(tokens, stream),
.ExpectedParamType => |*x| return x.render(tokens, stream),
.ExpectedExpr => |*x| return x.render(tokens, stream),
.ExpectedPrimaryExpr => |*x| return x.render(tokens, stream),
.ExpectedToken => |*x| return x.render(tokens, stream),
.ExpectedCommaOrEnd => |*x| return x.render(tokens, stream),
.ExpectedParamList => |*x| return x.render(tokens, stream),
.ExpectedPayload => |*x| return x.render(tokens, stream),
.ExpectedBlockOrAssignment => |*x| return x.render(tokens, stream),
.ExpectedBlockOrExpression => |*x| return x.render(tokens, stream),
.ExpectedExprOrAssignment => |*x| return x.render(tokens, stream),
.ExpectedPrefixExpr => |*x| return x.render(tokens, stream),
.ExpectedLoopExpr => |*x| return x.render(tokens, stream),
.ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
.ExpectedSuffixOp => |*x| return x.render(tokens, stream),
.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),
}
}
const token_tags = tree.tokens.items(.tag);
switch (parse_error.tag) {
.asterisk_after_ptr_deref => {
return stream.writeAll("'.*' cannot be followed by '*'. Are you missing a space?");
},
.decl_between_fields => {
return stream.writeAll("declarations are not allowed between container fields");
},
.expected_block => {
return stream.print("expected block or field, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_block_or_assignment => {
return stream.print("expected block or assignment, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_block_or_expr => {
return stream.print("expected block or expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_block_or_field => {
return stream.print("expected block or field, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_container_members => {
return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_expr => {
return stream.print("expected expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_expr_or_assignment => {
return stream.print("expected expression or assignment, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_fn => {
return stream.print("expected function, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_inlinable => {
return stream.print("expected 'while' or 'for', found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_labelable => {
return stream.print("expected 'while', 'for', 'inline', 'suspend', or '{{', found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_param_list => {
return stream.print("expected parameter list, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_prefix_expr => {
return stream.print("expected prefix expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_primary_type_expr => {
return stream.print("expected primary type expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_return_type => {
return stream.print("expected return type expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_semi_or_else => {
return stream.print("expected ';' or 'else', found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_semi_or_lbrace => {
return stream.print("expected ';' or '{{', found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_statement => {
return stream.print("expected statement, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_string_literal => {
return stream.print("expected string literal, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_suffix_op => {
return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_type_expr => {
return stream.print("expected type expression, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_var_decl => {
return stream.print("expected variable declaration, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.expected_var_decl_or_fn => {
return stream.print("expected variable declaration or function, found '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.extra_align_qualifier => {
return stream.writeAll("extra align qualifier");
},
.extra_allowzero_qualifier => {
return stream.writeAll("extra allowzero qualifier");
},
.extra_const_qualifier => {
return stream.writeAll("extra const qualifier");
},
.extra_volatile_qualifier => {
return stream.writeAll("extra volatile qualifier");
},
.invalid_token => {
return stream.print("invalid token '{s}'", .{
token_tags[parse_error.token].symbol(),
});
},
.same_line_doc_comment => {
return stream.writeAll("same line documentation comment");
},
.unattached_doc_comment => {
return stream.writeAll("unattached documentation comment");
},
pub fn errorToken(tree: Tree, parse_error: Error) TokenIndex {
switch (parse_error) {
.InvalidToken => |x| return x.token,
.ExpectedContainerMembers => |x| return x.token,
.ExpectedStringLiteral => |x| return x.token,
.ExpectedIntegerLiteral => |x| return x.token,
.ExpectedPubItem => |x| return x.token,
.ExpectedIdentifier => |x| return x.token,
.ExpectedStatement => |x| return x.token,
.ExpectedVarDeclOrFn => |x| return x.token,
.ExpectedVarDecl => |x| return x.token,
.ExpectedFn => |x| return x.token,
.ExpectedReturnType => |x| return x.token,
.ExpectedAggregateKw => |x| return x.token,
.SameLineDocComment => |x| return x.token,
.UnattachedDocComment => |x| return x.token,
.ExpectedEqOrSemi => |x| return x.token,
.ExpectedSemiOrLBrace => |x| return x.token,
.ExpectedSemiOrElse => |x| return x.token,
.ExpectedLabelOrLBrace => |x| return x.token,
.ExpectedLBrace => |x| return x.token,
.ExpectedColonOrRParen => |x| return x.token,
.ExpectedLabelable => |x| return x.token,
.ExpectedInlinable => |x| return x.token,
.ExpectedAsmOutputReturnOrType => |x| return x.token,
.ExpectedCall => |x| return tree.nodes.items(.main_token)[x.node],
.ExpectedCallOrFnProto => |x| return tree.nodes.items(.main_token)[x.node],
.ExpectedSliceOrRBracket => |x| return x.token,
.ExtraAlignQualifier => |x| return x.token,
.ExtraConstQualifier => |x| return x.token,
.ExtraVolatileQualifier => |x| return x.token,
.ExtraAllowZeroQualifier => |x| return x.token,
.ExpectedTypeExpr => |x| return x.token,
.ExpectedPrimaryTypeExpr => |x| return x.token,
.ExpectedParamType => |x| return x.token,
.ExpectedExpr => |x| return x.token,
.ExpectedPrimaryExpr => |x| return x.token,
.ExpectedToken => |x| return x.token,
.ExpectedCommaOrEnd => |x| return x.token,
.ExpectedParamList => |x| return x.token,
.ExpectedPayload => |x| return x.token,
.ExpectedBlockOrAssignment => |x| return x.token,
.ExpectedBlockOrExpression => |x| return x.token,
.ExpectedExprOrAssignment => |x| return x.token,
.ExpectedPrefixExpr => |x| return x.token,
.ExpectedLoopExpr => |x| return x.token,
.ExpectedDerefOrUnwrap => |x| return x.token,
.ExpectedSuffixOp => |x| return x.token,
.ExpectedBlockOrField => |x| return x.token,
.DeclBetweenFields => |x| return x.token,
.InvalidAnd => |x| return x.token,
.AsteriskAfterPointerDereference => |x| return x.token,
.expected_token => {
const found_tag = token_tags[parse_error.token];
const expected_symbol = parse_error.extra.expected_tag.symbol();
switch (found_tag) {
.invalid => return stream.print("expected '{s}', found invalid bytes", .{
expected_symbol,
}),
else => return stream.print("expected '{s}', found '{s}'", .{
expected_symbol, found_tag.symbol(),
}),
}
},
}
}
@ -2239,236 +2286,50 @@ pub const full = struct {
};
};
pub const Error = union(enum) {
InvalidToken: InvalidToken,
ExpectedContainerMembers: ExpectedContainerMembers,
ExpectedStringLiteral: ExpectedStringLiteral,
ExpectedIntegerLiteral: ExpectedIntegerLiteral,
ExpectedPubItem: ExpectedPubItem,
ExpectedIdentifier: ExpectedIdentifier,
ExpectedStatement: ExpectedStatement,
ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,
ExpectedVarDecl: ExpectedVarDecl,
ExpectedFn: ExpectedFn,
ExpectedReturnType: ExpectedReturnType,
ExpectedAggregateKw: ExpectedAggregateKw,
SameLineDocComment: SameLineDocComment,
UnattachedDocComment: UnattachedDocComment,
ExpectedEqOrSemi: ExpectedEqOrSemi,
ExpectedSemiOrLBrace: ExpectedSemiOrLBrace,
ExpectedSemiOrElse: ExpectedSemiOrElse,
ExpectedLabelOrLBrace: ExpectedLabelOrLBrace,
ExpectedLBrace: ExpectedLBrace,
ExpectedColonOrRParen: ExpectedColonOrRParen,
ExpectedLabelable: ExpectedLabelable,
ExpectedInlinable: ExpectedInlinable,
ExpectedAsmOutputReturnOrType: ExpectedAsmOutputReturnOrType,
ExpectedCall: ExpectedCall,
ExpectedCallOrFnProto: ExpectedCallOrFnProto,
ExpectedSliceOrRBracket: ExpectedSliceOrRBracket,
ExtraAlignQualifier: ExtraAlignQualifier,
ExtraConstQualifier: ExtraConstQualifier,
ExtraVolatileQualifier: ExtraVolatileQualifier,
ExtraAllowZeroQualifier: ExtraAllowZeroQualifier,
ExpectedTypeExpr: ExpectedTypeExpr,
ExpectedPrimaryTypeExpr: ExpectedPrimaryTypeExpr,
ExpectedParamType: ExpectedParamType,
ExpectedExpr: ExpectedExpr,
ExpectedPrimaryExpr: ExpectedPrimaryExpr,
ExpectedToken: ExpectedToken,
ExpectedCommaOrEnd: ExpectedCommaOrEnd,
ExpectedParamList: ExpectedParamList,
ExpectedPayload: ExpectedPayload,
ExpectedBlockOrAssignment: ExpectedBlockOrAssignment,
ExpectedBlockOrExpression: ExpectedBlockOrExpression,
ExpectedExprOrAssignment: ExpectedExprOrAssignment,
ExpectedPrefixExpr: ExpectedPrefixExpr,
ExpectedLoopExpr: ExpectedLoopExpr,
ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
ExpectedSuffixOp: ExpectedSuffixOp,
ExpectedBlockOrField: ExpectedBlockOrField,
DeclBetweenFields: DeclBetweenFields,
InvalidAnd: InvalidAnd,
AsteriskAfterPointerDereference: AsteriskAfterPointerDereference,
pub const Error = struct {
tag: Tag,
token: TokenIndex,
extra: union {
none: void,
expected_tag: Token.Tag,
} = .{ .none = {} },
pub const InvalidToken = SingleTokenError("Invalid token '{s}'");
pub const ExpectedContainerMembers = SingleTokenError("Expected test, comptime, var decl, or container field, found '{s}'");
pub const ExpectedStringLiteral = SingleTokenError("Expected string literal, found '{s}'");
pub const ExpectedIntegerLiteral = SingleTokenError("Expected integer literal, found '{s}'");
pub const ExpectedIdentifier = SingleTokenError("Expected identifier, found '{s}'");
pub const ExpectedStatement = SingleTokenError("Expected statement, found '{s}'");
pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found '{s}'");
pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{s}'");
pub const ExpectedFn = SingleTokenError("Expected function, found '{s}'");
pub const ExpectedReturnType = SingleTokenError("Expected return type expression, found '{s}'");
pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Tag.keyword_struct.symbol() ++ "', '" ++ Token.Tag.keyword_union.symbol() ++ "', '" ++ Token.Tag.keyword_enum.symbol() ++ "', or '" ++ Token.Tag.keyword_opaque.symbol() ++ "', found '{s}'");
pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{s}'");
pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found '{s}'");
pub const ExpectedSemiOrElse = SingleTokenError("Expected ';' or 'else', found '{s}'");
pub const ExpectedLBrace = SingleTokenError("Expected '{{', found '{s}'");
pub const ExpectedLabelOrLBrace = SingleTokenError("Expected label or '{{', found '{s}'");
pub const ExpectedColonOrRParen = SingleTokenError("Expected ':' or ')', found '{s}'");
pub const ExpectedLabelable = SingleTokenError("Expected 'while', 'for', 'inline', 'suspend', or '{{', found '{s}'");
pub const ExpectedInlinable = SingleTokenError("Expected 'while' or 'for', found '{s}'");
pub const ExpectedAsmOutputReturnOrType = SingleTokenError("Expected '->' or '" ++ Token.Tag.identifier.symbol() ++ "', found '{s}'");
pub const ExpectedSliceOrRBracket = SingleTokenError("Expected ']' or '..', found '{s}'");
pub const ExpectedTypeExpr = SingleTokenError("Expected type expression, found '{s}'");
pub const ExpectedPrimaryTypeExpr = SingleTokenError("Expected primary type expression, found '{s}'");
pub const ExpectedExpr = SingleTokenError("Expected expression, found '{s}'");
pub const ExpectedPrimaryExpr = SingleTokenError("Expected primary expression, found '{s}'");
pub const ExpectedParamList = SingleTokenError("Expected parameter list, found '{s}'");
pub const ExpectedPayload = SingleTokenError("Expected loop payload, found '{s}'");
pub const ExpectedBlockOrAssignment = SingleTokenError("Expected block or assignment, found '{s}'");
pub const ExpectedBlockOrExpression = SingleTokenError("Expected block or expression, found '{s}'");
pub const ExpectedExprOrAssignment = SingleTokenError("Expected expression or assignment, found '{s}'");
pub const ExpectedPrefixExpr = SingleTokenError("Expected prefix expression, found '{s}'");
pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found '{s}'");
pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found '{s}'");
pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found '{s}'");
pub const ExpectedBlockOrField = SingleTokenError("Expected block or field, found '{s}'");
pub const Tag = enum {
asterisk_after_ptr_deref,
decl_between_fields,
expected_block,
expected_block_or_assignment,
expected_block_or_expr,
expected_block_or_field,
expected_container_members,
expected_expr,
expected_expr_or_assignment,
expected_fn,
expected_inlinable,
expected_labelable,
expected_param_list,
expected_prefix_expr,
expected_primary_type_expr,
expected_return_type,
expected_semi_or_else,
expected_semi_or_lbrace,
expected_statement,
expected_string_literal,
expected_suffix_op,
expected_type_expr,
expected_var_decl,
expected_var_decl_or_fn,
extra_align_qualifier,
extra_allowzero_qualifier,
extra_const_qualifier,
extra_volatile_qualifier,
invalid_token,
same_line_doc_comment,
unattached_doc_comment,
pub const ExpectedParamType = SimpleError("Expected parameter type");
pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub");
pub const SameLineDocComment = SimpleError("Same line documentation comment");
pub const UnattachedDocComment = SimpleError("Unattached documentation comment");
pub const ExtraAlignQualifier = SimpleError("Extra align qualifier");
pub const ExtraConstQualifier = SimpleError("Extra const qualifier");
pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier");
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.Index,
pub fn render(self: ExpectedCall, tree: Tree, stream: anytype) !void {
const node_tag = tree.nodes.items(.tag)[self.node];
return stream.print("expected " ++ @tagName(Node.Tag.call) ++ ", found {s}", .{
@tagName(node_tag),
});
}
/// `expected_tag` is populated.
expected_token,
};
pub const ExpectedCallOrFnProto = struct {
node: Node.Index,
pub fn render(self: ExpectedCallOrFnProto, tree: Tree, stream: anytype) !void {
const node_tag = tree.nodes.items(.tag)[self.node];
return stream.print("expected " ++ @tagName(Node.Tag.call) ++ " or " ++
@tagName(Node.Tag.fn_proto) ++ ", found {s}", .{@tagName(node_tag)});
}
};
pub const ExpectedToken = struct {
token: TokenIndex,
expected_id: Token.Tag,
pub fn render(self: *const ExpectedToken, tokens: []const Token.Tag, stream: anytype) !void {
const found_token = tokens[self.token];
switch (found_token) {
.invalid => {
return stream.print("expected '{s}', found invalid bytes", .{self.expected_id.symbol()});
},
else => {
const token_name = found_token.symbol();
return stream.print("expected '{s}', found '{s}'", .{ self.expected_id.symbol(), token_name });
},
}
}
};
pub const ExpectedCommaOrEnd = struct {
token: TokenIndex,
end_id: Token.Tag,
pub fn render(self: *const ExpectedCommaOrEnd, tokens: []const Token.Tag, stream: anytype) !void {
const actual_token = tokens[self.token];
return stream.print("expected ',' or '{s}', found '{s}'", .{
self.end_id.symbol(),
actual_token.symbol(),
});
}
};
fn SingleTokenError(comptime msg: []const u8) type {
return struct {
const ThisError = @This();
token: TokenIndex,
pub fn render(self: *const ThisError, tokens: []const Token.Tag, stream: anytype) !void {
const actual_token = tokens[self.token];
return stream.print(msg, .{actual_token.symbol()});
}
};
}
fn SimpleError(comptime msg: []const u8) type {
return struct {
const ThisError = @This();
token: TokenIndex,
pub fn render(self: *const ThisError, tokens: []const Token.Tag, stream: anytype) !void {
return stream.writeAll(msg);
}
};
}
pub fn loc(self: Error) TokenIndex {
switch (self) {
.InvalidToken => |x| return x.token,
.ExpectedContainerMembers => |x| return x.token,
.ExpectedStringLiteral => |x| return x.token,
.ExpectedIntegerLiteral => |x| return x.token,
.ExpectedPubItem => |x| return x.token,
.ExpectedIdentifier => |x| return x.token,
.ExpectedStatement => |x| return x.token,
.ExpectedVarDeclOrFn => |x| return x.token,
.ExpectedVarDecl => |x| return x.token,
.ExpectedFn => |x| return x.token,
.ExpectedReturnType => |x| return x.token,
.ExpectedAggregateKw => |x| return x.token,
.UnattachedDocComment => |x| return x.token,
.ExpectedEqOrSemi => |x| return x.token,
.ExpectedSemiOrLBrace => |x| return x.token,
.ExpectedSemiOrElse => |x| return x.token,
.ExpectedLabelOrLBrace => |x| return x.token,
.ExpectedLBrace => |x| return x.token,
.ExpectedColonOrRParen => |x| return x.token,
.ExpectedLabelable => |x| return x.token,
.ExpectedInlinable => |x| return x.token,
.ExpectedAsmOutputReturnOrType => |x| return x.token,
.ExpectedCall => |x| @panic("TODO redo ast errors"),
.ExpectedCallOrFnProto => |x| @panic("TODO redo ast errors"),
.ExpectedSliceOrRBracket => |x| return x.token,
.ExtraAlignQualifier => |x| return x.token,
.ExtraConstQualifier => |x| return x.token,
.ExtraVolatileQualifier => |x| return x.token,
.ExtraAllowZeroQualifier => |x| return x.token,
.ExpectedTypeExpr => |x| return x.token,
.ExpectedPrimaryTypeExpr => |x| return x.token,
.ExpectedParamType => |x| return x.token,
.ExpectedExpr => |x| return x.token,
.ExpectedPrimaryExpr => |x| return x.token,
.ExpectedToken => |x| return x.token,
.ExpectedCommaOrEnd => |x| return x.token,
.ExpectedParamList => |x| return x.token,
.ExpectedPayload => |x| return x.token,
.ExpectedBlockOrAssignment => |x| return x.token,
.ExpectedBlockOrExpression => |x| return x.token,
.ExpectedExprOrAssignment => |x| return x.token,
.ExpectedPrefixExpr => |x| return x.token,
.ExpectedLoopExpr => |x| return x.token,
.ExpectedDerefOrUnwrap => |x| return x.token,
.ExpectedSuffixOp => |x| return x.token,
.ExpectedBlockOrField => |x| return x.token,
.DeclBetweenFields => |x| return x.token,
.InvalidAnd => |x| return x.token,
.AsteriskAfterPointerDereference => |x| return x.token,
}
}
};
pub const Node = struct {

View File

@ -150,14 +150,41 @@ const Parser = struct {
return result;
}
fn warn(p: *Parser, msg: ast.Error) error{OutOfMemory}!void {
fn warn(p: *Parser, tag: ast.Error.Tag) error{OutOfMemory}!void {
@setCold(true);
try p.warnMsg(.{ .tag = tag, .token = p.tok_i });
}
fn warnExpected(p: *Parser, expected_token: Token.Tag) error{OutOfMemory}!void {
@setCold(true);
try p.warnMsg(.{
.tag = .expected_token,
.token = p.tok_i,
.extra = .{ .expected_tag = expected_token },
});
}
fn warnMsg(p: *Parser, msg: ast.Error) error{OutOfMemory}!void {
@setCold(true);
try p.errors.append(p.gpa, msg);
}
fn fail(p: *Parser, msg: ast.Error) error{ ParseError, OutOfMemory } {
fn fail(p: *Parser, tag: ast.Error.Tag) error{ ParseError, OutOfMemory } {
@setCold(true);
try p.warn(msg);
return p.failMsg(.{ .tag = tag, .token = p.tok_i });
}
fn failExpected(p: *Parser, expected_token: Token.Tag) error{ ParseError, OutOfMemory } {
@setCold(true);
return p.failMsg(.{
.tag = .expected_token,
.token = p.tok_i,
.extra = .{ .expected_tag = expected_token },
});
}
fn failMsg(p: *Parser, msg: ast.Error) error{ ParseError, OutOfMemory } {
@setCold(true);
try p.warnMsg(msg);
return error.ParseError;
}
@ -190,7 +217,7 @@ const Parser = struct {
var trailing_comma = false;
while (true) {
const doc_comment = try p.eatDocComments ();
const doc_comment = try p.eatDocComments();
switch (p.token_tags[p.tok_i]) {
.keyword_test => {
@ -212,8 +239,9 @@ const Parser = struct {
.none => field_state = .seen,
.err, .seen => {},
.end => |node| {
try p.warn(.{
.DeclBetweenFields = .{ .token = p.nodes.items(.main_token)[node] },
try p.warnMsg(.{
.tag = .decl_between_fields,
.token = p.nodes.items(.main_token)[node],
});
// Continue parsing; error will be reported later.
field_state = .err;
@ -234,9 +262,7 @@ const Parser = struct {
}
// There is not allowed to be a decl after a field with no comma.
// Report error but recover parser.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
p.findNextContainerMember();
}
},
@ -267,7 +293,7 @@ const Parser = struct {
},
else => {
p.tok_i += 1;
try p.warn(.{ .ExpectedBlockOrField = .{ .token = p.tok_i } });
try p.warn(.expected_block_or_field);
},
},
.keyword_pub => {
@ -316,8 +342,9 @@ const Parser = struct {
.none => field_state = .seen,
.err, .seen => {},
.end => |node| {
try p.warn(.{
.DeclBetweenFields = .{ .token = p.nodes.items(.main_token)[node] },
try p.warnMsg(.{
.tag = .decl_between_fields,
.token = p.nodes.items(.main_token)[node],
});
// Continue parsing; error will be reported later.
field_state = .err;
@ -338,20 +365,21 @@ const Parser = struct {
}
// There is not allowed to be a decl after a field with no comma.
// Report error but recover parser.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
p.findNextContainerMember();
}
},
.eof, .r_brace => {
if (doc_comment) |tok| {
try p.warn(.{ .UnattachedDocComment = .{ .token = tok } });
try p.warnMsg(.{
.tag = .unattached_doc_comment,
.token = tok,
});
}
break;
},
else => {
try p.warn(.{ .ExpectedContainerMembers = .{ .token = p.tok_i } });
try p.warn(.expected_container_members);
// This was likely not supposed to end yet; try to find the next declaration.
p.findNextContainerMember();
},
@ -475,7 +503,7 @@ const Parser = struct {
const test_token = p.assertToken(.keyword_test);
const name_token = p.eatToken(.string_literal);
const block_node = try p.parseBlock();
if (block_node == 0) return p.fail(.{ .ExpectedLBrace = .{ .token = p.tok_i } });
if (block_node == 0) return p.fail(.expected_block);
return p.addNode(.{
.tag = .test_decl,
.main_token = test_token,
@ -540,15 +568,13 @@ const Parser = struct {
// Since parseBlock only return error.ParseError on
// a missing '}' we can assume this function was
// supposed to end here.
try p.warn(.{ .ExpectedSemiOrLBrace = .{ .token = p.tok_i } });
try p.warn(.expected_semi_or_lbrace);
return null_node;
},
}
}
if (expect_fn) {
try p.warn(.{
.ExpectedFn = .{ .token = p.tok_i },
});
try p.warn(.expected_fn);
return error.ParseError;
}
@ -559,11 +585,11 @@ const Parser = struct {
return var_decl;
}
if (thread_local_token != null) {
return p.fail(.{ .ExpectedVarDecl = .{ .token = p.tok_i } });
return p.fail(.expected_var_decl);
}
if (exported) {
return p.fail(.{ .ExpectedVarDeclOrFn = .{ .token = p.tok_i } });
return p.fail(.expected_var_decl_or_fn);
}
return p.expectUsingNamespace();
@ -618,7 +644,7 @@ const Parser = struct {
if (return_type_expr == 0) {
// most likely the user forgot to specify the return type.
// Mark return type as invalid and try to continue.
try p.warn(.{ .ExpectedReturnType = .{ .token = p.tok_i } });
try p.warn(.expected_return_type);
}
if (align_expr == 0 and section_expr == 0 and callconv_expr == 0) {
@ -901,7 +927,7 @@ const Parser = struct {
fn expectStatement(p: *Parser) !Node.Index {
const statement = try p.parseStatement();
if (statement == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.expected_statement);
}
return statement;
}
@ -940,7 +966,7 @@ const Parser = struct {
if (block_expr != 0) break :blk block_expr;
const assign_expr = try p.parseAssignExpr();
if (assign_expr == 0) {
return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
return p.fail(.expected_block_or_assignment);
}
if (p.eatToken(.semicolon)) |_| {
return p.addNode(.{
@ -957,7 +983,7 @@ const Parser = struct {
};
const else_token = p.eatToken(.keyword_else) orelse {
if (else_required) {
return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
return p.fail(.expected_semi_or_else);
}
return p.addNode(.{
.tag = .if_simple,
@ -993,7 +1019,7 @@ const Parser = struct {
if (loop_stmt != 0) return loop_stmt;
if (label_token != 0) {
return p.fail(.{ .ExpectedLabelable = .{ .token = p.tok_i } });
return p.fail(.expected_labelable);
}
return null_node;
@ -1012,7 +1038,7 @@ const Parser = struct {
if (inline_token == null) return null_node;
// If we've seen "inline", there should have been a "for" or "while"
return p.fail(.{ .ExpectedInlinable = .{ .token = p.tok_i } });
return p.fail(.expected_inlinable);
}
/// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
@ -1034,7 +1060,7 @@ const Parser = struct {
if (block_expr != 0) break :blk block_expr;
const assign_expr = try p.parseAssignExpr();
if (assign_expr == 0) {
return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
return p.fail(.expected_block_or_assignment);
}
if (p.eatToken(.semicolon)) |_| {
return p.addNode(.{
@ -1051,7 +1077,7 @@ const Parser = struct {
};
const else_token = p.eatToken(.keyword_else) orelse {
if (else_required) {
return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
return p.fail(.expected_semi_or_else);
}
return p.addNode(.{
.tag = .for_simple,
@ -1095,7 +1121,7 @@ const Parser = struct {
if (block_expr != 0) break :blk block_expr;
const assign_expr = try p.parseAssignExpr();
if (assign_expr == 0) {
return p.fail(.{ .ExpectedBlockOrAssignment = .{ .token = p.tok_i } });
return p.fail(.expected_block_or_assignment);
}
if (p.eatToken(.semicolon)) |_| {
if (cont_expr == 0) {
@ -1126,7 +1152,7 @@ const Parser = struct {
};
const else_token = p.eatToken(.keyword_else) orelse {
if (else_required) {
return p.fail(.{ .ExpectedSemiOrElse = .{ .token = p.tok_i } });
return p.fail(.expected_semi_or_else);
}
if (cont_expr == 0) {
return p.addNode(.{
@ -1186,7 +1212,7 @@ const Parser = struct {
fn expectBlockExprStatement(p: *Parser) !Node.Index {
const node = try p.parseBlockExprStatement();
if (node == 0) {
return p.fail(.{ .ExpectedBlockOrExpression = .{ .token = p.tok_i } });
return p.fail(.expected_block_or_expr);
}
return node;
}
@ -1259,7 +1285,7 @@ const Parser = struct {
fn expectAssignExpr(p: *Parser) !Node.Index {
const expr = try p.parseAssignExpr();
if (expr == 0) {
return p.fail(.{ .ExpectedExprOrAssignment = .{ .token = p.tok_i } });
return p.fail(.expected_expr_or_assignment);
}
return expr;
}
@ -1272,7 +1298,7 @@ const Parser = struct {
fn expectExpr(p: *Parser) Error!Node.Index {
const node = try p.parseExpr();
if (node == 0) {
return p.fail(.{ .ExpectedExpr = .{ .token = p.tok_i } });
return p.fail(.expected_expr);
} else {
return node;
}
@ -1289,7 +1315,7 @@ const Parser = struct {
const or_token = p.nextToken();
const rhs = try p.parseBoolAndExpr();
if (rhs == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
}
res = try p.addNode(.{
.tag = .bool_or,
@ -1316,7 +1342,7 @@ const Parser = struct {
const and_token = p.nextToken();
const rhs = try p.parseCompareExpr();
if (rhs == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
}
res = try p.addNode(.{
.tag = .bool_and,
@ -1385,7 +1411,7 @@ const Parser = struct {
_ = try p.parsePayload();
const rhs = try p.parseBitShiftExpr();
if (rhs == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
}
res = try p.addNode(.{
.tag = .@"catch",
@ -1413,7 +1439,7 @@ const Parser = struct {
fn expectBitwiseExpr(p: *Parser) Error!Node.Index {
const node = try p.parseBitwiseExpr();
if (node == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
} else {
return node;
}
@ -1447,7 +1473,7 @@ const Parser = struct {
fn expectBitShiftExpr(p: *Parser) Error!Node.Index {
const node = try p.parseBitShiftExpr();
if (node == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
} else {
return node;
}
@ -1487,7 +1513,7 @@ const Parser = struct {
fn expectAdditionExpr(p: *Parser) Error!Node.Index {
const node = try p.parseAdditionExpr();
if (node == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
}
return node;
}
@ -1528,7 +1554,7 @@ const Parser = struct {
fn expectMultiplyExpr(p: *Parser) Error!Node.Index {
const node = try p.parseMultiplyExpr();
if (node == 0) {
return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
return p.fail(.invalid_token);
}
return node;
}
@ -1566,7 +1592,7 @@ const Parser = struct {
fn expectPrefixExpr(p: *Parser) Error!Node.Index {
const node = try p.parsePrefixExpr();
if (node == 0) {
return p.fail(.{ .ExpectedPrefixExpr = .{ .token = p.tok_i } });
return p.fail(.expected_prefix_expr);
}
return node;
}
@ -1827,7 +1853,7 @@ const Parser = struct {
fn expectTypeExpr(p: *Parser) Error!Node.Index {
const node = try p.parseTypeExpr();
if (node == 0) {
return p.fail(.{ .ExpectedTypeExpr = .{ .token = p.tok_i } });
return p.fail(.expected_type_expr);
}
return node;
}
@ -1922,9 +1948,7 @@ const Parser = struct {
switch (p.token_tags[p.tok_i]) {
.keyword_for => return p.parseForExpr(),
.keyword_while => return p.parseWhileExpr(),
else => return p.fail(.{
.ExpectedInlinable = .{ .token = p.tok_i },
}),
else => return p.fail(.expected_inlinable),
}
},
.keyword_for => {
@ -1950,9 +1974,7 @@ const Parser = struct {
switch (p.token_tags[p.tok_i]) {
.keyword_for => return p.parseForExpr(),
.keyword_while => return p.parseWhileExpr(),
else => return p.fail(.{
.ExpectedInlinable = .{ .token = p.tok_i },
}),
else => return p.fail(.expected_inlinable),
}
},
.keyword_for => return p.parseForExpr(),
@ -2170,20 +2192,13 @@ const Parser = struct {
.r_brace => break,
.colon, .r_paren, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_brace,
},
});
return p.failExpected(.r_brace);
},
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -2214,9 +2229,7 @@ const Parser = struct {
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
var init_list = std.ArrayList(Node.Index).init(p.gpa);
@ -2278,7 +2291,7 @@ const Parser = struct {
res = node;
}
const lparen = (try p.expectTokenRecoverable(.l_paren)) orelse {
try p.warn(.{ .ExpectedParamList = .{ .token = p.tok_i } });
try p.warn(.expected_param_list);
return res;
};
if (p.eatToken(.r_paren)) |_| {
@ -2304,9 +2317,7 @@ const Parser = struct {
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
var param_list = std.ArrayList(Node.Index).init(p.gpa);
@ -2352,21 +2363,11 @@ const Parser = struct {
},
.colon, .r_brace, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_paren,
},
});
return p.failExpected(.r_paren);
},
else => {
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .comma,
},
});
try p.warnExpected(.comma);
},
}
}
@ -2405,9 +2406,7 @@ const Parser = struct {
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
var param_list = std.ArrayList(Node.Index).init(p.gpa);
@ -2453,21 +2452,11 @@ const Parser = struct {
},
.colon, .r_brace, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_paren,
},
});
return p.failExpected(.r_paren);
},
else => {
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .comma,
},
});
try p.warnExpected(.comma);
},
}
}
@ -2645,9 +2634,7 @@ const Parser = struct {
switch (p.token_tags[p.tok_i]) {
.keyword_for => return p.parseForTypeExpr(),
.keyword_while => return p.parseWhileTypeExpr(),
else => return p.fail(.{
.ExpectedInlinable = .{ .token = p.tok_i },
}),
else => return p.fail(.expected_inlinable),
}
},
.keyword_for => {
@ -2716,9 +2703,7 @@ const Parser = struct {
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
const field_init_two = try p.expectFieldInit();
const comma_two = p.eatToken(.comma);
@ -2733,9 +2718,7 @@ const Parser = struct {
});
}
if (comma_two == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
var init_list = std.ArrayList(Node.Index).init(p.gpa);
defer init_list.deinit();
@ -2754,21 +2737,11 @@ const Parser = struct {
.r_brace => break,
.colon, .r_paren, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_brace,
},
});
return p.failExpected(.r_brace);
},
else => {
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .comma,
},
});
try p.warnExpected(.comma);
},
}
}
@ -2797,9 +2770,7 @@ const Parser = struct {
});
}
if (comma_one == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
const elem_init_two = try p.expectExpr();
const comma_two = p.eatToken(.comma);
@ -2814,9 +2785,7 @@ const Parser = struct {
});
}
if (comma_two == null) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
}
var init_list = std.ArrayList(Node.Index).init(p.gpa);
defer init_list.deinit();
@ -2835,21 +2804,11 @@ const Parser = struct {
.r_brace => break,
.colon, .r_paren, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_brace,
},
});
return p.failExpected(.r_brace);
},
else => {
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .comma,
},
});
try p.warnExpected(.comma);
},
}
}
@ -2892,20 +2851,13 @@ const Parser = struct {
.r_brace => break,
.colon, .r_paren, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{
.token = p.tok_i,
.expected_id = .r_brace,
},
});
return p.failExpected(.r_brace);
},
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -2942,7 +2894,7 @@ const Parser = struct {
fn expectPrimaryTypeExpr(p: *Parser) !Node.Index {
const node = try p.parsePrimaryTypeExpr();
if (node == 0) {
return p.fail(.{ .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i } });
return p.fail(.expected_primary_type_expr);
}
return node;
}
@ -3095,9 +3047,7 @@ const Parser = struct {
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -3112,9 +3062,7 @@ const Parser = struct {
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -3126,9 +3074,7 @@ const Parser = struct {
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -3238,7 +3184,7 @@ const Parser = struct {
_ = p.eatToken(.colon) orelse return null_node;
_ = try p.expectToken(.l_paren);
const node = try p.parseAssignExpr();
if (node == 0) return p.fail(.{ .ExpectedExprOrAssignment = .{ .token = p.tok_i } });
if (node == 0) return p.fail(.expected_expr_or_assignment);
_ = try p.expectToken(.r_paren);
return node;
}
@ -3418,9 +3364,7 @@ const Parser = struct {
switch (p.token_tags[p.tok_i]) {
.keyword_align => {
if (result.align_node != 0) {
try p.warn(.{
.ExtraAlignQualifier = .{ .token = p.tok_i },
});
try p.warn(.extra_align_qualifier);
}
p.tok_i += 1;
_ = try p.expectToken(.l_paren);
@ -3436,27 +3380,21 @@ const Parser = struct {
},
.keyword_const => {
if (saw_const) {
try p.warn(.{
.ExtraConstQualifier = .{ .token = p.tok_i },
});
try p.warn(.extra_const_qualifier);
}
p.tok_i += 1;
saw_const = true;
},
.keyword_volatile => {
if (saw_volatile) {
try p.warn(.{
.ExtraVolatileQualifier = .{ .token = p.tok_i },
});
try p.warn(.extra_volatile_qualifier);
}
p.tok_i += 1;
saw_volatile = true;
},
.keyword_allowzero => {
if (saw_allowzero) {
try p.warn(.{
.ExtraAllowZeroQualifier = .{ .token = p.tok_i },
});
try p.warn(.extra_allowzero_qualifier);
}
p.tok_i += 1;
saw_allowzero = true;
@ -3539,11 +3477,10 @@ const Parser = struct {
},
}),
.invalid_periodasterisks => {
const period_asterisk = p.nextToken();
try p.warn(.{ .AsteriskAfterPointerDereference = .{ .token = period_asterisk } });
try p.warn(.asterisk_after_ptr_deref);
return p.addNode(.{
.tag = .deref,
.main_token = period_asterisk,
.main_token = p.nextToken(),
.data = .{
.lhs = lhs,
.rhs = undefined,
@ -3569,7 +3506,7 @@ const Parser = struct {
}),
else => {
p.tok_i += 1;
try p.warn(.{ .ExpectedSuffixOp = .{ .token = p.tok_i } });
try p.warn(.expected_suffix_op);
return null_node;
},
},
@ -3743,9 +3680,7 @@ const Parser = struct {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
} else unreachable;
@ -3763,17 +3698,13 @@ const Parser = struct {
.r_paren => return SmallSpan{ .zero_or_one = param_one },
.colon, .r_brace, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .r_paren },
});
return p.failExpected(.r_paren);
},
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
} else unreachable;
@ -3799,17 +3730,13 @@ const Parser = struct {
.r_paren => return SmallSpan{ .multi = list.toOwnedSlice() },
.colon, .r_brace, .r_bracket => {
p.tok_i -= 1;
return p.fail(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .r_paren },
});
return p.failExpected(.r_paren);
},
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -3836,9 +3763,7 @@ const Parser = struct {
else => {
// This is likely just a missing comma;
// give an error but continue parsing this list.
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -3852,9 +3777,7 @@ const Parser = struct {
fn parseBuiltinCall(p: *Parser) !Node.Index {
const builtin_token = p.assertToken(.builtin);
_ = (try p.expectTokenRecoverable(.l_paren)) orelse {
try p.warn(.{
.ExpectedParamList = .{ .token = p.tok_i },
});
try p.warn(.expected_param_list);
// Pretend this was an identifier so we can continue parsing.
return p.addNode(.{
.tag = .identifier,
@ -3901,9 +3824,7 @@ const Parser = struct {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
const param_two = try p.expectExpr();
@ -3932,9 +3853,7 @@ const Parser = struct {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
@ -3976,9 +3895,7 @@ const Parser = struct {
// This is likely just a missing comma;
// give an error but continue parsing this list.
p.tok_i -= 1;
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = .comma },
});
try p.warnExpected(.comma);
},
}
}
@ -4019,7 +3936,7 @@ const Parser = struct {
fn expectStringLiteral(p: *Parser) !Node.Index {
const node = try p.parseStringLiteral();
if (node == 0) {
return p.fail(.{ .ExpectedStringLiteral = .{ .token = p.tok_i } });
return p.fail(.expected_string_literal);
}
return node;
}
@ -4044,7 +3961,7 @@ const Parser = struct {
const then_payload = try p.parsePtrPayload();
const then_expr = try bodyParseFn(p);
if (then_expr == 0) return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
if (then_expr == 0) return p.fail(.invalid_token);
const else_token = p.eatToken(.keyword_else) orelse return p.addNode(.{
.tag = .if_simple,
@ -4056,7 +3973,7 @@ const Parser = struct {
});
const else_payload = try p.parsePayload();
const else_expr = try bodyParseFn(p);
if (else_expr == 0) return p.fail(.{ .InvalidToken = .{ .token = p.tok_i } });
if (else_expr == 0) return p.fail(.invalid_token);
return p.addNode(.{
.tag = .@"if",
@ -4076,7 +3993,10 @@ const Parser = struct {
if (p.eatToken(.doc_comment)) |tok| {
var first_line = tok;
if (tok > 0 and tokensOnSameLine(p, tok - 1, tok)) {
try p.warn(.{ .SameLineDocComment = .{ .token = tok } });
try p.warnMsg(.{
.tag = .same_line_doc_comment,
.token = tok,
});
first_line = p.eatToken(.doc_comment) orelse return null;
}
while (p.eatToken(.doc_comment)) |_| {}
@ -4102,16 +4022,18 @@ const Parser = struct {
fn expectToken(p: *Parser, tag: Token.Tag) Error!TokenIndex {
const token = p.nextToken();
if (p.token_tags[token] != tag) {
return p.fail(.{ .ExpectedToken = .{ .token = token, .expected_id = tag } });
return p.failMsg(.{
.tag = .expected_token,
.token = token,
.extra = .{ .expected_tag = tag },
});
}
return token;
}
fn expectTokenRecoverable(p: *Parser, tag: Token.Tag) !?TokenIndex {
if (p.token_tags[p.tok_i] != tag) {
try p.warn(.{
.ExpectedToken = .{ .token = p.tok_i, .expected_id = tag },
});
try p.warnExpected(tag);
return null;
} else {
return p.nextToken();

View File

@ -127,7 +127,7 @@ test "zig fmt: decl between fields" {
\\ b: usize,
\\};
, &[_]Error{
.DeclBetweenFields,
.decl_between_fields,
});
}
@ -135,7 +135,7 @@ test "zig fmt: eof after missing comma" {
try testError(
\\foo()
, &[_]Error{
.ExpectedToken,
.expected_token,
});
}
@ -3578,7 +3578,7 @@ test "zig fmt: file ends with struct field" {
// \\const container = extern {};
// \\
// , &[_]Error{
// .ExpectedExpr,
// .expected_expr,
// .ExpectedVarDeclOrFn,
// });
//}
@ -3598,12 +3598,12 @@ test "zig fmt: same line doc comment returns error" {
\\/// comment
\\
, &[_]Error{
.SameLineDocComment,
.SameLineDocComment,
.UnattachedDocComment,
.SameLineDocComment,
.SameLineDocComment,
.UnattachedDocComment,
.same_line_doc_comment,
.same_line_doc_comment,
.unattached_doc_comment,
.same_line_doc_comment,
.same_line_doc_comment,
.unattached_doc_comment,
});
}
@ -3678,10 +3678,10 @@ test "zig fmt: hexadeciaml float literals with underscore separators" {
}
test "zig fmt: C var args" {
try testCanonical(
\\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
\\
);
try testCanonical(
\\pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
\\
);
}
//test "zig fmt: Only indent multiline string literals in function calls" {
@ -4037,8 +4037,8 @@ test "recovery: top level" {
\\test "" {inline}
\\test "" {inline}
, &[_]Error{
.ExpectedInlinable,
.ExpectedInlinable,
.expected_inlinable,
.expected_inlinable,
});
}
@ -4049,8 +4049,8 @@ test "recovery: block statements" {
\\ inline;
\\}
, &[_]Error{
.InvalidToken,
.ExpectedInlinable,
.invalid_token,
.expected_inlinable,
});
}
@ -4066,10 +4066,10 @@ test "recovery: block statements" {
// \\ }
// \\}
// , &[_]Error{
// .ExpectedToken,
// .ExpectedToken,
// .InvalidAnd,
// .InvalidToken,
// .expected_token,
// .expected_token,
// .invalid_and,
// .invalid_token,
// });
//}
@ -4078,8 +4078,8 @@ test "recovery: extra qualifier" {
\\const a: *const const u8;
\\test ""
, &[_]Error{
.ExtraConstQualifier,
.ExpectedLBrace,
.extra_const_qualifier,
.expected_block,
});
}
@ -4091,8 +4091,8 @@ test "recovery: extra qualifier" {
// \\test ""
// , &[_]Error{
// .ExpectedReturnType,
// .InvalidAnd,
// .ExpectedLBrace,
// .invalid_and,
// .expected_block,
// });
//}
@ -4105,10 +4105,10 @@ test "recovery: extra qualifier" {
// \\ async a && b;
// \\}
// , &[_]Error{
// .ExpectedToken,
// .expected_token,
// .ExpectedPubItem,
// .ExpectedParamList,
// .InvalidAnd,
// .invalid_and,
// });
// try testError(
// \\threadlocal test "" {
@ -4117,7 +4117,7 @@ test "recovery: extra qualifier" {
// , &[_]Error{
// .ExpectedVarDecl,
// .ExpectedParamList,
// .InvalidAnd,
// .invalid_and,
// });
//}
@ -4126,13 +4126,13 @@ test "recovery: extra qualifier" {
// \\inline test "" { a && b; }
// , &[_]Error{
// .ExpectedFn,
// .InvalidAnd,
// .invalid_and,
// });
// try testError(
// \\extern "" test "" { a && b; }
// , &[_]Error{
// .ExpectedVarDeclOrFn,
// .InvalidAnd,
// .invalid_and,
// });
//}
@ -4144,12 +4144,12 @@ test "recovery: extra qualifier" {
// \\ @foo
// \\}
// , &[_]Error{
// .InvalidAnd,
// .ExpectedToken,
// .InvalidAnd,
// .ExpectedToken,
// .invalid_and,
// .expected_token,
// .invalid_and,
// .expected_token,
// .ExpectedParamList,
// .ExpectedToken,
// .expected_token,
// });
//}
@ -4163,12 +4163,12 @@ test "recovery: extra qualifier" {
// \\ a && b
// \\}
// , &[_]Error{
// .ExpectedExpr,
// .ExpectedToken,
// .ExpectedToken,
// .ExpectedContainerMembers,
// .InvalidAnd,
// .ExpectedToken,
// .expected_expr,
// .expected_token,
// .expected_token,
// .expected_container_members,
// .invalid_and,
// .expected_token,
// });
//}
@ -4178,7 +4178,7 @@ test "recovery: extra qualifier" {
// \\ a(comptime T: type)
// \\}
// , &[_]Error{
// .ExpectedToken,
// .expected_token,
// });
//}
@ -4189,10 +4189,10 @@ test "recovery: extra qualifier" {
// \\ a && b;
// \\}
// , &[_]Error{
// .ExpectedContainerMembers,
// .ExpectedContainerMembers,
// .ExpectedContainerMembers,
// .InvalidAnd,
// .expected_container_members,
// .expected_container_members,
// .expected_container_members,
// .invalid_and,
// });
//}
//
@ -4202,7 +4202,7 @@ test "recovery: mismatched bracket at top level" {
\\ arr: 128]?G
\\};
, &[_]Error{
.ExpectedToken,
.expected_token,
});
}
@ -4212,9 +4212,9 @@ test "recovery: mismatched bracket at top level" {
// \\ error && foo;
// \\}
// , &[_]Error{
// .ExpectedToken,
// .expected_token,
// .ExpectedIdentifier,
// .InvalidAnd,
// .invalid_and,
// });
//}
@ -4224,15 +4224,15 @@ test "recovery: mismatched bracket at top level" {
// \\ var sequence = "repeat".*** 10;
// \\}
// , &[_]Error{
// .AsteriskAfterPointerDereference,
// .asterisk_after_ptr_deref,
// });
// try testError(
// \\test "" {
// \\ var sequence = "repeat".** 10&&a;
// \\}
// , &[_]Error{
// .AsteriskAfterPointerDereference,
// .InvalidAnd,
// .asterisk_after_ptr_deref,
// .invalid_and,
// });
//}
@ -4245,10 +4245,10 @@ test "recovery: mismatched bracket at top level" {
// \\ a && b;
// \\}
// , &[_]Error{
// .ExpectedSemiOrElse,
// .ExpectedSemiOrElse,
// .ExpectedSemiOrElse,
// .InvalidAnd,
// .expected_semi_or_else,
// .expected_semi_or_else,
// .expected_semi_or_else,
// .invalid_and,
// });
//}
@ -4256,7 +4256,7 @@ test "recovery: invalid comptime" {
try testError(
\\comptime
, &[_]Error{
.ExpectedBlockOrField,
.expected_block_or_field,
});
}
@ -4264,12 +4264,12 @@ test "recovery: missing block after for/while loops" {
try testError(
\\test "" { while (foo) }
, &[_]Error{
.ExpectedBlockOrAssignment,
.expected_block_or_assignment,
});
try testError(
\\test "" { for (foo) |bar| }
, &[_]Error{
.ExpectedBlockOrAssignment,
.expected_block_or_assignment,
});
}
@ -4288,9 +4288,8 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
defer tree.deinit(allocator);
for (tree.errors) |parse_error| {
const error_token = tree.errorToken(parse_error);
const token_start = tree.tokens.items(.start)[error_token];
const loc = tree.tokenLocation(0, error_token);
const token_start = tree.tokens.items(.start)[parse_error.token];
const loc = tree.tokenLocation(0, parse_error.token);
try stderr.print("(memory buffer):{d}:{d}: error: ", .{ loc.line + 1, loc.column + 1 });
try tree.renderError(parse_error, stderr);
try stderr.print("\n{s}\n", .{source[loc.line_start..loc.line_end]});
@ -4362,7 +4361,7 @@ fn testCanonical(source: []const u8) !void {
return testTransform(source, source);
}
const Error = std.meta.Tag(std.zig.ast.Error);
const Error = std.zig.ast.Error.Tag;
fn testError(source: []const u8, expected_errors: []const Error) !void {
var tree = try std.zig.parse(std.testing.allocator, source);
@ -4370,6 +4369,6 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
std.testing.expect(tree.errors.len == expected_errors.len);
for (expected_errors) |expected, i| {
std.testing.expectEqual(expected, tree.errors[i]);
std.testing.expectEqual(expected, tree.errors[i].tag);
}
}

View File

@ -1723,7 +1723,7 @@ pub fn getAstTree(self: *Module, root_scope: *Scope.File) !*const ast.Tree {
err_msg.* = .{
.src_loc = .{
.file_scope = root_scope,
.byte_offset = tree.tokens.items(.start)[parse_err.loc()],
.byte_offset = tree.tokens.items(.start)[parse_err.token],
},
.msg = msg.toOwnedSlice(),
};

View File

@ -2898,7 +2898,7 @@ fn printErrMsgToFile(
.on => true,
.off => false,
};
const lok_token = parse_error.loc();
const lok_token = parse_error.token;
const token_starts = tree.tokens.items(.start);
const token_tags = tree.tokens.items(.tag);