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 @@
|
|||
fn main( a int) {}
|
||||
const (
|
||||
AWOO = 2
|
||||
)
|
||||
|
||||
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 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);
|
||||
},
|
||||
|
|
158
src/parser.zig
158
src/parser.zig
|
@ -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,35 +176,67 @@ pub const Parser = struct {
|
|||
self.statement();
|
||||
}
|
||||
|
||||
fn fnDecl(self: *@This()) !?*Node {
|
||||
var param_list = ast.ParamList.init(self.allocator);
|
||||
errdefer param_list.deinit();
|
||||
|
||||
_ = try self.consumeSingle(.Fn);
|
||||
var name = try self.consumeSingle(.Identifier);
|
||||
|
||||
_ = try self.consumeSingle(.LeftParen);
|
||||
|
||||
while (self.peek().ttype != .RightParen) {
|
||||
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 self.consumeSingle(.RightParen);
|
||||
|
||||
_ = try self.consumeSingle(.LeftBrace);
|
||||
// TODO block
|
||||
_ = try self.consumeSingle(.RightBrace);
|
||||
|
||||
std.debug.warn("!fn name: {}\n", name);
|
||||
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 => blk: {
|
||||
var param_list = ast.ParamList.init(self.allocator);
|
||||
errdefer param_list.deinit();
|
||||
.Fn => try self.fnDecl(),
|
||||
.Const => try self.constDecl(),
|
||||
|
||||
_ = try self.consumeSingle(.Fn);
|
||||
var name = try self.consumeSingle(.Identifier);
|
||||
|
||||
_ = try self.consumeSingle(.LeftParen);
|
||||
|
||||
while (self.peek().ttype != .RightParen) {
|
||||
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 self.consumeSingle(.RightParen);
|
||||
|
||||
_ = try self.consumeSingle(.LeftBrace);
|
||||
// TODO block
|
||||
_ = try self.consumeSingle(.RightBrace);
|
||||
|
||||
std.debug.warn("!fn name: {}\n", name);
|
||||
break :blk try self.mkFnDecl(name, param_list);
|
||||
},
|
||||
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();
|
||||
|
|
Loading…
Reference in a new issue