mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
parsing enum declarations
This commit is contained in:
parent
75d5786603
commit
d4b8852d78
@ -32,16 +32,24 @@ zig | C equivalent | Description
|
||||
```
|
||||
Root : many(TopLevelDecl) token(EOF)
|
||||
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
|
||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration | EnumDecl
|
||||
|
||||
VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
|
||||
|
||||
StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
|
||||
StructDecl : many(Directive) option(FnVisibleMod) token(Struct) StructPayload
|
||||
|
||||
StructPayload: token(Symbol) token(LBrace) many(StructMember) token(RBrace)
|
||||
|
||||
EnumDecl : many(Directive) option(FnVisibleMod) token(Enum) token(Symbol) token(LBrace) many(EnumField) token(RBrace)
|
||||
|
||||
StructMember: StructField | FnDecl
|
||||
|
||||
StructField : token(Symbol) token(Colon) Type token(Comma)
|
||||
|
||||
EnumField : (EnumDiscriminant | StructPayload) token(Comma)
|
||||
|
||||
EnumDiscriminant : token(Symbol) option(token(Eq) Expression)
|
||||
|
||||
Use : many(Directive) token(Use) token(String) token(Semicolon)
|
||||
|
||||
RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon)
|
||||
@ -160,7 +168,9 @@ SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression)
|
||||
|
||||
PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))
|
||||
|
||||
PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression)
|
||||
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
|
||||
|
||||
NamespaceSymbol : token(Symbol) token(ColonColon) token(Symbol)
|
||||
|
||||
StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
|
||||
|
||||
|
||||
@ -63,6 +63,8 @@ static AstNode *first_executing_node(AstNode *node) {
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeStructDecl:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumDecl:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueExpr:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeWhileExpr:
|
||||
@ -894,6 +896,11 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
// struct member fns will get resolved independently
|
||||
break;
|
||||
}
|
||||
case NodeTypeEnumDecl:
|
||||
{
|
||||
zig_panic("TODO resolve enum decl");
|
||||
break;
|
||||
}
|
||||
case NodeTypeVariableDeclaration:
|
||||
{
|
||||
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
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueExpr:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeCompilerFnExpr:
|
||||
@ -2490,6 +2498,8 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeStructDecl:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumDecl:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeCompilerFnExpr:
|
||||
zig_unreachable();
|
||||
@ -2589,13 +2599,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
case NodeTypeFnDef:
|
||||
analyze_top_level_fn_def(g, import, node);
|
||||
break;
|
||||
case NodeTypeRootExportDecl:
|
||||
case NodeTypeExternBlock:
|
||||
// already looked at these in the preview pass
|
||||
break;
|
||||
case NodeTypeUse:
|
||||
// already took care of this
|
||||
break;
|
||||
case NodeTypeStructDecl:
|
||||
{
|
||||
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
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeRootExportDecl:
|
||||
case NodeTypeExternBlock:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeEnumDecl:
|
||||
case NodeTypeVariableDeclaration:
|
||||
// handled in resolve phase
|
||||
// already took care of these
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeParamDecl:
|
||||
@ -2639,6 +2646,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueExpr:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeCompilerFnExpr:
|
||||
@ -2772,6 +2780,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
case NodeTypeLabel:
|
||||
case NodeTypeStructDecl:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumDecl:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueField:
|
||||
zig_unreachable();
|
||||
}
|
||||
@ -2879,6 +2889,11 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
||||
detect_top_level_decl_deps(g, import, fn_def_node);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NodeTypeEnumDecl:
|
||||
{
|
||||
zig_panic("TODO detect enum top level decl deps");
|
||||
break;
|
||||
}
|
||||
case NodeTypeExternBlock:
|
||||
@ -2974,6 +2989,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
||||
case NodeTypeAsmExpr:
|
||||
case NodeTypeFieldAccessExpr:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueExpr:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeCompilerFnExpr:
|
||||
|
||||
@ -1754,6 +1754,8 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
|
||||
case NodeTypeUse:
|
||||
case NodeTypeStructDecl:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeEnumDecl:
|
||||
case NodeTypeEnumField:
|
||||
case NodeTypeStructValueField:
|
||||
case NodeTypeCompilerFnExpr:
|
||||
zig_unreachable();
|
||||
|
||||
135
src/parser.cpp
135
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");
|
||||
}
|
||||
|
||||
@ -59,6 +59,8 @@ enum NodeType {
|
||||
NodeTypeStructField,
|
||||
NodeTypeStructValueExpr,
|
||||
NodeTypeStructValueField,
|
||||
NodeTypeEnumDecl,
|
||||
NodeTypeEnumField,
|
||||
NodeTypeCompilerFnExpr,
|
||||
NodeTypeCompilerFnType,
|
||||
};
|
||||
@ -316,6 +318,19 @@ struct AstNodeStructField {
|
||||
ZigList<AstNode *> *directives;
|
||||
};
|
||||
|
||||
struct AstNodeEnumDecl {
|
||||
Buf name;
|
||||
ZigList<AstNode *> fields;
|
||||
ZigList<AstNode *> *directives;
|
||||
VisibMod visib_mod;
|
||||
};
|
||||
|
||||
struct AstNodeEnumField {
|
||||
Buf name;
|
||||
ZigList<AstNode *> fields; // length 0 means simple enum
|
||||
AstNode *val_expr;
|
||||
};
|
||||
|
||||
struct AstNodeStringLiteral {
|
||||
Buf buf;
|
||||
bool c;
|
||||
@ -411,6 +426,8 @@ struct AstNode {
|
||||
AstNodeFieldAccessExpr field_access_expr;
|
||||
AstNodeStructDecl struct_decl;
|
||||
AstNodeStructField struct_field;
|
||||
AstNodeEnumDecl enum_decl;
|
||||
AstNodeEnumField enum_field;
|
||||
AstNodeStringLiteral string_literal;
|
||||
AstNodeCharLiteral char_literal;
|
||||
AstNodeNumberLiteral number_literal;
|
||||
|
||||
@ -235,6 +235,8 @@ static void end_token(Tokenize *t) {
|
||||
t->cur_tok->id = TokenIdKeywordAsm;
|
||||
} else if (mem_eql_str(token_mem, token_len, "struct")) {
|
||||
t->cur_tok->id = TokenIdKeywordStruct;
|
||||
} else if (mem_eql_str(token_mem, token_len, "enum")) {
|
||||
t->cur_tok->id = TokenIdKeywordEnum;
|
||||
} else if (mem_eql_str(token_mem, token_len, "while")) {
|
||||
t->cur_tok->id = TokenIdKeywordWhile;
|
||||
} else if (mem_eql_str(token_mem, token_len, "continue")) {
|
||||
@ -1021,6 +1023,7 @@ static const char * token_name(Token *token) {
|
||||
case TokenIdKeywordVolatile: return "Volatile";
|
||||
case TokenIdKeywordAsm: return "Asm";
|
||||
case TokenIdKeywordStruct: return "Struct";
|
||||
case TokenIdKeywordEnum: return "Enum";
|
||||
case TokenIdKeywordWhile: return "While";
|
||||
case TokenIdKeywordContinue: return "Continue";
|
||||
case TokenIdKeywordBreak: return "Break";
|
||||
|
||||
@ -32,6 +32,7 @@ enum TokenId {
|
||||
TokenIdKeywordAsm,
|
||||
TokenIdKeywordVolatile,
|
||||
TokenIdKeywordStruct,
|
||||
TokenIdKeywordEnum,
|
||||
TokenIdKeywordWhile,
|
||||
TokenIdKeywordContinue,
|
||||
TokenIdKeywordBreak,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user