aboutsummaryrefslogtreecommitdiff
path: root/src/parser.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2016-01-10 11:48:54 -0700
committerAndrew Kelley <superjoe30@gmail.com>2016-01-10 11:48:54 -0700
commitd4b8852d784b6f180e5329efa8d418397ee7f1ef (patch)
treed281a93575cd30dcf4c30339a8c5cfa312fa3828 /src/parser.cpp
parent75d57866035a5e27a7e62f7cfabbc899affd3e8b (diff)
downloadzig-d4b8852d784b6f180e5329efa8d418397ee7f1ef.tar.gz
zig-d4b8852d784b6f180e5329efa8d418397ee7f1ef.zip
parsing enum declarations
Diffstat (limited to 'src/parser.cpp')
-rw-r--r--src/parser.cpp135
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");
}