| ... | @@ -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 | }; |
| 490 | | 479 | |
| ... | @@ -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 | } |
| 2147 | | 2136 | |
| 2148 | /* | 2137 | /* |
| 2149 | VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression)) | 2138 | VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression)) |
| 2150 | */ | 2139 | */ |
| 2151 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) { | 2140 | static 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); |
| 2153 | | 2144 | |
| 2154 | VisibMod visib_mod; | | |
| 2155 | bool is_const; | 2145 | bool is_const; |
| 2156 | | 2146 | |
| 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 | } |
| 2194 | | 2156 | |
| | 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); |
| 2196 | | 2160 | |
| 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; |
| 2199 | | 2164 | |
| 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 | } |
| 2678 | | 2644 | |
| 2679 | /* | 2645 | /* |
| 2680 | FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression) | 2646 | FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression) |
| 2681 | */ | 2647 | */ |
| 2682 | static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) { | 2648 | static 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); |
| 2684 | | 2652 | |
| 2685 | VisibMod visib_mod; | 2653 | if (first_token->id != TokenIdKeywordFn) { |
| 2686 | | 2654 | 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; |
| 2715 | | 2661 | |
| 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 | | | |
| 2721 | | 2665 | |
| 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 | /* |
| 2744 | FnDef : FnProto Block | 2688 | FnDef : FnProto Block |
| 2745 | */ | 2689 | */ |
| 2746 | static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) { | 2690 | static 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); |
| 2751 | | 2697 | |
| 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 | /* | | |
| 2760 | FnDecl : FnProto token(Semicolon) | | |
| 2761 | */ | | |
| 2762 | static 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 | } |
| 2775 | | 2703 | |
| 2776 | /* | 2704 | /* |
| 2777 | Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen) | 2705 | ExternDecl : "extern" FnProto ";" |
| 2778 | */ | | |
| 2779 | /* | | |
| 2780 | ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnProtoDecl) token(RBrace) | | |
| 2781 | */ | 2706 | */ |
| 2782 | static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool mandatory) { | 2707 | static 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 | else | 2714 | } else { |
| 2788 | return nullptr; | 2715 | return nullptr; |
| | 2716 | } |
| 2789 | } | 2717 | } |
| 2790 | *token_index += 1; | 2718 | *token_index += 1; |
| 2791 | | 2719 | |
| 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 | } | | |
| 2823 | | 2721 | |
| | 2722 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2824 | | 2723 | |
| 2825 | zig_unreachable(); | 2724 | node->data.fn_proto.is_extern = true; |
| | 2725 | normalize_parent_ptrs(node); |
| | 2726 | return node; |
| 2826 | } | 2727 | } |
| 2827 | | 2728 | |
| 2828 | /* | 2729 | /* |
| 2829 | RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon) | 2730 | RootExportDecl : "export" "Symbol" "String" ";" |
| 2830 | */ | 2731 | */ |
| 2831 | static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, bool mandatory) { | 2732 | static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, |
| 2832 | assert(mandatory == false); | 2733 | ZigList<AstNode*> *directives) |
| 2833 | | 2734 | { |
| 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; |
| 2841 | | 2738 | |
| 2842 | *token_index += 2; | 2739 | *token_index += 1; |
| 2843 | | 2740 | |
| 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; | | |
| 2847 | | 2743 | |
| 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); |
| 2849 | | 2745 | |
| ... | @@ -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 | } |
| 2863 | | 2759 | |
| 2864 | /* | 2760 | /* |
| 2865 | Use : many(Directive) token(Use) token(String) token(Semicolon) | 2761 | Import : "import" "String" ";" |
| 2866 | */ | 2762 | */ |
| 2867 | static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { | 2763 | static 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; |
| 2872 | | 2770 | |
| ... | @@ -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); |
| 2880 | | 2778 | |
| 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; |
| 2882 | | 2782 | |
| 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 | } |
| 2891 | | 2787 | |
| 2892 | /* | 2788 | /* |
| 2893 | ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | 2789 | ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}" |
| 2894 | StructMember: StructField | FnDecl | 2790 | StructMember: many(Directive) option(VisibleMod) (StructField | FnDef) |
| 2895 | StructField : token(Symbol) option(token(Colon) Expression) token(Comma)) | 2791 | StructField : "Symbol" option(":" Expression) ",") |
| 2896 | */ | 2792 | */ |
| 2897 | static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { | 2793 | static 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); |
| 2899 | | 2797 | |
| 2900 | VisibMod visib_mod; | | |
| 2901 | ContainerKind kind; | 2798 | ContainerKind kind; |
| 2902 | | 2799 | |
| 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; |
| 2934 | | 2808 | |
| 2935 | Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol); | 2809 | Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 2936 | | 2810 | |
| ... | @@ -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; |
| 2941 | | 2816 | |
| 2942 | ast_eat_token(pc, token_index, TokenIdLBrace); | 2817 | ast_eat_token(pc, token_index, TokenIdLBrace); |
| 2943 | | 2818 | |
| 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 | } |
| 2952 | | 2835 | |
| 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); |
| 2960 | | 2843 | |
| 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; | | |
| 2966 | | 2848 | |
| 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; |
| 2972 | | 2854 | |
| 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; |
| 2975 | | 2857 | |
| 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); |
| 2977 | | 2859 | |
| ... | @@ -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 | } |
| 2998 | | 2880 | |
| 2999 | /* | 2881 | /* |
| 3000 | ErrorValueDecl : option(FnVisibleMod) "error" "Symbol" | 2882 | ErrorValueDecl : "error" "Symbol" ";" |
| 3001 | */ | 2883 | */ |
| 3002 | static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, bool mandatory) { | 2884 | static 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); |
| 3004 | | 2888 | |
| 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; |
| 3035 | | 2893 | |
| 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); |
| 3038 | | 2896 | |
| 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); |
| 3042 | | 2901 | |
| 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 | } |
| 3046 | | 2905 | |
| 3047 | /* | 2906 | /* |
| 3048 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | 2907 | TopLevelDecl : many(Directive) option(FnVisibleMod) (FnDef | ExternFnProto | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | CImportDecl) |
| 3049 | */ | 2908 | */ |
| 3050 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { | 2909 | static 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); | | |
| 3056 | | 2914 | |
| 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 | } |
| 3062 | | 2926 | |
| 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 | } |
| 3068 | | 2943 | |
| 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 | } |
| 3074 | | 2949 | |
| 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 | } |
| 3080 | | 2955 | |
| 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 | } |
| 3086 | | 2961 | |
| 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 | } |
| 3098 | | 2969 | |
| 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 | } |
| 3104 | | 2975 | |
| | 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 | // none | 3054 | // none |
| 3184 | break; | 3055 | break; |