Commit 53d58684a6

Andrew Kelley <superjoe30@gmail.com>
2017-12-11 04:44:04
self-hosted: parse var decls
1 parent f210f17
Changed files (1)
src-self-hosted
src-self-hosted/main.zig
@@ -562,9 +562,9 @@ const AstNodeVarDecl = struct {
     visib_token: ?Token,
     name_token: Token,
     eq_token: Token,
-    mut: Mutability,
-    is_comptime: Comptime,
-    is_extern: Extern,
+    mut_token: Token,
+    comptime_token: ?Token,
+    extern_token: ?Token,
     lib_name: ?&AstNode,
     type_node: ?&AstNode,
     align_node: ?&AstNode,
@@ -608,10 +608,10 @@ const AstNodeFnProto = struct {
     name_token: ?Token,
     params: ArrayList(&AstNode),
     return_type: ?&AstNode,
-    var_args: VarArgs,
-    is_extern: Extern,
-    is_inline: Inline,
-    cc: CallingConvention,
+    var_args_token: ?Token,
+    extern_token: ?Token,
+    inline_token: ?Token,
+    cc_token: ?Token,
     fn_def_node: ?&AstNode,
     lib_name: ?&AstNode, // populated if this is an extern declaration
     align_expr: ?&AstNode, // populated if align(A) is present
@@ -729,10 +729,15 @@ const Parser = struct {
         self.allocator.free(self.utility_bytes);
     }
 
+    const TopLevelExternCtx = struct {
+        visib_token: ?Token,
+        extern_token: Token,
+    };
+
     const State = union(enum) {
         TopLevel,
         TopLevelModifier: ?Token,
-        TopLevelExtern: ?Token,
+        TopLevelExtern: TopLevelExternCtx,
         Expression: &&AstNode,
         GroupedExpression: &&AstNode,
         UnwrapExpression: &&AstNode,
@@ -803,25 +808,22 @@ const Parser = struct {
                             stack.append(State { .TopLevelModifier = token }) %% unreachable;
                             continue;
                         },
-                        Token.Id.Keyword_const => {
-                            stack.append(State.TopLevel) %% unreachable;
-                            // TODO shouldn't need this cast
-                            const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
-                                Mutability.Const, Comptime.No, Extern.No);
-                            %return stack.append(State { .VarDecl = var_decl_node });
-                            continue;
-                        },
-                        Token.Id.Keyword_var => {
+                        Token.Id.Keyword_const, Token.Id.Keyword_var => {
                             stack.append(State.TopLevel) %% unreachable;
                             // TODO shouldn't need this cast
                             const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
-                                Mutability.Var, Comptime.No, Extern.No);
+                                token, (?Token)(null), (?Token)(null));
                             %return stack.append(State { .VarDecl = var_decl_node });
                             continue;
                         },
                         Token.Id.Eof => return root_node,
                         Token.Id.Keyword_extern => {
-                            stack.append(State { .TopLevelExtern = null }) %% unreachable;
+                            stack.append(State {
+                                .TopLevelExtern = TopLevelExternCtx {
+                                    .visib_token = null,
+                                    .extern_token = token,
+                                }
+                            }) %% unreachable;
                             continue;
                         },
                         else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
@@ -830,43 +832,43 @@ const Parser = struct {
                 State.TopLevelModifier => |visib_token| {
                     const token = self.getNextToken();
                     switch (token.id) {
-                        Token.Id.Keyword_const => {
-                            stack.append(State.TopLevel) %% unreachable;
-                            const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
-                                Mutability.Const, Comptime.No, Extern.No);
-                            %return stack.append(State { .VarDecl = var_decl_node });
-                            continue;
-                        },
-                        Token.Id.Keyword_var => {
+                        Token.Id.Keyword_const, Token.Id.Keyword_var => {
                             stack.append(State.TopLevel) %% unreachable;
+                            // TODO shouldn't need the casts here
                             const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
-                                Mutability.Var, Comptime.No, Extern.No);
+                                token, (?Token)(null), (?Token)(null));
                             %return stack.append(State { .VarDecl = var_decl_node });
                             continue;
                         },
                         Token.Id.Keyword_extern => {
-                            stack.append(State { .TopLevelExtern = visib_token }) %% unreachable;
+                            stack.append(State {
+                                .TopLevelExtern = TopLevelExternCtx {
+                                    .visib_token = visib_token,
+                                    .extern_token = token,
+                                },
+                            }) %% unreachable;
                             continue;
                         },
                         else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
                     }
                 },
-                State.TopLevelExtern => |visib_token| {
+                State.TopLevelExtern => |ctx| {
                     const token = self.getNextToken();
                     switch (token.id) {
-                        Token.Id.Keyword_var => {
+                        Token.Id.Keyword_var, Token.Id.Keyword_const => {
                             stack.append(State.TopLevel) %% unreachable;
-                            const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
-                                Mutability.Var, Comptime.No, Extern.Yes);
+                            // TODO shouldn't need these casts
+                            const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, ctx.visib_token,
+                                token, (?Token)(null), (?Token)(ctx.extern_token));
                             %return stack.append(State { .VarDecl = var_decl_node });
                             continue;
                         },
                         Token.Id.Keyword_fn => {
                             stack.append(State.TopLevel) %% unreachable;
                             %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
-                            // TODO shouldn't need this cast
+                            // TODO shouldn't need these casts
                             const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,
-                                Extern.Yes, CallingConvention.Auto, (?Token)(null), Inline.Auto);
+                                (?Token)(ctx.extern_token), (?Token)(null), (?Token)(null), (?Token)(null));
                             %return stack.append(State { .FnProto = fn_proto_node });
                             continue;
                         },
@@ -876,16 +878,10 @@ const Parser = struct {
                         Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
                             stack.append(State.TopLevel) %% unreachable;
                             %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
-                            const cc = switch (token.id) {
-                                Token.Id.Keyword_coldcc => CallingConvention.Cold,
-                                Token.Id.Keyword_nakedcc => CallingConvention.Naked,
-                                Token.Id.Keyword_stdcallcc => CallingConvention.Stdcall,
-                                else => unreachable,
-                            };
                             const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
                             // TODO shouldn't need this cast
                             const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,
-                                Extern.Yes, cc, (?Token)(null), Inline.Auto);
+                                (?Token)(ctx.extern_token), (?Token)(token), (?Token)(null), (?Token)(null));
                             %return stack.append(State { .FnProto = fn_proto_node });
                             continue;
                         },
@@ -1137,8 +1133,8 @@ const Parser = struct {
         return node;
     }
 
-    fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut: Mutability, is_comptime: Comptime,
-        is_extern: Extern) -> %&AstNodeVarDecl
+    fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
+        extern_token: &const ?Token) -> %&AstNodeVarDecl
     {
         const node = %return self.allocator.create(AstNodeVarDecl);
         %defer self.allocator.destroy(node);
@@ -1146,9 +1142,9 @@ const Parser = struct {
         *node = AstNodeVarDecl {
             .base = AstNode {.id = AstNode.Id.VarDecl},
             .visib_token = *visib_token,
-            .mut = mut,
-            .is_comptime = is_comptime,
-            .is_extern = is_extern,
+            .mut_token = *mut_token,
+            .comptime_token = *comptime_token,
+            .extern_token = *extern_token,
             .type_node = null,
             .align_node = null,
             .init_node = null,
@@ -1171,8 +1167,8 @@ const Parser = struct {
         return node;
     }
 
-    fn createFnProto(self: &Parser, fn_token: &const Token, is_extern: Extern,
-        cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto
+    fn createFnProto(self: &Parser, fn_token: &const Token, extern_token: &const ?Token,
+        cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&AstNodeFnProto
     {
         const node = %return self.allocator.create(AstNodeFnProto);
         %defer self.allocator.destroy(node);
@@ -1184,10 +1180,10 @@ const Parser = struct {
             .fn_token = *fn_token,
             .params = ArrayList(&AstNode).init(self.allocator),
             .return_type = null,
-            .var_args = VarArgs.No,
-            .is_extern = is_extern,
-            .is_inline = is_inline,
-            .cc = cc,
+            .var_args_token = null,
+            .extern_token = *extern_token,
+            .inline_token = *inline_token,
+            .cc_token = *cc_token,
             .fn_def_node = null,
             .lib_name = null,
             .align_expr = null,
@@ -1242,18 +1238,19 @@ const Parser = struct {
     }
 
     fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,
-        is_extern: Extern, cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto
+        extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,
+        inline_token: &const ?Token) -> %&AstNodeFnProto
     {
-        const node = %return self.createFnProto(fn_token, is_extern, cc, visib_token, is_inline);
+        const node = %return self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
         %defer self.allocator.destroy(node);
         %return list.append(&node.base);
         return node;
     }
 
-    fn createAttachVarDecl(self: &Parser, list: &ArrayList(&AstNode), visib_token: &const ?Token, mut: Mutability,
-        is_comptime: Comptime, is_extern: Extern) -> %&AstNodeVarDecl
+    fn createAttachVarDecl(self: &Parser, list: &ArrayList(&AstNode), visib_token: &const ?Token,
+        mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&AstNodeVarDecl
     {
-        const node = %return self.createVarDecl(visib_token, mut, is_comptime, is_extern);
+        const node = %return self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
         %defer self.allocator.destroy(node);
         %return list.append(&node.base);
         return node;
@@ -1376,8 +1373,8 @@ const Parser = struct {
                                     else => unreachable,
                                 };
                             }
-                            if (fn_proto.is_extern == Extern.Yes) {
-                                %return stream.print("extern ");
+                            if (fn_proto.extern_token) |extern_token| {
+                                %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
                             }
                             %return stream.print("fn");
 
@@ -1403,6 +1400,30 @@ const Parser = struct {
                                 }
                             }
                         },
+                        AstNode.Id.VarDecl => {
+                            const var_decl = @fieldParentPtr(AstNodeVarDecl, "base", decl);
+                            if (var_decl.visib_token) |visib_token| {
+                                %return stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
+                            }
+                            if (var_decl.extern_token) |extern_token| {
+                                %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
+                                if (var_decl.lib_name != null) {
+                                    @panic("TODO");
+                                }
+                            }
+                            if (var_decl.comptime_token) |comptime_token| {
+                                %return stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
+                            }
+                            %return stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
+                            %return stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
+
+                            %return stream.print(" = ");
+
+                            %return stack.append(RenderState { .Text = ";\n" });
+                            if (var_decl.init_node) |init_node| {
+                                %return stack.append(RenderState { .Expression = init_node });
+                            }
+                        },
                         else => unreachable,
                     }
                 },
@@ -1570,4 +1591,12 @@ test "zig fmt" {
         \\extern fn puts(s: &const u8) -> c_int;
         \\
     );
+
+    testCanonical(
+        \\const a = b;
+        \\pub const a = b;
+        \\var a = b;
+        \\pub var a = b;
+        \\
+    );
 }