diff options
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 135 |
1 files changed, 130 insertions, 5 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 31f9aadcd8..bcdb58b545 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -144,6 +144,10 @@ const char *node_type_str(NodeType node_type) { return "StructDecl"; case NodeTypeStructField: return "StructField"; + case NodeTypeEnumDecl: + return "EnumDecl"; + case NodeTypeEnumField: + return "EnumField"; case NodeTypeStructValueExpr: return "StructValueExpr"; case NodeTypeStructValueField: @@ -429,6 +433,24 @@ void ast_print(AstNode *node, int indent) { fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name)); ast_print(node->data.struct_field.type, indent + 2); break; + case NodeTypeEnumDecl: + fprintf(stderr, "%s '%s'\n", + node_type_str(node->type), buf_ptr(&node->data.enum_decl.name)); + for (int i = 0; i < node->data.enum_decl.fields.length; i += 1) { + AstNode *child = node->data.enum_decl.fields.at(i); + ast_print(child, indent + 2); + } + break; + case NodeTypeEnumField: + fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.enum_field.name)); + if (node->data.enum_field.val_expr) { + ast_print(node->data.enum_field.val_expr, indent + 2); + } + for (int i = 0; i < node->data.enum_field.fields.length; i += 1) { + AstNode *child = node->data.enum_field.fields.at(i); + ast_print(child, indent + 2); + } + break; case NodeTypeStructValueExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); ast_print(node->data.struct_val_expr.type, indent + 2); @@ -2705,7 +2727,106 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { } /* -StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) +EnumDecl : many(Directive) option(FnVisibleMod) token(Enum) token(Symbol) token(LBrace) many(EnumField) token(RBrace) +EnumField : (EnumDiscriminant | StructPayload) token(Comma) +EnumDiscriminant : token(Symbol) option(token(Eq) Expression) +*/ +static AstNode *ast_parse_enum_decl(ParseContext *pc, int *token_index) { + Token *first_token = &pc->tokens->at(*token_index); + + VisibMod visib_mod; + if (first_token->id == TokenIdKeywordPub) { + Token *next_token = &pc->tokens->at(*token_index + 1); + if (next_token->id == TokenIdKeywordEnum) { + visib_mod = VisibModPub; + *token_index += 2; + } else { + return nullptr; + } + } else if (first_token->id == TokenIdKeywordExport) { + Token *next_token = &pc->tokens->at(*token_index + 1); + if (next_token->id == TokenIdKeywordEnum) { + visib_mod = VisibModExport; + *token_index += 2; + } else { + return nullptr; + } + } else if (first_token->id == TokenIdKeywordEnum) { + visib_mod = VisibModPrivate; + *token_index += 1; + } else { + return nullptr; + } + + Token *enum_name = ast_eat_token(pc, token_index, TokenIdSymbol); + AstNode *node = ast_create_node(pc, NodeTypeEnumDecl, first_token); + ast_buf_from_token(pc, enum_name, &node->data.enum_decl.name); + node->data.enum_decl.visib_mod = visib_mod; + + node->data.enum_decl.directives = pc->directive_list; + pc->directive_list = nullptr; + + ast_eat_token(pc, token_index, TokenIdLBrace); + + for (;;) { + Token *token = &pc->tokens->at(*token_index); + + if (token->id == TokenIdRBrace) { + *token_index += 1; + break; + } else if (token->id == TokenIdSymbol) { + AstNode *field_node = ast_create_node(pc, NodeTypeEnumField, token); + *token_index += 1; + + ast_buf_from_token(pc, token, &field_node->data.enum_field.name); + + Token *eq_tok = &pc->tokens->at(*token_index); + if (eq_tok->id == TokenIdEq) { + *token_index += 1; + + field_node->data.enum_field.val_expr = ast_parse_expression(pc, token_index, true); + } else if (eq_tok->id == TokenIdLBrace) { + *token_index += 1; + + for (;;) { + Token *token = &pc->tokens->at(*token_index); + + if (token->id == TokenIdRBrace) { + *token_index += 1; + break; + } else if (token->id == TokenIdSymbol) { + AstNode *sub_field_node = ast_create_node(pc, NodeTypeStructField, token); + *token_index += 1; + + ast_buf_from_token(pc, token, &sub_field_node->data.struct_field.name); + + ast_eat_token(pc, token_index, TokenIdColon); + + sub_field_node->data.struct_field.type = ast_parse_type(pc, token_index); + + ast_eat_token(pc, token_index, TokenIdComma); + + field_node->data.enum_decl.fields.append(sub_field_node); + } else { + ast_invalid_token_error(pc, token); + } + } + } + + ast_eat_token(pc, token_index, TokenIdComma); + + node->data.enum_decl.fields.append(field_node); + } else { + ast_invalid_token_error(pc, token); + } + } + + return node; +} + +/* +StructDecl : many(Directive) option(FnVisibleMod) token(Struct) StructPayload +StructPayload: token(Symbol) token(LBrace) many(StructMember) token(RBrace) StructMember: StructField | FnDecl StructField : token(Symbol) token(Colon) Type token(Comma) */ @@ -2737,9 +2858,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { return nullptr; } - Token *struct_name = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, struct_name, TokenIdSymbol); + Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol); AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token); 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) { } /* -TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration +TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | EnumDecl */ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) { for (;;) { @@ -2837,6 +2956,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis continue; } + AstNode *enum_node = ast_parse_enum_decl(pc, token_index); + if (enum_node) { + top_level_decls->append(enum_node); + continue; + } + if (pc->directive_list->length > 0) { ast_error(pc, directive_token, "invalid directive"); } |
