authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-10 22:44:04-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-10 22:44:04-05:00
log53d58684a6cb09f6c8463b162e5c059a45ca56eb
treeb524a73cceb4474ec623a13f57443e9a8fb13d4d
parentf210f17d306ed1298901d38a29c1e50a1ee38ae5

self-hosted: parse var decls


1 files changed, 89 insertions(+), 60 deletions(-)

src-self-hosted/main.zig+89-60
...@@ -562,9 +562,9 @@ const AstNodeVarDecl = struct {...@@ -562,9 +562,9 @@ const AstNodeVarDecl = struct {
562 visib_token: ?Token,562 visib_token: ?Token,
563 name_token: Token,563 name_token: Token,
564 eq_token: Token,564 eq_token: Token,
565 mut: Mutability,565 mut_token: Token,
566 is_comptime: Comptime,566 comptime_token: ?Token,
567 is_extern: Extern,567 extern_token: ?Token,
568 lib_name: ?&AstNode,568 lib_name: ?&AstNode,
569 type_node: ?&AstNode,569 type_node: ?&AstNode,
570 align_node: ?&AstNode,570 align_node: ?&AstNode,
...@@ -608,10 +608,10 @@ const AstNodeFnProto = struct {...@@ -608,10 +608,10 @@ const AstNodeFnProto = struct {
608 name_token: ?Token,608 name_token: ?Token,
609 params: ArrayList(&AstNode),609 params: ArrayList(&AstNode),
610 return_type: ?&AstNode,610 return_type: ?&AstNode,
611 var_args: VarArgs,611 var_args_token: ?Token,
612 is_extern: Extern,612 extern_token: ?Token,
613 is_inline: Inline,613 inline_token: ?Token,
614 cc: CallingConvention,614 cc_token: ?Token,
615 fn_def_node: ?&AstNode,615 fn_def_node: ?&AstNode,
616 lib_name: ?&AstNode, // populated if this is an extern declaration616 lib_name: ?&AstNode, // populated if this is an extern declaration
617 align_expr: ?&AstNode, // populated if align(A) is present617 align_expr: ?&AstNode, // populated if align(A) is present
...@@ -729,10 +729,15 @@ const Parser = struct {...@@ -729,10 +729,15 @@ const Parser = struct {
729 self.allocator.free(self.utility_bytes);729 self.allocator.free(self.utility_bytes);
730 }730 }
731731
732 const TopLevelExternCtx = struct {
733 visib_token: ?Token,
734 extern_token: Token,
735 };
736
732 const State = union(enum) {737 const State = union(enum) {
733 TopLevel,738 TopLevel,
734 TopLevelModifier: ?Token,739 TopLevelModifier: ?Token,
735 TopLevelExtern: ?Token,740 TopLevelExtern: TopLevelExternCtx,
736 Expression: &&AstNode,741 Expression: &&AstNode,
737 GroupedExpression: &&AstNode,742 GroupedExpression: &&AstNode,
738 UnwrapExpression: &&AstNode,743 UnwrapExpression: &&AstNode,
...@@ -803,25 +808,22 @@ const Parser = struct {...@@ -803,25 +808,22 @@ const Parser = struct {
803 stack.append(State { .TopLevelModifier = token }) %% unreachable;808 stack.append(State { .TopLevelModifier = token }) %% unreachable;
804 continue;809 continue;
805 },810 },
806 Token.Id.Keyword_const => {811 Token.Id.Keyword_const, Token.Id.Keyword_var => {
807 stack.append(State.TopLevel) %% unreachable;
808 // TODO shouldn't need this cast
809 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
810 Mutability.Const, Comptime.No, Extern.No);
811 %return stack.append(State { .VarDecl = var_decl_node });
812 continue;
813 },
814 Token.Id.Keyword_var => {
815 stack.append(State.TopLevel) %% unreachable;812 stack.append(State.TopLevel) %% unreachable;
816 // TODO shouldn't need this cast813 // TODO shouldn't need this cast
817 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),814 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, (?Token)(null),
818 Mutability.Var, Comptime.No, Extern.No);815 token, (?Token)(null), (?Token)(null));
819 %return stack.append(State { .VarDecl = var_decl_node });816 %return stack.append(State { .VarDecl = var_decl_node });
820 continue;817 continue;
821 },818 },
822 Token.Id.Eof => return root_node,819 Token.Id.Eof => return root_node,
823 Token.Id.Keyword_extern => {820 Token.Id.Keyword_extern => {
824 stack.append(State { .TopLevelExtern = null }) %% unreachable;821 stack.append(State {
822 .TopLevelExtern = TopLevelExternCtx {
823 .visib_token = null,
824 .extern_token = token,
825 }
826 }) %% unreachable;
825 continue;827 continue;
826 },828 },
827 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),829 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
...@@ -830,43 +832,43 @@ const Parser = struct {...@@ -830,43 +832,43 @@ const Parser = struct {
830 State.TopLevelModifier => |visib_token| {832 State.TopLevelModifier => |visib_token| {
831 const token = self.getNextToken();833 const token = self.getNextToken();
832 switch (token.id) {834 switch (token.id) {
833 Token.Id.Keyword_const => {835 Token.Id.Keyword_const, Token.Id.Keyword_var => {
834 stack.append(State.TopLevel) %% unreachable;
835 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
836 Mutability.Const, Comptime.No, Extern.No);
837 %return stack.append(State { .VarDecl = var_decl_node });
838 continue;
839 },
840 Token.Id.Keyword_var => {
841 stack.append(State.TopLevel) %% unreachable;836 stack.append(State.TopLevel) %% unreachable;
837 // TODO shouldn't need the casts here
842 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,838 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,
843 Mutability.Var, Comptime.No, Extern.No);839 token, (?Token)(null), (?Token)(null));
844 %return stack.append(State { .VarDecl = var_decl_node });840 %return stack.append(State { .VarDecl = var_decl_node });
845 continue;841 continue;
846 },842 },
847 Token.Id.Keyword_extern => {843 Token.Id.Keyword_extern => {
848 stack.append(State { .TopLevelExtern = visib_token }) %% unreachable;844 stack.append(State {
845 .TopLevelExtern = TopLevelExternCtx {
846 .visib_token = visib_token,
847 .extern_token = token,
848 },
849 }) %% unreachable;
849 continue;850 continue;
850 },851 },
851 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),852 else => return self.parseError(token, "expected top level declaration, found {}", @tagName(token.id)),
852 }853 }
853 },854 },
854 State.TopLevelExtern => |visib_token| {855 State.TopLevelExtern => |ctx| {
855 const token = self.getNextToken();856 const token = self.getNextToken();
856 switch (token.id) {857 switch (token.id) {
857 Token.Id.Keyword_var => {858 Token.Id.Keyword_var, Token.Id.Keyword_const => {
858 stack.append(State.TopLevel) %% unreachable;859 stack.append(State.TopLevel) %% unreachable;
859 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, visib_token,860 // TODO shouldn't need these casts
860 Mutability.Var, Comptime.No, Extern.Yes);861 const var_decl_node = %return self.createAttachVarDecl(&root_node.decls, ctx.visib_token,
862 token, (?Token)(null), (?Token)(ctx.extern_token));
861 %return stack.append(State { .VarDecl = var_decl_node });863 %return stack.append(State { .VarDecl = var_decl_node });
862 continue;864 continue;
863 },865 },
864 Token.Id.Keyword_fn => {866 Token.Id.Keyword_fn => {
865 stack.append(State.TopLevel) %% unreachable;867 stack.append(State.TopLevel) %% unreachable;
866 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });868 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
867 // TODO shouldn't need this cast869 // TODO shouldn't need these casts
868 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,870 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token,
869 Extern.Yes, CallingConvention.Auto, (?Token)(null), Inline.Auto);871 (?Token)(ctx.extern_token), (?Token)(null), (?Token)(null), (?Token)(null));
870 %return stack.append(State { .FnProto = fn_proto_node });872 %return stack.append(State { .FnProto = fn_proto_node });
871 continue;873 continue;
872 },874 },
...@@ -876,16 +878,10 @@ const Parser = struct {...@@ -876,16 +878,10 @@ const Parser = struct {
876 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {878 Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
877 stack.append(State.TopLevel) %% unreachable;879 stack.append(State.TopLevel) %% unreachable;
878 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });880 %return stack.append(State { .ExpectToken = Token.Id.Semicolon });
879 const cc = switch (token.id) {
880 Token.Id.Keyword_coldcc => CallingConvention.Cold,
881 Token.Id.Keyword_nakedcc => CallingConvention.Naked,
882 Token.Id.Keyword_stdcallcc => CallingConvention.Stdcall,
883 else => unreachable,
884 };
885 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);881 const fn_token = %return self.eatToken(Token.Id.Keyword_fn);
886 // TODO shouldn't need this cast882 // TODO shouldn't need this cast
887 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,883 const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, fn_token,
888 Extern.Yes, cc, (?Token)(null), Inline.Auto);884 (?Token)(ctx.extern_token), (?Token)(token), (?Token)(null), (?Token)(null));
889 %return stack.append(State { .FnProto = fn_proto_node });885 %return stack.append(State { .FnProto = fn_proto_node });
890 continue;886 continue;
891 },887 },
...@@ -1137,8 +1133,8 @@ const Parser = struct {...@@ -1137,8 +1133,8 @@ const Parser = struct {
1137 return node;1133 return node;
1138 }1134 }
11391135
1140 fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut: Mutability, is_comptime: Comptime,1136 fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
1141 is_extern: Extern) -> %&AstNodeVarDecl1137 extern_token: &const ?Token) -> %&AstNodeVarDecl
1142 {1138 {
1143 const node = %return self.allocator.create(AstNodeVarDecl);1139 const node = %return self.allocator.create(AstNodeVarDecl);
1144 %defer self.allocator.destroy(node);1140 %defer self.allocator.destroy(node);
...@@ -1146,9 +1142,9 @@ const Parser = struct {...@@ -1146,9 +1142,9 @@ const Parser = struct {
1146 *node = AstNodeVarDecl {1142 *node = AstNodeVarDecl {
1147 .base = AstNode {.id = AstNode.Id.VarDecl},1143 .base = AstNode {.id = AstNode.Id.VarDecl},
1148 .visib_token = *visib_token,1144 .visib_token = *visib_token,
1149 .mut = mut,1145 .mut_token = *mut_token,
1150 .is_comptime = is_comptime,1146 .comptime_token = *comptime_token,
1151 .is_extern = is_extern,1147 .extern_token = *extern_token,
1152 .type_node = null,1148 .type_node = null,
1153 .align_node = null,1149 .align_node = null,
1154 .init_node = null,1150 .init_node = null,
...@@ -1171,8 +1167,8 @@ const Parser = struct {...@@ -1171,8 +1167,8 @@ const Parser = struct {
1171 return node;1167 return node;
1172 }1168 }
11731169
1174 fn createFnProto(self: &Parser, fn_token: &const Token, is_extern: Extern,1170 fn createFnProto(self: &Parser, fn_token: &const Token, extern_token: &const ?Token,
1175 cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto1171 cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&AstNodeFnProto
1176 {1172 {
1177 const node = %return self.allocator.create(AstNodeFnProto);1173 const node = %return self.allocator.create(AstNodeFnProto);
1178 %defer self.allocator.destroy(node);1174 %defer self.allocator.destroy(node);
...@@ -1184,10 +1180,10 @@ const Parser = struct {...@@ -1184,10 +1180,10 @@ const Parser = struct {
1184 .fn_token = *fn_token,1180 .fn_token = *fn_token,
1185 .params = ArrayList(&AstNode).init(self.allocator),1181 .params = ArrayList(&AstNode).init(self.allocator),
1186 .return_type = null,1182 .return_type = null,
1187 .var_args = VarArgs.No,1183 .var_args_token = null,
1188 .is_extern = is_extern,1184 .extern_token = *extern_token,
1189 .is_inline = is_inline,1185 .inline_token = *inline_token,
1190 .cc = cc,1186 .cc_token = *cc_token,
1191 .fn_def_node = null,1187 .fn_def_node = null,
1192 .lib_name = null,1188 .lib_name = null,
1193 .align_expr = null,1189 .align_expr = null,
...@@ -1242,18 +1238,19 @@ const Parser = struct {...@@ -1242,18 +1238,19 @@ const Parser = struct {
1242 }1238 }
12431239
1244 fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,1240 fn createAttachFnProto(self: &Parser, list: &ArrayList(&AstNode), fn_token: &const Token,
1245 is_extern: Extern, cc: CallingConvention, visib_token: &const ?Token, is_inline: Inline) -> %&AstNodeFnProto1241 extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,
1242 inline_token: &const ?Token) -> %&AstNodeFnProto
1246 {1243 {
1247 const node = %return self.createFnProto(fn_token, is_extern, cc, visib_token, is_inline);1244 const node = %return self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
1248 %defer self.allocator.destroy(node);1245 %defer self.allocator.destroy(node);
1249 %return list.append(&node.base);1246 %return list.append(&node.base);
1250 return node;1247 return node;
1251 }1248 }
12521249
1253 fn createAttachVarDecl(self: &Parser, list: &ArrayList(&AstNode), visib_token: &const ?Token, mut: Mutability,1250 fn createAttachVarDecl(self: &Parser, list: &ArrayList(&AstNode), visib_token: &const ?Token,
1254 is_comptime: Comptime, is_extern: Extern) -> %&AstNodeVarDecl1251 mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&AstNodeVarDecl
1255 {1252 {
1256 const node = %return self.createVarDecl(visib_token, mut, is_comptime, is_extern);1253 const node = %return self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
1257 %defer self.allocator.destroy(node);1254 %defer self.allocator.destroy(node);
1258 %return list.append(&node.base);1255 %return list.append(&node.base);
1259 return node;1256 return node;
...@@ -1376,8 +1373,8 @@ const Parser = struct {...@@ -1376,8 +1373,8 @@ const Parser = struct {
1376 else => unreachable,1373 else => unreachable,
1377 };1374 };
1378 }1375 }
1379 if (fn_proto.is_extern == Extern.Yes) {1376 if (fn_proto.extern_token) |extern_token| {
1380 %return stream.print("extern ");1377 %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1381 }1378 }
1382 %return stream.print("fn");1379 %return stream.print("fn");
13831380
...@@ -1403,6 +1400,30 @@ const Parser = struct {...@@ -1403,6 +1400,30 @@ const Parser = struct {
1403 }1400 }
1404 }1401 }
1405 },1402 },
1403 AstNode.Id.VarDecl => {
1404 const var_decl = @fieldParentPtr(AstNodeVarDecl, "base", decl);
1405 if (var_decl.visib_token) |visib_token| {
1406 %return stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
1407 }
1408 if (var_decl.extern_token) |extern_token| {
1409 %return stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1410 if (var_decl.lib_name != null) {
1411 @panic("TODO");
1412 }
1413 }
1414 if (var_decl.comptime_token) |comptime_token| {
1415 %return stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
1416 }
1417 %return stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
1418 %return stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
1419
1420 %return stream.print(" = ");
1421
1422 %return stack.append(RenderState { .Text = ";\n" });
1423 if (var_decl.init_node) |init_node| {
1424 %return stack.append(RenderState { .Expression = init_node });
1425 }
1426 },
1406 else => unreachable,1427 else => unreachable,
1407 }1428 }
1408 },1429 },
...@@ -1570,4 +1591,12 @@ test "zig fmt" {...@@ -1570,4 +1591,12 @@ test "zig fmt" {
1570 \\extern fn puts(s: &const u8) -> c_int;1591 \\extern fn puts(s: &const u8) -> c_int;
1571 \\1592 \\
1572 );1593 );
1594
1595 testCanonical(
1596 \\const a = b;
1597 \\pub const a = b;
1598 \\var a = b;
1599 \\pub var a = b;
1600 \\
1601 );
1573}1602}