add basic const parsing (needs expr)
- parser: fix main root loop's priming
This commit is contained in:
parent
89e386d2d4
commit
899c015cbe
3 changed files with 102 additions and 86 deletions
|
@ -1 +1,5 @@
|
||||||
|
const (
|
||||||
|
AWOO = 2
|
||||||
|
)
|
||||||
|
|
||||||
fn main(a int) {}
|
fn main(a int) {}
|
||||||
|
|
24
src/ast.zig
24
src/ast.zig
|
@ -4,12 +4,14 @@ 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);
|
||||||
|
pub const ConstList = std.ArrayList(SingleConst);
|
||||||
|
|
||||||
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
|
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
|
||||||
pub const NodeType = enum {
|
pub const NodeType = enum {
|
||||||
Root,
|
Root,
|
||||||
FnDecl,
|
FnDecl,
|
||||||
FnCall,
|
FnCall,
|
||||||
|
ConstDecl,
|
||||||
String,
|
String,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,9 +33,17 @@ pub const FnCall = struct {
|
||||||
arguments: NodeList,
|
arguments: NodeList,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const SingleConst = struct {
|
||||||
|
name: Token,
|
||||||
|
|
||||||
|
// TODO expr
|
||||||
|
value: Token,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Node = union(NodeType) {
|
pub const Node = union(NodeType) {
|
||||||
Root: NodeList,
|
Root: NodeList,
|
||||||
FnDecl: FnDecl,
|
FnDecl: FnDecl,
|
||||||
|
ConstDecl: ConstList,
|
||||||
FnCall: FnCall,
|
FnCall: FnCall,
|
||||||
String: Token,
|
String: Token,
|
||||||
};
|
};
|
||||||
|
@ -67,11 +77,25 @@ pub fn printNode(node: *Node, ident: usize) void {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.ConstDecl => |consts| {
|
||||||
|
print(ident, "ConstDecl ({} consts)\n", consts.len);
|
||||||
|
for (consts.toSlice()) |const_decl| {
|
||||||
|
print(
|
||||||
|
ident + 1,
|
||||||
|
"'{}' = '{}'\n",
|
||||||
|
const_decl.name.lexeme,
|
||||||
|
const_decl.value.lexeme,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
.Root => {
|
.Root => {
|
||||||
for (node.Root.toSlice()) |child| {
|
for (node.Root.toSlice()) |child| {
|
||||||
printNode(child, ident + 1);
|
printNode(child, ident + 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
print(ident, "unknown node: {}\n", node);
|
print(ident, "unknown node: {}\n", node);
|
||||||
},
|
},
|
||||||
|
|
122
src/parser.zig
122
src/parser.zig
|
@ -76,6 +76,7 @@ pub const Parser = struct {
|
||||||
);
|
);
|
||||||
|
|
||||||
self.tokens[self.tokens.len - 1] = token;
|
self.tokens[self.tokens.len - 1] = token;
|
||||||
|
std.debug.warn("skip to {}\n", token);
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +88,6 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consumeSingle(self: *Parser, ttype: TokenType) !Token {
|
fn consumeSingle(self: *Parser, ttype: TokenType) !Token {
|
||||||
std.debug.warn("consume {}, has {}\n", ttype, self.peek().ttype);
|
|
||||||
|
|
||||||
if (self.check(ttype)) {
|
if (self.check(ttype)) {
|
||||||
var cur = self.peek();
|
var cur = self.peek();
|
||||||
_ = try self.nextToken();
|
_ = try self.nextToken();
|
||||||
|
@ -122,34 +121,13 @@ pub const Parser = struct {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mkConstDecl(self: *Parser, consts: ast.ConstList) !*ast.Node {
|
||||||
|
var node = try self.allocator.create(Node);
|
||||||
|
node.* = Node{ .ConstDecl = consts };
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
fn functionDecl(self: *Parser) !*ast.Node {
|
fn functionDecl(self: *Parser) !*ast.Node {
|
||||||
_ = try self.consumeSingle(.Fn);
|
|
||||||
var name = try self.consumeSingle(.Identifier);
|
|
||||||
_ = try self.consumeSingle(.LeftParen);
|
|
||||||
|
|
||||||
var param_list = ast.ParamList.init(self.allocator);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
var tok = self.peek();
|
|
||||||
|
|
||||||
switch (tok.ttype) {
|
|
||||||
.RightParen => break,
|
|
||||||
.Identifier => {},
|
|
||||||
else => try self.doError("expected identifier, got {}", tok.ttype),
|
|
||||||
}
|
|
||||||
|
|
||||||
var typetok = try self.nextToken();
|
|
||||||
if (typetok.ttype != .Identifier) {
|
|
||||||
try self.doError("expected identifier for type, got {}", typetok.ttype);
|
|
||||||
}
|
|
||||||
|
|
||||||
var param = try self.allocator.create(ast.ParamDecl);
|
|
||||||
param.* = ast.ParamDecl{ .param_name = tok, .param_type = typetok };
|
|
||||||
|
|
||||||
std.debug.warn("param! {}\n", param);
|
|
||||||
try param_list.append(param);
|
|
||||||
tok = try self.nextToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
// function body
|
// function body
|
||||||
_ = try self.nextToken();
|
_ = try self.nextToken();
|
||||||
|
@ -173,34 +151,6 @@ pub const Parser = struct {
|
||||||
return try self.mkFnDecl(name, param_list);
|
return try self.mkFnDecl(name, param_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
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(),
|
||||||
|
@ -216,8 +166,6 @@ pub const Parser = struct {
|
||||||
|
|
||||||
fn block(self: *Parser) anyerror!*ast.Node {
|
fn block(self: *Parser) anyerror!*ast.Node {
|
||||||
|
|
||||||
// TODO if(self.accept(.Const))
|
|
||||||
|
|
||||||
// while receiving functions, process more
|
// while receiving functions, process more
|
||||||
while (self.accept(.Fn)) {
|
while (self.accept(.Fn)) {
|
||||||
try self.consumeSingle(.LeftParen);
|
try self.consumeSingle(.LeftParen);
|
||||||
|
@ -228,9 +176,7 @@ pub const Parser = struct {
|
||||||
self.statement();
|
self.statement();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn topDecl(self: *@This()) !?*Node {
|
fn fnDecl(self: *@This()) !?*Node {
|
||||||
return switch (self.peek().ttype) {
|
|
||||||
.Fn => blk: {
|
|
||||||
var param_list = ast.ParamList.init(self.allocator);
|
var param_list = ast.ParamList.init(self.allocator);
|
||||||
errdefer param_list.deinit();
|
errdefer param_list.deinit();
|
||||||
|
|
||||||
|
@ -243,7 +189,10 @@ pub const Parser = struct {
|
||||||
const param_name = try self.consumeSingle(.Identifier);
|
const param_name = try self.consumeSingle(.Identifier);
|
||||||
const param_type = try self.consumeSingle(.Identifier);
|
const param_type = try self.consumeSingle(.Identifier);
|
||||||
|
|
||||||
try param_list.append(ast.ParamDecl{ .name = param_name, .typ = param_type });
|
try param_list.append(ast.ParamDecl{
|
||||||
|
.name = param_name,
|
||||||
|
.typ = param_type,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = try self.consumeSingle(.RightParen);
|
_ = try self.consumeSingle(.RightParen);
|
||||||
|
@ -253,10 +202,41 @@ pub const Parser = struct {
|
||||||
_ = try self.consumeSingle(.RightBrace);
|
_ = try self.consumeSingle(.RightBrace);
|
||||||
|
|
||||||
std.debug.warn("!fn name: {}\n", name);
|
std.debug.warn("!fn name: {}\n", name);
|
||||||
break :blk try self.mkFnDecl(name, param_list);
|
return try self.mkFnDecl(name, param_list);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
fn constDecl(self: *@This()) !?*Node {
|
||||||
|
var consts = ast.ConstList.init(self.allocator);
|
||||||
|
errdefer consts.deinit();
|
||||||
|
|
||||||
|
_ = try self.consumeSingle(.Const);
|
||||||
|
|
||||||
|
_ = try self.consumeSingle(.LeftParen);
|
||||||
|
|
||||||
|
while (self.peek().ttype != .RightParen) {
|
||||||
|
const const_name = try self.consumeSingle(.Identifier);
|
||||||
|
_ = try self.consumeSingle(.Equal);
|
||||||
|
|
||||||
|
// TODO expr
|
||||||
|
const const_value = self.peek();
|
||||||
|
_ = try self.nextToken();
|
||||||
|
//const const_value = try self.consumeSingle(.Identifier);
|
||||||
|
|
||||||
|
try consts.append(ast.SingleConst{ .name = const_name, .value = const_value });
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = try self.consumeSingle(.RightParen);
|
||||||
|
|
||||||
|
return self.mkConstDecl(consts);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn topDecl(self: *@This()) !?*Node {
|
||||||
|
return switch (self.peek().ttype) {
|
||||||
|
.Fn => try self.fnDecl(),
|
||||||
|
.Const => try self.constDecl(),
|
||||||
|
|
||||||
else => |ttype| blk: {
|
else => |ttype| blk: {
|
||||||
self.doError("expected fn, got {}\n", ttype);
|
self.doError("(basic) expected fn/const, got {}\n", ttype);
|
||||||
break :blk null;
|
break :blk null;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -266,8 +246,16 @@ pub const Parser = struct {
|
||||||
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);
|
||||||
|
|
||||||
|
var token_opt: ?Token = null;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var token = try self.nextToken();
|
if (token_opt == null) {
|
||||||
|
token_opt = try self.nextToken();
|
||||||
|
} else {
|
||||||
|
token_opt = self.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = token_opt.?;
|
||||||
if (token.ttype == .EOF) break;
|
if (token.ttype == .EOF) break;
|
||||||
|
|
||||||
var node = try self.topDecl();
|
var node = try self.topDecl();
|
||||||
|
|
Loading…
Reference in a new issue