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...@@ -498,6 +498,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool m
498static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory);498static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory);
499static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,499static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
500 ZigList<AstNode*> *directives, VisibMod visib_mod);500 ZigList<AstNode*> *directives, VisibMod visib_mod);
501static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index);
501502
502static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {503static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
503 if (token->id == token_id) {504 if (token->id == token_id) {
...@@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo
1215 if (prefix_op == PrefixOpInvalid) {1216 if (prefix_op == PrefixOpInvalid) {
1216 return ast_parse_suffix_op_expr(pc, token_index, mandatory);1217 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
1217 }1218 }
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
1218 *token_index += 1;1227 *token_index += 1;
12191228
1229
1220 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);1230 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
1221 AstNode *parent_node = node;1231 AstNode *parent_node = node;
1222 if (token->id == TokenIdBoolAnd) {1232 if (token->id == TokenIdBoolAnd) {
...@@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
16351645
1636/*1646/*
1637ReturnExpression : option("%" | "?") "return" option(Expression)1647ReturnExpression : option("%" | "?") "return" option(Expression)
1638DeferExpression = option("%" | "?") "defer" option(Expression)
1639*/1648*/
1640static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) {1649static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index) {
1641 Token *token = &pc->tokens->at(*token_index);1650 Token *token = &pc->tokens->at(*token_index);
16421651
1643 NodeType node_type;1652 NodeType node_type;
...@@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1649 kind = ReturnKindError;1658 kind = ReturnKindError;
1650 node_type = NodeTypeReturnExpr;1659 node_type = NodeTypeReturnExpr;
1651 *token_index += 2;1660 *token_index += 2;
1652 } else if (next_token->id == TokenIdKeywordDefer) {
1653 kind = ReturnKindError;
1654 node_type = NodeTypeDefer;
1655 *token_index += 2;
1656 } else {1661 } else {
1657 return nullptr;1662 return nullptr;
1658 }1663 }
...@@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1662 kind = ReturnKindMaybe;1667 kind = ReturnKindMaybe;
1663 node_type = NodeTypeReturnExpr;1668 node_type = NodeTypeReturnExpr;
1664 *token_index += 2;1669 *token_index += 2;
1665 } else if (next_token->id == TokenIdKeywordDefer) {
1666 kind = ReturnKindMaybe;
1667 node_type = NodeTypeDefer;
1668 *token_index += 2;
1669 } else {1670 } else {
1670 return nullptr;1671 return nullptr;
1671 }1672 }
...@@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1673 kind = ReturnKindUnconditional;1674 kind = ReturnKindUnconditional;
1674 node_type = NodeTypeReturnExpr;1675 node_type = NodeTypeReturnExpr;
1675 *token_index += 1;1676 *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 }
1676 } else if (token->id == TokenIdKeywordDefer) {1716 } else if (token->id == TokenIdKeywordDefer) {
1677 kind = ReturnKindUnconditional;1717 kind = ReturnKindUnconditional;
1678 node_type = NodeTypeDefer;1718 node_type = NodeTypeDefer;
...@@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde...@@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde
1682 }1722 }
16831723
1684 AstNode *node = ast_create_node(pc, node_type, token);1724 AstNode *node = ast_create_node(pc, node_type, token);
1685 node->data.return_expr.kind = kind;1725 node->data.defer.kind = kind;
1686 node->data.return_expr.expr = ast_parse_expression(pc, token_index, false);1726 node->data.defer.expr = ast_parse_expression(pc, token_index, false);
16871727
1688 normalize_parent_ptrs(node);1728 normalize_parent_ptrs(node);
1689 return node;1729 return node;
...@@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression...@@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression
2068static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {2108static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
2069 Token *token = &pc->tokens->at(*token_index);2109 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);
2072 if (return_expr)2112 if (return_expr)
2073 return return_expr;2113 return return_expr;
20742114
...@@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {...@@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
21422182
2143/*2183/*
2144Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)2184Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
2145Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression2185Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression
2146*/2186*/
2147static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) {2187static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) {
2148 Token *last_token = &pc->tokens->at(*token_index);2188 Token *last_token = &pc->tokens->at(*token_index);
...@@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato...@@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
2171 } else {2211 } else {
2172 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,2212 statement_node = ast_parse_variable_declaration_expr(pc, token_index, false,
2173 nullptr, VisibModPrivate);2213 nullptr, VisibModPrivate);
2214 if (!statement_node) {
2215 statement_node = ast_parse_defer_expr(pc, token_index);
2216 }
2174 if (statement_node) {2217 if (statement_node) {
2175 semicolon_expected = true;2218 semicolon_expected = true;
2176 } else {2219 } else {
test/self_hosted.zig+15
...@@ -173,3 +173,18 @@ fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {...@@ -173,3 +173,18 @@ fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {
173 },173 },
174 }174 }
175}175}
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}