authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 19:16:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-06 19:16:01-07:00
log73727bd1c517efdb99064d1c80c26a55bf52ac8b
tree4cbfc58ea7a3414dadee4b39a471c3da7b5fcb20
parent65a03c5859e57820d2c28ad2952dda3fd4ac7d9c

parser recognizes %return in a prefix op expression

also defer only valid at statement level now see #110

2 files changed, 72 insertions(+), 14 deletions(-)

src/parser.cpp+57-14
......@@ -498,6 +498,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool m
498498static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory);
499499static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
500500 ZigList<AstNode*> *directives, VisibMod visib_mod);
501static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index);
501502
502503static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
503504 if (token->id == token_id) {
......@@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
12151216 if (prefix_op == PrefixOpInvalid) {
12161217 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
12171218 }
1219
1220 if (prefix_op == PrefixOpError || prefix_op == PrefixOpMaybe) {
1221 Token *maybe_return = &pc->tokens->at(*token_index + 1);
1222 if (maybe_return->id == TokenIdKeywordReturn) {
1223 return ast_parse_return_expr(pc, token_index);
1224 }
1225 }
1226
12181227 *token_index += 1;
12191228
1229
12201230 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
12211231 AstNode *parent_node = node;
12221232 if (token->id == TokenIdBoolAnd) {
......@@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
16351645
16361646/*
16371647ReturnExpression : option("%" | "?") "return" option(Expression)
1638DeferExpression = option("%" | "?") "defer" option(Expression)
16391648*/
1640static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) {
1649static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index) {
16411650 Token *token = &pc->tokens->at(*token_index);
16421651
16431652 NodeType node_type;
......@@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
16491658 kind = ReturnKindError;
16501659 node_type = NodeTypeReturnExpr;
16511660 *token_index += 2;
1652 } else if (next_token->id == TokenIdKeywordDefer) {
1653 kind = ReturnKindError;
1654 node_type = NodeTypeDefer;
1655 *token_index += 2;
16561661 } else {
16571662 return nullptr;
16581663 }
......@@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
16621667 kind = ReturnKindMaybe;
16631668 node_type = NodeTypeReturnExpr;
16641669 *token_index += 2;
1665 } else if (next_token->id == TokenIdKeywordDefer) {
1666 kind = ReturnKindMaybe;
1667 node_type = NodeTypeDefer;
1668 *token_index += 2;
16691670 } else {
16701671 return nullptr;
16711672 }
......@@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
16731674 kind = ReturnKindUnconditional;
16741675 node_type = NodeTypeReturnExpr;
16751676 *token_index += 1;
1677 } else {
1678 return nullptr;
1679 }
1680
1681 AstNode *node = ast_create_node(pc, node_type, token);
1682 node->data.return_expr.kind = kind;
1683 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);
1684
1685 normalize_parent_ptrs(node);
1686 return node;
1687}
1688
1689/*
1690Defer = option("%" | "?") "defer" option(Expression)
1691*/
1692static AstNode *ast_parse_defer_expr(ParseContext *pc, int *token_index) {
1693 Token *token = &pc->tokens->at(*token_index);
1694
1695 NodeType node_type;
1696 ReturnKind kind;
1697
1698 if (token->id == TokenIdPercent) {
1699 Token *next_token = &pc->tokens->at(*token_index + 1);
1700 if (next_token->id == TokenIdKeywordDefer) {
1701 kind = ReturnKindError;
1702 node_type = NodeTypeDefer;
1703 *token_index += 2;
1704 } else {
1705 return nullptr;
1706 }
1707 } else if (token->id == TokenIdMaybe) {
1708 Token *next_token = &pc->tokens->at(*token_index + 1);
1709 if (next_token->id == TokenIdKeywordDefer) {
1710 kind = ReturnKindMaybe;
1711 node_type = NodeTypeDefer;
1712 *token_index += 2;
1713 } else {
1714 return nullptr;
1715 }
16761716 } else if (token->id == TokenIdKeywordDefer) {
16771717 kind = ReturnKindUnconditional;
16781718 node_type = NodeTypeDefer;
......@@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
16821722 }
16831723
16841724 AstNode *node = ast_create_node(pc, node_type, token);
1685 node->data.return_expr.kind = kind;
1686 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);
1725 node->data.defer.kind = kind;
1726 node->data.defer.expr = ast_parse_expression(pc, token_index, false);
16871727
16881728 normalize_parent_ptrs(node);
16891729 return node;
......@@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression
20682108static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
20692109 Token *token = &pc->tokens->at(*token_index);
20702110
2071 AstNode *return_expr = ast_parse_return_or_defer_expr(pc, token_index);
2111 AstNode *return_expr = ast_parse_return_expr(pc, token_index);
20722112 if (return_expr)
20732113 return return_expr;
20742114
......@@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
21422182
21432183/*
21442184Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
2145Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression
2185Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression
21462186*/
21472187static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) {
21482188 Token *last_token = &pc->tokens->at(*token_index);
......@@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
21712211 } else {
21722212 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,
21732213 nullptr, VisibModPrivate);
2214 if (!statement_node) {
2215 statement_node = ast_parse_defer_expr(pc, token_index);
2216 }
21742217 if (statement_node) {
21752218 semicolon_expected = true;
21762219 } else {
test/self_hosted.zig+15
......@@ -173,3 +173,18 @@ fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {
173173 },
174174 }
175175}
176
177
178#attribute("test")
179fn err_return_in_assignment() {
180 %%do_err_return_in_assignment();
181}
182
183fn do_err_return_in_assignment() -> %void {
184 var x : i32 = undefined;
185 x = %return make_a_non_err();
186}
187
188fn make_a_non_err() -> %i32 {
189 return 1;
190}