Compare commits

..

No commits in common. "3ad0859bc90e9d3473f733a80305525876ece5d2" and "084c5cc6ee36e3002bdffe7a0d7cea0ba1b4ff26" have entirely different histories.

4 changed files with 30 additions and 78 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,24 +1,15 @@
const std = @import("std"); const std = @import("std");
pub fn report(line: usize, where: []const u8, ctx_opt: ?[]const u8, message: []const u8) void { pub fn report(line: usize, where: []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, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: ...) void { pub fn reportFmt(line: usize, 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

@ -38,12 +38,10 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result {
var parser = parsers.Parser.init(allocator, &scan); var parser = parsers.Parser.init(allocator, &scan);
var root = try parser.parse(); var root = try parser.parse();
if (root == null) { var it = root.Root.iterator();
return Result.ParseError;
}
std.debug.warn("parse tree\n"); std.debug.warn("parse tree\n");
printer.printNode(root.?, 0); //printer.printNode(root, 0);
return Result.Ok; return Result.Ok;
} }

View file

@ -3,7 +3,7 @@ const scanners = @import("scanners.zig");
const main = @import("main.zig"); const main = @import("main.zig");
const ast = @import("ast.zig"); const ast = @import("ast.zig");
const tokens = @import("tokens.zig"); const tokens = @import("tokens.zig");
const ereport = @import("errors.zig"); const err = @import("errors.zig");
const printer = @import("ast_printer.zig"); const printer = @import("ast_printer.zig");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
@ -31,7 +31,6 @@ 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{
@ -45,47 +44,12 @@ pub const Parser = struct {
self.tokens.deinit(); self.tokens.deinit();
} }
fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: ...) void { fn doError(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; self.hadError = true;
std.debug.warn("parser error at line {}", self.scanner.line); std.debug.warn("parser error at line {}\n\t", 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");
return ParseError.CompileError;
}
fn synchronize(self: *Parser) !void {
// TODO is it nextToken()?
_ = try self.nextToken();
while (!self.isAtEnd()) {
if (self.previous().typ == .Semicolon) return;
// TODO add more "stmt"-"starting" tokens here
switch (self.peek().typ) {
.Fn => return,
else => {},
}
_ = try self.nextToken();
}
} }
fn peek(self: *Parser) Token { fn peek(self: *Parser) Token {
@ -96,12 +60,11 @@ pub const Parser = struct {
return self.tokens.at(self.tokens.len - 2); return self.tokens.at(self.tokens.len - 2);
} }
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError!void {
std.debug.warn("ctx: '{}'\n", self.err_ctx);
if (token.typ == .EOF) { if (token.typ == .EOF) {
ereport.report(token.line, " at end", self.err_ctx, msg); err.report(token.line, " at end", msg);
} else { } else {
ereport.reportFmt(token.line, self.err_ctx, " at '{}': {}", token.lexeme, msg); err.reportFmt(token.line, " at '{}': {}", token.lexeme, msg);
} }
return ParseError.CompileError; return ParseError.CompileError;
@ -141,7 +104,8 @@ pub const Parser = struct {
return tok; return tok;
} }
return self.tokenError(self.peek(), msg); try self.tokenError(self.peek(), msg);
return ParseError.CompileError;
} }
/// Consume the current token. Gives default error messages /// Consume the current token. Gives default error messages
@ -161,7 +125,8 @@ pub const Parser = struct {
self.peek().typ, self.peek().typ,
); );
return self.tokenError(self.peek(), buf); try self.tokenError(self.peek(), buf);
return ParseError.CompileError;
} }
/// check() against multiple tokens /// check() against multiple tokens
@ -404,7 +369,7 @@ pub const Parser = struct {
return expr; return expr;
} }
pub fn parse(self: *Parser) !?*ast.Node { pub fn parse(self: *Parser) !*ast.Node {
var root = try Node.mkRoot(self.allocator); var root = try Node.mkRoot(self.allocator);
var token_opt: ?Token = null; var token_opt: ?Token = null;
@ -419,10 +384,7 @@ pub const Parser = struct {
var token = token_opt.?; var token = token_opt.?;
if (token.typ == .EOF) break; if (token.typ == .EOF) break;
var node = self.parseTopDecl() catch |err| { var node = try self.parseTopDecl();
if (err == ParseError.CompileError) return null;
return err;
};
try root.Root.append(node.*); try root.Root.append(node.*);
} }
@ -457,8 +419,6 @@ 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) {
@ -643,8 +603,6 @@ 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(),
@ -652,7 +610,8 @@ pub const Parser = struct {
.Enum => try self.parseEnumDecl(), .Enum => try self.parseEnumDecl(),
else => |typ| blk: { else => |typ| blk: {
return self.doError("expected Fn, Const, Struct, got {}\n", typ); self.doError("expected Fn, Const, Struct, got {}\n", typ);
return ParseError.CompileError;
}, },
}; };
} }
@ -881,7 +840,8 @@ pub const Parser = struct {
.Get => |get| { .Get => |get| {
switch (op.typ) { switch (op.typ) {
.ColonEqual => { .ColonEqual => {
return self.doError("can not initialize struct field"); self.doError("can not initialize struct field");
return ParseError.CompileError;
}, },
.Equal => return try self.mkSet(get.struc, get.name, value), .Equal => return try self.mkSet(get.struc, get.name, value),
@ -900,7 +860,8 @@ pub const Parser = struct {
}, },
else => |expr_typ| { else => |expr_typ| {
return self.doError("Invalid assignment target {}", expr_typ); self.doError("Invalid assignment target {}", expr_typ);
return ParseError.CompileError;
}, },
} }
} }
@ -1036,7 +997,7 @@ pub const Parser = struct {
expr = try self.mkGet(expr, name); expr = try self.mkGet(expr, name);
} }
} else { } else {
return self.tokenError(self.peek(), "Expect expression."); break;
} }
} }
@ -1070,7 +1031,8 @@ pub const Parser = struct {
// <expr>{a: 10 b: 10} // <expr>{a: 10 b: 10}
// for this to work properly, <expr> must be Variable, since its a type. // for this to work properly, <expr> must be Variable, since its a type.
if (ast.ExprType(expr.*) != .Variable) { if (ast.ExprType(expr.*) != .Variable) {
return self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*)); self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*));
return ParseError.CompileError;
} }
var inits = ast.StructInitList.init(self.allocator); var inits = ast.StructInitList.init(self.allocator);
@ -1134,7 +1096,8 @@ pub const Parser = struct {
}, },
else => blk: { else => blk: {
return self.doError("expected literal, got {}", curtype); self.doError("expected literal, got {}", curtype);
return ParseError.CompileError;
}, },
}; };