Commit 3b80e66507

Jimmi Holst Christensen <jhc@liab.dk>
2018-04-10 14:52:47
std.zig.parser now parses toplevel use
1 parent db0812d
Changed files (2)
std/zig/ast.zig
@@ -11,6 +11,7 @@ pub const Node = struct {
     pub const Id = enum {
         Root,
         VarDecl,
+        Use,
         ErrorSetDecl,
         ContainerDecl,
         StructField,
@@ -63,6 +64,7 @@ pub const Node = struct {
         return switch (base.id) {
             Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),
             Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index),
+            Id.Use => @fieldParentPtr(NodeUse, "base", base).iterate(index),
             Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).iterate(index),
             Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).iterate(index),
             Id.StructField => @fieldParentPtr(NodeStructField, "base", base).iterate(index),
@@ -116,6 +118,7 @@ pub const Node = struct {
         return switch (base.id) {
             Id.Root => @fieldParentPtr(NodeRoot, "base", base).firstToken(),
             Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).firstToken(),
+            Id.Use => @fieldParentPtr(NodeUse, "base", base).firstToken(),
             Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).firstToken(),
             Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).firstToken(),
             Id.StructField => @fieldParentPtr(NodeStructField, "base", base).firstToken(),
@@ -169,6 +172,7 @@ pub const Node = struct {
         return switch (base.id) {
             Id.Root => @fieldParentPtr(NodeRoot, "base", base).lastToken(),
             Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).lastToken(),
+            Id.Use => @fieldParentPtr(NodeUse, "base", base).lastToken(),
             Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).lastToken(),
             Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).lastToken(),
             Id.StructField => @fieldParentPtr(NodeStructField, "base", base).lastToken(),
@@ -288,6 +292,31 @@ pub const NodeVarDecl = struct {
     }
 };
 
+pub const NodeUse = struct {
+    base: Node,
+    visib_token: ?Token,
+    expr: &Node,
+    semicolon_token: Token,
+
+    pub fn iterate(self: &NodeUse, index: usize) ?&Node {
+        var i = index;
+
+        if (i < 1) return self.expr;
+        i -= 1;
+
+        return null;
+    }
+
+    pub fn firstToken(self: &NodeUse) Token {
+        if (self.visib_token) |visib_token| return visib_token;
+        return self.expr.firstToken();
+    }
+
+    pub fn lastToken(self: &NodeUse) Token {
+        return self.semicolon_token;
+    }
+};
+
 pub const NodeErrorSetDecl = struct {
     base: Node,
     error_token: Token,
std/zig/parser.zig
@@ -348,31 +348,54 @@ pub const Parser = struct {
                 },
                 State.TopLevelExtern => |ctx| {
                     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 {
-                                .decls = ctx.decls,
+                    switch (token.id) {
+                        Token.Id.Keyword_use => {
+                            const node = try arena.create(ast.NodeUse);
+                            *node = ast.NodeUse {
+                                .base = self.initNode(ast.Node.Id.Use),
                                 .visib_token = ctx.visib_token,
-                                .extern_token = token,
-                                .lib_name = lib_name,
-                            },
-                        }) catch unreachable;
-                        continue;
+                                .expr = undefined,
+                                .semicolon_token = undefined,
+                            };
+                            try ctx.decls.append(&node.base);
+
+                            stack.append(State {
+                                .ExpectTokenSave = ExpectTokenSave {
+                                    .id = Token.Id.Semicolon,
+                                    .ptr = &node.semicolon_token,
+                                }
+                            }) catch unreachable;
+                            try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
+                            continue;
+                        },
+                        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 {
+                                    .decls = ctx.decls,
+                                    .visib_token = ctx.visib_token,
+                                    .extern_token = token,
+                                    .lib_name = lib_name,
+                                },
+                            }) catch unreachable;
+                            continue;
+                        },
+                        else => {
+                            self.putBackToken(token);
+                            stack.append(State { .TopLevelDecl = ctx }) catch unreachable;
+                            continue;
+                        }
                     }
-                    self.putBackToken(token);
-                    stack.append(State { .TopLevelDecl = ctx }) catch unreachable;
-                    continue;
                 },
                 State.TopLevelDecl => |ctx| {
                     const token = self.getNextToken();
@@ -3068,6 +3091,15 @@ pub const Parser = struct {
 
                             try stack.append(RenderState { .Expression = decl });
                         },
+                        ast.Node.Id.Use => {
+                            const use_decl = @fieldParentPtr(ast.NodeUse, "base", decl);
+                            if (use_decl.visib_token) |visib_token| {
+                                try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
+                            }
+                            try stream.print("use ");
+                            try stack.append(RenderState { .Text = ";" });
+                            try stack.append(RenderState { .Expression = use_decl.expr });
+                        },
                         ast.Node.Id.VarDecl => {
                             const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
                             try stack.append(RenderState { .VarDecl = var_decl});
@@ -4086,6 +4118,7 @@ pub const Parser = struct {
                     ast.Node.Id.EnumTag,
                     ast.Node.Id.Root,
                     ast.Node.Id.VarDecl,
+                    ast.Node.Id.Use,
                     ast.Node.Id.TestDecl,
                     ast.Node.Id.ParamDecl => unreachable,
                 },
@@ -5000,3 +5033,11 @@ test "zig fmt: Block after if" {
         \\
     );
 }
+
+test "zig fmt: use" {
+    try testCanonical(
+        \\use @import("std");
+        \\pub use @import("std");
+        \\
+    );
+}