redo parser for the 300th time
This commit is contained in:
parent
cf45f3f3ee
commit
e3fdf5399b
|
@ -1,3 +1 @@
|
||||||
fn main(a int) {
|
fn main() {}
|
||||||
// println("hello world!");
|
|
||||||
}
|
|
||||||
|
|
10
src/ast.zig
10
src/ast.zig
|
@ -5,9 +5,12 @@ const Token = tokens.Token;
|
||||||
pub const NodeList = std.ArrayList(*Node);
|
pub const NodeList = std.ArrayList(*Node);
|
||||||
pub const ParamList = std.ArrayList(*ParamDecl);
|
pub const ParamList = std.ArrayList(*ParamDecl);
|
||||||
|
|
||||||
|
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
|
||||||
pub const NodeType = enum {
|
pub const NodeType = enum {
|
||||||
Root,
|
Root,
|
||||||
FnDecl,
|
FnDecl,
|
||||||
|
FnCall,
|
||||||
|
String,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ParamDecl = struct {
|
pub const ParamDecl = struct {
|
||||||
|
@ -23,9 +26,16 @@ pub const FnDecl = struct {
|
||||||
body: NodeList,
|
body: NodeList,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const FnCall = struct {
|
||||||
|
func_name: Token,
|
||||||
|
arguments: NodeList,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Node = union(NodeType) {
|
pub const Node = union(NodeType) {
|
||||||
Root: NodeList,
|
Root: NodeList,
|
||||||
FnDecl: FnDecl,
|
FnDecl: FnDecl,
|
||||||
|
FnCall: FnCall,
|
||||||
|
String: Token,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn mkRoot(allocator: *std.mem.Allocator) !*Node {
|
pub fn mkRoot(allocator: *std.mem.Allocator) !*Node {
|
||||||
|
|
|
@ -18,16 +18,18 @@ pub const Parser = struct {
|
||||||
|
|
||||||
tokens: []Token = undefined,
|
tokens: []Token = undefined,
|
||||||
|
|
||||||
|
hadError: bool = false,
|
||||||
|
|
||||||
pub fn init(allocator: *Allocator, scanner: *Scanner) Parser {
|
pub fn init(allocator: *Allocator, scanner: *Scanner) Parser {
|
||||||
return Parser{ .allocator = allocator, .scanner = scanner };
|
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("parser error at line {}\n\t", self.scanner.line);
|
||||||
std.debug.warn(fmt, args);
|
std.debug.warn(fmt, args);
|
||||||
std.debug.warn("\n");
|
std.debug.warn("\n");
|
||||||
|
|
||||||
return Result.CompileError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek(self: *Parser) Token {
|
fn peek(self: *Parser) Token {
|
||||||
|
@ -152,11 +154,18 @@ pub const Parser = struct {
|
||||||
// function body
|
// function body
|
||||||
_ = try self.nextToken();
|
_ = try self.nextToken();
|
||||||
_ = try self.consumeSingle(.LeftBrace);
|
_ = try self.consumeSingle(.LeftBrace);
|
||||||
|
var body = ast.NodeList.init(self.allocator);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var tok = self.peek();
|
var tok = self.peek();
|
||||||
if (tok.ttype == .RightBrace) break;
|
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);
|
_ = try self.consumeSingle(.RightBrace);
|
||||||
|
@ -164,9 +173,38 @@ pub const Parser = struct {
|
||||||
return try self.mkFnDecl(name, param_list);
|
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) {
|
var node = switch (token.ttype) {
|
||||||
.Fn => try self.functionDecl(),
|
.Fn => try self.functionDecl(),
|
||||||
|
.Identifier => try self.functionCall(),
|
||||||
else => blk: {
|
else => blk: {
|
||||||
try self.doError("TODO handle {}\n", token.ttype);
|
try self.doError("TODO handle {}\n", token.ttype);
|
||||||
return Result.CompileError;
|
return Result.CompileError;
|
||||||
|
@ -176,18 +214,53 @@ pub const Parser = struct {
|
||||||
return node;
|
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 {
|
pub fn parse(self: *Parser) !*ast.Node {
|
||||||
self.tokens = try self.allocator.alloc(Token, 0);
|
self.tokens = try self.allocator.alloc(Token, 0);
|
||||||
var root = try ast.mkRoot(self.allocator);
|
var root = try ast.mkRoot(self.allocator);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var token = try self.nextToken();
|
var token = try self.nextToken();
|
||||||
|
|
||||||
if (token.ttype == .EOF) break;
|
if (token.ttype == .EOF) break;
|
||||||
|
|
||||||
var node = try self.processToken(token);
|
var node = try self.topDecl();
|
||||||
std.debug.warn("node: {}\n", node.*);
|
if (node == null) continue;
|
||||||
try root.Root.append(node);
|
try root.Root.append(node.?);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.hadError) {
|
||||||
|
return error.ParseError;
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
|
Loading…
Reference in New Issue