parsing enum declarations

This commit is contained in:
Andrew Kelley
2016-01-10 11:48:54 -07:00
parent 75d5786603
commit d4b8852d78
7 changed files with 190 additions and 16 deletions

View File

@@ -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");
}