add basic const parsing (needs expr)

- parser: fix main root loop's priming
This commit is contained in:
Luna 2019-08-23 16:34:41 -03:00
parent 89e386d2d4
commit 899c015cbe
3 changed files with 102 additions and 86 deletions

View file

@ -1 +1,5 @@
const (
AWOO = 2
)
fn main(a int) {}

View file

@ -4,12 +4,14 @@ const Token = tokens.Token;
pub const NodeList = std.ArrayList(*Node);
pub const ParamList = std.ArrayList(ParamDecl);
pub const ConstList = std.ArrayList(SingleConst);
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
pub const NodeType = enum {
Root,
FnDecl,
FnCall,
ConstDecl,
String,
};
@ -31,9 +33,17 @@ pub const FnCall = struct {
arguments: NodeList,
};
pub const SingleConst = struct {
name: Token,
// TODO expr
value: Token,
};
pub const Node = union(NodeType) {
Root: NodeList,
FnDecl: FnDecl,
ConstDecl: ConstList,
FnCall: FnCall,
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 => {
for (node.Root.toSlice()) |child| {
printNode(child, ident + 1);
}
},
else => {
print(ident, "unknown node: {}\n", node);
},

View file

@ -76,6 +76,7 @@ pub const Parser = struct {
);
self.tokens[self.tokens.len - 1] = token;
std.debug.warn("skip to {}\n", token);
return token;
}
@ -87,8 +88,6 @@ pub const Parser = struct {
}
fn consumeSingle(self: *Parser, ttype: TokenType) !Token {
std.debug.warn("consume {}, has {}\n", ttype, self.peek().ttype);
if (self.check(ttype)) {
var cur = self.peek();
_ = try self.nextToken();
@ -122,34 +121,13 @@ pub const Parser = struct {
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 {
_ = 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
_ = try self.nextToken();
@ -173,34 +151,6 @@ pub const Parser = struct {
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 {
var node = switch (token.ttype) {
.Fn => try self.functionDecl(),
@ -216,8 +166,6 @@ pub const Parser = struct {
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);
@ -228,9 +176,7 @@ pub const Parser = struct {
self.statement();
}
fn topDecl(self: *@This()) !?*Node {
return switch (self.peek().ttype) {
.Fn => blk: {
fn fnDecl(self: *@This()) !?*Node {
var param_list = ast.ParamList.init(self.allocator);
errdefer param_list.deinit();
@ -243,7 +189,10 @@ pub const Parser = struct {
const param_name = 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);
@ -253,10 +202,41 @@ pub const Parser = struct {
_ = try self.consumeSingle(.RightBrace);
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: {
self.doError("expected fn, got {}\n", ttype);
self.doError("(basic) expected fn/const, got {}\n", ttype);
break :blk null;
},
};
@ -266,8 +246,16 @@ pub const Parser = struct {
self.tokens = try self.allocator.alloc(Token, 0);
var root = try ast.mkRoot(self.allocator);
var token_opt: ?Token = null;
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;
var node = try self.topDecl();