Compare commits
No commits in common. "e3fdf5399b0f0d69835ed0eb8fefa9b77953949a" and "11f810a5f31cc94a9a146e8b228aae74a087af85" have entirely different histories.
e3fdf5399b
...
11f810a5f3
3 changed files with 16 additions and 100 deletions
|
@ -1 +1,3 @@
|
||||||
fn main() {}
|
fn main(a int) {
|
||||||
|
// println("hello world!");
|
||||||
|
}
|
||||||
|
|
10
src/ast.zig
10
src/ast.zig
|
@ -5,12 +5,9 @@ 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 {
|
||||||
|
@ -26,16 +23,9 @@ 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 {
|
||||||
|
|
102
src/parser.zig
102
src/parser.zig
|
@ -18,18 +18,16 @@ 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: ...) void {
|
fn doError(self: *Parser, comptime fmt: []const u8, args: ...) Result!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 {
|
||||||
|
@ -132,10 +130,9 @@ pub const Parser = struct {
|
||||||
while (true) {
|
while (true) {
|
||||||
var tok = self.peek();
|
var tok = self.peek();
|
||||||
|
|
||||||
switch (tok.ttype) {
|
if (tok.ttype == .RightParen) break;
|
||||||
.RightParen => break,
|
if (tok.ttype != .Identifier) {
|
||||||
.Identifier => {},
|
try self.doError("expected identifier, got {}", tok.ttype);
|
||||||
else => try self.doError("expected identifier, got {}", tok.ttype),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var typetok = try self.nextToken();
|
var typetok = try self.nextToken();
|
||||||
|
@ -148,24 +145,15 @@ pub const Parser = struct {
|
||||||
|
|
||||||
std.debug.warn("param! {}\n", param);
|
std.debug.warn("param! {}\n", param);
|
||||||
try param_list.append(param);
|
try param_list.append(param);
|
||||||
tok = try self.nextToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function body
|
// function body
|
||||||
_ = 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?
|
||||||
// TODO statements
|
//var node = self.processToken(tok);
|
||||||
//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);
|
||||||
|
@ -173,38 +161,9 @@ pub const Parser = struct {
|
||||||
return try self.mkFnDecl(name, param_list);
|
return try self.mkFnDecl(name, param_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn functionCall(self: *Parser) !*ast.Node {
|
fn processToken(self: *Parser, token: Token) !*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;
|
||||||
|
@ -214,53 +173,18 @@ 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.topDecl();
|
var node = try self.processToken(token);
|
||||||
if (node == null) continue;
|
std.debug.warn("{}\n", node.*);
|
||||||
try root.Root.append(node.?);
|
try root.Root.append(node);
|
||||||
}
|
|
||||||
|
|
||||||
if (self.hadError) {
|
|
||||||
return error.ParseError;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue