Improve parser error handling
This commit is contained in:
parent
7236c0b43a
commit
cb5d7c7798
|
@ -1,4 +1,5 @@
|
|||
const std = @import("std");
|
||||
const token = @import("token.zig");
|
||||
|
||||
pub var hasError: bool = false;
|
||||
|
||||
|
@ -6,7 +7,20 @@ pub fn err(line: u64, message: []const u8) void {
|
|||
report(line, "", message);
|
||||
}
|
||||
|
||||
pub fn report(line: u64, where: []u8, message: []const u8) void {
|
||||
pub fn errToken(tok: token.Token, message: []const u8) void {
|
||||
if (tok.token_type == token.TokenType.EOF) {
|
||||
report(tok.line, " at end", message);
|
||||
} else {
|
||||
var buffer = [_]u8{0} ** 100;
|
||||
const where = std.fmt.bufPrint(&buffer, " at '{s}'", .{tok.lexeme}) catch {
|
||||
std.debug.print("Format error: buffer empty", .{});
|
||||
std.process.exit(1);
|
||||
};
|
||||
report(tok.line, where, message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report(line: u64, where: []const u8, message: []const u8) void {
|
||||
std.debug.print("[line {}] Error{s}: {s}\n", .{ line, where, message });
|
||||
hasError = true;
|
||||
}
|
||||
|
|
|
@ -67,8 +67,10 @@ fn run(allocator: std.mem.Allocator, bytes: []u8) !void {
|
|||
.allocator = alloc,
|
||||
};
|
||||
|
||||
const expression = try parse.expression();
|
||||
// std.debug.print("AST: {}", .{expression.*});
|
||||
expr.AstPrint(expression.*);
|
||||
const expression = parse.parse();
|
||||
if (err.hasError) {
|
||||
return;
|
||||
}
|
||||
expr.AstPrint(expression);
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ const Token = token_zig.Token;
|
|||
|
||||
const errors_zig = @import("error.zig");
|
||||
const err = errors_zig.err;
|
||||
const errToken = errors_zig.errToken;
|
||||
|
||||
const ParseError = error{
|
||||
UnmatchedParen,
|
||||
UnexpectedToken,
|
||||
};
|
||||
|
||||
pub const Parser = struct {
|
||||
const Self = @This();
|
||||
|
@ -20,11 +26,20 @@ pub const Parser = struct {
|
|||
allocator: std.mem.Allocator,
|
||||
current: u64 = 0,
|
||||
|
||||
pub fn expression(self: *Self) !*Expr {
|
||||
pub fn parse(self: *Self) Expr {
|
||||
var expr = self.expression() catch blk: {
|
||||
break :blk &Expr{ .literal = LiteralExpr{
|
||||
.nil = false,
|
||||
} };
|
||||
};
|
||||
return expr.*;
|
||||
}
|
||||
|
||||
fn expression(self: *Self) !*Expr {
|
||||
return self.equality();
|
||||
}
|
||||
|
||||
pub fn equality(self: *Self) !*Expr {
|
||||
fn equality(self: *Self) !*Expr {
|
||||
var expr = try self.comparison();
|
||||
|
||||
while (true) {
|
||||
|
@ -128,7 +143,7 @@ pub const Parser = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn primary(self: *Self) error{OutOfMemory}!*Expr {
|
||||
fn primary(self: *Self) error{ OutOfMemory, UnmatchedParen, UnexpectedToken }!*Expr {
|
||||
var expr = try self.allocator.create(Expr);
|
||||
const token = self.advance();
|
||||
switch (token.token_type) {
|
||||
|
@ -143,12 +158,13 @@ pub const Parser = struct {
|
|||
};
|
||||
var next_token = self.advance();
|
||||
if (next_token.token_type != TokenType.RIGHT_PAREN) {
|
||||
err(next_token.line, "Unclosed left paren.");
|
||||
errToken(next_token, "Unclosed left paren.");
|
||||
return ParseError.UnmatchedParen;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
err(token.line, "Unexpected primary token type.");
|
||||
expr.* = Expr{ .literal = LiteralExpr{ .nil = false } };
|
||||
errToken(token, "Unexpected token.");
|
||||
return ParseError.UnexpectedToken;
|
||||
},
|
||||
}
|
||||
return expr;
|
||||
|
|
Loading…
Reference in New Issue