redo parser for the 300th time
This commit is contained in:
parent
cf45f3f3ee
commit
e3fdf5399b
3 changed files with 94 additions and 13 deletions
|
@ -1,3 +1 @@
|
|||
fn main(a int) {
|
||||
// println("hello world!");
|
||||
}
|
||||
fn main() {}
|
||||
|
|
10
src/ast.zig
10
src/ast.zig
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue