std.zig.parser now handles lib name for extern var and fn

master
Jimmi Holst Christensen 2018-03-31 17:46:29 +02:00
parent cda3509353
commit 4793c3397e
2 changed files with 102 additions and 63 deletions

View File

@ -624,7 +624,7 @@ pub const NodeLineComment = struct {
pub const NodeTestDecl = struct {
base: Node,
test_token: Token,
name_token: Token,
name: &Node,
body_node: &Node,
pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node {
@ -644,4 +644,3 @@ pub const NodeTestDecl = struct {
return self.body_node.lastToken();
}
};

View File

@ -55,6 +55,7 @@ pub const Parser = struct {
const TopLevelDeclCtx = struct {
visib_token: ?Token,
extern_token: ?Token,
lib_name: ?&ast.Node,
};
const DestPtr = union(enum) {
@ -183,8 +184,9 @@ pub const Parser = struct {
if (lbrace.id != Token.Id.LBrace)
return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id));
const name = try self.createStringLiteral(arena, name_token);
const block = try self.createBlock(arena, token);
const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, name_token, block);
const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
try stack.append(State { .Block = block });
continue;
},
@ -202,10 +204,22 @@ pub const Parser = struct {
State.TopLevelExtern => |visib_token| {
const token = self.getNextToken();
if (token.id == Token.Id.Keyword_extern) {
const lib_name_token = self.getNextToken();
const lib_name = blk: {
if (lib_name_token.id == Token.Id.StringLiteral) {
const res = try self.createStringLiteral(arena, lib_name_token);
break :blk &res.base;
} else {
self.putBackToken(lib_name_token);
break :blk null;
}
};
stack.append(State {
.TopLevelDecl = TopLevelDeclCtx {
.visib_token = visib_token,
.extern_token = token,
.lib_name = lib_name,
},
}) catch unreachable;
continue;
@ -215,6 +229,7 @@ pub const Parser = struct {
.TopLevelDecl = TopLevelDeclCtx {
.visib_token = visib_token,
.extern_token = null,
.lib_name = null,
},
}) catch unreachable;
continue;
@ -226,7 +241,7 @@ pub const Parser = struct {
stack.append(State.TopLevel) catch unreachable;
// TODO shouldn't need these casts
const var_decl_node = try self.createAttachVarDecl(arena, &root_node.decls, ctx.visib_token,
token, (?Token)(null), ctx.extern_token);
token, (?Token)(null), ctx.extern_token, ctx.lib_name);
try stack.append(State { .VarDecl = var_decl_node });
continue;
},
@ -234,20 +249,17 @@ pub const Parser = struct {
stack.append(State.TopLevel) catch unreachable;
// TODO shouldn't need these casts
const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, token,
ctx.extern_token, (?Token)(null), ctx.visib_token, (?Token)(null));
ctx.extern_token, ctx.lib_name, (?Token)(null), ctx.visib_token, (?Token)(null));
try stack.append(State { .FnDef = fn_proto });
try stack.append(State { .FnProto = fn_proto });
continue;
},
Token.Id.StringLiteral => {
@panic("TODO extern with string literal");
},
Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
stack.append(State.TopLevel) catch unreachable;
const fn_token = try self.eatToken(Token.Id.Keyword_fn);
// TODO shouldn't need this cast
const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, fn_token,
ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null));
ctx.extern_token, ctx.lib_name, (?Token)(token), (?Token)(null), (?Token)(null));
try stack.append(State { .FnDef = fn_proto });
try stack.append(State { .FnProto = fn_proto });
continue;
@ -437,11 +449,7 @@ pub const Parser = struct {
continue;
},
Token.Id.StringLiteral => {
const node = try arena.create(ast.NodeStringLiteral);
*node = ast.NodeStringLiteral {
.base = self.initNode(ast.Node.Id.StringLiteral),
.token = token,
};
const node = try self.createStringLiteral(arena, token);
try stack.append(State {
.Operand = &node.base
});
@ -722,7 +730,7 @@ pub const Parser = struct {
if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
// TODO shouldn't need these casts
const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
mut_token, (?Token)(comptime_token), (?Token)(null));
mut_token, (?Token)(comptime_token), (?Token)(null), null);
try stack.append(State { .VarDecl = var_decl });
continue;
}
@ -736,7 +744,7 @@ pub const Parser = struct {
if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
// TODO shouldn't need these casts
const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
mut_token, (?Token)(null), (?Token)(null));
mut_token, (?Token)(null), (?Token)(null), null);
try stack.append(State { .VarDecl = var_decl });
continue;
}
@ -852,7 +860,7 @@ pub const Parser = struct {
}
fn createVarDecl(self: &Parser, arena: &mem.Allocator, visib_token: &const ?Token, mut_token: &const Token,
comptime_token: &const ?Token, extern_token: &const ?Token) !&ast.NodeVarDecl
comptime_token: &const ?Token, extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
{
const node = try arena.create(ast.NodeVarDecl);
@ -865,7 +873,7 @@ pub const Parser = struct {
.type_node = null,
.align_node = null,
.init_node = null,
.lib_name = null,
.lib_name = lib_name,
// initialized later
.name_token = undefined,
.eq_token = undefined,
@ -874,7 +882,18 @@ pub const Parser = struct {
return node;
}
fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name_token: &const Token,
fn createStringLiteral(self: &Parser, arena: &mem.Allocator, token: &const Token) !&ast.NodeStringLiteral {
const node = try arena.create(ast.NodeStringLiteral);
assert(token.id == Token.Id.StringLiteral);
*node = ast.NodeStringLiteral {
.base = self.initNode(ast.Node.Id.StringLiteral),
.token = *token,
};
return node;
}
fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name: &ast.Node,
block: &ast.NodeBlock) !&ast.NodeTestDecl
{
const node = try arena.create(ast.NodeTestDecl);
@ -882,14 +901,14 @@ pub const Parser = struct {
*node = ast.NodeTestDecl {
.base = self.initNode(ast.Node.Id.TestDecl),
.test_token = *test_token,
.name_token = *name_token,
.name = name,
.body_node = &block.base,
};
return node;
}
fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,
cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
{
const node = try arena.create(ast.NodeFnProto);
@ -905,7 +924,7 @@ pub const Parser = struct {
.inline_token = *inline_token,
.cc_token = *cc_token,
.body_node = null,
.lib_name = null,
.lib_name = lib_name,
.align_expr = null,
};
return node;
@ -1015,27 +1034,27 @@ pub const Parser = struct {
}
fn createAttachFnProto(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), fn_token: &const Token,
extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,
extern_token: &const ?Token, lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token,
inline_token: &const ?Token) !&ast.NodeFnProto
{
const node = try self.createFnProto(arena, fn_token, extern_token, cc_token, visib_token, inline_token);
const node = try self.createFnProto(arena, fn_token, extern_token, lib_name, cc_token, visib_token, inline_token);
try list.append(&node.base);
return node;
}
fn createAttachVarDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
extern_token: &const ?Token) !&ast.NodeVarDecl
extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
{
const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token);
const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token, lib_name);
try list.append(&node.base);
return node;
}
fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
test_token: &const Token, name_token: &const Token, block: &ast.NodeBlock) !&ast.NodeTestDecl
test_token: &const Token, name: &ast.Node, block: &ast.NodeBlock) !&ast.NodeTestDecl
{
const node = try self.createTestDecl(arena, test_token, name_token, block);
const node = try self.createTestDecl(arena, test_token, name, block);
try list.append(&node.base);
return node;
}
@ -1169,23 +1188,6 @@ pub const Parser = struct {
switch (decl.id) {
ast.Node.Id.FnProto => {
const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl);
if (fn_proto.visib_token) |visib_token| {
switch (visib_token.id) {
Token.Id.Keyword_pub => try stream.print("pub "),
Token.Id.Keyword_export => try stream.print("export "),
else => unreachable,
}
}
if (fn_proto.extern_token) |extern_token| {
try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
}
try stream.print("fn");
if (fn_proto.name_token) |name_token| {
try stream.print(" {}", self.tokenizer.getTokenSlice(name_token));
}
try stream.print("(");
if (fn_proto.body_node == null) {
try stack.append(RenderState { .Text = ";" });
@ -1201,6 +1203,27 @@ pub const Parser = struct {
try stack.append(RenderState { .Text = ", " });
}
}
try stack.append(RenderState { .Text = "(" });
if (fn_proto.name_token) |name_token| {
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(name_token) });
}
try stack.append(RenderState { .Text = "fn " });
if (fn_proto.lib_name) |lib_name| {
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Expression = lib_name });
}
if (fn_proto.extern_token) |extern_token| {
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) });
}
if (fn_proto.visib_token) |visib_token| {
assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) });
}
},
ast.Node.Id.VarDecl => {
const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
@ -1208,29 +1231,16 @@ pub const Parser = struct {
},
ast.Node.Id.TestDecl => {
const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl);
try stream.print("test {} ", self.tokenizer.getTokenSlice(test_decl.name_token));
try stream.print("test ");
try stack.append(RenderState { .Expression = test_decl.body_node });
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Expression = test_decl.name });
},
else => unreachable,
}
},
RenderState.VarDecl => |var_decl| {
if (var_decl.visib_token) |visib_token| {
try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
}
if (var_decl.extern_token) |extern_token| {
try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
if (var_decl.lib_name != null) {
@panic("TODO");
}
}
if (var_decl.comptime_token) |comptime_token| {
try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
}
try stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
try stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
try stack.append(RenderState { .Text = ";" });
if (var_decl.init_node) |init_node| {
try stack.append(RenderState { .Expression = init_node });
@ -1242,8 +1252,30 @@ pub const Parser = struct {
try stack.append(RenderState { .Text = " align(" });
}
if (var_decl.type_node) |type_node| {
try stream.print(": ");
try stack.append(RenderState { .Expression = type_node });
try stack.append(RenderState { .Text = ": " });
}
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.name_token) });
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.mut_token) });
if (var_decl.comptime_token) |comptime_token| {
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(comptime_token) });
}
if (var_decl.extern_token) |extern_token| {
if (var_decl.lib_name != null) {
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Expression = ??var_decl.lib_name });
}
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) });
}
if (var_decl.visib_token) |visib_token| {
try stack.append(RenderState { .Text = " " });
try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) });
}
},
@ -1612,6 +1644,14 @@ test "zig fmt: global declarations" {
\\pub const a: i32 = b;
\\var a: i32 = b;
\\pub var a: i32 = b;
\\extern const a: i32 = b;
\\pub extern const a: i32 = b;
\\extern var a: i32 = b;
\\pub extern var a: i32 = b;
\\extern "a" const a: i32 = b;
\\pub extern "a" const a: i32 = b;
\\extern "a" var a: i32 = b;
\\pub extern "a" var a: i32 = b;
\\
);
}
@ -2232,7 +2272,7 @@ test "zig fmt: coroutines" {
\\ x += 1;
\\ suspend |p| {
\\ }
\\ const p = async simpleAsyncFn() cache unreachable;
\\ const p = async simpleAsyncFn() catch unreachable;
\\ await p;
\\}
\\