From 2bb2e61ee288a02e184e5b8422859a4afcbb4813 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Jan 2016 18:58:28 -0700 Subject: parser: allow missing fn name and missing param names now these problems are caught in analyzer this is for purpose of function type, see #14 --- src/analyze.cpp | 21 ++++++++++++++++++++- src/parser.cpp | 43 +++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index 3e3bf2b5f3..c3d66a26f8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -457,6 +457,10 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t assert(node->type == NodeTypeFnProto); AstNodeFnProto *fn_proto = &node->data.fn_proto; + if (fn_proto->skip) { + return; + } + TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); fn_table_entry->type_entry = fn_type; fn_type->data.fn.calling_convention = fn_table_entry->internal_linkage ? LLVMFastCallConv : LLVMCCallConv; @@ -932,6 +936,9 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *proto_node) { + if (proto_node->data.fn_proto.skip) { + return; + } AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node; AstNode *struct_node = proto_node->data.fn_proto.struct_node; bool is_extern = proto_node->data.fn_proto.is_extern; @@ -4307,6 +4314,10 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo buf_sprintf("byvalue struct parameters not yet supported on exported functions")); } + if (buf_len(¶m_decl->name) == 0) { + add_node_error(g, param_decl_node, buf_sprintf("missing parameter name")); + } + VariableTableEntry *var = add_local_var(g, param_decl_node, context, ¶m_decl->name, type, true); var->src_arg_index = i; param_decl_node->data.param_decl.variable = var; @@ -4682,6 +4693,15 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast } case NodeTypeFnProto: { + // if the name is missing, we immediately announce an error + Buf *name = &node->data.fn_proto.name; + if (buf_len(name) == 0) { + node->data.fn_proto.skip = true; + add_node_error(g, node, buf_sprintf("missing function name")); + break; + } + + // determine which other top level declarations this function prototype depends on. TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl; decl_node->deps.init(1); @@ -4692,7 +4712,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast } collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node); - Buf *name = &node->data.fn_proto.name; decl_node->name = name; decl_node->import = import; if (decl_node->deps.size() > 0) { diff --git a/src/parser.cpp b/src/parser.cpp index 170d579956..e717a18941 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -569,35 +569,33 @@ static void ast_parse_directives(ParseContext *pc, int *token_index, } /* -ParamDecl : option("noalias") "Symbol" ":" PrefixOpExpression | "..." +ParamDecl = option("noalias") option("Symbol" ":") PrefixOpExpression | "..." */ static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) { - Token *first_token = &pc->tokens->at(*token_index); + Token *token = &pc->tokens->at(*token_index); - if (first_token->id == TokenIdEllipsis) { + if (token->id == TokenIdEllipsis) { *token_index += 1; return nullptr; } - AstNode *node = ast_create_node(pc, NodeTypeParamDecl, first_token); - Token *name_token; + AstNode *node = ast_create_node(pc, NodeTypeParamDecl, token); - if (first_token->id == TokenIdKeywordNoAlias) { + if (token->id == TokenIdKeywordNoAlias) { node->data.param_decl.is_noalias = true; *token_index += 1; - name_token = ast_eat_token(pc, token_index, TokenIdSymbol); - } else if (first_token->id == TokenIdSymbol) { - name_token = first_token; - *token_index += 1; - } else { - ast_invalid_token_error(pc, first_token); + token = &pc->tokens->at(*token_index); } - ast_buf_from_token(pc, name_token, &node->data.param_decl.name); + buf_resize(&node->data.param_decl.name, 0); - Token *colon = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, colon, TokenIdColon); + if (token->id == TokenIdSymbol) { + Token *next_token = &pc->tokens->at(*token_index + 1); + if (next_token->id == TokenIdColon) { + ast_buf_from_token(pc, token, &node->data.param_decl.name); + *token_index += 2; + } + } node->data.param_decl.type = ast_parse_prefix_op_expr(pc, token_index, true); @@ -2179,7 +2177,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato } /* -FnProto : "fn" "Symbol" ParamDeclList option("->" PrefixOpExpression) +FnProto : "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression) */ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory, ZigList *directives, VisibMod visib_mod) @@ -2200,11 +2198,12 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand node->data.fn_proto.directives = directives; Token *fn_name = &pc->tokens->at(*token_index); - *token_index += 1; - ast_expect_token(pc, fn_name, TokenIdSymbol); - - ast_buf_from_token(pc, fn_name, &node->data.fn_proto.name); - + if (fn_name->id == TokenIdSymbol) { + *token_index += 1; + ast_buf_from_token(pc, fn_name, &node->data.fn_proto.name); + } else { + buf_resize(&node->data.fn_proto.name, 0); + } ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); -- cgit v1.2.3