ability to specify function type

closes #14
This commit is contained in:
Andrew Kelley
2016-01-28 20:26:40 -07:00
parent 2bb2e61ee2
commit a5c2de5fee
5 changed files with 170 additions and 70 deletions

View File

@@ -503,6 +503,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory);
static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool mandatory);
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory);
static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
ZigList<AstNode*> *directives, VisibMod visib_mod);
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
if (token->id == token_id) {
@@ -671,7 +673,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
Token *l_paren = &pc->tokens->at(*token_index);
if (l_paren->id != TokenIdLParen) {
if (mandatory) {
ast_invalid_token_error(pc, l_paren);
ast_expect_token(pc, l_paren, TokenIdLParen);
} else {
return nullptr;
}
@@ -695,7 +697,7 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bo
Token *l_bracket = &pc->tokens->at(*token_index);
if (l_bracket->id != TokenIdLBracket) {
if (mandatory) {
ast_invalid_token_error(pc, l_bracket);
ast_expect_token(pc, l_bracket, TokenIdLBracket);
} else {
return nullptr;
}
@@ -865,7 +867,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
if (asm_token->id != TokenIdKeywordAsm) {
if (mandatory) {
ast_invalid_token_error(pc, asm_token);
ast_expect_token(pc, asm_token, TokenIdKeywordAsm);
} else {
return nullptr;
}
@@ -905,7 +907,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand
}
/*
PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("error" "." "Symbol")
PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol")
KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" | "error"
*/
static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
@@ -956,6 +958,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
AstNode *node = ast_create_node(pc, NodeTypeErrorType, token);
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordExtern) {
*token_index += 1;
AstNode *node = ast_parse_fn_proto(pc, token_index, true, nullptr, VisibModPrivate);
node->data.fn_proto.is_extern = true;
return node;
} else if (token->id == TokenIdAtSign) {
*token_index += 1;
Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
@@ -1002,6 +1009,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
return array_type_node;
}
AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, nullptr, VisibModPrivate);
if (fn_proto_node) {
return fn_proto_node;
}
AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false);
if (asm_expr) {
return asm_expr;
@@ -1055,7 +1067,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, int *token_index,
token = &pc->tokens->at(*token_index);
continue;
} else if (comma_tok->id != TokenIdRBrace) {
ast_invalid_token_error(pc, comma_tok);
ast_expect_token(pc, comma_tok, TokenIdRBrace);
} else {
*token_index += 1;
break;
@@ -1084,7 +1096,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, int *token_index,
token = &pc->tokens->at(*token_index);
continue;
} else if (comma_tok->id != TokenIdRBrace) {
ast_invalid_token_error(pc, comma_tok);
ast_expect_token(pc, comma_tok, TokenIdRBrace);
} else {
*token_index += 1;
break;
@@ -1555,7 +1567,7 @@ static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandator
if (else_token->id != TokenIdKeywordElse) {
if (mandatory) {
ast_invalid_token_error(pc, else_token);
ast_expect_token(pc, else_token, TokenIdKeywordElse);
} else {
return nullptr;
}
@@ -1574,7 +1586,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
Token *if_tok = &pc->tokens->at(*token_index);
if (if_tok->id != TokenIdKeywordIf) {
if (mandatory) {
ast_invalid_token_error(pc, if_tok);
ast_expect_token(pc, if_tok, TokenIdKeywordIf);
} else {
return nullptr;
}
@@ -1637,7 +1649,8 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
kind = ReturnKindError;
*token_index += 2;
} else if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, next_token, TokenIdKeywordReturn);
zig_unreachable();
} else {
return nullptr;
}
@@ -1647,7 +1660,8 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
kind = ReturnKindMaybe;
*token_index += 2;
} else if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, next_token, TokenIdKeywordReturn);
zig_unreachable();
} else {
return nullptr;
}
@@ -1655,7 +1669,8 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
kind = ReturnKindUnconditional;
*token_index += 1;
} else if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, token, TokenIdKeywordReturn);
zig_unreachable();
} else {
return nullptr;
}
@@ -1756,7 +1771,7 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, int *token_index, bool ma
if (token->id != TokenIdKeywordWhile) {
if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, token, TokenIdKeywordWhile);
} else {
return nullptr;
}
@@ -1791,7 +1806,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, int *token_index, bool mand
if (token->id != TokenIdKeywordFor) {
if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, token, TokenIdKeywordFor);
} else {
return nullptr;
}
@@ -1829,7 +1844,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, int *token_index, bool m
if (token->id != TokenIdKeywordSwitch) {
if (mandatory) {
ast_invalid_token_error(pc, token);
ast_expect_token(pc, token, TokenIdKeywordSwitch);
} else {
return nullptr;
}
@@ -2082,7 +2097,7 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato
Token *symbol_token = &pc->tokens->at(*token_index);
if (symbol_token->id != TokenIdSymbol) {
if (mandatory) {
ast_invalid_token_error(pc, symbol_token);
ast_expect_token(pc, symbol_token, TokenIdSymbol);
} else {
return nullptr;
}
@@ -2091,7 +2106,7 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato
Token *colon_token = &pc->tokens->at(*token_index + 1);
if (colon_token->id != TokenIdColon) {
if (mandatory) {
ast_invalid_token_error(pc, colon_token);
ast_expect_token(pc, colon_token, TokenIdColon);
} else {
return nullptr;
}
@@ -2122,7 +2137,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
if (last_token->id != TokenIdLBrace) {
if (mandatory) {
ast_invalid_token_error(pc, last_token);
ast_expect_token(pc, last_token, TokenIdLBrace);
} else {
return nullptr;
}
@@ -2245,7 +2260,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool m
Token *extern_kw = &pc->tokens->at(*token_index);
if (extern_kw->id != TokenIdKeywordExtern) {
if (mandatory) {
ast_invalid_token_error(pc, extern_kw);
ast_expect_token(pc, extern_kw, TokenIdKeywordExtern);
} else {
return nullptr;
}
@@ -2591,7 +2606,9 @@ void normalize_parent_ptrs(AstNode *node) {
break;
case NodeTypeFnProto:
set_field(&node->data.fn_proto.return_type);
set_list_fields(node->data.fn_proto.directives);
if (node->data.fn_proto.directives) {
set_list_fields(node->data.fn_proto.directives);
}
set_list_fields(&node->data.fn_proto.params);
break;
case NodeTypeFnDef: