diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-12-10 22:44:04 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-12-10 22:44:04 -0500 |
| commit | 53d58684a6cb09f6c8463b162e5c059a45ca56eb (patch) | |
| tree | b524a73cceb4474ec623a13f57443e9a8fb13d4d | |
| parent | f210f17d306ed1298901d38a29c1e50a1ee38ae5 (diff) | |
| download | zig-53d58684a6cb09f6c8463b162e5c059a45ca56eb.tar.gz zig-53d58684a6cb09f6c8463b162e5c059a45ca56eb.zip | |
self-hosted: parse var decls
| -rw-r--r-- | src-self-hosted/main.zig | 149 |
1 files changed, 89 insertions, 60 deletions
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 209ee829e5..e3026a2968 100644 --- a/src-self-hosted/main.zig +++ b/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; + \\ + ); } |
