authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-26 13:08:21-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-26 13:08:21-07:00
log5afe473a86c2fe32b6d7c472b71f88e70ac671c6
treef96903b0859c702fa7391d40024056cb1d2563d1
parentbc896149966afb3740a02cd34939f0543b769be7

different extern syntax and simplify parsing top level decls


8 files changed, 174 insertions(+), 353 deletions(-)

doc/langref.md+14-12
...@@ -5,31 +5,33 @@...@@ -5,31 +5,33 @@
5```5```
6Root : many(TopLevelDecl) "EOF"6Root : many(TopLevelDecl) "EOF"
77
8TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl8TopLevelDecl : many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl)
99
10ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"10CImportDecl : "c_import" Block
1111
12VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression12ErrorValueDecl : "error" "Symbol" ";"
1313
14ContainerDecl : many(Directive) option(FnVisibleMod) ("struct" | "enum") "Symbol" "{" many(StructMember) "}"14GlobalVarDecl : VariableDeclaration ";"
1515
16StructMember: StructField | FnDecl16VariableDeclaration : ("var" | "const") "Symbol" option(":" PrefixOpExpression) "=" Expression
17
18ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
19
20StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
1721
18StructField : "Symbol" option(":" Expression) ",")22StructField : "Symbol" option(":" Expression) ",")
1923
20Import : many(Directive) "import" "String" ";"24Import : "import" "String" ";"
2125
22RootExportDecl : many(Directive) "export" "Symbol" "String" ";"26RootExportDecl : "export" "Symbol" "String" ";"
2327
24ExternBlock : many(Directive) "extern" "{" many(FnDecl) "}"28ExternDecl : "extern" FnProto ";"
2529
26FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)30FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
2731
28Directive : "#" "Symbol" "(" "String" ")"32Directive : "#" "Symbol" "(" "String" ")"
2933
30FnVisibleMod : "pub" | "export"34VisibleMod : "pub" | "export"
31
32FnDecl : FnProto ";"
3335
34FnDef : FnProto Block36FnDef : FnProto Block
3537
doc/vim/syntax/zig.vim+1-1
...@@ -14,7 +14,7 @@ syn keyword zigConditional if else switch...@@ -14,7 +14,7 @@ syn keyword zigConditional if else switch
14syn keyword zigRepeat while for14syn keyword zigRepeat while for
1515
16syn keyword zigConstant null undefined16syn keyword zigConstant null undefined
17syn keyword zigKeyword fn import17syn keyword zigKeyword fn import c_import
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error
19syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong19syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong
2020
example/hello_world/hello_libc.zig+2-4
...@@ -1,9 +1,7 @@...@@ -1,9 +1,7 @@
1#link("c")
1export executable "hello";2export executable "hello";
23
3#link("c")4extern fn printf(__format: &const u8, ...) -> c_int;
4extern {
5 fn printf(__format: &const u8, ...) -> c_int;
6}
75
8export fn main(argc: c_int, argv: &&u8) -> c_int {6export fn main(argc: c_int, argv: &&u8) -> c_int {
9 printf(c"Hello, world!\n");7 printf(c"Hello, world!\n");
src/all_types.hpp+6-10
...@@ -121,7 +121,6 @@ enum NodeType {...@@ -121,7 +121,6 @@ enum NodeType {
121 NodeTypeFnDecl,121 NodeTypeFnDecl,
122 NodeTypeParamDecl,122 NodeTypeParamDecl,
123 NodeTypeBlock,123 NodeTypeBlock,
124 NodeTypeExternBlock,
125 NodeTypeDirective,124 NodeTypeDirective,
126 NodeTypeReturnExpr,125 NodeTypeReturnExpr,
127 NodeTypeVariableDeclaration,126 NodeTypeVariableDeclaration,
...@@ -178,11 +177,10 @@ struct AstNodeFnProto {...@@ -178,11 +177,10 @@ struct AstNodeFnProto {
178 ZigList<AstNode *> params;177 ZigList<AstNode *> params;
179 AstNode *return_type;178 AstNode *return_type;
180 bool is_var_args;179 bool is_var_args;
180 bool is_extern;
181181
182 // populated by semantic analyzer:182 // populated by semantic analyzer:
183183
184 // the extern block this fn proto is inside. can be null.
185 AstNode *extern_node;
186 // the struct decl node this fn proto is inside. can be null.184 // the struct decl node this fn proto is inside. can be null.
187 AstNode *struct_node;185 AstNode *struct_node;
188 // the function definition this fn proto is inside. can be null.186 // the function definition this fn proto is inside. can be null.
...@@ -247,6 +245,7 @@ struct AstNodeVariableDeclaration {...@@ -247,6 +245,7 @@ struct AstNodeVariableDeclaration {
247 // one or both of type and expr will be non null245 // one or both of type and expr will be non null
248 AstNode *type;246 AstNode *type;
249 AstNode *expr;247 AstNode *expr;
248 ZigList<AstNode *> *directives;
250249
251 // populated by semantic analyzer250 // populated by semantic analyzer
252 TopLevelDecl top_level_decl;251 TopLevelDecl top_level_decl;
...@@ -255,8 +254,9 @@ struct AstNodeVariableDeclaration {...@@ -255,8 +254,9 @@ struct AstNodeVariableDeclaration {
255};254};
256255
257struct AstNodeErrorValueDecl {256struct AstNodeErrorValueDecl {
258 VisibMod visib_mod;
259 Buf name;257 Buf name;
258 VisibMod visib_mod;
259 ZigList<AstNode *> *directives;
260260
261 // populated by semantic analyzer261 // populated by semantic analyzer
262 TopLevelDecl top_level_decl;262 TopLevelDecl top_level_decl;
...@@ -378,11 +378,6 @@ struct AstNodeFieldAccessExpr {...@@ -378,11 +378,6 @@ struct AstNodeFieldAccessExpr {
378 StructValExprCodeGen resolved_struct_val_expr; // for enum values378 StructValExprCodeGen resolved_struct_val_expr; // for enum values
379};379};
380380
381struct AstNodeExternBlock {
382 ZigList<AstNode *> *directives;
383 ZigList<AstNode *> fn_decls;
384};
385
386struct AstNodeDirective {381struct AstNodeDirective {
387 Buf name;382 Buf name;
388 Buf param;383 Buf param;
...@@ -418,6 +413,7 @@ struct AstNodePrefixOpExpr {...@@ -418,6 +413,7 @@ struct AstNodePrefixOpExpr {
418struct AstNodeUse {413struct AstNodeUse {
419 Buf path;414 Buf path;
420 ZigList<AstNode *> *directives;415 ZigList<AstNode *> *directives;
416 VisibMod visib_mod;
421417
422 // populated by semantic analyzer418 // populated by semantic analyzer
423 ImportTableEntry *import;419 ImportTableEntry *import;
...@@ -559,6 +555,7 @@ struct AstNodeStructField {...@@ -559,6 +555,7 @@ struct AstNodeStructField {
559 Buf name;555 Buf name;
560 AstNode *type;556 AstNode *type;
561 ZigList<AstNode *> *directives;557 ZigList<AstNode *> *directives;
558 VisibMod visib_mod;
562};559};
563560
564struct AstNodeStringLiteral {561struct AstNodeStringLiteral {
...@@ -697,7 +694,6 @@ struct AstNode {...@@ -697,7 +694,6 @@ struct AstNode {
697 AstNodeErrorValueDecl error_value_decl;694 AstNodeErrorValueDecl error_value_decl;
698 AstNodeBinOpExpr bin_op_expr;695 AstNodeBinOpExpr bin_op_expr;
699 AstNodeUnwrapErrorExpr unwrap_err_expr;696 AstNodeUnwrapErrorExpr unwrap_err_expr;
700 AstNodeExternBlock extern_block;
701 AstNodeDirective directive;697 AstNodeDirective directive;
702 AstNodePrefixOpExpr prefix_op_expr;698 AstNodePrefixOpExpr prefix_op_expr;
703 AstNodeFnCallExpr fn_call_expr;699 AstNodeFnCallExpr fn_call_expr;
src/analyze.cpp+6-35
...@@ -45,7 +45,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -45,7 +45,6 @@ static AstNode *first_executing_node(AstNode *node) {
45 case NodeTypeFnDecl:45 case NodeTypeFnDecl:
46 case NodeTypeParamDecl:46 case NodeTypeParamDecl:
47 case NodeTypeBlock:47 case NodeTypeBlock:
48 case NodeTypeExternBlock:
49 case NodeTypeDirective:48 case NodeTypeDirective:
50 case NodeTypeReturnExpr:49 case NodeTypeReturnExpr:
51 case NodeTypeVariableDeclaration:50 case NodeTypeVariableDeclaration:
...@@ -897,8 +896,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -897,8 +896,8 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
897 AstNode *proto_node)896 AstNode *proto_node)
898{897{
899 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;898 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
900 AstNode *extern_node = proto_node->data.fn_proto.extern_node;
901 AstNode *struct_node = proto_node->data.fn_proto.struct_node;899 AstNode *struct_node = proto_node->data.fn_proto.struct_node;
900 bool is_extern = proto_node->data.fn_proto.is_extern;
902 TypeTableEntry *struct_type;901 TypeTableEntry *struct_type;
903 if (struct_node) {902 if (struct_node) {
904 assert(struct_node->type == NodeTypeStructDecl);903 assert(struct_node->type == NodeTypeStructDecl);
...@@ -914,7 +913,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -914,7 +913,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
914 auto entry = fn_table->maybe_get(proto_name);913 auto entry = fn_table->maybe_get(proto_name);
915 bool skip = false;914 bool skip = false;
916 bool is_internal = (proto_node->data.fn_proto.visib_mod != VisibModExport);915 bool is_internal = (proto_node->data.fn_proto.visib_mod != VisibModExport);
917 bool is_c_compat = !is_internal || extern_node;916 bool is_c_compat = !is_internal || is_extern;
918 bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate);917 bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate);
919 if (entry) {918 if (entry) {
920 add_node_error(g, proto_node,919 add_node_error(g, proto_node,
...@@ -922,7 +921,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -922,7 +921,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
922 proto_node->data.fn_proto.skip = true;921 proto_node->data.fn_proto.skip = true;
923 skip = true;922 skip = true;
924 }923 }
925 if (!extern_node && proto_node->data.fn_proto.is_var_args) {924 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
926 add_node_error(g, proto_node,925 add_node_error(g, proto_node,
927 buf_sprintf("variadic arguments only allowed in extern functions"));926 buf_sprintf("variadic arguments only allowed in extern functions"));
928 }927 }
...@@ -935,7 +934,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -935,7 +934,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
935 fn_table_entry->proto_node = proto_node;934 fn_table_entry->proto_node = proto_node;
936 fn_table_entry->fn_def_node = fn_def_node;935 fn_table_entry->fn_def_node = fn_def_node;
937 fn_table_entry->internal_linkage = !is_c_compat;936 fn_table_entry->internal_linkage = !is_c_compat;
938 fn_table_entry->is_extern = extern_node;937 fn_table_entry->is_extern = is_extern;
939 fn_table_entry->label_table.init(8);938 fn_table_entry->label_table.init(8);
940 fn_table_entry->member_of_struct = struct_type;939 fn_table_entry->member_of_struct = struct_type;
941940
...@@ -950,7 +949,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -950,7 +949,7 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
950949
951 g->fn_protos.append(fn_table_entry);950 g->fn_protos.append(fn_table_entry);
952951
953 if (!extern_node) {952 if (!is_extern) {
954 g->fn_defs.append(fn_table_entry);953 g->fn_defs.append(fn_table_entry);
955 }954 }
956955
...@@ -1021,19 +1020,6 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo...@@ -1021,19 +1020,6 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo
10211020
1022static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {1021static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1023 switch (node->type) {1022 switch (node->type) {
1024 case NodeTypeExternBlock:
1025 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {
1026 AstNode *directive_node = node->data.extern_block.directives->at(i);
1027 Buf *name = &directive_node->data.directive.name;
1028 Buf *param = &directive_node->data.directive.param;
1029 if (buf_eql_str(name, "link")) {
1030 g->link_table.put(param, true);
1031 } else {
1032 add_node_error(g, directive_node,
1033 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
1034 }
1035 }
1036 break;
1037 case NodeTypeFnProto:1023 case NodeTypeFnProto:
1038 preview_fn_proto(g, import, node);1024 preview_fn_proto(g, import, node);
1039 break;1025 break;
...@@ -4051,7 +4037,6 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -4051,7 +4037,6 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
4051 case NodeTypeParamDecl:4037 case NodeTypeParamDecl:
4052 case NodeTypeRoot:4038 case NodeTypeRoot:
4053 case NodeTypeRootExportDecl:4039 case NodeTypeRootExportDecl:
4054 case NodeTypeExternBlock:
4055 case NodeTypeFnDef:4040 case NodeTypeFnDef:
4056 case NodeTypeUse:4041 case NodeTypeUse:
4057 case NodeTypeLabel:4042 case NodeTypeLabel:
...@@ -4155,15 +4140,14 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4155,15 +4140,14 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
4155 break;4140 break;
4156 }4141 }
4157 case NodeTypeRootExportDecl:4142 case NodeTypeRootExportDecl:
4158 case NodeTypeExternBlock:
4159 case NodeTypeUse:4143 case NodeTypeUse:
4160 case NodeTypeVariableDeclaration:4144 case NodeTypeVariableDeclaration:
4161 case NodeTypeErrorValueDecl:4145 case NodeTypeErrorValueDecl:
4146 case NodeTypeFnProto:
4162 // already took care of these4147 // already took care of these
4163 break;4148 break;
4164 case NodeTypeDirective:4149 case NodeTypeDirective:
4165 case NodeTypeParamDecl:4150 case NodeTypeParamDecl:
4166 case NodeTypeFnProto:
4167 case NodeTypeFnDecl:4151 case NodeTypeFnDecl:
4168 case NodeTypeReturnExpr:4152 case NodeTypeReturnExpr:
4169 case NodeTypeRoot:4153 case NodeTypeRoot:
...@@ -4350,7 +4334,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode...@@ -4350,7 +4334,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
4350 break;4334 break;
4351 case NodeTypeVariableDeclaration:4335 case NodeTypeVariableDeclaration:
4352 case NodeTypeFnProto:4336 case NodeTypeFnProto:
4353 case NodeTypeExternBlock:
4354 case NodeTypeRootExportDecl:4337 case NodeTypeRootExportDecl:
4355 case NodeTypeFnDef:4338 case NodeTypeFnDef:
4356 case NodeTypeRoot:4339 case NodeTypeRoot:
...@@ -4453,16 +4436,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -4453,16 +4436,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
44534436
4454 break;4437 break;
4455 }4438 }
4456 case NodeTypeExternBlock:
4457 for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) {
4458 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
4459 assert(fn_decl->type == NodeTypeFnDecl);
4460 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
4461 fn_proto->data.fn_proto.extern_node = node;
4462 detect_top_level_decl_deps(g, import, fn_proto);
4463 }
4464 resolve_top_level_decl(g, import, node);
4465 break;
4466 case NodeTypeFnDef:4439 case NodeTypeFnDef:
4467 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;4440 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
4468 detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto);4441 detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto);
...@@ -4786,7 +4759,6 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -4786,7 +4759,6 @@ Expr *get_resolved_expr(AstNode *node) {
4786 case NodeTypeFnDef:4759 case NodeTypeFnDef:
4787 case NodeTypeFnDecl:4760 case NodeTypeFnDecl:
4788 case NodeTypeParamDecl:4761 case NodeTypeParamDecl:
4789 case NodeTypeExternBlock:
4790 case NodeTypeDirective:4762 case NodeTypeDirective:
4791 case NodeTypeUse:4763 case NodeTypeUse:
4792 case NodeTypeStructDecl:4764 case NodeTypeStructDecl:
...@@ -4832,7 +4804,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -4832,7 +4804,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
4832 case NodeTypeFnDecl:4804 case NodeTypeFnDecl:
4833 case NodeTypeParamDecl:4805 case NodeTypeParamDecl:
4834 case NodeTypeBlock:4806 case NodeTypeBlock:
4835 case NodeTypeExternBlock:
4836 case NodeTypeDirective:4807 case NodeTypeDirective:
4837 case NodeTypeStringLiteral:4808 case NodeTypeStringLiteral:
4838 case NodeTypeCharLiteral:4809 case NodeTypeCharLiteral:
src/codegen.cpp+5-15
...@@ -2249,7 +2249,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2249,7 +2249,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2249 case NodeTypeFnDef:2249 case NodeTypeFnDef:
2250 case NodeTypeFnDecl:2250 case NodeTypeFnDecl:
2251 case NodeTypeParamDecl:2251 case NodeTypeParamDecl:
2252 case NodeTypeExternBlock:
2253 case NodeTypeDirective:2252 case NodeTypeDirective:
2254 case NodeTypeUse:2253 case NodeTypeUse:
2255 case NodeTypeStructDecl:2254 case NodeTypeStructDecl:
...@@ -3001,18 +3000,6 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -3001,18 +3000,6 @@ static void init(CodeGen *g, Buf *source_path) {
30013000
3002}3001}
30033002
3004static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {
3005 for (int i = 0; i < directives->length; i += 1) {
3006 AstNode *directive_node = directives->at(i);
3007 if (buf_eql_str(&directive_node->data.directive.name, "link") &&
3008 buf_eql_str(&directive_node->data.directive.param, "c"))
3009 {
3010 return true;
3011 }
3012 }
3013 return false;
3014}
3015
3016static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {3003static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
3017 char *dot1 = strstr(buf_ptr(buf), ".");3004 char *dot1 = strstr(buf_ptr(buf), ".");
3018 if (!dot1)3005 if (!dot1)
...@@ -3114,6 +3101,11 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -3114,6 +3101,11 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
3114 Buf *param = &directive_node->data.directive.param;3101 Buf *param = &directive_node->data.directive.param;
3115 if (buf_eql_str(name, "version")) {3102 if (buf_eql_str(name, "version")) {
3116 set_root_export_version(g, param, directive_node);3103 set_root_export_version(g, param, directive_node);
3104 } else if (buf_eql_str(name, "link")) {
3105 g->link_table.put(param, true);
3106 if (buf_eql_str(param, "c")) {
3107 g->link_libc = true;
3108 }
3117 } else {3109 } else {
3118 add_node_error(g, directive_node,3110 add_node_error(g, directive_node,
3119 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));3111 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
...@@ -3204,8 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -3204,8 +3196,6 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
3204 if (buf_eql_str(proto_name, "main") && !is_private) {3196 if (buf_eql_str(proto_name, "main") && !is_private) {
3205 g->have_exported_main = true;3197 g->have_exported_main = true;
3206 }3198 }
3207 } else if (top_level_decl->type == NodeTypeExternBlock) {
3208 g->link_libc = directives_contains_link_libc(top_level_decl->data.extern_block.directives);
3209 }3199 }
3210 }3200 }
32113201
src/parser.cpp+132-261
...@@ -105,8 +105,6 @@ const char *node_type_str(NodeType node_type) {...@@ -105,8 +105,6 @@ const char *node_type_str(NodeType node_type) {
105 return "ArrayAccessExpr";105 return "ArrayAccessExpr";
106 case NodeTypeSliceExpr:106 case NodeTypeSliceExpr:
107 return "SliceExpr";107 return "SliceExpr";
108 case NodeTypeExternBlock:
109 return "ExternBlock";
110 case NodeTypeDirective:108 case NodeTypeDirective:
111 return "Directive";109 return "Directive";
112 case NodeTypeReturnExpr:110 case NodeTypeReturnExpr:
...@@ -258,15 +256,6 @@ void ast_print(AstNode *node, int indent) {...@@ -258,15 +256,6 @@ void ast_print(AstNode *node, int indent) {
258 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));256 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
259 break;257 break;
260 }258 }
261 case NodeTypeExternBlock:
262 {
263 fprintf(stderr, "%s\n", node_type_str(node->type));
264 for (int i = 0; i < node->data.extern_block.fn_decls.length; i += 1) {
265 AstNode *child = node->data.extern_block.fn_decls.at(i);
266 ast_print(child, indent + 2);
267 }
268 break;
269 }
270 case NodeTypeFnDecl:259 case NodeTypeFnDecl:
271 fprintf(stderr, "%s\n", node_type_str(node->type));260 fprintf(stderr, "%s\n", node_type_str(node->type));
272 ast_print(node->data.fn_decl.fn_proto, indent + 2);261 ast_print(node->data.fn_decl.fn_proto, indent + 2);
...@@ -482,9 +471,9 @@ struct ParseContext {...@@ -482,9 +471,9 @@ struct ParseContext {
482 Buf *buf;471 Buf *buf;
483 AstNode *root;472 AstNode *root;
484 ZigList<Token> *tokens;473 ZigList<Token> *tokens;
485 ZigList<AstNode *> *directive_list;
486 ImportTableEntry *owner;474 ImportTableEntry *owner;
487 ErrColor err_color;475 ErrColor err_color;
476 bool parsed_root_export;
488 uint32_t *next_node_index;477 uint32_t *next_node_index;
489};478};
490479
...@@ -2146,56 +2135,32 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m...@@ -2146,56 +2135,32 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
2146}2135}
21472136
2148/*2137/*
2149VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))2138VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression))
2150*/2139*/
2151static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {2140static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory,
2141 ZigList<AstNode*> *directives, VisibMod visib_mod)
2142{
2152 Token *first_token = &pc->tokens->at(*token_index);2143 Token *first_token = &pc->tokens->at(*token_index);
21532144
2154 VisibMod visib_mod;
2155 bool is_const;2145 bool is_const;
21562146
2157 if (first_token->id == TokenIdKeywordPub) {2147 if (first_token->id == TokenIdKeywordVar) {
2158 Token *next_token = &pc->tokens->at(*token_index + 1);2148 is_const = false;
2159 if (next_token->id == TokenIdKeywordVar ||2149 } else if (first_token->id == TokenIdKeywordConst) {
2160 next_token->id == TokenIdKeywordConst)2150 is_const = true;
2161 {
2162 visib_mod = VisibModPub;
2163 is_const = (next_token->id == TokenIdKeywordConst);
2164 *token_index += 2;
2165 } else if (mandatory) {
2166 ast_invalid_token_error(pc, next_token);
2167 } else {
2168 return nullptr;
2169 }
2170 } else if (first_token->id == TokenIdKeywordExport) {
2171 Token *next_token = &pc->tokens->at(*token_index + 1);
2172 if (next_token->id == TokenIdKeywordVar ||
2173 next_token->id == TokenIdKeywordConst)
2174 {
2175 visib_mod = VisibModExport;
2176 is_const = (next_token->id == TokenIdKeywordConst);
2177 *token_index += 2;
2178 } else if (mandatory) {
2179 ast_invalid_token_error(pc, next_token);
2180 } else {
2181 return nullptr;
2182 }
2183 } else if (first_token->id == TokenIdKeywordVar ||
2184 first_token->id == TokenIdKeywordConst)
2185 {
2186 visib_mod = VisibModPrivate;
2187 is_const = (first_token->id == TokenIdKeywordConst);
2188 *token_index += 1;
2189 } else if (mandatory) {2151 } else if (mandatory) {
2190 ast_invalid_token_error(pc, first_token);2152 ast_invalid_token_error(pc, first_token);
2191 } else {2153 } else {
2192 return nullptr;2154 return nullptr;
2193 }2155 }
21942156
2157 *token_index += 1;
2158
2195 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);2159 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);
21962160
2197 node->data.variable_declaration.is_const = is_const;2161 node->data.variable_declaration.is_const = is_const;
2198 node->data.variable_declaration.visib_mod = visib_mod;2162 node->data.variable_declaration.visib_mod = visib_mod;
2163 node->data.variable_declaration.directives = directives;
21992164
2200 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);2165 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
2201 ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);2166 ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
...@@ -2643,7 +2608,8 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato...@@ -2643,7 +2608,8 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
2643 if (statement_node) {2608 if (statement_node) {
2644 semicolon_expected = false;2609 semicolon_expected = false;
2645 } else {2610 } else {
2646 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false);2611 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,
2612 nullptr, VisibModPrivate);
2647 if (statement_node) {2613 if (statement_node) {
2648 semicolon_expected = true;2614 semicolon_expected = true;
2649 } else {2615 } else {
...@@ -2677,47 +2643,25 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato...@@ -2677,47 +2643,25 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
2677}2643}
26782644
2679/*2645/*
2680FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)2646FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression)
2681*/2647*/
2682static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) {2648static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
2649 ZigList<AstNode*> *directives, VisibMod visib_mod)
2650{
2683 Token *first_token = &pc->tokens->at(*token_index);2651 Token *first_token = &pc->tokens->at(*token_index);
26842652
2685 VisibMod visib_mod;2653 if (first_token->id != TokenIdKeywordFn) {
26862654 if (mandatory) {
2687 if (first_token->id == TokenIdKeywordPub) {2655 ast_expect_token(pc, first_token, TokenIdKeywordFn);
2688 Token *next_token = &pc->tokens->at(*token_index + 1);
2689 if (next_token->id == TokenIdKeywordFn) {
2690 visib_mod = VisibModPub;
2691 *token_index += 2;
2692 } else if (mandatory) {
2693 ast_invalid_token_error(pc, first_token);
2694 } else {
2695 return nullptr;
2696 }
2697 } else if (first_token->id == TokenIdKeywordExport) {
2698 Token *next_token = &pc->tokens->at(*token_index + 1);
2699 if (next_token->id == TokenIdKeywordFn) {
2700 visib_mod = VisibModExport;
2701 *token_index += 2;
2702 } else if (mandatory) {
2703 ast_invalid_token_error(pc, first_token);
2704 } else {2656 } else {
2705 return nullptr;2657 return nullptr;
2706 }2658 }
2707 } else if (first_token->id == TokenIdKeywordFn) {
2708 visib_mod = VisibModPrivate;
2709 *token_index += 1;
2710 } else if (mandatory) {
2711 ast_invalid_token_error(pc, first_token);
2712 } else {
2713 return nullptr;
2714 }2659 }
2660 *token_index += 1;
27152661
2716 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);2662 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);
2717 node->data.fn_proto.visib_mod = visib_mod;2663 node->data.fn_proto.visib_mod = visib_mod;
2718 node->data.fn_proto.directives = pc->directive_list;2664 node->data.fn_proto.directives = directives;
2719 pc->directive_list = nullptr;
2720
27212665
2722 Token *fn_name = &pc->tokens->at(*token_index);2666 Token *fn_name = &pc->tokens->at(*token_index);
2723 *token_index += 1;2667 *token_index += 1;
...@@ -2743,107 +2687,59 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand...@@ -2743,107 +2687,59 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
2743/*2687/*
2744FnDef : FnProto Block2688FnDef : FnProto Block
2745*/2689*/
2746static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) {2690static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory,
2747 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory);2691 ZigList<AstNode*> *directives, VisibMod visib_mod)
2692{
2693 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod);
2748 if (!fn_proto)2694 if (!fn_proto)
2749 return nullptr;2695 return nullptr;
2750 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);2696 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);
27512697
2752 node->data.fn_def.fn_proto = fn_proto;2698 node->data.fn_def.fn_proto = fn_proto;
2753 node->data.fn_def.body = ast_parse_block(pc, token_index, true);2699 node->data.fn_def.body = ast_parse_block(pc, token_index, true);
2754
2755 normalize_parent_ptrs(node);
2756 return node;
2757}
2758
2759/*
2760FnDecl : FnProto token(Semicolon)
2761*/
2762static AstNode *ast_parse_fn_decl(ParseContext *pc, int *token_index) {
2763 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, true);
2764 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDecl, fn_proto);
2765
2766 node->data.fn_decl.fn_proto = fn_proto;
2767
2768 Token *semicolon = &pc->tokens->at(*token_index);
2769 *token_index += 1;
2770 ast_expect_token(pc, semicolon, TokenIdSemicolon);
2771
2772 normalize_parent_ptrs(node);2700 normalize_parent_ptrs(node);
2773 return node;2701 return node;
2774}2702}
27752703
2776/*2704/*
2777Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)2705ExternDecl : "extern" FnProto ";"
2778*/
2779/*
2780ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnProtoDecl) token(RBrace)
2781*/2706*/
2782static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool mandatory) {2707static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool mandatory,
2708 ZigList<AstNode *> *directives, VisibMod visib_mod)
2709{
2783 Token *extern_kw = &pc->tokens->at(*token_index);2710 Token *extern_kw = &pc->tokens->at(*token_index);
2784 if (extern_kw->id != TokenIdKeywordExtern) {2711 if (extern_kw->id != TokenIdKeywordExtern) {
2785 if (mandatory)2712 if (mandatory) {
2786 ast_invalid_token_error(pc, extern_kw);2713 ast_invalid_token_error(pc, extern_kw);
2787 else2714 } else {
2788 return nullptr;2715 return nullptr;
2716 }
2789 }2717 }
2790 *token_index += 1;2718 *token_index += 1;
27912719
2792 AstNode *node = ast_create_node(pc, NodeTypeExternBlock, extern_kw);2720 AstNode *node = ast_parse_fn_proto(pc, token_index, true, directives, visib_mod);
2793
2794 node->data.extern_block.directives = pc->directive_list;
2795 pc->directive_list = nullptr;
2796
2797 Token *l_brace = &pc->tokens->at(*token_index);
2798 *token_index += 1;
2799 ast_expect_token(pc, l_brace, TokenIdLBrace);
2800
2801 for (;;) {
2802 Token *directive_token = &pc->tokens->at(*token_index);
2803 assert(!pc->directive_list);
2804 pc->directive_list = allocate<ZigList<AstNode*>>(1);
2805 ast_parse_directives(pc, token_index, pc->directive_list);
2806
2807 Token *token = &pc->tokens->at(*token_index);
2808 if (token->id == TokenIdRBrace) {
2809 if (pc->directive_list->length > 0) {
2810 ast_error(pc, directive_token, "invalid directive");
2811 }
2812 pc->directive_list = nullptr;
2813
2814 *token_index += 1;
2815
2816 normalize_parent_ptrs(node);
2817 return node;
2818 } else {
2819 AstNode *child = ast_parse_fn_decl(pc, token_index);
2820 node->data.extern_block.fn_decls.append(child);
2821 }
2822 }
28232721
2722 ast_eat_token(pc, token_index, TokenIdSemicolon);
28242723
2825 zig_unreachable();2724 node->data.fn_proto.is_extern = true;
2725 normalize_parent_ptrs(node);
2726 return node;
2826}2727}
28272728
2828/*2729/*
2829RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon)2730RootExportDecl : "export" "Symbol" "String" ";"
2830*/2731*/
2831static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, bool mandatory) {2732static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index,
2832 assert(mandatory == false);2733 ZigList<AstNode*> *directives)
28332734{
2834 Token *export_kw = &pc->tokens->at(*token_index);2735 Token *export_type = &pc->tokens->at(*token_index);
2835 if (export_kw->id != TokenIdKeywordExport)
2836 return nullptr;
2837
2838 Token *export_type = &pc->tokens->at(*token_index + 1);
2839 if (export_type->id != TokenIdSymbol)2736 if (export_type->id != TokenIdSymbol)
2840 return nullptr;2737 return nullptr;
28412738
2842 *token_index += 2;2739 *token_index += 1;
28432740
2844 AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_kw);2741 AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_type);
2845 node->data.root_export_decl.directives = pc->directive_list;2742 node->data.root_export_decl.directives = directives;
2846 pc->directive_list = nullptr;
28472743
2848 ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type);2744 ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type);
28492745
...@@ -2862,11 +2758,13 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b...@@ -2862,11 +2758,13 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
2862}2758}
28632759
2864/*2760/*
2865Use : many(Directive) token(Use) token(String) token(Semicolon)2761Import : "import" "String" ";"
2866*/2762*/
2867static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {2763static AstNode *ast_parse_import(ParseContext *pc, int *token_index,
2868 Token *use_kw = &pc->tokens->at(*token_index);2764 ZigList<AstNode*> *directives, VisibMod visib_mod)
2869 if (use_kw->id != TokenIdKeywordImport)2765{
2766 Token *import_kw = &pc->tokens->at(*token_index);
2767 if (import_kw->id != TokenIdKeywordImport)
2870 return nullptr;2768 return nullptr;
2871 *token_index += 1;2769 *token_index += 1;
28722770
...@@ -2878,59 +2776,35 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {...@@ -2878,59 +2776,35 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
2878 *token_index += 1;2776 *token_index += 1;
2879 ast_expect_token(pc, semicolon, TokenIdSemicolon);2777 ast_expect_token(pc, semicolon, TokenIdSemicolon);
28802778
2881 AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);2779 AstNode *node = ast_create_node(pc, NodeTypeUse, import_kw);
2780 node->data.use.visib_mod = visib_mod;
2781 node->data.use.directives = directives;
28822782
2883 parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr);2783 parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr);
2884
2885 node->data.use.directives = pc->directive_list;
2886 pc->directive_list = nullptr;
2887
2888 normalize_parent_ptrs(node);2784 normalize_parent_ptrs(node);
2889 return node;2785 return node;
2890}2786}
28912787
2892/*2788/*
2893ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)2789ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}"
2894StructMember: StructField | FnDecl2790StructMember: many(Directive) option(VisibleMod) (StructField | FnDef)
2895StructField : token(Symbol) option(token(Colon) Expression) token(Comma))2791StructField : "Symbol" option(":" Expression) ",")
2896*/2792*/
2897static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {2793static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
2794 ZigList<AstNode*> *directives, VisibMod visib_mod)
2795{
2898 Token *first_token = &pc->tokens->at(*token_index);2796 Token *first_token = &pc->tokens->at(*token_index);
28992797
2900 VisibMod visib_mod;
2901 ContainerKind kind;2798 ContainerKind kind;
29022799
2903 if (first_token->id == TokenIdKeywordPub) {2800 if (first_token->id == TokenIdKeywordStruct) {
2904 Token *next_token = &pc->tokens->at(*token_index + 1);2801 kind = ContainerKindStruct;
2905 if (next_token->id == TokenIdKeywordStruct ||2802 } else if (first_token->id == TokenIdKeywordEnum) {
2906 next_token->id == TokenIdKeywordEnum)2803 kind = ContainerKindEnum;
2907 {
2908 visib_mod = VisibModPub;
2909 kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2910 *token_index += 2;
2911 } else {
2912 return nullptr;
2913 }
2914 } else if (first_token->id == TokenIdKeywordExport) {
2915 Token *next_token = &pc->tokens->at(*token_index + 1);
2916 if (next_token->id == TokenIdKeywordStruct ||
2917 next_token->id == TokenIdKeywordEnum)
2918 {
2919 visib_mod = VisibModExport;
2920 kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2921 *token_index += 2;
2922 } else {
2923 return nullptr;
2924 }
2925 } else if (first_token->id == TokenIdKeywordStruct ||
2926 first_token->id == TokenIdKeywordEnum)
2927 {
2928 visib_mod = VisibModPrivate;
2929 kind = (first_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum;
2930 *token_index += 1;
2931 } else {2804 } else {
2932 return nullptr;2805 return nullptr;
2933 }2806 }
2807 *token_index += 1;
29342808
2935 Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol);2809 Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol);
29362810
...@@ -2938,19 +2812,28 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2938,19 +2812,28 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2938 node->data.struct_decl.kind = kind;2812 node->data.struct_decl.kind = kind;
2939 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);2813 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);
2940 node->data.struct_decl.visib_mod = visib_mod;2814 node->data.struct_decl.visib_mod = visib_mod;
2815 node->data.struct_decl.directives = directives;
29412816
2942 ast_eat_token(pc, token_index, TokenIdLBrace);2817 ast_eat_token(pc, token_index, TokenIdLBrace);
29432818
2944 node->data.struct_decl.directives = pc->directive_list;
2945 pc->directive_list = nullptr;
2946
2947 for (;;) {2819 for (;;) {
2948 assert(!pc->directive_list);
2949 pc->directive_list = allocate<ZigList<AstNode*>>(1);
2950 Token *directive_token = &pc->tokens->at(*token_index);2820 Token *directive_token = &pc->tokens->at(*token_index);
2951 ast_parse_directives(pc, token_index, pc->directive_list);2821 ZigList<AstNode *> *directive_list = allocate<ZigList<AstNode*>>(1);
2822 ast_parse_directives(pc, token_index, directive_list);
2823
2824 Token *visib_tok = &pc->tokens->at(*token_index);
2825 VisibMod visib_mod;
2826 if (visib_tok->id == TokenIdKeywordPub) {
2827 *token_index += 1;
2828 visib_mod = VisibModPub;
2829 } else if (visib_tok->id == TokenIdKeywordExport) {
2830 *token_index += 1;
2831 visib_mod = VisibModExport;
2832 } else {
2833 visib_mod = VisibModPrivate;
2834 }
29522835
2953 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false);2836 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod);
2954 if (fn_def_node) {2837 if (fn_def_node) {
2955 node->data.struct_decl.fns.append(fn_def_node);2838 node->data.struct_decl.fns.append(fn_def_node);
2956 continue;2839 continue;
...@@ -2959,10 +2842,9 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2959,10 +2842,9 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2959 Token *token = &pc->tokens->at(*token_index);2842 Token *token = &pc->tokens->at(*token_index);
29602843
2961 if (token->id == TokenIdRBrace) {2844 if (token->id == TokenIdRBrace) {
2962 if (pc->directive_list->length > 0) {2845 if (directive_list->length > 0) {
2963 ast_error(pc, directive_token, "invalid directive");2846 ast_error(pc, directive_token, "invalid directive");
2964 }2847 }
2965 pc->directive_list = nullptr;
29662848
2967 *token_index += 1;2849 *token_index += 1;
2968 break;2850 break;
...@@ -2970,8 +2852,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2970,8 +2852,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2970 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);2852 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
2971 *token_index += 1;2853 *token_index += 1;
29722854
2973 field_node->data.struct_field.directives = pc->directive_list;2855 field_node->data.struct_field.visib_mod = visib_mod;
2974 pc->directive_list = nullptr;2856 field_node->data.struct_field.directives = directive_list;
29752857
2976 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);2858 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
29772859
...@@ -2997,47 +2879,24 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2997,47 +2879,24 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2997}2879}
29982880
2999/*2881/*
3000ErrorValueDecl : option(FnVisibleMod) "error" "Symbol"2882ErrorValueDecl : "error" "Symbol" ";"
3001*/2883*/
3002static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, bool mandatory) {2884static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,
2885 ZigList<AstNode*> *directives, VisibMod visib_mod)
2886{
3003 Token *first_token = &pc->tokens->at(*token_index);2887 Token *first_token = &pc->tokens->at(*token_index);
30042888
3005 VisibMod visib_mod;2889 if (first_token->id != TokenIdKeywordError) {
3006
3007 if (first_token->id == TokenIdKeywordPub) {
3008 Token *next_token = &pc->tokens->at(*token_index + 1);
3009 if (next_token->id == TokenIdKeywordError) {
3010 visib_mod = VisibModPub;
3011 *token_index += 2;
3012 } else if (mandatory) {
3013 ast_invalid_token_error(pc, next_token);
3014 } else {
3015 return nullptr;
3016 }
3017 } else if (first_token->id == TokenIdKeywordExport) {
3018 Token *next_token = &pc->tokens->at(*token_index + 1);
3019 if (next_token->id == TokenIdKeywordError) {
3020 visib_mod = VisibModExport;
3021 *token_index += 2;
3022 } else if (mandatory) {
3023 ast_invalid_token_error(pc, next_token);
3024 } else {
3025 return nullptr;
3026 }
3027 } else if (first_token->id == TokenIdKeywordError) {
3028 visib_mod = VisibModPrivate;
3029 *token_index += 1;
3030 } else if (mandatory) {
3031 ast_invalid_token_error(pc, first_token);
3032 } else {
3033 return nullptr;2890 return nullptr;
3034 }2891 }
2892 *token_index += 1;
30352893
3036 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);2894 Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
3037 ast_eat_token(pc, token_index, TokenIdSemicolon);2895 ast_eat_token(pc, token_index, TokenIdSemicolon);
30382896
3039 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);2897 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
3040 node->data.error_value_decl.visib_mod = visib_mod;2898 node->data.error_value_decl.visib_mod = visib_mod;
2899 node->data.error_value_decl.directives = directives;
3041 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);2900 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);
30422901
3043 normalize_parent_ptrs(node);2902 normalize_parent_ptrs(node);
...@@ -3045,63 +2904,79 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b...@@ -3045,63 +2904,79 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b
3045}2904}
30462905
3047/*2906/*
3048TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl2907TopLevelDecl : many(Directive) option(FnVisibleMod) (FnDef | ExternFnProto | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | CImportDecl)
3049*/2908*/
3050static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {2909static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
3051 for (;;) {2910 for (;;) {
3052 Token *directive_token = &pc->tokens->at(*token_index);2911 Token *directive_token = &pc->tokens->at(*token_index);
3053 assert(!pc->directive_list);2912 ZigList<AstNode *> *directives = allocate<ZigList<AstNode*>>(1);
3054 pc->directive_list = allocate<ZigList<AstNode*>>(1);2913 ast_parse_directives(pc, token_index, directives);
3055 ast_parse_directives(pc, token_index, pc->directive_list);
30562914
3057 AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, false);2915 Token *visib_tok = &pc->tokens->at(*token_index);
3058 if (root_export_decl_node) {2916 VisibMod visib_mod;
3059 top_level_decls->append(root_export_decl_node);2917 if (visib_tok->id == TokenIdKeywordPub) {
3060 continue;2918 *token_index += 1;
2919 visib_mod = VisibModPub;
2920 } else if (visib_tok->id == TokenIdKeywordExport) {
2921 *token_index += 1;
2922 visib_mod = VisibModExport;
2923 } else {
2924 visib_mod = VisibModPrivate;
3061 }2925 }
30622926
3063 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false);2927 bool try_to_parse_root_export = (visib_mod == VisibModExport && !pc->parsed_root_export);
2928 pc->parsed_root_export = true;
2929
2930 if (try_to_parse_root_export) {
2931 AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, directives);
2932 if (root_export_decl_node) {
2933 top_level_decls->append(root_export_decl_node);
2934 continue;
2935 }
2936 }
2937
2938 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);
3064 if (fn_def_node) {2939 if (fn_def_node) {
3065 top_level_decls->append(fn_def_node);2940 top_level_decls->append(fn_def_node);
3066 continue;2941 continue;
3067 }2942 }
30682943
3069 AstNode *extern_node = ast_parse_extern_block(pc, token_index, false);2944 AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, directives, visib_mod);
3070 if (extern_node) {2945 if (fn_proto_node) {
3071 top_level_decls->append(extern_node);2946 top_level_decls->append(fn_proto_node);
3072 continue;2947 continue;
3073 }2948 }
30742949
3075 AstNode *use_node = ast_parse_use(pc, token_index);2950 AstNode *import_node = ast_parse_import(pc, token_index, directives, visib_mod);
3076 if (use_node) {2951 if (import_node) {
3077 top_level_decls->append(use_node);2952 top_level_decls->append(import_node);
3078 continue;2953 continue;
3079 }2954 }
30802955
3081 AstNode *struct_node = ast_parse_struct_decl(pc, token_index);2956 AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod);
3082 if (struct_node) {2957 if (struct_node) {
3083 top_level_decls->append(struct_node);2958 top_level_decls->append(struct_node);
3084 continue;2959 continue;
3085 }2960 }
30862961
3087 if (pc->directive_list->length > 0) {2962 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false,
3088 ast_error(pc, directive_token, "invalid directive");2963 directives, visib_mod);
3089 }
3090 pc->directive_list = nullptr;
3091
3092 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false);
3093 if (var_decl_node) {2964 if (var_decl_node) {
3094 ast_eat_token(pc, token_index, TokenIdSemicolon);2965 ast_eat_token(pc, token_index, TokenIdSemicolon);
3095 top_level_decls->append(var_decl_node);2966 top_level_decls->append(var_decl_node);
3096 continue;2967 continue;
3097 }2968 }
30982969
3099 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, false);2970 AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, directives, visib_mod);
3100 if (error_value_node) {2971 if (error_value_node) {
3101 top_level_decls->append(error_value_node);2972 top_level_decls->append(error_value_node);
3102 continue;2973 continue;
3103 }2974 }
31042975
2976 if (directives->length > 0) {
2977 ast_error(pc, directive_token, "invalid directive");
2978 }
2979
3105 return;2980 return;
3106 }2981 }
3107 zig_unreachable();2982 zig_unreachable();
...@@ -3175,10 +3050,6 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -3175,10 +3050,6 @@ void normalize_parent_ptrs(AstNode *node) {
3175 case NodeTypeBlock:3050 case NodeTypeBlock:
3176 set_list_fields(&node->data.block.statements);3051 set_list_fields(&node->data.block.statements);
3177 break;3052 break;
3178 case NodeTypeExternBlock:
3179 set_list_fields(node->data.extern_block.directives);
3180 set_list_fields(&node->data.extern_block.fn_decls);
3181 break;
3182 case NodeTypeDirective:3053 case NodeTypeDirective:
3183 // none3054 // none
3184 break;3055 break;
test/run_tests.cpp+8-15
...@@ -97,10 +97,8 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source...@@ -97,10 +97,8 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
97static void add_compiling_test_cases(void) {97static void add_compiling_test_cases(void) {
98 add_simple_case("hello world with libc", R"SOURCE(98 add_simple_case("hello world with libc", R"SOURCE(
99#link("c")99#link("c")
100extern {100export executable "test";
101 fn puts(s: &const u8) -> c_int;101extern fn puts(s: &const u8) -> c_int;
102}
103
104export fn main(argc: c_int, argv: &&u8) -> c_int {102export fn main(argc: c_int, argv: &&u8) -> c_int {
105 puts(c"Hello, world!");103 puts(c"Hello, world!");
106 return 0;104 return 0;
...@@ -482,9 +480,8 @@ pub fn main(args: [][]u8) -> %void {...@@ -482,9 +480,8 @@ pub fn main(args: [][]u8) -> %void {
482480
483 add_simple_case("number literals", R"SOURCE(481 add_simple_case("number literals", R"SOURCE(
484#link("c")482#link("c")
485extern {483export executable "test";
486 fn printf(__format: &const u8, ...) -> c_int;484extern fn printf(__format: &const u8, ...) -> c_int;
487}
488485
489export fn main(argc: c_int, argv: &&u8) -> c_int {486export fn main(argc: c_int, argv: &&u8) -> c_int {
490 printf(c"\n");487 printf(c"\n");
...@@ -1321,13 +1318,11 @@ fn a() {}...@@ -1321,13 +1318,11 @@ fn a() {}
13211318
1322 add_compile_fail_case("bad directive", R"SOURCE(1319 add_compile_fail_case("bad directive", R"SOURCE(
1323#bogus1("")1320#bogus1("")
1324extern {1321extern fn b();
1325 fn b();
1326}
1327#bogus2("")1322#bogus2("")
1328fn a() {}1323fn a() {}
1329 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",1324 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
1330 ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");1325 ".tmp_source.zig:4:1: error: invalid directive: 'bogus2'");
13311326
1332 add_compile_fail_case("unreachable with return", R"SOURCE(1327 add_compile_fail_case("unreachable with return", R"SOURCE(
1333fn a() -> unreachable {return;}1328fn a() -> unreachable {return;}
...@@ -1668,11 +1663,9 @@ fn f() {...@@ -1668,11 +1663,9 @@ fn f() {
1668 )SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression");1663 )SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression");
16691664
1670 add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE(1665 add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE(
1671extern {1666extern fn foo() -> i32;
1672 fn foo() -> i32;
1673}
1674const x = foo();1667const x = foo();
1675 )SOURCE", 1, ".tmp_source.zig:5:11: error: global variable initializer requires constant expression");1668 )SOURCE", 1, ".tmp_source.zig:3:11: error: global variable initializer requires constant expression");
16761669
1677 add_compile_fail_case("non compile time string concatenation", R"SOURCE(1670 add_compile_fail_case("non compile time string concatenation", R"SOURCE(
1678fn f(s: []u8) -> []u8 {1671fn f(s: []u8) -> []u8 {