authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-04-02 15:14:35-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-04-02 15:15:48-07:00
log0594487a2e98e18a18c0c6bdb2532c5e36fc6ea7
treecb82a82a5d6e20b1f30a53af48822951fc7a1d9d
parenta33be6fc9906e010a44087dc2b7143717d875505

fix else-if parsing

implicit semicolon rules apply recursively to the "else" clause of if and try if (a) {} else {} // implicit semicolon if (a) {} else if (a) {} // implicit semicolon if (a) {} else while (a) {} // implicit semicolon

2 files changed, 19 insertions(+), 10 deletions(-)

doc/langref.md+3-3
...@@ -93,11 +93,11 @@ Defer(body) = option("%" | "?") "defer" body...@@ -93,11 +93,11 @@ Defer(body) = option("%" | "?") "defer" body
9393
94IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)94IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body)
9595
96IfBoolExpression(body) = "if" "(" Expression ")" body option("else" body)96IfBoolExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
9797
98TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") body)98TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") BlockExpression(body))
9999
100IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" body)100IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" BlockExpression(body))
101101
102BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression102BoolAndExpression = ComparisonExpression "and" BoolAndExpression | ComparisonExpression
103103
src/parser.cpp+16-7
...@@ -212,6 +212,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {...@@ -212,6 +212,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) {
212}212}
213213
214static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_index, bool mandatory);214static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_index, bool mandatory);
215static AstNode *ast_parse_block_expr_or_expression(ParseContext *pc, size_t *token_index, bool mandatory);
215static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory);216static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory);
216static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory);217static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory);
217static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory);218static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory);
...@@ -701,7 +702,7 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m...@@ -701,7 +702,7 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
701 ast_eat_token(pc, token_index, TokenIdBinOr);702 ast_eat_token(pc, token_index, TokenIdBinOr);
702 }703 }
703704
704 node->data.try_expr.else_node = ast_parse_block_or_expression(pc, token_index, true);705 node->data.try_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
705 }706 }
706707
707 return node;708 return node;
...@@ -1439,7 +1440,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma...@@ -1439,7 +1440,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
1439 Token *else_token = &pc->tokens->at(*token_index);1440 Token *else_token = &pc->tokens->at(*token_index);
1440 if (else_token->id == TokenIdKeywordElse) {1441 if (else_token->id == TokenIdKeywordElse) {
1441 *token_index += 1;1442 *token_index += 1;
1442 node->data.if_var_expr.else_node = ast_parse_block_or_expression(pc, token_index, true);1443 node->data.if_var_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
1443 }1444 }
14441445
1445 return node;1446 return node;
...@@ -1452,7 +1453,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma...@@ -1452,7 +1453,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma
1452 Token *else_token = &pc->tokens->at(*token_index);1453 Token *else_token = &pc->tokens->at(*token_index);
1453 if (else_token->id == TokenIdKeywordElse) {1454 if (else_token->id == TokenIdKeywordElse) {
1454 *token_index += 1;1455 *token_index += 1;
1455 node->data.if_bool_expr.else_node = ast_parse_block_or_expression(pc, token_index, true);1456 node->data.if_bool_expr.else_node = ast_parse_block_expr_or_expression(pc, token_index, true);
1456 }1457 }
14571458
1458 return node;1459 return node;
...@@ -1860,15 +1861,15 @@ static bool statement_has_block_body(AstNode *node) {...@@ -1860,15 +1861,15 @@ static bool statement_has_block_body(AstNode *node) {
1860 switch (node->type) {1861 switch (node->type) {
1861 case NodeTypeIfBoolExpr:1862 case NodeTypeIfBoolExpr:
1862 if (node->data.if_bool_expr.else_node)1863 if (node->data.if_bool_expr.else_node)
1863 return node->data.if_bool_expr.else_node->type == NodeTypeBlock;1864 return statement_has_block_body(node->data.if_bool_expr.else_node);
1864 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;1865 return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
1865 case NodeTypeIfVarExpr:1866 case NodeTypeIfVarExpr:
1866 if (node->data.if_var_expr.else_node)1867 if (node->data.if_var_expr.else_node)
1867 return node->data.if_var_expr.else_node->type == NodeTypeBlock;1868 return statement_has_block_body(node->data.if_var_expr.else_node);
1868 return node->data.if_var_expr.then_block->type == NodeTypeBlock;1869 return node->data.if_var_expr.then_block->type == NodeTypeBlock;
1869 case NodeTypeTryExpr:1870 case NodeTypeTryExpr:
1870 if (node->data.try_expr.else_node)1871 if (node->data.try_expr.else_node)
1871 return node->data.try_expr.else_node->type == NodeTypeBlock;1872 return statement_has_block_body(node->data.try_expr.else_node);
1872 return node->data.try_expr.then_node->type == NodeTypeBlock;1873 return node->data.try_expr.then_node->type == NodeTypeBlock;
1873 case NodeTypeWhileExpr:1874 case NodeTypeWhileExpr:
1874 return node->data.while_expr.body->type == NodeTypeBlock;1875 return node->data.while_expr.body->type == NodeTypeBlock;
...@@ -1882,7 +1883,7 @@ static bool statement_has_block_body(AstNode *node) {...@@ -1882,7 +1883,7 @@ static bool statement_has_block_body(AstNode *node) {
1882 case NodeTypeDefer:1883 case NodeTypeDefer:
1883 return node->data.defer.expr->type == NodeTypeBlock;1884 return node->data.defer.expr->type == NodeTypeBlock;
1884 default:1885 default:
1885 zig_unreachable();1886 return false;
1886 }1887 }
1887}1888}
18881889
...@@ -2030,6 +2031,14 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, size_t *token_index, bool m...@@ -2030,6 +2031,14 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, size_t *token_index, bool m
2030 return node;2031 return node;
2031}2032}
20322033
2034static AstNode *ast_parse_block_expr_or_expression(ParseContext *pc, size_t *token_index, bool mandatory) {
2035 AstNode *block_expr = ast_parse_block_expr(pc, token_index, false);
2036 if (block_expr)
2037 return block_expr;
2038
2039 return ast_parse_expression(pc, token_index, mandatory);
2040}
2041
2033/*2042/*
2034BlockOrExpression = Block | Expression2043BlockOrExpression = Block | Expression
2035*/2044*/