From 5afe473a86c2fe32b6d7c472b71f88e70ac671c6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 Jan 2016 13:08:21 -0700 Subject: different extern syntax and simplify parsing top level decls --- src/parser.cpp | 393 +++++++++++++++++++-------------------------------------- 1 file changed, 132 insertions(+), 261 deletions(-) (limited to 'src/parser.cpp') diff --git a/src/parser.cpp b/src/parser.cpp index 3c0812fbe0..2b6b030d06 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -105,8 +105,6 @@ const char *node_type_str(NodeType node_type) { return "ArrayAccessExpr"; case NodeTypeSliceExpr: return "SliceExpr"; - case NodeTypeExternBlock: - return "ExternBlock"; case NodeTypeDirective: return "Directive"; case NodeTypeReturnExpr: @@ -258,15 +256,6 @@ void ast_print(AstNode *node, int indent) { fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf)); break; } - case NodeTypeExternBlock: - { - fprintf(stderr, "%s\n", node_type_str(node->type)); - for (int i = 0; i < node->data.extern_block.fn_decls.length; i += 1) { - AstNode *child = node->data.extern_block.fn_decls.at(i); - ast_print(child, indent + 2); - } - break; - } case NodeTypeFnDecl: fprintf(stderr, "%s\n", node_type_str(node->type)); ast_print(node->data.fn_decl.fn_proto, indent + 2); @@ -482,9 +471,9 @@ struct ParseContext { Buf *buf; AstNode *root; ZigList *tokens; - ZigList *directive_list; ImportTableEntry *owner; ErrColor err_color; + bool parsed_root_export; uint32_t *next_node_index; }; @@ -2146,56 +2135,32 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m } /* -VariableDeclaration : option(FnVisibleMod) ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression)) +VariableDeclaration : ("var" | "const") "Symbol" ("=" Expression | ":" PrefixOpExpression option("=" Expression)) */ -static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory, + ZigList *directives, VisibMod visib_mod) +{ Token *first_token = &pc->tokens->at(*token_index); - VisibMod visib_mod; bool is_const; - if (first_token->id == TokenIdKeywordPub) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordVar || - next_token->id == TokenIdKeywordConst) - { - visib_mod = VisibModPub; - is_const = (next_token->id == TokenIdKeywordConst); - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, next_token); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordExport) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordVar || - next_token->id == TokenIdKeywordConst) - { - visib_mod = VisibModExport; - is_const = (next_token->id == TokenIdKeywordConst); - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, next_token); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordVar || - first_token->id == TokenIdKeywordConst) - { - visib_mod = VisibModPrivate; - is_const = (first_token->id == TokenIdKeywordConst); - *token_index += 1; + if (first_token->id == TokenIdKeywordVar) { + is_const = false; + } else if (first_token->id == TokenIdKeywordConst) { + is_const = true; } else if (mandatory) { ast_invalid_token_error(pc, first_token); } else { return nullptr; } + *token_index += 1; + AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token); node->data.variable_declaration.is_const = is_const; node->data.variable_declaration.visib_mod = visib_mod; + node->data.variable_declaration.directives = directives; Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol); ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol); @@ -2643,7 +2608,8 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato if (statement_node) { semicolon_expected = false; } else { - statement_node = ast_parse_variable_declaration_expr(pc, token_index, false); + statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, + nullptr, VisibModPrivate); if (statement_node) { semicolon_expected = true; } else { @@ -2677,47 +2643,25 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato } /* -FnProto : many(Directive) option(FnVisibleMod) "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression) +FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression) */ -static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory, + ZigList *directives, VisibMod visib_mod) +{ 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 == TokenIdKeywordFn) { - visib_mod = VisibModPub; - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, first_token); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordExport) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordFn) { - visib_mod = VisibModExport; - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, first_token); + if (first_token->id != TokenIdKeywordFn) { + if (mandatory) { + ast_expect_token(pc, first_token, TokenIdKeywordFn); } else { return nullptr; } - } else if (first_token->id == TokenIdKeywordFn) { - visib_mod = VisibModPrivate; - *token_index += 1; - } else if (mandatory) { - ast_invalid_token_error(pc, first_token); - } else { - return nullptr; } + *token_index += 1; AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token); node->data.fn_proto.visib_mod = visib_mod; - node->data.fn_proto.directives = pc->directive_list; - pc->directive_list = nullptr; - + node->data.fn_proto.directives = directives; Token *fn_name = &pc->tokens->at(*token_index); *token_index += 1; @@ -2743,107 +2687,59 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand /* FnDef : FnProto Block */ -static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) { - AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory); +static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory, + ZigList *directives, VisibMod visib_mod) +{ + AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, directives, visib_mod); if (!fn_proto) return nullptr; AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto); node->data.fn_def.fn_proto = fn_proto; node->data.fn_def.body = ast_parse_block(pc, token_index, true); - - normalize_parent_ptrs(node); - return node; -} - -/* -FnDecl : FnProto token(Semicolon) -*/ -static AstNode *ast_parse_fn_decl(ParseContext *pc, int *token_index) { - AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, true); - AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDecl, fn_proto); - - node->data.fn_decl.fn_proto = fn_proto; - - Token *semicolon = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, semicolon, TokenIdSemicolon); - normalize_parent_ptrs(node); return node; } /* -Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen) -*/ -/* -ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnProtoDecl) token(RBrace) +ExternDecl : "extern" FnProto ";" */ -static AstNode *ast_parse_extern_block(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool mandatory, + ZigList *directives, VisibMod visib_mod) +{ Token *extern_kw = &pc->tokens->at(*token_index); if (extern_kw->id != TokenIdKeywordExtern) { - if (mandatory) + if (mandatory) { ast_invalid_token_error(pc, extern_kw); - else + } else { return nullptr; + } } *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeExternBlock, extern_kw); - - node->data.extern_block.directives = pc->directive_list; - pc->directive_list = nullptr; - - Token *l_brace = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, l_brace, TokenIdLBrace); - - for (;;) { - Token *directive_token = &pc->tokens->at(*token_index); - assert(!pc->directive_list); - pc->directive_list = allocate>(1); - ast_parse_directives(pc, token_index, pc->directive_list); - - Token *token = &pc->tokens->at(*token_index); - if (token->id == TokenIdRBrace) { - if (pc->directive_list->length > 0) { - ast_error(pc, directive_token, "invalid directive"); - } - pc->directive_list = nullptr; - - *token_index += 1; - - normalize_parent_ptrs(node); - return node; - } else { - AstNode *child = ast_parse_fn_decl(pc, token_index); - node->data.extern_block.fn_decls.append(child); - } - } + AstNode *node = ast_parse_fn_proto(pc, token_index, true, directives, visib_mod); + ast_eat_token(pc, token_index, TokenIdSemicolon); - zig_unreachable(); + node->data.fn_proto.is_extern = true; + normalize_parent_ptrs(node); + return node; } /* -RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon) +RootExportDecl : "export" "Symbol" "String" ";" */ -static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, bool mandatory) { - assert(mandatory == false); - - Token *export_kw = &pc->tokens->at(*token_index); - if (export_kw->id != TokenIdKeywordExport) - return nullptr; - - Token *export_type = &pc->tokens->at(*token_index + 1); +static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, + ZigList *directives) +{ + Token *export_type = &pc->tokens->at(*token_index); if (export_type->id != TokenIdSymbol) return nullptr; - *token_index += 2; + *token_index += 1; - AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_kw); - node->data.root_export_decl.directives = pc->directive_list; - pc->directive_list = nullptr; + AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_type); + node->data.root_export_decl.directives = directives; ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type); @@ -2862,11 +2758,13 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b } /* -Use : many(Directive) token(Use) token(String) token(Semicolon) +Import : "import" "String" ";" */ -static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { - Token *use_kw = &pc->tokens->at(*token_index); - if (use_kw->id != TokenIdKeywordImport) +static AstNode *ast_parse_import(ParseContext *pc, int *token_index, + ZigList *directives, VisibMod visib_mod) +{ + Token *import_kw = &pc->tokens->at(*token_index); + if (import_kw->id != TokenIdKeywordImport) return nullptr; *token_index += 1; @@ -2878,59 +2776,35 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { *token_index += 1; ast_expect_token(pc, semicolon, TokenIdSemicolon); - AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw); + AstNode *node = ast_create_node(pc, NodeTypeUse, import_kw); + node->data.use.visib_mod = visib_mod; + node->data.use.directives = directives; parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr); - - node->data.use.directives = pc->directive_list; - pc->directive_list = nullptr; - normalize_parent_ptrs(node); return node; } /* -ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace) -StructMember: StructField | FnDecl -StructField : token(Symbol) option(token(Colon) Expression) token(Comma)) +ContainerDecl : ("struct" | "enum") "Symbol" "{" many(StructMember) "}" +StructMember: many(Directive) option(VisibleMod) (StructField | FnDef) +StructField : "Symbol" option(":" Expression) ",") */ -static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { +static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index, + ZigList *directives, VisibMod visib_mod) +{ Token *first_token = &pc->tokens->at(*token_index); - VisibMod visib_mod; ContainerKind kind; - if (first_token->id == TokenIdKeywordPub) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordStruct || - next_token->id == TokenIdKeywordEnum) - { - visib_mod = VisibModPub; - kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum; - *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 == TokenIdKeywordStruct || - next_token->id == TokenIdKeywordEnum) - { - visib_mod = VisibModExport; - kind = (next_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum; - *token_index += 2; - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordStruct || - first_token->id == TokenIdKeywordEnum) - { - visib_mod = VisibModPrivate; - kind = (first_token->id == TokenIdKeywordStruct) ? ContainerKindStruct : ContainerKindEnum; - *token_index += 1; + if (first_token->id == TokenIdKeywordStruct) { + kind = ContainerKindStruct; + } else if (first_token->id == TokenIdKeywordEnum) { + kind = ContainerKindEnum; } else { return nullptr; } + *token_index += 1; Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol); @@ -2938,19 +2812,28 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { node->data.struct_decl.kind = kind; ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name); node->data.struct_decl.visib_mod = visib_mod; + node->data.struct_decl.directives = directives; ast_eat_token(pc, token_index, TokenIdLBrace); - node->data.struct_decl.directives = pc->directive_list; - pc->directive_list = nullptr; - for (;;) { - assert(!pc->directive_list); - pc->directive_list = allocate>(1); Token *directive_token = &pc->tokens->at(*token_index); - ast_parse_directives(pc, token_index, pc->directive_list); + ZigList *directive_list = allocate>(1); + ast_parse_directives(pc, token_index, directive_list); + + Token *visib_tok = &pc->tokens->at(*token_index); + VisibMod visib_mod; + if (visib_tok->id == TokenIdKeywordPub) { + *token_index += 1; + visib_mod = VisibModPub; + } else if (visib_tok->id == TokenIdKeywordExport) { + *token_index += 1; + visib_mod = VisibModExport; + } else { + visib_mod = VisibModPrivate; + } - AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false); + AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directive_list, visib_mod); if (fn_def_node) { node->data.struct_decl.fns.append(fn_def_node); continue; @@ -2959,10 +2842,9 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { Token *token = &pc->tokens->at(*token_index); if (token->id == TokenIdRBrace) { - if (pc->directive_list->length > 0) { + if (directive_list->length > 0) { ast_error(pc, directive_token, "invalid directive"); } - pc->directive_list = nullptr; *token_index += 1; break; @@ -2970,8 +2852,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token); *token_index += 1; - field_node->data.struct_field.directives = pc->directive_list; - pc->directive_list = nullptr; + field_node->data.struct_field.visib_mod = visib_mod; + field_node->data.struct_field.directives = directive_list; ast_buf_from_token(pc, token, &field_node->data.struct_field.name); @@ -2997,47 +2879,24 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { } /* -ErrorValueDecl : option(FnVisibleMod) "error" "Symbol" +ErrorValueDecl : "error" "Symbol" ";" */ -static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, bool mandatory) { +static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, + ZigList *directives, VisibMod visib_mod) +{ 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 == TokenIdKeywordError) { - visib_mod = VisibModPub; - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, next_token); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordExport) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordError) { - visib_mod = VisibModExport; - *token_index += 2; - } else if (mandatory) { - ast_invalid_token_error(pc, next_token); - } else { - return nullptr; - } - } else if (first_token->id == TokenIdKeywordError) { - visib_mod = VisibModPrivate; - *token_index += 1; - } else if (mandatory) { - ast_invalid_token_error(pc, first_token); - } else { + if (first_token->id != TokenIdKeywordError) { return nullptr; } + *token_index += 1; Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); ast_eat_token(pc, token_index, TokenIdSemicolon); AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token); node->data.error_value_decl.visib_mod = visib_mod; + node->data.error_value_decl.directives = directives; ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name); normalize_parent_ptrs(node); @@ -3045,63 +2904,79 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index, b } /* -TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl +TopLevelDecl : many(Directive) option(FnVisibleMod) (FnDef | ExternFnProto | RootExportDecl | Import | ContainerDecl | VariableDeclaration | ErrorValueDecl | CImportDecl) */ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList *top_level_decls) { for (;;) { Token *directive_token = &pc->tokens->at(*token_index); - assert(!pc->directive_list); - pc->directive_list = allocate>(1); - ast_parse_directives(pc, token_index, pc->directive_list); + ZigList *directives = allocate>(1); + ast_parse_directives(pc, token_index, directives); - AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, false); - if (root_export_decl_node) { - top_level_decls->append(root_export_decl_node); - continue; + Token *visib_tok = &pc->tokens->at(*token_index); + VisibMod visib_mod; + if (visib_tok->id == TokenIdKeywordPub) { + *token_index += 1; + visib_mod = VisibModPub; + } else if (visib_tok->id == TokenIdKeywordExport) { + *token_index += 1; + visib_mod = VisibModExport; + } else { + visib_mod = VisibModPrivate; } - AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false); + bool try_to_parse_root_export = (visib_mod == VisibModExport && !pc->parsed_root_export); + pc->parsed_root_export = true; + + if (try_to_parse_root_export) { + AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, directives); + if (root_export_decl_node) { + top_level_decls->append(root_export_decl_node); + continue; + } + } + + AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod); if (fn_def_node) { top_level_decls->append(fn_def_node); continue; } - AstNode *extern_node = ast_parse_extern_block(pc, token_index, false); - if (extern_node) { - top_level_decls->append(extern_node); + AstNode *fn_proto_node = ast_parse_extern_decl(pc, token_index, false, directives, visib_mod); + if (fn_proto_node) { + top_level_decls->append(fn_proto_node); continue; } - AstNode *use_node = ast_parse_use(pc, token_index); - if (use_node) { - top_level_decls->append(use_node); + AstNode *import_node = ast_parse_import(pc, token_index, directives, visib_mod); + if (import_node) { + top_level_decls->append(import_node); continue; } - AstNode *struct_node = ast_parse_struct_decl(pc, token_index); + AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod); if (struct_node) { top_level_decls->append(struct_node); continue; } - if (pc->directive_list->length > 0) { - ast_error(pc, directive_token, "invalid directive"); - } - pc->directive_list = nullptr; - - AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false); + AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, + directives, visib_mod); if (var_decl_node) { ast_eat_token(pc, token_index, TokenIdSemicolon); top_level_decls->append(var_decl_node); continue; } - AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, false); + AstNode *error_value_node = ast_parse_error_value_decl(pc, token_index, directives, visib_mod); if (error_value_node) { top_level_decls->append(error_value_node); continue; } + if (directives->length > 0) { + ast_error(pc, directive_token, "invalid directive"); + } + return; } zig_unreachable(); @@ -3175,10 +3050,6 @@ void normalize_parent_ptrs(AstNode *node) { case NodeTypeBlock: set_list_fields(&node->data.block.statements); break; - case NodeTypeExternBlock: - set_list_fields(node->data.extern_block.directives); - set_list_fields(&node->data.extern_block.fn_decls); - break; case NodeTypeDirective: // none break; -- cgit v1.2.3