diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-02-06 19:16:01 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-02-06 19:16:01 -0700 |
| commit | 73727bd1c517efdb99064d1c80c26a55bf52ac8b (patch) | |
| tree | 4cbfc58ea7a3414dadee4b39a471c3da7b5fcb20 /src/parser.cpp | |
| parent | 65a03c5859e57820d2c28ad2952dda3fd4ac7d9c (diff) | |
| download | zig-73727bd1c517efdb99064d1c80c26a55bf52ac8b.tar.gz zig-73727bd1c517efdb99064d1c80c26a55bf52ac8b.zip | |
parser recognizes %return in a prefix op expression
also defer only valid at statement level now
see #110
Diffstat (limited to 'src/parser.cpp')
| -rw-r--r-- | src/parser.cpp | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/src/parser.cpp b/src/parser.cpp index 13b260a659..7a9d2a0eaa 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -498,6 +498,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, int *token_index, bool m 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 AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index); static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { if (token->id == token_id) { @@ -1215,8 +1216,17 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, boo if (prefix_op == PrefixOpInvalid) { return ast_parse_suffix_op_expr(pc, token_index, mandatory); } + + if (prefix_op == PrefixOpError || prefix_op == PrefixOpMaybe) { + Token *maybe_return = &pc->tokens->at(*token_index + 1); + if (maybe_return->id == TokenIdKeywordReturn) { + return ast_parse_return_expr(pc, token_index); + } + } + *token_index += 1; + AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token); AstNode *parent_node = node; if (token->id == TokenIdBoolAnd) { @@ -1635,9 +1645,8 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda /* ReturnExpression : option("%" | "?") "return" option(Expression) -DeferExpression = option("%" | "?") "defer" option(Expression) */ -static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_index) { +static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index) { Token *token = &pc->tokens->at(*token_index); NodeType node_type; @@ -1649,10 +1658,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde kind = ReturnKindError; node_type = NodeTypeReturnExpr; *token_index += 2; - } else if (next_token->id == TokenIdKeywordDefer) { - kind = ReturnKindError; - node_type = NodeTypeDefer; - *token_index += 2; } else { return nullptr; } @@ -1662,10 +1667,6 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde kind = ReturnKindMaybe; node_type = NodeTypeReturnExpr; *token_index += 2; - } else if (next_token->id == TokenIdKeywordDefer) { - kind = ReturnKindMaybe; - node_type = NodeTypeDefer; - *token_index += 2; } else { return nullptr; } @@ -1673,6 +1674,45 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde kind = ReturnKindUnconditional; node_type = NodeTypeReturnExpr; *token_index += 1; + } else { + return nullptr; + } + + AstNode *node = ast_create_node(pc, node_type, token); + node->data.return_expr.kind = kind; + node->data.return_expr.expr = ast_parse_expression(pc, token_index, false); + + normalize_parent_ptrs(node); + return node; +} + +/* +Defer = option("%" | "?") "defer" option(Expression) +*/ +static AstNode *ast_parse_defer_expr(ParseContext *pc, int *token_index) { + Token *token = &pc->tokens->at(*token_index); + + NodeType node_type; + ReturnKind kind; + + if (token->id == TokenIdPercent) { + Token *next_token = &pc->tokens->at(*token_index + 1); + if (next_token->id == TokenIdKeywordDefer) { + kind = ReturnKindError; + node_type = NodeTypeDefer; + *token_index += 2; + } else { + return nullptr; + } + } else if (token->id == TokenIdMaybe) { + Token *next_token = &pc->tokens->at(*token_index + 1); + if (next_token->id == TokenIdKeywordDefer) { + kind = ReturnKindMaybe; + node_type = NodeTypeDefer; + *token_index += 2; + } else { + return nullptr; + } } else if (token->id == TokenIdKeywordDefer) { kind = ReturnKindUnconditional; node_type = NodeTypeDefer; @@ -1682,8 +1722,8 @@ static AstNode *ast_parse_return_or_defer_expr(ParseContext *pc, int *token_inde } AstNode *node = ast_create_node(pc, node_type, token); - node->data.return_expr.kind = kind; - node->data.return_expr.expr = ast_parse_expression(pc, token_index, false); + node->data.defer.kind = kind; + node->data.defer.expr = ast_parse_expression(pc, token_index, false); normalize_parent_ptrs(node); return node; @@ -2068,7 +2108,7 @@ NonBlockExpression : ReturnExpression | AssignmentExpression static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); - AstNode *return_expr = ast_parse_return_or_defer_expr(pc, token_index); + AstNode *return_expr = ast_parse_return_expr(pc, token_index); if (return_expr) return return_expr; @@ -2142,7 +2182,7 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { /* Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) -Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression +Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression */ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory) { Token *last_token = &pc->tokens->at(*token_index); @@ -2171,6 +2211,9 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato } else { statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, nullptr, VisibModPrivate); + if (!statement_node) { + statement_node = ast_parse_defer_expr(pc, token_index); + } if (statement_node) { semicolon_expected = true; } else { |
