refactor: new direction for error reporting

This commit is contained in:
Brett Broadhurst 2026-03-18 17:52:07 -06:00
parent 72b686d750
commit c940374f27
Failed to generate hash of commit
11 changed files with 758 additions and 582 deletions

View file

@ -1,14 +1,17 @@
//! Abstract Syntax Tree for Ink source code.
const std = @import("std");
const ink = @import("root.zig");
const Tokenizer = @import("tokenizer.zig").Tokenizer;
const Render = @import("Ast/Render.zig");
const Parse = @import("Parse.zig");
const Ast = @This();
const assert = std.debug.assert;
filename: []const u8,
source: []const u8,
// TODO: Make this non-nullable. Empty files are valid.
root: ?*Node = null,
errors: []Error,
errors: []const Error,
pub const Node = struct {
tag: Tag,
@ -215,24 +218,22 @@ pub const Error = struct {
};
pub const Tag = enum {
panic,
unexpected_token,
unknown_identifier,
redefined_identifier,
assignment_to_const,
expected_token,
expected_newline,
expected_expression,
expected_double_quote,
expected_identifier,
expected_expression,
invalid_expression,
invalid_lvalue,
too_many_arguments,
too_many_parameters,
invalid_else_stmt,
unexpected_else_stmt,
invalid_switch_case,
unexpected_token,
};
pub fn tokenSlice(err: Error, tree: Ast) []const u8 {
assert(err.loc.start <= err.loc.end);
return tree.source[err.loc.start..err.loc.end];
}
};
pub fn parse(
@ -280,16 +281,35 @@ pub fn render(
return Render.renderTree(gpa, writer, &ast, options);
}
pub fn renderErrors(
ast: Ast,
gpa: std.mem.Allocator,
writer: *std.Io.Writer,
options: Render.Options,
) !void {
return Render.renderErrors(gpa, writer, &ast, options);
pub fn renderError(tree: Ast, w: *std.Io.Writer, parse_error: Error) !void {
switch (parse_error.tag) {
.expected_token => try w.writeAll("expected token"),
.expected_newline => try w.writeAll("expected newline"),
.expected_double_quote => try w.writeAll("unterminated string, expected closing quote"),
.expected_identifier => try w.writeAll("expected identifier"),
.expected_expression => try w.writeAll("expected expression"),
.unexpected_token => try w.writeAll("unexpected token"),
.invalid_expression => try w.writeAll("invalid expression"),
.invalid_lvalue => try w.writeAll("invalid lvalue for assignment"),
.too_many_arguments => try w.print("too many arguments to '{s}'", .{
errorSlice(tree, parse_error),
}),
.too_many_parameters => try w.print("too many parameters defined for '{s}'", .{
errorSlice(tree, parse_error),
}),
}
}
pub fn deinit(ast: *Ast, gpa: std.mem.Allocator) void {
gpa.free(ast.errors);
ast.* = undefined;
pub fn errorSlice(tree: Ast, parse_error: Ast.Error) []const u8 {
return tree.source[parse_error.loc.start..parse_error.loc.end];
}
pub fn nodeSlice(tree: Ast, node: *const Ast.Node) []const u8 {
assert(node.loc.start <= node.loc.end);
return tree.source[node.loc.start..node.loc.end];
}
pub fn deinit(tree: *Ast, gpa: std.mem.Allocator) void {
gpa.free(tree.errors);
tree.* = undefined;
}