add 'error contexts' to parser error reports

This commit is contained in:
Luna 2019-09-20 13:16:55 -03:00
parent 7ddd37b725
commit 3ad0859bc9
3 changed files with 39 additions and 8 deletions

View File

@ -1,4 +1,4 @@
import std; // import std;
fn add(a: i32, b: i32) i32 { fn add(a: i32, b: i32) i32 {
return a + b; return a + b;

View File

@ -1,15 +1,24 @@
const std = @import("std"); const std = @import("std");
pub fn report(line: usize, where: []const u8, message: []const u8) void { 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); std.debug.warn("[line {}] Error{}: {}", line, where, message);
} }
}
pub fn reportN(line: usize, message: []const u8) void { pub fn reportN(line: usize, message: []const u8) void {
report(line, "", message); report(line, "", message);
} }
pub fn reportFmt(line: usize, comptime fmt: []const u8, args: ...) void { 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("[line {}] Error", line);
}
std.debug.warn(fmt, args); std.debug.warn(fmt, args);
std.debug.warn("\n"); std.debug.warn("\n");
} }

View File

@ -31,6 +31,7 @@ pub const Parser = struct {
tokens: TokenList, tokens: TokenList,
hadError: bool = false, hadError: bool = false,
err_ctx: ?[]const u8 = null,
pub fn init(allocator: *Allocator, scanner: *Scanner) Parser { pub fn init(allocator: *Allocator, scanner: *Scanner) Parser {
return Parser{ return Parser{
@ -44,10 +45,26 @@ pub const Parser = struct {
self.tokens.deinit(); 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 { fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError {
self.hadError = true; 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(fmt, args);
std.debug.warn("\n"); std.debug.warn("\n");
@ -80,10 +97,11 @@ pub const Parser = struct {
} }
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError {
std.debug.warn("ctx: '{}'\n", self.err_ctx);
if (token.typ == .EOF) { if (token.typ == .EOF) {
ereport.report(token.line, " at end", msg); ereport.report(token.line, " at end", self.err_ctx, msg);
} else { } else {
ereport.reportFmt(token.line, " at '{}': {}", token.lexeme, msg); ereport.reportFmt(token.line, self.err_ctx, " at '{}': {}", token.lexeme, msg);
} }
return ParseError.CompileError; return ParseError.CompileError;
@ -439,6 +457,8 @@ pub const Parser = struct {
const name = try self.consumeSingle(.Identifier); const name = try self.consumeSingle(.Identifier);
self.setErrContext("function {}", name.lexeme);
_ = try self.consumeSingle(.LeftParen); _ = try self.consumeSingle(.LeftParen);
while (self.peek().typ != .RightParen) { while (self.peek().typ != .RightParen) {
@ -623,6 +643,8 @@ pub const Parser = struct {
} }
fn parseTopDecl(self: *@This()) !*Node { fn parseTopDecl(self: *@This()) !*Node {
self.setErrContext(null);
return switch (self.peek().typ) { return switch (self.peek().typ) {
.Fn => try self.parseFnDecl(), .Fn => try self.parseFnDecl(),
.Const => try self.parseConstDecl(), .Const => try self.parseConstDecl(),