From 3ad0859bc90e9d3473f733a80305525876ece5d2 Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 20 Sep 2019 13:16:55 -0300 Subject: [PATCH] add 'error contexts' to parser error reports --- examples/hello.ry | 2 +- src/errors.zig | 17 +++++++++++++---- src/parsers.zig | 28 +++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/examples/hello.ry b/examples/hello.ry index 1bf8dba..8c6d510 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -1,4 +1,4 @@ -import std; +// import std; fn add(a: i32, b: i32) i32 { return a + b; diff --git a/src/errors.zig b/src/errors.zig index c7e9c2b..9043f2e 100644 --- a/src/errors.zig +++ b/src/errors.zig @@ -1,15 +1,24 @@ const std = @import("std"); -pub fn report(line: usize, where: []const u8, message: []const u8) void { - std.debug.warn("[line {}] Error{}: {}", line, where, message); +pub fn report(line: usize, where: []const u8, ctx_opt: ?[]const u8, message: []const u8) void { + if (ctx_opt) |ctx| { + std.debug.warn("[line {}] Error{} on {}: {}", line, where, ctx, message); + } else { + std.debug.warn("[line {}] Error{}: {}", line, where, message); + } } pub fn reportN(line: usize, message: []const u8) void { report(line, "", message); } -pub fn reportFmt(line: usize, comptime fmt: []const u8, args: ...) void { - std.debug.warn("[line {}] Error", line); +pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: ...) void { + if (ctx_opt) |ctx| { + std.debug.warn("[line {}] Error on {}", line, ctx); + } else { + std.debug.warn("[line {}] Error", line); + } + std.debug.warn(fmt, args); std.debug.warn("\n"); } diff --git a/src/parsers.zig b/src/parsers.zig index de655e7..bb8e873 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -31,6 +31,7 @@ pub const Parser = struct { tokens: TokenList, hadError: bool = false, + err_ctx: ?[]const u8 = null, pub fn init(allocator: *Allocator, scanner: *Scanner) Parser { return Parser{ @@ -44,10 +45,26 @@ pub const Parser = struct { self.tokens.deinit(); } + fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: ...) void { + if (fmt == null) { + self.err_ctx = null; + return; + } + + var buf = self.allocator.alloc(u8, 256) catch unreachable; + self.err_ctx = std.fmt.bufPrint(buf, fmt.?, args) catch unreachable; + } + fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError { self.hadError = true; - std.debug.warn("parser error at line {}\n\t", self.scanner.line); + std.debug.warn("parser error at line {}", self.scanner.line); + if (self.err_ctx) |ctx| { + std.debug.warn(" on {}", ctx); + } + + std.debug.warn("\n\t"); + std.debug.warn(fmt, args); std.debug.warn("\n"); @@ -80,10 +97,11 @@ pub const Parser = struct { } fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { + std.debug.warn("ctx: '{}'\n", self.err_ctx); if (token.typ == .EOF) { - ereport.report(token.line, " at end", msg); + ereport.report(token.line, " at end", self.err_ctx, msg); } else { - ereport.reportFmt(token.line, " at '{}': {}", token.lexeme, msg); + ereport.reportFmt(token.line, self.err_ctx, " at '{}': {}", token.lexeme, msg); } return ParseError.CompileError; @@ -439,6 +457,8 @@ pub const Parser = struct { const name = try self.consumeSingle(.Identifier); + self.setErrContext("function {}", name.lexeme); + _ = try self.consumeSingle(.LeftParen); while (self.peek().typ != .RightParen) { @@ -623,6 +643,8 @@ pub const Parser = struct { } fn parseTopDecl(self: *@This()) !*Node { + self.setErrContext(null); + return switch (self.peek().typ) { .Fn => try self.parseFnDecl(), .Const => try self.parseConstDecl(),