Source
pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
switch (parse_error.tag) {
.asterisk_after_ptr_deref => {
// Note that the token will point at the `.*` but ideally the source
// location would point to the `*` after the `.*`.
return stream.writeAll("'.*' cannot be followed by '*'. Are you missing a space?");
},
.chained_comparison_operators => {
return stream.writeAll("comparison operators cannot be chained");
},
.decl_between_fields => {
return stream.writeAll("declarations are not allowed between container fields");
},
.expected_block => {
return stream.print("expected block, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_block_or_assignment => {
return stream.print("expected block or assignment, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_block_or_expr => {
return stream.print("expected block or expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_block_or_field => {
return stream.print("expected block or field, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_container_members => {
return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{
tree.tokenTag(parse_error.token).symbol(),
});
},
.expected_expr => {
return stream.print("expected expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_expr_or_assignment => {
return stream.print("expected expression or assignment, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_expr_or_var_decl => {
return stream.print("expected expression or var decl, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_fn => {
return stream.print("expected function, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_inlinable => {
return stream.print("expected 'while' or 'for', found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_labelable => {
return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_param_list => {
return stream.print("expected parameter list, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_prefix_expr => {
return stream.print("expected prefix expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_primary_type_expr => {
return stream.print("expected primary type expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_pub_item => {
return stream.writeAll("expected function or variable declaration after pub");
},
.expected_return_type => {
return stream.print("expected return type expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_semi_or_else => {
return stream.writeAll("expected ';' or 'else' after statement");
},
.expected_semi_or_lbrace => {
return stream.writeAll("expected ';' or block after function prototype");
},
.expected_statement => {
return stream.print("expected statement, found '{s}'", .{
tree.tokenTag(parse_error.token).symbol(),
});
},
.expected_suffix_op => {
return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_type_expr => {
return stream.print("expected type expression, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_var_decl => {
return stream.print("expected variable declaration, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_var_decl_or_fn => {
return stream.print("expected variable declaration or function, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_loop_payload => {
return stream.print("expected loop payload, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.expected_container => {
return stream.print("expected a struct, enum or union, found '{s}'", .{
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
});
},
.extern_fn_body => {
return stream.writeAll("extern functions have no body");
},
.extra_addrspace_qualifier => {
return stream.writeAll("extra addrspace qualifier");
},
.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");
},
.ptr_mod_on_array_child_type => {
return stream.print("pointer modifier '{s}' not allowed on array child type", .{
tree.tokenTag(parse_error.token).symbol(),
});
},
.invalid_bit_range => {
return stream.writeAll("bit range not allowed on slices and arrays");
},
.same_line_doc_comment => {
return stream.writeAll("same line documentation comment");
},
.unattached_doc_comment => {
return stream.writeAll("unattached documentation comment");
},
.test_doc_comment => {
return stream.writeAll("documentation comments cannot be attached to tests");
},
.comptime_doc_comment => {
return stream.writeAll("documentation comments cannot be attached to comptime blocks");
},
.varargs_nonfinal => {
return stream.writeAll("function prototype has parameter after varargs");
},
.expected_continue_expr => {
return stream.writeAll("expected ':' before while continue expression");
},
.expected_semi_after_decl => {
return stream.writeAll("expected ';' after declaration");
},
.expected_semi_after_stmt => {
return stream.writeAll("expected ';' after statement");
},
.expected_comma_after_field => {
return stream.writeAll("expected ',' after field");
},
.expected_comma_after_arg => {
return stream.writeAll("expected ',' after argument");
},
.expected_comma_after_param => {
return stream.writeAll("expected ',' after parameter");
},
.expected_comma_after_initializer => {
return stream.writeAll("expected ',' after initializer");
},
.expected_comma_after_switch_prong => {
return stream.writeAll("expected ',' after switch prong");
},
.expected_comma_after_for_operand => {
return stream.writeAll("expected ',' after for operand");
},
.expected_comma_after_capture => {
return stream.writeAll("expected ',' after for capture");
},
.expected_initializer => {
return stream.writeAll("expected field initializer");
},
.mismatched_binary_op_whitespace => {
return stream.print("binary operator `{s}` has whitespace on one side, but not the other.", .{tree.tokenTag(parse_error.token).lexeme().?});
},
.invalid_ampersand_ampersand => {
return stream.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND");
},
.c_style_container => {
return stream.print("'{s} {s}' is invalid", .{
parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token),
});
},
.zig_style_container => {
return stream.print("to declare a container do 'const {s} = {s}'", .{
tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(),
});
},
.previous_field => {
return stream.writeAll("field before declarations here");
},
.next_field => {
return stream.writeAll("field after declarations here");
},
.expected_var_const => {
return stream.writeAll("expected 'var' or 'const' before variable declaration");
},
.wrong_equal_var_decl => {
return stream.writeAll("variable initialized with '==' instead of '='");
},
.var_const_decl => {
return stream.writeAll("use 'var' or 'const' to declare variable");
},
.extra_for_capture => {
return stream.writeAll("extra capture in for loop");
},
.for_input_not_captured => {
return stream.writeAll("for input is not captured");
},
.invalid_byte => {
const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];
return stream.print("{s} contains invalid byte: '{'}'", .{
switch (tok_slice[0]) {
'\'' => "character literal",
'"', '\\' => "string literal",
'/' => "comment",
else => unreachable,
},
std.zig.fmtEscapes(tok_slice[parse_error.extra.offset..][0..1]),
});
},
.expected_token => {
const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));
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(),
}),
}
},
}
}