redo parser for the 300th time

This commit is contained in:
Luna 2019-08-23 11:57:49 -03:00
parent cf45f3f3ee
commit e3fdf5399b
3 changed files with 94 additions and 13 deletions

View File

@ -1,3 +1 @@
fn main(a int) {
// println("hello world!");
}
fn main() {}

View File

@ -5,9 +5,12 @@ const Token = tokens.Token;
pub const NodeList = std.ArrayList(*Node);
pub const ParamList = std.ArrayList(*ParamDecl);
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
pub const NodeType = enum {
Root,
FnDecl,
FnCall,
String,
};
pub const ParamDecl = struct {
@ -23,9 +26,16 @@ pub const FnDecl = struct {
body: NodeList,
};
pub const FnCall = struct {
func_name: Token,
arguments: NodeList,
};
pub const Node = union(NodeType) {
Root: NodeList,
FnDecl: FnDecl,
FnCall: FnCall,
String: Token,
};
pub fn mkRoot(allocator: *std.mem.Allocator) !*Node {

View File

@ -18,16 +18,18 @@ pub const Parser = struct {
tokens: []Token = undefined,
hadError: bool = false,
pub fn init(allocator: *Allocator, scanner: *Scanner) Parser {
return Parser{ .allocator = allocator, .scanner = scanner };
}
fn doError(self: *Parser, comptime fmt: []const u8, args: ...) Result!void {
fn doError(self: *Parser, comptime fmt: []const u8, args: ...) void {
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 Result.CompileError;
}
fn peek(self: *Parser) Token {
@ -152,11 +154,18 @@ pub const Parser = struct {
// function body
_ = try self.nextToken();
_ = try self.consumeSingle(.LeftBrace);
var body = ast.NodeList.init(self.allocator);
while (true) {
var tok = self.peek();
if (tok.ttype == .RightBrace) break;
// TODO statements?
//var node = self.processToken(tok);
// TODO statements
//var node = try self.processToken(tok);
//std.debug.warn("stmt:{}\n", node);
//try body.append(node);
tok = try self.nextToken();
}
_ = try self.consumeSingle(.RightBrace);
@ -164,9 +173,38 @@ pub const Parser = struct {
return try self.mkFnDecl(name, param_list);
}
fn processToken(self: *Parser, token: Token) !*ast.Node {
fn functionCall(self: *Parser) !*ast.Node {
var identifier = try self.consumeSingle(.Identifier);
_ = try self.consumeSingle(.LeftParen);
// arguments
var args = ast.NodeList.init(self.allocator);
while (true) {
var tok = self.peek();
switch (tok.ttype) {
.RightParen => break,
.String => blk: {
var node = try self.allocator.create(Node);
node.* = Node{ .String = tok };
try args.append(node);
},
else => {},
}
tok = try self.nextToken();
}
_ = try self.consumeSingle(.RightParen);
return Node{ .FnCall = ast.FnCall{ .func_name = identifier, .arguments = args } };
}
fn processToken(self: *Parser, token: Token) anyerror!*ast.Node {
var node = switch (token.ttype) {
.Fn => try self.functionDecl(),
.Identifier => try self.functionCall(),
else => blk: {
try self.doError("TODO handle {}\n", token.ttype);
return Result.CompileError;
@ -176,18 +214,53 @@ pub const Parser = struct {
return node;
}
fn block(self: *Parser) anyerror!*ast.Node {
// TODO if(self.accept(.Const))
// while receiving functions, process more
while (self.accept(.Fn)) {
try self.consumeSingle(.LeftParen);
try self.consumeSingle(.RightParen);
var block = try self.block();
}
self.statement();
}
fn topDecl(self: *@This()) !?*Node {
return switch (self.peek().ttype) {
.Fn => blk: {
_ = try self.consumeSingle(.Fn);
var name = try self.consumeSingle(.Identifier);
std.debug.warn("!fn name: {}\n", name);
break :blk try self.mkFnDecl(
name,
ast.ParamList.init(self.allocator),
);
},
else => |ttype| blk: {
self.doError("expected fn, got {}\n", ttype);
break :blk null;
},
};
}
pub fn parse(self: *Parser) !*ast.Node {
self.tokens = try self.allocator.alloc(Token, 0);
var root = try ast.mkRoot(self.allocator);
while (true) {
var token = try self.nextToken();
if (token.ttype == .EOF) break;
var node = try self.processToken(token);
std.debug.warn("node: {}\n", node.*);
try root.Root.append(node);
var node = try self.topDecl();
if (node == null) continue;
try root.Root.append(node.?);
}
if (self.hadError) {
return error.ParseError;
}
return root;