| ... | @@ -211,6 +211,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) { | ... | @@ -211,6 +211,7 @@ static void ast_invalid_token_error(ParseContext *pc, Token *token) { |
| 211 | ast_error(pc, token, "invalid token: '%s'", buf_ptr(&token_value)); | 211 | ast_error(pc, token, "invalid token: '%s'", buf_ptr(&token_value)); |
| 212 | } | 212 | } |
| 213 | | 213 | |
| | 214 | static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_index, bool mandatory); |
| 214 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory); | 215 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory); |
| 215 | static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory); | 216 | static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory); |
| 216 | static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory); | 217 | static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory); |
| ... | @@ -632,12 +633,12 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b | ... | @@ -632,12 +633,12 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 632 | if (require_block_body) | 633 | if (require_block_body) |
| 633 | node->data.comptime_expr.expr = ast_parse_block(pc, token_index, true); | 634 | node->data.comptime_expr.expr = ast_parse_block(pc, token_index, true); |
| 634 | else | 635 | else |
| 635 | node->data.comptime_expr.expr = ast_parse_expression(pc, token_index, true); | 636 | node->data.comptime_expr.expr = ast_parse_block_or_expression(pc, token_index, true); |
| 636 | return node; | 637 | return node; |
| 637 | } | 638 | } |
| 638 | | 639 | |
| 639 | /* | 640 | /* |
| 640 | TryExpression = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" Expression option("else" option("|" Symbol "|") Expression) | 641 | TryExpression(body) = "try" "(" option(("const" | "var") option("*") Symbol "=") Expression ")" body option("else" option("|" Symbol "|") body) |
| 641 | */ | 642 | */ |
| 642 | static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 643 | static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 643 | Token *try_token = &pc->tokens->at(*token_index); | 644 | Token *try_token = &pc->tokens->at(*token_index); |
| ... | @@ -685,29 +686,29 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m | ... | @@ -685,29 +686,29 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m |
| 685 | | 686 | |
| 686 | ast_eat_token(pc, token_index, TokenIdRParen); | 687 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 687 | | 688 | |
| 688 | node->data.try_expr.then_node = ast_parse_expression(pc, token_index, true); | 689 | node->data.try_expr.then_node = ast_parse_block_or_expression(pc, token_index, true); |
| 689 | | 690 | |
| 690 | Token *else_token = &pc->tokens->at(*token_index); | 691 | Token *else_token = &pc->tokens->at(*token_index); |
| 691 | if (else_token->id != TokenIdKeywordElse) | 692 | if (else_token->id == TokenIdKeywordElse) { |
| 692 | return node; | | |
| 693 | | | |
| 694 | *token_index += 1; | | |
| 695 | Token *open_bar_tok = &pc->tokens->at(*token_index); | | |
| 696 | if (open_bar_tok->id == TokenIdBinOr) { | | |
| 697 | *token_index += 1; | 693 | *token_index += 1; |
| | 694 | Token *open_bar_tok = &pc->tokens->at(*token_index); |
| | 695 | if (open_bar_tok->id == TokenIdBinOr) { |
| | 696 | *token_index += 1; |
| 698 | | 697 | |
| 699 | Token *err_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); | 698 | Token *err_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); |
| 700 | node->data.try_expr.err_symbol = token_buf(err_name_tok); | 699 | node->data.try_expr.err_symbol = token_buf(err_name_tok); |
| 701 | | 700 | |
| 702 | ast_eat_token(pc, token_index, TokenIdBinOr); | 701 | ast_eat_token(pc, token_index, TokenIdBinOr); |
| | 702 | } |
| | 703 | |
| | 704 | node->data.try_expr.else_node = ast_parse_block_or_expression(pc, token_index, true); |
| 703 | } | 705 | } |
| 704 | | 706 | |
| 705 | node->data.try_expr.else_node = ast_parse_expression(pc, token_index, true); | | |
| 706 | return node; | 707 | return node; |
| 707 | } | 708 | } |
| 708 | | 709 | |
| 709 | /* | 710 | /* |
| 710 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | 711 | PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl |
| 711 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable" | 712 | KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable" |
| 712 | */ | 713 | */ |
| 713 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 714 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| ... | @@ -1381,27 +1382,9 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, b | ... | @@ -1381,27 +1382,9 @@ static AstNode *ast_parse_bool_and_expr(ParseContext *pc, size_t *token_index, b |
| 1381 | } | 1382 | } |
| 1382 | | 1383 | |
| 1383 | /* | 1384 | /* |
| 1384 | Else : token(Else) Expression | 1385 | IfExpression(body) = IfVarExpression(body) | IfBoolExpression(body) |
| 1385 | */ | 1386 | IfBoolExpression(body) = "if" "(" Expression ")" body option("else" body) |
| 1386 | static AstNode *ast_parse_else(ParseContext *pc, size_t *token_index, bool mandatory) { | 1387 | IfVarExpression(body) = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" body Option("else" body) |
| 1387 | Token *else_token = &pc->tokens->at(*token_index); | | |
| 1388 | | | |
| 1389 | if (else_token->id != TokenIdKeywordElse) { | | |
| 1390 | if (mandatory) { | | |
| 1391 | ast_expect_token(pc, else_token, TokenIdKeywordElse); | | |
| 1392 | } else { | | |
| 1393 | return nullptr; | | |
| 1394 | } | | |
| 1395 | } | | |
| 1396 | *token_index += 1; | | |
| 1397 | | | |
| 1398 | return ast_parse_expression(pc, token_index, true); | | |
| 1399 | } | | |
| 1400 | | | |
| 1401 | /* | | |
| 1402 | IfExpression : IfVarExpression | IfBoolExpression | | |
| 1403 | IfBoolExpression = "if" "(" Expression ")" Expression option(Else) | | |
| 1404 | IfVarExpression = "if" "(" ("const" | "var") option("*") Symbol option(":" TypeExpr) "?=" Expression ")" Expression Option(Else) | | |
| 1405 | */ | 1388 | */ |
| 1406 | static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1389 | static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1407 | Token *if_token = &pc->tokens->at(*token_index); | 1390 | Token *if_token = &pc->tokens->at(*token_index); |
| ... | @@ -1451,16 +1434,26 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma | ... | @@ -1451,16 +1434,26 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, size_t *token_index, bool ma |
| 1451 | ast_invalid_token_error(pc, eq_or_colon); | 1434 | ast_invalid_token_error(pc, eq_or_colon); |
| 1452 | } | 1435 | } |
| 1453 | ast_eat_token(pc, token_index, TokenIdRParen); | 1436 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 1454 | node->data.if_var_expr.then_block = ast_parse_expression(pc, token_index, true); | 1437 | node->data.if_var_expr.then_block = ast_parse_block_or_expression(pc, token_index, true); |
| 1455 | node->data.if_var_expr.else_node = ast_parse_else(pc, token_index, false); | 1438 | |
| | 1439 | Token *else_token = &pc->tokens->at(*token_index); |
| | 1440 | if (else_token->id == TokenIdKeywordElse) { |
| | 1441 | *token_index += 1; |
| | 1442 | node->data.if_var_expr.else_node = ast_parse_block_or_expression(pc, token_index, true); |
| | 1443 | } |
| 1456 | | 1444 | |
| 1457 | return node; | 1445 | return node; |
| 1458 | } else { | 1446 | } else { |
| 1459 | AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token); | 1447 | AstNode *node = ast_create_node(pc, NodeTypeIfBoolExpr, if_token); |
| 1460 | node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true); | 1448 | node->data.if_bool_expr.condition = ast_parse_expression(pc, token_index, true); |
| 1461 | ast_eat_token(pc, token_index, TokenIdRParen); | 1449 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 1462 | node->data.if_bool_expr.then_block = ast_parse_expression(pc, token_index, true); | 1450 | node->data.if_bool_expr.then_block = ast_parse_block_or_expression(pc, token_index, true); |
| 1463 | node->data.if_bool_expr.else_node = ast_parse_else(pc, token_index, false); | 1451 | |
| | 1452 | Token *else_token = &pc->tokens->at(*token_index); |
| | 1453 | if (else_token->id == TokenIdKeywordElse) { |
| | 1454 | *token_index += 1; |
| | 1455 | node->data.if_bool_expr.else_node = ast_parse_block_or_expression(pc, token_index, true); |
| | 1456 | } |
| 1464 | | 1457 | |
| 1465 | return node; | 1458 | return node; |
| 1466 | } | 1459 | } |
| ... | @@ -1509,7 +1502,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) { | ... | @@ -1509,7 +1502,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index) { |
| 1509 | } | 1502 | } |
| 1510 | | 1503 | |
| 1511 | /* | 1504 | /* |
| 1512 | Defer = option("%" | "?") "defer" Expression | 1505 | Defer(body) = option("%" | "?") "defer" body |
| 1513 | */ | 1506 | */ |
| 1514 | static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { | 1507 | static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1515 | Token *token = &pc->tokens->at(*token_index); | 1508 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -1545,7 +1538,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { | ... | @@ -1545,7 +1538,7 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1545 | | 1538 | |
| 1546 | AstNode *node = ast_create_node(pc, node_type, token); | 1539 | AstNode *node = ast_create_node(pc, node_type, token); |
| 1547 | node->data.defer.kind = kind; | 1540 | node->data.defer.kind = kind; |
| 1548 | node->data.defer.expr = ast_parse_expression(pc, token_index, true); | 1541 | node->data.defer.expr = ast_parse_block_or_expression(pc, token_index, true); |
| 1549 | | 1542 | |
| 1550 | return node; | 1543 | return node; |
| 1551 | } | 1544 | } |
| ... | @@ -1648,7 +1641,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo | ... | @@ -1648,7 +1641,7 @@ static AstNode *ast_parse_bool_or_expr(ParseContext *pc, size_t *token_index, bo |
| 1648 | } | 1641 | } |
| 1649 | | 1642 | |
| 1650 | /* | 1643 | /* |
| 1651 | WhileExpression = option("inline") "while" "(" Expression option(";" Expression) ")" Expression | 1644 | WhileExpression(body) = option("inline") "while" "(" Expression option(";" Expression) ")" body |
| 1652 | */ | 1645 | */ |
| 1653 | static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1646 | static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1654 | Token *first_token = &pc->tokens->at(*token_index); | 1647 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -1686,12 +1679,12 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool | ... | @@ -1686,12 +1679,12 @@ static AstNode *ast_parse_while_expr(ParseContext *pc, size_t *token_index, bool |
| 1686 | | 1679 | |
| 1687 | if (semi_or_rparen->id == TokenIdRParen) { | 1680 | if (semi_or_rparen->id == TokenIdRParen) { |
| 1688 | *token_index += 1; | 1681 | *token_index += 1; |
| 1689 | node->data.while_expr.body = ast_parse_expression(pc, token_index, true); | 1682 | node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true); |
| 1690 | } else if (semi_or_rparen->id == TokenIdSemicolon) { | 1683 | } else if (semi_or_rparen->id == TokenIdSemicolon) { |
| 1691 | *token_index += 1; | 1684 | *token_index += 1; |
| 1692 | node->data.while_expr.continue_expr = ast_parse_expression(pc, token_index, true); | 1685 | node->data.while_expr.continue_expr = ast_parse_expression(pc, token_index, true); |
| 1693 | ast_eat_token(pc, token_index, TokenIdRParen); | 1686 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 1694 | node->data.while_expr.body = ast_parse_expression(pc, token_index, true); | 1687 | node->data.while_expr.body = ast_parse_block_or_expression(pc, token_index, true); |
| 1695 | } else { | 1688 | } else { |
| 1696 | ast_invalid_token_error(pc, semi_or_rparen); | 1689 | ast_invalid_token_error(pc, semi_or_rparen); |
| 1697 | } | 1690 | } |
| ... | @@ -1708,7 +1701,7 @@ static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index) { | ... | @@ -1708,7 +1701,7 @@ static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index) { |
| 1708 | } | 1701 | } |
| 1709 | | 1702 | |
| 1710 | /* | 1703 | /* |
| 1711 | ForExpression = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") Expression | 1704 | ForExpression(body) = option("inline") "for" "(" Expression ")" option("|" option("*") Symbol option("," Symbol) "|") body |
| 1712 | */ | 1705 | */ |
| 1713 | static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1706 | static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1714 | Token *first_token = &pc->tokens->at(*token_index); | 1707 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -1766,7 +1759,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool m | ... | @@ -1766,7 +1759,7 @@ static AstNode *ast_parse_for_expr(ParseContext *pc, size_t *token_index, bool m |
| 1766 | ast_eat_token(pc, token_index, TokenIdBinOr); | 1759 | ast_eat_token(pc, token_index, TokenIdBinOr); |
| 1767 | } | 1760 | } |
| 1768 | | 1761 | |
| 1769 | node->data.for_expr.body = ast_parse_expression(pc, token_index, true); | 1762 | node->data.for_expr.body = ast_parse_block_or_expression(pc, token_index, true); |
| 1770 | | 1763 | |
| 1771 | return node; | 1764 | return node; |
| 1772 | } | 1765 | } |
| ... | @@ -1861,8 +1854,36 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo | ... | @@ -1861,8 +1854,36 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo |
| 1861 | } | 1854 | } |
| 1862 | } | 1855 | } |
| 1863 | | 1856 | |
| | 1857 | static bool block_expr_has_block_body(AstNode *node) { |
| | 1858 | switch (node->type) { |
| | 1859 | case NodeTypeIfBoolExpr: |
| | 1860 | if (node->data.if_bool_expr.else_node) |
| | 1861 | return node->data.if_bool_expr.else_node->type == NodeTypeBlock; |
| | 1862 | return node->data.if_bool_expr.then_block->type == NodeTypeBlock; |
| | 1863 | case NodeTypeIfVarExpr: |
| | 1864 | if (node->data.if_var_expr.else_node) |
| | 1865 | return node->data.if_var_expr.else_node->type == NodeTypeBlock; |
| | 1866 | return node->data.if_var_expr.then_block->type == NodeTypeBlock; |
| | 1867 | case NodeTypeTryExpr: |
| | 1868 | if (node->data.try_expr.else_node) |
| | 1869 | return node->data.try_expr.else_node->type == NodeTypeBlock; |
| | 1870 | return node->data.try_expr.then_node->type == NodeTypeBlock; |
| | 1871 | case NodeTypeWhileExpr: |
| | 1872 | return node->data.while_expr.body->type == NodeTypeBlock; |
| | 1873 | case NodeTypeForExpr: |
| | 1874 | return node->data.for_expr.body->type == NodeTypeBlock; |
| | 1875 | case NodeTypeSwitchExpr: |
| | 1876 | case NodeTypeBlock: |
| | 1877 | return true; |
| | 1878 | case NodeTypeCompTime: |
| | 1879 | return node->data.comptime_expr.expr->type == NodeTypeBlock; |
| | 1880 | default: |
| | 1881 | zig_unreachable(); |
| | 1882 | } |
| | 1883 | } |
| | 1884 | |
| 1864 | /* | 1885 | /* |
| 1865 | BlockExpression = IfExpression | Block | WhileExpression | ForExpression | SwitchExpression | CompTimeExpression | TryExpression | 1886 | BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body) |
| 1866 | */ | 1887 | */ |
| 1867 | static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 1888 | static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 1868 | Token *token = &pc->tokens->at(*token_index); | 1889 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -2006,38 +2027,29 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, size_t *token_index, bool m | ... | @@ -2006,38 +2027,29 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, size_t *token_index, bool m |
| 2006 | } | 2027 | } |
| 2007 | | 2028 | |
| 2008 | /* | 2029 | /* |
| 2009 | NonBlockExpression : ReturnExpression | AssignmentExpression | 2030 | BlockOrExpression = Block | Expression |
| 2010 | */ | 2031 | */ |
| 2011 | static AstNode *ast_parse_non_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 2032 | static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2012 | Token *token = &pc->tokens->at(*token_index); | 2033 | AstNode *block_expr = ast_parse_block(pc, token_index, false); |
| 2013 | | 2034 | if (block_expr) |
| 2014 | AstNode *return_expr = ast_parse_return_expr(pc, token_index); | 2035 | return block_expr; |
| 2015 | if (return_expr) | | |
| 2016 | return return_expr; | | |
| 2017 | | | |
| 2018 | AstNode *ass_expr = ast_parse_ass_expr(pc, token_index, false); | | |
| 2019 | if (ass_expr) | | |
| 2020 | return ass_expr; | | |
| 2021 | | | |
| 2022 | if (mandatory) | | |
| 2023 | ast_invalid_token_error(pc, token); | | |
| 2024 | | 2036 | |
| 2025 | return nullptr; | 2037 | return ast_parse_expression(pc, token_index, mandatory); |
| 2026 | } | 2038 | } |
| 2027 | | 2039 | |
| 2028 | /* | 2040 | /* |
| 2029 | Expression : BlockExpression | NonBlockExpression | 2041 | Expression = ReturnExpression | AssignmentExpression |
| 2030 | */ | 2042 | */ |
| 2031 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory) { | 2043 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2032 | Token *token = &pc->tokens->at(*token_index); | 2044 | Token *token = &pc->tokens->at(*token_index); |
| 2033 | | 2045 | |
| 2034 | AstNode *block_expr = ast_parse_block_expr(pc, token_index, false); | 2046 | AstNode *return_expr = ast_parse_return_expr(pc, token_index); |
| 2035 | if (block_expr) | 2047 | if (return_expr) |
| 2036 | return block_expr; | 2048 | return return_expr; |
| 2037 | | 2049 | |
| 2038 | AstNode *non_block_expr = ast_parse_non_block_expr(pc, token_index, false); | 2050 | AstNode *ass_expr = ast_parse_ass_expr(pc, token_index, false); |
| 2039 | if (non_block_expr) | 2051 | if (ass_expr) |
| 2040 | return non_block_expr; | 2052 | return ass_expr; |
| 2041 | | 2053 | |
| 2042 | if (mandatory) | 2054 | if (mandatory) |
| 2043 | ast_invalid_token_error(pc, token); | 2055 | ast_invalid_token_error(pc, token); |
| ... | @@ -2080,8 +2092,8 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { | ... | @@ -2080,8 +2092,8 @@ static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) { |
| 2080 | } | 2092 | } |
| 2081 | | 2093 | |
| 2082 | /* | 2094 | /* |
| 2083 | Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace) | 2095 | Block = "{" many(Statement) option(Expression) "}" |
| 2084 | Statement = Label | VariableDeclaration ";" | Defer ";" | NonBlockExpression ";" | BlockExpression | 2096 | Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" |
| 2085 | */ | 2097 | */ |
| 2086 | static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory) { | 2098 | static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2087 | Token *last_token = &pc->tokens->at(*token_index); | 2099 | Token *last_token = &pc->tokens->at(*token_index); |
| ... | @@ -2100,7 +2112,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2100,7 +2112,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2100 | for (;;) { | 2112 | for (;;) { |
| 2101 | AstNode *statement_node = ast_parse_label(pc, token_index, false); | 2113 | AstNode *statement_node = ast_parse_label(pc, token_index, false); |
| 2102 | bool need_implicit_final_void_statement = false; | 2114 | bool need_implicit_final_void_statement = false; |
| 2103 | bool semicolon_expected; | 2115 | bool semicolon_expected = true; |
| 2104 | if (statement_node) { | 2116 | if (statement_node) { |
| 2105 | semicolon_expected = false; | 2117 | semicolon_expected = false; |
| 2106 | // if a label is the last thing in a block, add a void statement. | 2118 | // if a label is the last thing in a block, add a void statement. |
| ... | @@ -2109,17 +2121,18 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand | ... | @@ -2109,17 +2121,18 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2109 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); | 2121 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); |
| 2110 | if (!statement_node) { | 2122 | if (!statement_node) { |
| 2111 | statement_node = ast_parse_defer_expr(pc, token_index); | 2123 | statement_node = ast_parse_defer_expr(pc, token_index); |
| 2112 | } | | |
| 2113 | if (statement_node) { | | |
| 2114 | semicolon_expected = true; | | |
| 2115 | } else { | | |
| 2116 | statement_node = ast_parse_block_expr(pc, token_index, false); | | |
| 2117 | semicolon_expected = !statement_node; | | |
| 2118 | if (!statement_node) { | 2124 | if (!statement_node) { |
| 2119 | statement_node = ast_parse_non_block_expr(pc, token_index, false); | 2125 | statement_node = ast_parse_block_expr(pc, token_index, false); |
| 2120 | if (!statement_node) { | 2126 | if (statement_node) { |
| 2121 | // final semicolon means add a void statement. | 2127 | if (block_expr_has_block_body(statement_node)) { |
| 2122 | need_implicit_final_void_statement = true; | 2128 | semicolon_expected = false; |
| | 2129 | } |
| | 2130 | } else { |
| | 2131 | statement_node = ast_parse_expression(pc, token_index, false); |
| | 2132 | if (!statement_node) { |
| | 2133 | // final semicolon means add a void statement. |
| | 2134 | need_implicit_final_void_statement = true; |
| | 2135 | } |
| 2123 | } | 2136 | } |
| 2124 | } | 2137 | } |
| 2125 | } | 2138 | } |
| ... | @@ -2301,7 +2314,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi | ... | @@ -2301,7 +2314,7 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi |
| 2301 | /* | 2314 | /* |
| 2302 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}" | 2315 | ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}" |
| 2303 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) | 2316 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 2304 | ContainerField = Symbol option(":" Expression) ",") | 2317 | ContainerField = Symbol option(":" Expression) "," |
| 2305 | */ | 2318 | */ |
| 2306 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { | 2319 | static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2307 | Token *first_token = &pc->tokens->at(*token_index); | 2320 | Token *first_token = &pc->tokens->at(*token_index); |