| author | |
| committer | |
| log | d4b8852d784b6f180e5329efa8d418397ee7f1ef |
| tree | d281a93575cd30dcf4c30339a8c5cfa312fa3828 |
| parent | 75d57866035a5e27a7e62f7cfabbc899affd3e8b |
7 files changed, 190 insertions(+), 16 deletions(-)
doc/langref.md+13-3| ... | @@ -32,16 +32,24 @@ zig | C equivalent | Description | ... | @@ -32,16 +32,24 @@ zig | C equivalent | Description |
| 32 | ``` | 32 | ``` |
| 33 | Root : many(TopLevelDecl) token(EOF) | 33 | Root : many(TopLevelDecl) token(EOF) |
| 34 | 34 | ||
| 35 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | 35 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | EnumDecl |
| 36 | 36 | ||
| 37 | VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression)) | 37 | VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression)) |
| 38 | 38 | ||
| 39 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | 39 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) StructPayload |
| 40 | |||
| 41 | StructPayload: token(Symbol) token(LBrace) many(StructMember) token(RBrace) | ||
| 42 | |||
| 43 | EnumDecl : many(Directive) option(FnVisibleMod) token(Enum) token(Symbol) token(LBrace) many(EnumField) token(RBrace) | ||
| 40 | 44 | ||
| 41 | StructMember: StructField | FnDecl | 45 | StructMember: StructField | FnDecl |
| 42 | 46 | ||
| 43 | StructField : token(Symbol) token(Colon) Type token(Comma) | 47 | StructField : token(Symbol) token(Colon) Type token(Comma) |
| 44 | 48 | ||
| 49 | EnumField : (EnumDiscriminant | StructPayload) token(Comma) | ||
| 50 | |||
| 51 | EnumDiscriminant : token(Symbol) option(token(Eq) Expression) | ||
| 52 | |||
| 45 | Use : many(Directive) token(Use) token(String) token(Semicolon) | 53 | Use : many(Directive) token(Use) token(String) token(Semicolon) |
| 46 | 54 | ||
| 47 | RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon) | 55 | RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon) |
| ... | @@ -160,7 +168,9 @@ SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) | ... | @@ -160,7 +168,9 @@ SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) |
| 160 | 168 | ||
| 161 | PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const))) | 169 | PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const))) |
| 162 | 170 | ||
| 163 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression) | 171 | PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression) | NamespaceSymbol |
| 172 | |||
| 173 | NamespaceSymbol : token(Symbol) token(ColonColon) token(Symbol) | ||
| 164 | 174 | ||
| 165 | StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace) | 175 | StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace) |
| 166 | 176 |
src/analyze.cpp+24-8| ... | @@ -63,6 +63,8 @@ static AstNode *first_executing_node(AstNode *node) { | ... | @@ -63,6 +63,8 @@ static AstNode *first_executing_node(AstNode *node) { |
| 63 | case NodeTypeAsmExpr: | 63 | case NodeTypeAsmExpr: |
| 64 | case NodeTypeStructDecl: | 64 | case NodeTypeStructDecl: |
| 65 | case NodeTypeStructField: | 65 | case NodeTypeStructField: |
| 66 | case NodeTypeEnumDecl: | ||
| 67 | case NodeTypeEnumField: | ||
| 66 | case NodeTypeStructValueExpr: | 68 | case NodeTypeStructValueExpr: |
| 67 | case NodeTypeStructValueField: | 69 | case NodeTypeStructValueField: |
| 68 | case NodeTypeWhileExpr: | 70 | case NodeTypeWhileExpr: |
| ... | @@ -894,6 +896,11 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -894,6 +896,11 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 894 | // struct member fns will get resolved independently | 896 | // struct member fns will get resolved independently |
| 895 | break; | 897 | break; |
| 896 | } | 898 | } |
| 899 | case NodeTypeEnumDecl: | ||
| 900 | { | ||
| 901 | zig_panic("TODO resolve enum decl"); | ||
| 902 | break; | ||
| 903 | } | ||
| 897 | case NodeTypeVariableDeclaration: | 904 | case NodeTypeVariableDeclaration: |
| 898 | { | 905 | { |
| 899 | VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context, | 906 | VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context, |
| ... | @@ -936,6 +943,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -936,6 +943,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 936 | case NodeTypeAsmExpr: | 943 | case NodeTypeAsmExpr: |
| 937 | case NodeTypeFieldAccessExpr: | 944 | case NodeTypeFieldAccessExpr: |
| 938 | case NodeTypeStructField: | 945 | case NodeTypeStructField: |
| 946 | case NodeTypeEnumField: | ||
| 939 | case NodeTypeStructValueExpr: | 947 | case NodeTypeStructValueExpr: |
| 940 | case NodeTypeStructValueField: | 948 | case NodeTypeStructValueField: |
| 941 | case NodeTypeCompilerFnExpr: | 949 | case NodeTypeCompilerFnExpr: |
| ... | @@ -2490,6 +2498,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -2490,6 +2498,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2490 | case NodeTypeLabel: | 2498 | case NodeTypeLabel: |
| 2491 | case NodeTypeStructDecl: | 2499 | case NodeTypeStructDecl: |
| 2492 | case NodeTypeStructField: | 2500 | case NodeTypeStructField: |
| 2501 | case NodeTypeEnumDecl: | ||
| 2502 | case NodeTypeEnumField: | ||
| 2493 | case NodeTypeStructValueField: | 2503 | case NodeTypeStructValueField: |
| 2494 | case NodeTypeCompilerFnExpr: | 2504 | case NodeTypeCompilerFnExpr: |
| 2495 | zig_unreachable(); | 2505 | zig_unreachable(); |
| ... | @@ -2589,13 +2599,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2589,13 +2599,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2589 | case NodeTypeFnDef: | 2599 | case NodeTypeFnDef: |
| 2590 | analyze_top_level_fn_def(g, import, node); | 2600 | analyze_top_level_fn_def(g, import, node); |
| 2591 | break; | 2601 | break; |
| 2592 | case NodeTypeRootExportDecl: | ||
| 2593 | case NodeTypeExternBlock: | ||
| 2594 | // already looked at these in the preview pass | ||
| 2595 | break; | ||
| 2596 | case NodeTypeUse: | ||
| 2597 | // already took care of this | ||
| 2598 | break; | ||
| 2599 | case NodeTypeStructDecl: | 2602 | case NodeTypeStructDecl: |
| 2600 | { | 2603 | { |
| 2601 | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { | 2604 | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { |
| ... | @@ -2604,8 +2607,12 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2604,8 +2607,12 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2604 | } | 2607 | } |
| 2605 | break; | 2608 | break; |
| 2606 | } | 2609 | } |
| 2610 | case NodeTypeRootExportDecl: | ||
| 2611 | case NodeTypeExternBlock: | ||
| 2612 | case NodeTypeUse: | ||
| 2613 | case NodeTypeEnumDecl: | ||
| 2607 | case NodeTypeVariableDeclaration: | 2614 | case NodeTypeVariableDeclaration: |
| 2608 | // handled in resolve phase | 2615 | // already took care of these |
| 2609 | break; | 2616 | break; |
| 2610 | case NodeTypeDirective: | 2617 | case NodeTypeDirective: |
| 2611 | case NodeTypeParamDecl: | 2618 | case NodeTypeParamDecl: |
| ... | @@ -2639,6 +2646,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2639,6 +2646,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 2639 | case NodeTypeAsmExpr: | 2646 | case NodeTypeAsmExpr: |
| 2640 | case NodeTypeFieldAccessExpr: | 2647 | case NodeTypeFieldAccessExpr: |
| 2641 | case NodeTypeStructField: | 2648 | case NodeTypeStructField: |
| 2649 | case NodeTypeEnumField: | ||
| 2642 | case NodeTypeStructValueExpr: | 2650 | case NodeTypeStructValueExpr: |
| 2643 | case NodeTypeStructValueField: | 2651 | case NodeTypeStructValueField: |
| 2644 | case NodeTypeCompilerFnExpr: | 2652 | case NodeTypeCompilerFnExpr: |
| ... | @@ -2772,6 +2780,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -2772,6 +2780,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 2772 | case NodeTypeLabel: | 2780 | case NodeTypeLabel: |
| 2773 | case NodeTypeStructDecl: | 2781 | case NodeTypeStructDecl: |
| 2774 | case NodeTypeStructField: | 2782 | case NodeTypeStructField: |
| 2783 | case NodeTypeEnumDecl: | ||
| 2784 | case NodeTypeEnumField: | ||
| 2775 | case NodeTypeStructValueField: | 2785 | case NodeTypeStructValueField: |
| 2776 | zig_unreachable(); | 2786 | zig_unreachable(); |
| 2777 | } | 2787 | } |
| ... | @@ -2879,6 +2889,11 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2879,6 +2889,11 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2879 | detect_top_level_decl_deps(g, import, fn_def_node); | 2889 | detect_top_level_decl_deps(g, import, fn_def_node); |
| 2880 | } | 2890 | } |
| 2881 | 2891 | ||
| 2892 | break; | ||
| 2893 | } | ||
| 2894 | case NodeTypeEnumDecl: | ||
| 2895 | { | ||
| 2896 | zig_panic("TODO detect enum top level decl deps"); | ||
| 2882 | break; | 2897 | break; |
| 2883 | } | 2898 | } |
| 2884 | case NodeTypeExternBlock: | 2899 | case NodeTypeExternBlock: |
| ... | @@ -2974,6 +2989,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -2974,6 +2989,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 2974 | case NodeTypeAsmExpr: | 2989 | case NodeTypeAsmExpr: |
| 2975 | case NodeTypeFieldAccessExpr: | 2990 | case NodeTypeFieldAccessExpr: |
| 2976 | case NodeTypeStructField: | 2991 | case NodeTypeStructField: |
| 2992 | case NodeTypeEnumField: | ||
| 2977 | case NodeTypeStructValueExpr: | 2993 | case NodeTypeStructValueExpr: |
| 2978 | case NodeTypeStructValueField: | 2994 | case NodeTypeStructValueField: |
| 2979 | case NodeTypeCompilerFnExpr: | 2995 | case NodeTypeCompilerFnExpr: |
src/codegen.cpp+2| ... | @@ -1754,6 +1754,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1754,6 +1754,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1754 | case NodeTypeUse: | 1754 | case NodeTypeUse: |
| 1755 | case NodeTypeStructDecl: | 1755 | case NodeTypeStructDecl: |
| 1756 | case NodeTypeStructField: | 1756 | case NodeTypeStructField: |
| 1757 | case NodeTypeEnumDecl: | ||
| 1758 | case NodeTypeEnumField: | ||
| 1757 | case NodeTypeStructValueField: | 1759 | case NodeTypeStructValueField: |
| 1758 | case NodeTypeCompilerFnExpr: | 1760 | case NodeTypeCompilerFnExpr: |
| 1759 | zig_unreachable(); | 1761 | zig_unreachable(); |
src/parser.cpp+130-5| ... | @@ -144,6 +144,10 @@ const char *node_type_str(NodeType node_type) { | ... | @@ -144,6 +144,10 @@ const char *node_type_str(NodeType node_type) { |
| 144 | return "StructDecl"; | 144 | return "StructDecl"; |
| 145 | case NodeTypeStructField: | 145 | case NodeTypeStructField: |
| 146 | return "StructField"; | 146 | return "StructField"; |
| 147 | case NodeTypeEnumDecl: | ||
| 148 | return "EnumDecl"; | ||
| 149 | case NodeTypeEnumField: | ||
| 150 | return "EnumField"; | ||
| 147 | case NodeTypeStructValueExpr: | 151 | case NodeTypeStructValueExpr: |
| 148 | return "StructValueExpr"; | 152 | return "StructValueExpr"; |
| 149 | case NodeTypeStructValueField: | 153 | case NodeTypeStructValueField: |
| ... | @@ -429,6 +433,24 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -429,6 +433,24 @@ void ast_print(AstNode *node, int indent) { |
| 429 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name)); | 433 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name)); |
| 430 | ast_print(node->data.struct_field.type, indent + 2); | 434 | ast_print(node->data.struct_field.type, indent + 2); |
| 431 | break; | 435 | break; |
| 436 | case NodeTypeEnumDecl: | ||
| 437 | fprintf(stderr, "%s '%s'\n", | ||
| 438 | node_type_str(node->type), buf_ptr(&node->data.enum_decl.name)); | ||
| 439 | for (int i = 0; i < node->data.enum_decl.fields.length; i += 1) { | ||
| 440 | AstNode *child = node->data.enum_decl.fields.at(i); | ||
| 441 | ast_print(child, indent + 2); | ||
| 442 | } | ||
| 443 | break; | ||
| 444 | case NodeTypeEnumField: | ||
| 445 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.enum_field.name)); | ||
| 446 | if (node->data.enum_field.val_expr) { | ||
| 447 | ast_print(node->data.enum_field.val_expr, indent + 2); | ||
| 448 | } | ||
| 449 | for (int i = 0; i < node->data.enum_field.fields.length; i += 1) { | ||
| 450 | AstNode *child = node->data.enum_field.fields.at(i); | ||
| 451 | ast_print(child, indent + 2); | ||
| 452 | } | ||
| 453 | break; | ||
| 432 | case NodeTypeStructValueExpr: | 454 | case NodeTypeStructValueExpr: |
| 433 | fprintf(stderr, "%s\n", node_type_str(node->type)); | 455 | fprintf(stderr, "%s\n", node_type_str(node->type)); |
| 434 | ast_print(node->data.struct_val_expr.type, indent + 2); | 456 | ast_print(node->data.struct_val_expr.type, indent + 2); |
| ... | @@ -2705,7 +2727,106 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { | ... | @@ -2705,7 +2727,106 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { |
| 2705 | } | 2727 | } |
| 2706 | 2728 | ||
| 2707 | /* | 2729 | /* |
| 2708 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | 2730 | EnumDecl : many(Directive) option(FnVisibleMod) token(Enum) token(Symbol) token(LBrace) many(EnumField) token(RBrace) |
| 2731 | EnumField : (EnumDiscriminant | StructPayload) token(Comma) | ||
| 2732 | EnumDiscriminant : token(Symbol) option(token(Eq) Expression) | ||
| 2733 | */ | ||
| 2734 | static AstNode *ast_parse_enum_decl(ParseContext *pc, int *token_index) { | ||
| 2735 | Token *first_token = &pc->tokens->at(*token_index); | ||
| 2736 | |||
| 2737 | VisibMod visib_mod; | ||
| 2738 | if (first_token->id == TokenIdKeywordPub) { | ||
| 2739 | Token *next_token = &pc->tokens->at(*token_index + 1); | ||
| 2740 | if (next_token->id == TokenIdKeywordEnum) { | ||
| 2741 | visib_mod = VisibModPub; | ||
| 2742 | *token_index += 2; | ||
| 2743 | } else { | ||
| 2744 | return nullptr; | ||
| 2745 | } | ||
| 2746 | } else if (first_token->id == TokenIdKeywordExport) { | ||
| 2747 | Token *next_token = &pc->tokens->at(*token_index + 1); | ||
| 2748 | if (next_token->id == TokenIdKeywordEnum) { | ||
| 2749 | visib_mod = VisibModExport; | ||
| 2750 | *token_index += 2; | ||
| 2751 | } else { | ||
| 2752 | return nullptr; | ||
| 2753 | } | ||
| 2754 | } else if (first_token->id == TokenIdKeywordEnum) { | ||
| 2755 | visib_mod = VisibModPrivate; | ||
| 2756 | *token_index += 1; | ||
| 2757 | } else { | ||
| 2758 | return nullptr; | ||
| 2759 | } | ||
| 2760 | |||
| 2761 | Token *enum_name = ast_eat_token(pc, token_index, TokenIdSymbol); | ||
| 2762 | AstNode *node = ast_create_node(pc, NodeTypeEnumDecl, first_token); | ||
| 2763 | ast_buf_from_token(pc, enum_name, &node->data.enum_decl.name); | ||
| 2764 | node->data.enum_decl.visib_mod = visib_mod; | ||
| 2765 | |||
| 2766 | node->data.enum_decl.directives = pc->directive_list; | ||
| 2767 | pc->directive_list = nullptr; | ||
| 2768 | |||
| 2769 | ast_eat_token(pc, token_index, TokenIdLBrace); | ||
| 2770 | |||
| 2771 | for (;;) { | ||
| 2772 | Token *token = &pc->tokens->at(*token_index); | ||
| 2773 | |||
| 2774 | if (token->id == TokenIdRBrace) { | ||
| 2775 | *token_index += 1; | ||
| 2776 | break; | ||
| 2777 | } else if (token->id == TokenIdSymbol) { | ||
| 2778 | AstNode *field_node = ast_create_node(pc, NodeTypeEnumField, token); | ||
| 2779 | *token_index += 1; | ||
| 2780 | |||
| 2781 | ast_buf_from_token(pc, token, &field_node->data.enum_field.name); | ||
| 2782 | |||
| 2783 | Token *eq_tok = &pc->tokens->at(*token_index); | ||
| 2784 | if (eq_tok->id == TokenIdEq) { | ||
| 2785 | *token_index += 1; | ||
| 2786 | |||
| 2787 | field_node->data.enum_field.val_expr = ast_parse_expression(pc, token_index, true); | ||
| 2788 | } else if (eq_tok->id == TokenIdLBrace) { | ||
| 2789 | *token_index += 1; | ||
| 2790 | |||
| 2791 | for (;;) { | ||
| 2792 | Token *token = &pc->tokens->at(*token_index); | ||
| 2793 | |||
| 2794 | if (token->id == TokenIdRBrace) { | ||
| 2795 | *token_index += 1; | ||
| 2796 | break; | ||
| 2797 | } else if (token->id == TokenIdSymbol) { | ||
| 2798 | AstNode *sub_field_node = ast_create_node(pc, NodeTypeStructField, token); | ||
| 2799 | *token_index += 1; | ||
| 2800 | |||
| 2801 | ast_buf_from_token(pc, token, &sub_field_node->data.struct_field.name); | ||
| 2802 | |||
| 2803 | ast_eat_token(pc, token_index, TokenIdColon); | ||
| 2804 | |||
| 2805 | sub_field_node->data.struct_field.type = ast_parse_type(pc, token_index); | ||
| 2806 | |||
| 2807 | ast_eat_token(pc, token_index, TokenIdComma); | ||
| 2808 | |||
| 2809 | field_node->data.enum_decl.fields.append(sub_field_node); | ||
| 2810 | } else { | ||
| 2811 | ast_invalid_token_error(pc, token); | ||
| 2812 | } | ||
| 2813 | } | ||
| 2814 | } | ||
| 2815 | |||
| 2816 | ast_eat_token(pc, token_index, TokenIdComma); | ||
| 2817 | |||
| 2818 | node->data.enum_decl.fields.append(field_node); | ||
| 2819 | } else { | ||
| 2820 | ast_invalid_token_error(pc, token); | ||
| 2821 | } | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | return node; | ||
| 2825 | } | ||
| 2826 | |||
| 2827 | /* | ||
| 2828 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) StructPayload | ||
| 2829 | StructPayload: token(Symbol) token(LBrace) many(StructMember) token(RBrace) | ||
| 2709 | StructMember: StructField | FnDecl | 2830 | StructMember: StructField | FnDecl |
| 2710 | StructField : token(Symbol) token(Colon) Type token(Comma) | 2831 | StructField : token(Symbol) token(Colon) Type token(Comma) |
| 2711 | */ | 2832 | */ |
| ... | @@ -2737,9 +2858,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { | ... | @@ -2737,9 +2858,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { |
| 2737 | return nullptr; | 2858 | return nullptr; |
| 2738 | } | 2859 | } |
| 2739 | 2860 | ||
| 2740 | Token *struct_name = &pc->tokens->at(*token_index); | 2861 | Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 2741 | *token_index += 1; | ||
| 2742 | ast_expect_token(pc, struct_name, TokenIdSymbol); | ||
| 2743 | 2862 | ||
| 2744 | AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token); | 2863 | AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token); |
| 2745 | ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name); | 2864 | ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name); |
| ... | @@ -2798,7 +2917,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { | ... | @@ -2798,7 +2917,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { |
| 2798 | } | 2917 | } |
| 2799 | 2918 | ||
| 2800 | /* | 2919 | /* |
| 2801 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | 2920 | TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | EnumDecl |
| 2802 | */ | 2921 | */ |
| 2803 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { | 2922 | static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2804 | for (;;) { | 2923 | for (;;) { |
| ... | @@ -2837,6 +2956,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis | ... | @@ -2837,6 +2956,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2837 | continue; | 2956 | continue; |
| 2838 | } | 2957 | } |
| 2839 | 2958 | ||
| 2959 | AstNode *enum_node = ast_parse_enum_decl(pc, token_index); | ||
| 2960 | if (enum_node) { | ||
| 2961 | top_level_decls->append(enum_node); | ||
| 2962 | continue; | ||
| 2963 | } | ||
| 2964 | |||
| 2840 | if (pc->directive_list->length > 0) { | 2965 | if (pc->directive_list->length > 0) { |
| 2841 | ast_error(pc, directive_token, "invalid directive"); | 2966 | ast_error(pc, directive_token, "invalid directive"); |
| 2842 | } | 2967 | } |
src/parser.hpp+17| ... | @@ -59,6 +59,8 @@ enum NodeType { | ... | @@ -59,6 +59,8 @@ enum NodeType { |
| 59 | NodeTypeStructField, | 59 | NodeTypeStructField, |
| 60 | NodeTypeStructValueExpr, | 60 | NodeTypeStructValueExpr, |
| 61 | NodeTypeStructValueField, | 61 | NodeTypeStructValueField, |
| 62 | NodeTypeEnumDecl, | ||
| 63 | NodeTypeEnumField, | ||
| 62 | NodeTypeCompilerFnExpr, | 64 | NodeTypeCompilerFnExpr, |
| 63 | NodeTypeCompilerFnType, | 65 | NodeTypeCompilerFnType, |
| 64 | }; | 66 | }; |
| ... | @@ -316,6 +318,19 @@ struct AstNodeStructField { | ... | @@ -316,6 +318,19 @@ struct AstNodeStructField { |
| 316 | ZigList<AstNode *> *directives; | 318 | ZigList<AstNode *> *directives; |
| 317 | }; | 319 | }; |
| 318 | 320 | ||
| 321 | struct AstNodeEnumDecl { | ||
| 322 | Buf name; | ||
| 323 | ZigList<AstNode *> fields; | ||
| 324 | ZigList<AstNode *> *directives; | ||
| 325 | VisibMod visib_mod; | ||
| 326 | }; | ||
| 327 | |||
| 328 | struct AstNodeEnumField { | ||
| 329 | Buf name; | ||
| 330 | ZigList<AstNode *> fields; // length 0 means simple enum | ||
| 331 | AstNode *val_expr; | ||
| 332 | }; | ||
| 333 | |||
| 319 | struct AstNodeStringLiteral { | 334 | struct AstNodeStringLiteral { |
| 320 | Buf buf; | 335 | Buf buf; |
| 321 | bool c; | 336 | bool c; |
| ... | @@ -411,6 +426,8 @@ struct AstNode { | ... | @@ -411,6 +426,8 @@ struct AstNode { |
| 411 | AstNodeFieldAccessExpr field_access_expr; | 426 | AstNodeFieldAccessExpr field_access_expr; |
| 412 | AstNodeStructDecl struct_decl; | 427 | AstNodeStructDecl struct_decl; |
| 413 | AstNodeStructField struct_field; | 428 | AstNodeStructField struct_field; |
| 429 | AstNodeEnumDecl enum_decl; | ||
| 430 | AstNodeEnumField enum_field; | ||
| 414 | AstNodeStringLiteral string_literal; | 431 | AstNodeStringLiteral string_literal; |
| 415 | AstNodeCharLiteral char_literal; | 432 | AstNodeCharLiteral char_literal; |
| 416 | AstNodeNumberLiteral number_literal; | 433 | AstNodeNumberLiteral number_literal; |
src/tokenizer.cpp+3| ... | @@ -235,6 +235,8 @@ static void end_token(Tokenize *t) { | ... | @@ -235,6 +235,8 @@ static void end_token(Tokenize *t) { |
| 235 | t->cur_tok->id = TokenIdKeywordAsm; | 235 | t->cur_tok->id = TokenIdKeywordAsm; |
| 236 | } else if (mem_eql_str(token_mem, token_len, "struct")) { | 236 | } else if (mem_eql_str(token_mem, token_len, "struct")) { |
| 237 | t->cur_tok->id = TokenIdKeywordStruct; | 237 | t->cur_tok->id = TokenIdKeywordStruct; |
| 238 | } else if (mem_eql_str(token_mem, token_len, "enum")) { | ||
| 239 | t->cur_tok->id = TokenIdKeywordEnum; | ||
| 238 | } else if (mem_eql_str(token_mem, token_len, "while")) { | 240 | } else if (mem_eql_str(token_mem, token_len, "while")) { |
| 239 | t->cur_tok->id = TokenIdKeywordWhile; | 241 | t->cur_tok->id = TokenIdKeywordWhile; |
| 240 | } else if (mem_eql_str(token_mem, token_len, "continue")) { | 242 | } else if (mem_eql_str(token_mem, token_len, "continue")) { |
| ... | @@ -1021,6 +1023,7 @@ static const char * token_name(Token *token) { | ... | @@ -1021,6 +1023,7 @@ static const char * token_name(Token *token) { |
| 1021 | case TokenIdKeywordVolatile: return "Volatile"; | 1023 | case TokenIdKeywordVolatile: return "Volatile"; |
| 1022 | case TokenIdKeywordAsm: return "Asm"; | 1024 | case TokenIdKeywordAsm: return "Asm"; |
| 1023 | case TokenIdKeywordStruct: return "Struct"; | 1025 | case TokenIdKeywordStruct: return "Struct"; |
| 1026 | case TokenIdKeywordEnum: return "Enum"; | ||
| 1024 | case TokenIdKeywordWhile: return "While"; | 1027 | case TokenIdKeywordWhile: return "While"; |
| 1025 | case TokenIdKeywordContinue: return "Continue"; | 1028 | case TokenIdKeywordContinue: return "Continue"; |
| 1026 | case TokenIdKeywordBreak: return "Break"; | 1029 | case TokenIdKeywordBreak: return "Break"; |
src/tokenizer.hpp+1| ... | @@ -32,6 +32,7 @@ enum TokenId { | ... | @@ -32,6 +32,7 @@ enum TokenId { |
| 32 | TokenIdKeywordAsm, | 32 | TokenIdKeywordAsm, |
| 33 | TokenIdKeywordVolatile, | 33 | TokenIdKeywordVolatile, |
| 34 | TokenIdKeywordStruct, | 34 | TokenIdKeywordStruct, |
| 35 | TokenIdKeywordEnum, | ||
| 35 | TokenIdKeywordWhile, | 36 | TokenIdKeywordWhile, |
| 36 | TokenIdKeywordContinue, | 37 | TokenIdKeywordContinue, |
| 37 | TokenIdKeywordBreak, | 38 | TokenIdKeywordBreak, |