add synchronization to the parser
This commit is contained in:
parent
084c5cc6ee
commit
7ddd37b725
2 changed files with 41 additions and 24 deletions
|
@ -38,10 +38,12 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result {
|
|||
|
||||
var parser = parsers.Parser.init(allocator, &scan);
|
||||
var root = try parser.parse();
|
||||
var it = root.Root.iterator();
|
||||
if (root == null) {
|
||||
return Result.ParseError;
|
||||
}
|
||||
|
||||
std.debug.warn("parse tree\n");
|
||||
//printer.printNode(root, 0);
|
||||
printer.printNode(root.?, 0);
|
||||
|
||||
return Result.Ok;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ const scanners = @import("scanners.zig");
|
|||
const main = @import("main.zig");
|
||||
const ast = @import("ast.zig");
|
||||
const tokens = @import("tokens.zig");
|
||||
const err = @import("errors.zig");
|
||||
const ereport = @import("errors.zig");
|
||||
const printer = @import("ast_printer.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
@ -44,12 +44,31 @@ pub const Parser = struct {
|
|||
self.tokens.deinit();
|
||||
}
|
||||
|
||||
fn doError(self: *Parser, comptime fmt: []const u8, args: ...) void {
|
||||
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(fmt, args);
|
||||
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 {
|
||||
|
@ -60,11 +79,11 @@ pub const Parser = struct {
|
|||
return self.tokens.at(self.tokens.len - 2);
|
||||
}
|
||||
|
||||
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError!void {
|
||||
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError {
|
||||
if (token.typ == .EOF) {
|
||||
err.report(token.line, " at end", msg);
|
||||
ereport.report(token.line, " at end", msg);
|
||||
} else {
|
||||
err.reportFmt(token.line, " at '{}': {}", token.lexeme, msg);
|
||||
ereport.reportFmt(token.line, " at '{}': {}", token.lexeme, msg);
|
||||
}
|
||||
|
||||
return ParseError.CompileError;
|
||||
|
@ -104,8 +123,7 @@ pub const Parser = struct {
|
|||
return tok;
|
||||
}
|
||||
|
||||
try self.tokenError(self.peek(), msg);
|
||||
return ParseError.CompileError;
|
||||
return self.tokenError(self.peek(), msg);
|
||||
}
|
||||
|
||||
/// Consume the current token. Gives default error messages
|
||||
|
@ -125,8 +143,7 @@ pub const Parser = struct {
|
|||
self.peek().typ,
|
||||
);
|
||||
|
||||
try self.tokenError(self.peek(), buf);
|
||||
return ParseError.CompileError;
|
||||
return self.tokenError(self.peek(), buf);
|
||||
}
|
||||
|
||||
/// check() against multiple tokens
|
||||
|
@ -369,7 +386,7 @@ pub const Parser = struct {
|
|||
return expr;
|
||||
}
|
||||
|
||||
pub fn parse(self: *Parser) !*ast.Node {
|
||||
pub fn parse(self: *Parser) !?*ast.Node {
|
||||
var root = try Node.mkRoot(self.allocator);
|
||||
|
||||
var token_opt: ?Token = null;
|
||||
|
@ -384,7 +401,10 @@ pub const Parser = struct {
|
|||
var token = token_opt.?;
|
||||
if (token.typ == .EOF) break;
|
||||
|
||||
var node = try self.parseTopDecl();
|
||||
var node = self.parseTopDecl() catch |err| {
|
||||
if (err == ParseError.CompileError) return null;
|
||||
return err;
|
||||
};
|
||||
try root.Root.append(node.*);
|
||||
}
|
||||
|
||||
|
@ -610,8 +630,7 @@ pub const Parser = struct {
|
|||
.Enum => try self.parseEnumDecl(),
|
||||
|
||||
else => |typ| blk: {
|
||||
self.doError("expected Fn, Const, Struct, got {}\n", typ);
|
||||
return ParseError.CompileError;
|
||||
return self.doError("expected Fn, Const, Struct, got {}\n", typ);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -840,8 +859,7 @@ pub const Parser = struct {
|
|||
.Get => |get| {
|
||||
switch (op.typ) {
|
||||
.ColonEqual => {
|
||||
self.doError("can not initialize struct field");
|
||||
return ParseError.CompileError;
|
||||
return self.doError("can not initialize struct field");
|
||||
},
|
||||
|
||||
.Equal => return try self.mkSet(get.struc, get.name, value),
|
||||
|
@ -860,8 +878,7 @@ pub const Parser = struct {
|
|||
},
|
||||
|
||||
else => |expr_typ| {
|
||||
self.doError("Invalid assignment target {}", expr_typ);
|
||||
return ParseError.CompileError;
|
||||
return self.doError("Invalid assignment target {}", expr_typ);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -997,7 +1014,7 @@ pub const Parser = struct {
|
|||
expr = try self.mkGet(expr, name);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
return self.tokenError(self.peek(), "Expect expression.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,8 +1048,7 @@ pub const Parser = struct {
|
|||
// <expr>{a: 10 b: 10}
|
||||
// for this to work properly, <expr> must be Variable, since its a type.
|
||||
if (ast.ExprType(expr.*) != .Variable) {
|
||||
self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*));
|
||||
return ParseError.CompileError;
|
||||
return self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*));
|
||||
}
|
||||
|
||||
var inits = ast.StructInitList.init(self.allocator);
|
||||
|
@ -1096,8 +1112,7 @@ pub const Parser = struct {
|
|||
},
|
||||
|
||||
else => blk: {
|
||||
self.doError("expected literal, got {}", curtype);
|
||||
return ParseError.CompileError;
|
||||
return self.doError("expected literal, got {}", curtype);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue