LCOV - code coverage report
Current view: top level - src - parser.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 1624 1901 85.4 %
Date: 1970-01-01 00:00:01 Functions: 122 128 95.3 %
Branches: 573 680 84.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2015 Andrew Kelley
       3                 :            :  *
       4                 :            :  * This file is part of zig, which is MIT licensed.
       5                 :            :  * See http://opensource.org/licenses/MIT
       6                 :            :  */
       7                 :            : 
       8                 :            : #include "parser.hpp"
       9                 :            : #include "errmsg.hpp"
      10                 :            : #include "analyze.hpp"
      11                 :            : 
      12                 :            : #include <stdarg.h>
      13                 :            : #include <stdio.h>
      14                 :            : #include <limits.h>
      15                 :            : #include <errno.h>
      16                 :            : 
      17                 :            : struct ParseContext {
      18                 :            :     Buf *buf;
      19                 :            :     size_t current_token;
      20                 :            :     ZigList<Token> *tokens;
      21                 :            :     ZigType *owner;
      22                 :            :     ErrColor err_color;
      23                 :            : };
      24                 :            : 
      25                 :            : struct PtrPayload {
      26                 :            :     Token *asterisk;
      27                 :            :     Token *payload;
      28                 :            : };
      29                 :            : 
      30                 :            : struct PtrIndexPayload {
      31                 :            :     Token *asterisk;
      32                 :            :     Token *payload;
      33                 :            :     Token *index;
      34                 :            : };
      35                 :            : 
      36                 :            : static AstNode *ast_parse_root(ParseContext *pc);
      37                 :            : static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc);
      38                 :            : static AstNode *ast_parse_test_decl(ParseContext *pc);
      39                 :            : static AstNode *ast_parse_top_level_comptime(ParseContext *pc);
      40                 :            : static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod);
      41                 :            : static AstNode *ast_parse_fn_proto(ParseContext *pc);
      42                 :            : static AstNode *ast_parse_var_decl(ParseContext *pc);
      43                 :            : static AstNode *ast_parse_container_field(ParseContext *pc);
      44                 :            : static AstNode *ast_parse_statement(ParseContext *pc);
      45                 :            : static AstNode *ast_parse_if_statement(ParseContext *pc);
      46                 :            : static AstNode *ast_parse_labeled_statement(ParseContext *pc);
      47                 :            : static AstNode *ast_parse_loop_statement(ParseContext *pc);
      48                 :            : static AstNode *ast_parse_for_statement(ParseContext *pc);
      49                 :            : static AstNode *ast_parse_while_statement(ParseContext *pc);
      50                 :            : static AstNode *ast_parse_block_expr_statement(ParseContext *pc);
      51                 :            : static AstNode *ast_parse_block_expr(ParseContext *pc);
      52                 :            : static AstNode *ast_parse_assign_expr(ParseContext *pc);
      53                 :            : static AstNode *ast_parse_expr(ParseContext *pc);
      54                 :            : static AstNode *ast_parse_bool_or_expr(ParseContext *pc);
      55                 :            : static AstNode *ast_parse_bool_and_expr(ParseContext *pc);
      56                 :            : static AstNode *ast_parse_compare_expr(ParseContext *pc);
      57                 :            : static AstNode *ast_parse_bitwise_expr(ParseContext *pc);
      58                 :            : static AstNode *ast_parse_bit_shit_expr(ParseContext *pc);
      59                 :            : static AstNode *ast_parse_addition_expr(ParseContext *pc);
      60                 :            : static AstNode *ast_parse_multiply_expr(ParseContext *pc);
      61                 :            : static AstNode *ast_parse_prefix_expr(ParseContext *pc);
      62                 :            : static AstNode *ast_parse_primary_expr(ParseContext *pc);
      63                 :            : static AstNode *ast_parse_if_expr(ParseContext *pc);
      64                 :            : static AstNode *ast_parse_block(ParseContext *pc);
      65                 :            : static AstNode *ast_parse_loop_expr(ParseContext *pc);
      66                 :            : static AstNode *ast_parse_for_expr(ParseContext *pc);
      67                 :            : static AstNode *ast_parse_while_expr(ParseContext *pc);
      68                 :            : static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc);
      69                 :            : static AstNode *ast_parse_init_list(ParseContext *pc);
      70                 :            : static AstNode *ast_parse_type_expr(ParseContext *pc);
      71                 :            : static AstNode *ast_parse_error_union_expr(ParseContext *pc);
      72                 :            : static AstNode *ast_parse_suffix_expr(ParseContext *pc);
      73                 :            : static AstNode *ast_parse_primary_type_expr(ParseContext *pc);
      74                 :            : static AstNode *ast_parse_container_decl(ParseContext *pc);
      75                 :            : static AstNode *ast_parse_error_set_decl(ParseContext *pc);
      76                 :            : static AstNode *ast_parse_grouped_expr(ParseContext *pc);
      77                 :            : static AstNode *ast_parse_if_type_expr(ParseContext *pc);
      78                 :            : static AstNode *ast_parse_labeled_type_expr(ParseContext *pc);
      79                 :            : static AstNode *ast_parse_loop_type_expr(ParseContext *pc);
      80                 :            : static AstNode *ast_parse_for_type_expr(ParseContext *pc);
      81                 :            : static AstNode *ast_parse_while_type_expr(ParseContext *pc);
      82                 :            : static AstNode *ast_parse_switch_expr(ParseContext *pc);
      83                 :            : static AstNode *ast_parse_asm_expr(ParseContext *pc);
      84                 :            : static AstNode *ast_parse_enum_lit(ParseContext *pc);
      85                 :            : static AstNode *ast_parse_asm_output(ParseContext *pc);
      86                 :            : static AsmOutput *ast_parse_asm_output_item(ParseContext *pc);
      87                 :            : static AstNode *ast_parse_asm_input(ParseContext *pc);
      88                 :            : static AsmInput *ast_parse_asm_input_item(ParseContext *pc);
      89                 :            : static AstNode *ast_parse_asm_clobbers(ParseContext *pc);
      90                 :            : static Token *ast_parse_break_label(ParseContext *pc);
      91                 :            : static Token *ast_parse_block_label(ParseContext *pc);
      92                 :            : static AstNode *ast_parse_field_init(ParseContext *pc);
      93                 :            : static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
      94                 :            : static AstNode *ast_parse_link_section(ParseContext *pc);
      95                 :            : static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
      96                 :            : static AstNode *ast_parse_param_decl(ParseContext *pc);
      97                 :            : static AstNode *ast_parse_param_type(ParseContext *pc);
      98                 :            : static AstNode *ast_parse_if_prefix(ParseContext *pc);
      99                 :            : static AstNode *ast_parse_while_prefix(ParseContext *pc);
     100                 :            : static AstNode *ast_parse_for_prefix(ParseContext *pc);
     101                 :            : static Token *ast_parse_payload(ParseContext *pc);
     102                 :            : static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc);
     103                 :            : static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc);
     104                 :            : static AstNode *ast_parse_switch_prong(ParseContext *pc);
     105                 :            : static AstNode *ast_parse_switch_case(ParseContext *pc);
     106                 :            : static AstNode *ast_parse_switch_item(ParseContext *pc);
     107                 :            : static AstNode *ast_parse_assign_op(ParseContext *pc);
     108                 :            : static AstNode *ast_parse_compare_op(ParseContext *pc);
     109                 :            : static AstNode *ast_parse_bitwise_op(ParseContext *pc);
     110                 :            : static AstNode *ast_parse_bit_shift_op(ParseContext *pc);
     111                 :            : static AstNode *ast_parse_addition_op(ParseContext *pc);
     112                 :            : static AstNode *ast_parse_multiply_op(ParseContext *pc);
     113                 :            : static AstNode *ast_parse_prefix_op(ParseContext *pc);
     114                 :            : static AstNode *ast_parse_prefix_type_op(ParseContext *pc);
     115                 :            : static AstNode *ast_parse_suffix_op(ParseContext *pc);
     116                 :            : static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc);
     117                 :            : static AstNode *ast_parse_array_type_start(ParseContext *pc);
     118                 :            : static AstNode *ast_parse_ptr_type_start(ParseContext *pc);
     119                 :            : static AstNode *ast_parse_container_decl_auto(ParseContext *pc);
     120                 :            : static AstNode *ast_parse_container_decl_type(ParseContext *pc);
     121                 :            : static AstNode *ast_parse_byte_align(ParseContext *pc);
     122                 :            : 
     123                 :            : ATTRIBUTE_PRINTF(3, 4)
     124                 :            : ATTRIBUTE_NORETURN
     125                 :          0 : static void ast_error(ParseContext *pc, Token *token, const char *format, ...) {
     126                 :            :     va_list ap;
     127                 :          0 :     va_start(ap, format);
     128                 :          0 :     Buf *msg = buf_vprintf(format, ap);
     129                 :          0 :     va_end(ap);
     130                 :            : 
     131                 :            : 
     132                 :          0 :     ErrorMsg *err = err_msg_create_with_line(pc->owner->data.structure.root_struct->path,
     133                 :            :             token->start_line, token->start_column,
     134                 :          0 :             pc->owner->data.structure.root_struct->source_code,
     135                 :          0 :             pc->owner->data.structure.root_struct->line_offsets, msg);
     136                 :          0 :     err->line_start = token->start_line;
     137                 :          0 :     err->column_start = token->start_column;
     138                 :            : 
     139                 :          0 :     print_err_msg(err, pc->err_color);
     140                 :          0 :     exit(EXIT_FAILURE);
     141                 :            : }
     142                 :            : 
     143                 :          0 : static Buf ast_token_str(Buf *input, Token *token) {
     144                 :          0 :     Buf str = BUF_INIT;
     145                 :          0 :     buf_init_from_mem(&str, buf_ptr(input) + token->start_pos, token->end_pos - token->start_pos);
     146                 :          0 :     return str;
     147                 :            : }
     148                 :            : 
     149                 :            : ATTRIBUTE_NORETURN
     150                 :          0 : static void ast_invalid_token_error(ParseContext *pc, Token *token) {
     151                 :          0 :     Buf token_value = ast_token_str(pc->buf, token);
     152                 :          0 :     ast_error(pc, token, "invalid token: '%s'", buf_ptr(&token_value));
     153                 :            : }
     154                 :            : 
     155                 :    1473162 : static AstNode *ast_create_node_no_line_info(ParseContext *pc, NodeType type) {
     156                 :    1473162 :     AstNode *node = allocate<AstNode>(1);
     157                 :    1473162 :     node->type = type;
     158                 :    1473162 :     node->owner = pc->owner;
     159                 :    1473162 :     return node;
     160                 :            : }
     161                 :            : 
     162                 :    1405610 : static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_token) {
     163                 :    1405610 :     assert(first_token);
     164                 :    1405610 :     AstNode *node = ast_create_node_no_line_info(pc, type);
     165                 :    1405610 :     node->line = first_token->start_line;
     166                 :    1405610 :     node->column = first_token->start_column;
     167                 :    1405610 :     return node;
     168                 :            : }
     169                 :            : 
     170                 :      67247 : static AstNode *ast_create_node_copy_line_info(ParseContext *pc, NodeType type, AstNode *from) {
     171                 :      67247 :     assert(from);
     172                 :      67247 :     AstNode *node = ast_create_node_no_line_info(pc, type);
     173                 :      67247 :     node->line = from->line;
     174                 :      67247 :     node->column = from->column;
     175                 :      67247 :     return node;
     176                 :            : }
     177                 :            : 
     178                 :   54198995 : static Token *peek_token_i(ParseContext *pc, size_t i) {
     179                 :   54198995 :     return &pc->tokens->at(pc->current_token + i);
     180                 :            : }
     181                 :            : 
     182                 :   54198995 : static Token *peek_token(ParseContext *pc) {
     183                 :   54198995 :     return peek_token_i(pc, 0);
     184                 :            : }
     185                 :            : 
     186                 :    3556752 : static Token *eat_token(ParseContext *pc) {
     187                 :    3556752 :     Token *res = peek_token(pc);
     188                 :    3556752 :     pc->current_token += 1;
     189                 :    3556752 :     return res;
     190                 :            : }
     191                 :            : 
     192                 :   45995436 : static Token *eat_token_if(ParseContext *pc, TokenId id) {
     193                 :   45995436 :     Token *res = peek_token(pc);
     194         [ +  + ]:   45995436 :     if (res->id == id)
     195                 :    2613825 :         return eat_token(pc);
     196                 :            : 
     197                 :   43381611 :     return nullptr;
     198                 :            : }
     199                 :            : 
     200                 :     843448 : static Token *expect_token(ParseContext *pc, TokenId id) {
     201                 :     843448 :     Token *res = eat_token(pc);
     202         [ -  + ]:     843448 :     if (res->id != id)
     203                 :          0 :         ast_error(pc, res, "expected token '%s', found '%s'", token_name(id), token_name(res->id));
     204                 :            : 
     205                 :     843448 :     return res;
     206                 :            : }
     207                 :            : 
     208                 :     831739 : static void put_back_token(ParseContext *pc) {
     209                 :     831739 :     pc->current_token -= 1;
     210                 :     831739 : }
     211                 :            : 
     212                 :     838641 : static Buf *token_buf(Token *token) {
     213         [ +  + ]:     838641 :     if (token == nullptr)
     214                 :      18600 :         return nullptr;
     215 [ +  + ][ +  - ]:     820041 :     assert(token->id == TokenIdStringLiteral || token->id == TokenIdSymbol);
     216                 :     820041 :     return &token->data.str_lit.str;
     217                 :            : }
     218                 :            : 
     219                 :         48 : static BigInt *token_bigint(Token *token) {
     220                 :         48 :     assert(token->id == TokenIdIntLiteral);
     221                 :         48 :     return &token->data.int_lit.bigint;
     222                 :            : }
     223                 :            : 
     224                 :     434860 : static AstNode *token_symbol(ParseContext *pc, Token *token) {
     225                 :     434860 :     assert(token->id == TokenIdSymbol);
     226                 :     434860 :     AstNode *res = ast_create_node(pc, NodeTypeSymbol, token);
     227                 :     434860 :     res->data.symbol_expr.symbol = token_buf(token);
     228                 :     434860 :     return res;
     229                 :            : }
     230                 :            : 
     231                 :            : // (Rule SEP)* Rule?
     232                 :            : template<typename T>
     233                 :     171840 : static ZigList<T *> ast_parse_list(ParseContext *pc, TokenId sep, T *(*parser)(ParseContext*)) {
     234                 :     171840 :     ZigList<T *> res = {};
     235                 :     116894 :     while (true) {
     236                 :     288734 :         T *curr = parser(pc);
     237   [ +  +  +  +  :     288734 :         if (curr == nullptr)
             +  +  +  + ]
     238                 :      24166 :             break;
     239                 :            : 
     240                 :     264568 :         res.append(curr);
     241   [ +  +  +  +  :     264568 :         if (eat_token_if(pc, sep) == nullptr)
             +  +  +  + ]
     242                 :     147674 :             break;
     243                 :            :     }
     244                 :            : 
     245                 :     171840 :     return res;
     246                 :            : }
     247                 :            : 
     248                 :     451111 : static AstNode *ast_expect(ParseContext *pc, AstNode *(*parser)(ParseContext*)) {
     249                 :     451111 :     AstNode *res = parser(pc);
     250         [ -  + ]:     451111 :     if (res == nullptr)
     251                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     252                 :     451111 :     return res;
     253                 :            : }
     254                 :            : 
     255                 :            : enum BinOpChain {
     256                 :            :     BinOpChainOnce,
     257                 :            :     BinOpChainInf,
     258                 :            : };
     259                 :            : 
     260                 :            : // Op* Child
     261                 :    2136489 : static AstNode *ast_parse_prefix_op_expr(
     262                 :            :     ParseContext *pc,
     263                 :            :     AstNode *(*op_parser)(ParseContext *),
     264                 :            :     AstNode *(*child_parser)(ParseContext *)
     265                 :            : ) {
     266                 :    2136489 :     AstNode *res = nullptr;
     267                 :    2136489 :     AstNode **right = &res;
     268                 :            :     while (true) {
     269                 :    2200592 :         AstNode *prefix = op_parser(pc);
     270         [ +  + ]:    2200592 :         if (prefix == nullptr)
     271                 :    2136489 :             break;
     272                 :            : 
     273                 :      64103 :         *right = prefix;
     274   [ +  +  +  +  :      64103 :         switch (prefix->type) {
             +  +  +  - ]
     275                 :      22501 :             case NodeTypePrefixOpExpr:
     276                 :      22501 :                 right = &prefix->data.prefix_op_expr.primary_expr;
     277                 :      22501 :                 break;
     278                 :      10928 :             case NodeTypeReturnExpr:
     279                 :      10928 :                 right = &prefix->data.return_expr.expr;
     280                 :      10928 :                 break;
     281                 :        216 :             case NodeTypeAwaitExpr:
     282                 :        216 :                 right = &prefix->data.await_expr.expr;
     283                 :        216 :                 break;
     284                 :         64 :             case NodeTypeAnyFrameType:
     285                 :         64 :                 right = &prefix->data.anyframe_type.payload_type;
     286                 :         64 :                 break;
     287                 :      10959 :             case NodeTypeArrayType:
     288                 :      10959 :                 right = &prefix->data.array_type.child_type;
     289                 :      10959 :                 break;
     290                 :       4227 :             case NodeTypeInferredArrayType:
     291                 :       4227 :                 right = &prefix->data.inferred_array_type.child_type;
     292                 :       4227 :                 break;
     293                 :      15208 :             case NodeTypePointerType: {
     294                 :            :                 // We might get two pointers from *_ptr_type_start
     295                 :      15208 :                 AstNode *child = prefix->data.pointer_type.op_expr;
     296         [ +  + ]:      15208 :                 if (child == nullptr)
     297                 :      15134 :                     child = prefix;
     298                 :      15208 :                 right = &child->data.pointer_type.op_expr;
     299                 :      15208 :                 break;
     300                 :            :             }
     301                 :          0 :             default:
     302                 :          0 :                 zig_unreachable();
     303                 :            :         }
     304                 :      64103 :     }
     305                 :            : 
     306                 :            :     // If we have already consumed a token, and determined that
     307                 :            :     // this node is a prefix op, then we expect that the node has
     308                 :            :     // a child.
     309         [ +  + ]:    2136489 :     if (res != nullptr) {
     310                 :      59991 :         *right = ast_expect(pc, child_parser);
     311                 :            :     } else {
     312                 :            :         // Otherwise, if we didn't consume a token, then we can return
     313                 :            :         // null, if the child expr did.
     314                 :    2076498 :         *right = child_parser(pc);
     315         [ +  + ]:    2076498 :         if (*right == nullptr)
     316                 :     269594 :             return nullptr;
     317                 :            :     }
     318                 :            : 
     319                 :    2136489 :     return res;
     320                 :            : }
     321                 :            : 
     322                 :            : // Child (Op Child)(*/?)
     323                 :    4909269 : static AstNode *ast_parse_bin_op_expr(
     324                 :            :     ParseContext *pc,
     325                 :            :     BinOpChain chain,
     326                 :            :     AstNode *(*op_parse)(ParseContext*),
     327                 :            :     AstNode *(*child_parse)(ParseContext*)
     328                 :            : ) {
     329                 :    4909269 :     AstNode *res = child_parse(pc);
     330         [ +  + ]:    4909269 :     if (res == nullptr)
     331                 :     664667 :         return nullptr;
     332                 :            : 
     333                 :      29915 :     do {
     334                 :    4274517 :         AstNode *op = op_parse(pc);
     335         [ +  + ]:    4274517 :         if (op == nullptr)
     336                 :    4189212 :             break;
     337                 :            : 
     338                 :      85305 :         AstNode *left = res;
     339                 :      85305 :         AstNode *right = ast_expect(pc, child_parse);
     340                 :      85305 :         res = op;
     341      [ +  +  - ]:      85305 :         switch (op->type) {
     342                 :      83110 :             case NodeTypeBinOpExpr:
     343                 :      83110 :                 op->data.bin_op_expr.op1 = left;
     344                 :      83110 :                 op->data.bin_op_expr.op2 = right;
     345                 :      83110 :                 break;
     346                 :       2195 :             case NodeTypeCatchExpr:
     347                 :       2195 :                 op->data.unwrap_err_expr.op1 = left;
     348                 :       2195 :                 op->data.unwrap_err_expr.op2 = right;
     349                 :       2195 :                 break;
     350                 :          0 :             default:
     351                 :          0 :                 zig_unreachable();
     352                 :            :         }
     353         [ +  + ]:      85305 :     } while (chain == BinOpChainInf);
     354                 :            : 
     355                 :    4244602 :     return res;
     356                 :            : }
     357                 :            : 
     358                 :            : // IfPrefix Body (KEYWORD_else Payload? Body)?
     359                 :     977348 : static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
     360                 :     977348 :     AstNode *res = ast_parse_if_prefix(pc);
     361         [ +  + ]:     977348 :     if (res == nullptr)
     362                 :     975735 :         return nullptr;
     363                 :            : 
     364                 :       1613 :     AstNode *body = ast_expect(pc, body_parser);
     365                 :       1613 :     Token *err_payload = nullptr;
     366                 :       1613 :     AstNode *else_body = nullptr;
     367         [ +  + ]:       1613 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
     368                 :       1504 :         err_payload = ast_parse_payload(pc);
     369                 :       1504 :         else_body = ast_expect(pc, body_parser);
     370                 :            :     }
     371                 :            : 
     372                 :       1613 :     assert(res->type == NodeTypeIfOptional);
     373         [ +  + ]:       1613 :     if (err_payload != nullptr) {
     374                 :         75 :         AstNodeTestExpr old = res->data.test_expr;
     375                 :         75 :         res->type = NodeTypeIfErrorExpr;
     376                 :         75 :         res->data.if_err_expr.target_node = old.target_node;
     377                 :         75 :         res->data.if_err_expr.var_is_ptr = old.var_is_ptr;
     378                 :         75 :         res->data.if_err_expr.var_symbol = old.var_symbol;
     379                 :         75 :         res->data.if_err_expr.then_node = body;
     380                 :         75 :         res->data.if_err_expr.err_symbol = token_buf(err_payload);
     381                 :         75 :         res->data.if_err_expr.else_node = else_body;
     382                 :         75 :         return res;
     383                 :            :     }
     384                 :            : 
     385         [ +  + ]:       1538 :     if (res->data.test_expr.var_symbol != nullptr) {
     386                 :        154 :         res->data.test_expr.then_node = body;
     387                 :        154 :         res->data.test_expr.else_node = else_body;
     388                 :        154 :         return res;
     389                 :            :     }
     390                 :            : 
     391                 :       1384 :     AstNodeTestExpr old = res->data.test_expr;
     392                 :       1384 :     res->type = NodeTypeIfBoolExpr;
     393                 :       1384 :     res->data.if_bool_expr.condition = old.target_node;
     394                 :       1384 :     res->data.if_bool_expr.then_block = body;
     395                 :       1384 :     res->data.if_bool_expr.else_node = else_body;
     396                 :     977348 :     return res;
     397                 :            : }
     398                 :            : 
     399                 :            : // KEYWORD_inline? (ForLoop / WhileLoop)
     400                 :    1371676 : static AstNode *ast_parse_loop_expr_helper(
     401                 :            :     ParseContext *pc,
     402                 :            :     AstNode *(*for_parser)(ParseContext *),
     403                 :            :     AstNode *(*while_parser)(ParseContext *)
     404                 :            : ) {
     405                 :    1371676 :     Token *inline_token = eat_token_if(pc, TokenIdKeywordInline);
     406                 :    1371676 :     AstNode *for_expr = for_parser(pc);
     407         [ +  + ]:    1371676 :     if (for_expr != nullptr) {
     408                 :         51 :         assert(for_expr->type == NodeTypeForExpr);
     409                 :         51 :         for_expr->data.for_expr.is_inline = inline_token != nullptr;
     410                 :         51 :         return for_expr;
     411                 :            :     }
     412                 :            : 
     413                 :    1371625 :     AstNode *while_expr = while_parser(pc);
     414         [ +  + ]:    1371625 :     if (while_expr != nullptr) {
     415                 :        138 :         assert(while_expr->type == NodeTypeWhileExpr);
     416                 :        138 :         while_expr->data.while_expr.is_inline = inline_token != nullptr;
     417                 :        138 :         return while_expr;
     418                 :            :     }
     419                 :            : 
     420         [ -  + ]:    1371487 :     if (inline_token != nullptr)
     421                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     422                 :    1371487 :     return nullptr;
     423                 :            : }
     424                 :            : 
     425                 :            : // ForPrefix Body (KEYWORD_else Body)?
     426                 :    1371676 : static AstNode *ast_parse_for_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
     427                 :    1371676 :     AstNode *res = ast_parse_for_prefix(pc);
     428         [ +  + ]:    1371676 :     if (res == nullptr)
     429                 :    1371625 :         return nullptr;
     430                 :            : 
     431                 :         51 :     AstNode *body = ast_expect(pc, body_parser);
     432                 :         51 :     AstNode *else_body = nullptr;
     433         [ +  + ]:         51 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr)
     434                 :         42 :         else_body = ast_expect(pc, body_parser);
     435                 :            : 
     436                 :         51 :     assert(res->type == NodeTypeForExpr);
     437                 :         51 :     res->data.for_expr.body = body;
     438                 :         51 :     res->data.for_expr.else_node = else_body;
     439                 :         51 :     return res;
     440                 :            : }
     441                 :            : 
     442                 :            : // WhilePrefix Body (KEYWORD_else Payload? Body)?
     443                 :    1371625 : static AstNode *ast_parse_while_expr_helper(ParseContext *pc, AstNode *(*body_parser)(ParseContext*)) {
     444                 :    1371625 :     AstNode *res = ast_parse_while_prefix(pc);
     445         [ +  + ]:    1371625 :     if (res == nullptr)
     446                 :    1371487 :         return nullptr;
     447                 :            : 
     448                 :        138 :     AstNode *body = ast_expect(pc, body_parser);
     449                 :        138 :     Token *err_payload = nullptr;
     450                 :        138 :     AstNode *else_body = nullptr;
     451         [ +  + ]:        138 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
     452                 :        121 :         err_payload = ast_parse_payload(pc);
     453                 :        121 :         else_body = ast_expect(pc, body_parser);
     454                 :            :     }
     455                 :            : 
     456                 :        138 :     assert(res->type == NodeTypeWhileExpr);
     457                 :        138 :     res->data.while_expr.body = body;
     458                 :        138 :     res->data.while_expr.err_symbol = token_buf(err_payload);
     459                 :        138 :     res->data.while_expr.else_node = else_body;
     460                 :        138 :     return res;
     461                 :            : }
     462                 :            : 
     463                 :            : template<TokenId id, BinOpType op>
     464                 :    1806397 : AstNode *ast_parse_bin_op_simple(ParseContext *pc) {
     465                 :    1806397 :     Token *op_token = eat_token_if(pc, id);
     466   [ +  +  +  +  :    1806397 :     if (op_token == nullptr)
                   +  + ]
     467                 :    1800909 :         return nullptr;
     468                 :            : 
     469                 :       5488 :     AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
     470                 :       5488 :     res->data.bin_op_expr.bin_op = op;
     471                 :       5488 :     return res;
     472                 :            : }
     473                 :            : 
     474                 :       1804 : AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ZigType *owner, ErrColor err_color) {
     475                 :       1804 :     ParseContext pc = {};
     476                 :       1804 :     pc.err_color = err_color;
     477                 :       1804 :     pc.owner = owner;
     478                 :       1804 :     pc.buf = buf;
     479                 :       1804 :     pc.tokens = tokens;
     480                 :       1804 :     return ast_parse_root(&pc);
     481                 :            : }
     482                 :            : 
     483                 :            : // Root <- skip ContainerMembers eof
     484                 :       1804 : static AstNode *ast_parse_root(ParseContext *pc) {
     485                 :       1804 :     Token *first = peek_token(pc);
     486                 :       1804 :     AstNodeContainerDecl members = ast_parse_container_members(pc);
     487         [ -  + ]:       1804 :     if (pc->current_token != pc->tokens->length - 1)
     488                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     489                 :            : 
     490                 :       1804 :     AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first);
     491                 :       1804 :     node->data.container_decl.fields = members.fields;
     492                 :       1804 :     node->data.container_decl.decls = members.decls;
     493                 :       1804 :     node->data.container_decl.layout = ContainerLayoutAuto;
     494                 :       1804 :     node->data.container_decl.kind = ContainerKindStruct;
     495                 :       1804 :     node->data.container_decl.is_root = true;
     496                 :            : 
     497                 :       1804 :     return node;
     498                 :            : }
     499                 :            : 
     500                 :            : // ContainerMembers
     501                 :            : //     <- TestDecl ContainerMembers
     502                 :            : //      / TopLevelComptime ContainerMembers
     503                 :            : //      / KEYWORD_pub? TopLevelDecl ContainerMembers
     504                 :            : //      / KEYWORD_pub? ContainerField COMMA ContainerMembers
     505                 :            : //      / KEYWORD_pub? ContainerField
     506                 :            : //      /
     507                 :       9330 : static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
     508                 :       9330 :     AstNodeContainerDecl res = {};
     509                 :            :     for (;;) {
     510                 :     108390 :         AstNode *test_decl = ast_parse_test_decl(pc);
     511         [ +  + ]:     108390 :         if (test_decl != nullptr) {
     512                 :       8753 :             res.decls.append(test_decl);
     513                 :       8753 :             continue;
     514                 :            :         }
     515                 :            : 
     516                 :      99637 :         AstNode *top_level_comptime = ast_parse_top_level_comptime(pc);
     517         [ +  + ]:      99637 :         if (top_level_comptime != nullptr) {
     518                 :        104 :             res.decls.append(top_level_comptime);
     519                 :        104 :             continue;
     520                 :            :         }
     521                 :            : 
     522                 :      99533 :         Token *visib_token = eat_token_if(pc, TokenIdKeywordPub);
     523         [ +  + ]:      99533 :         VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate;
     524                 :            : 
     525                 :      99533 :         AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod);
     526         [ +  + ]:      99533 :         if (top_level_decl != nullptr) {
     527                 :      61225 :             res.decls.append(top_level_decl);
     528                 :      61225 :             continue;
     529                 :            :         }
     530                 :            : 
     531                 :      38308 :         AstNode *container_field = ast_parse_container_field(pc);
     532         [ +  + ]:      38308 :         if (container_field != nullptr) {
     533                 :      29010 :             assert(container_field->type == NodeTypeStructField);
     534                 :      29010 :             container_field->data.struct_field.visib_mod = visib_mod;
     535                 :      29010 :             res.fields.append(container_field);
     536         [ +  + ]:      29010 :             if (eat_token_if(pc, TokenIdComma) != nullptr) {
     537                 :      28978 :                 continue;
     538                 :            :             } else {
     539                 :         32 :                 break;
     540                 :            :             }
     541                 :            :         }
     542                 :            : 
     543                 :            :         // We visib_token wasn't eaten, then we haven't consumed the first token in this rule yet.
     544                 :            :         // It is therefore safe to return and let the caller continue parsing.
     545         [ +  - ]:       9298 :         if (visib_token == nullptr)
     546                 :       9298 :             break;
     547                 :            : 
     548                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     549                 :      99060 :     }
     550                 :            : 
     551                 :       9330 :     return res;
     552                 :            : }
     553                 :            : 
     554                 :            : // TestDecl <- KEYWORD_test STRINGLITERAL Block
     555                 :     108390 : static AstNode *ast_parse_test_decl(ParseContext *pc) {
     556                 :     108390 :     Token *test = eat_token_if(pc, TokenIdKeywordTest);
     557         [ +  + ]:     108390 :     if (test == nullptr)
     558                 :      99637 :         return nullptr;
     559                 :            : 
     560                 :       8753 :     Token *name = expect_token(pc, TokenIdStringLiteral);
     561                 :       8753 :     AstNode *block = ast_expect(pc, ast_parse_block);
     562                 :       8753 :     AstNode *res = ast_create_node(pc, NodeTypeTestDecl, test);
     563                 :       8753 :     res->data.test_decl.name = token_buf(name);
     564                 :       8753 :     res->data.test_decl.body = block;
     565                 :       8753 :     return res;
     566                 :            : }
     567                 :            : 
     568                 :            : // TopLevelComptime <- KEYWORD_comptime BlockExpr
     569                 :      99637 : static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
     570                 :      99637 :     Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
     571         [ +  + ]:      99637 :     if (comptime == nullptr)
     572                 :      99533 :         return nullptr;
     573                 :            : 
     574                 :        104 :     AstNode *block = ast_expect(pc, ast_parse_block_expr);
     575                 :        104 :     AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
     576                 :        104 :     res->data.comptime_expr.expr = block;
     577                 :        104 :     return res;
     578                 :            : }
     579                 :            : 
     580                 :            : // TopLevelDecl
     581                 :            : //     <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
     582                 :            : //      / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
     583                 :            : //      / KEYWORD_use Expr SEMICOLON
     584                 :      99533 : static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
     585                 :      99533 :     Token *first = eat_token_if(pc, TokenIdKeywordExport);
     586         [ +  + ]:      99533 :     if (first == nullptr)
     587                 :      95956 :         first = eat_token_if(pc, TokenIdKeywordExtern);
     588         [ +  + ]:      99533 :     if (first == nullptr)
     589                 :      94164 :         first = eat_token_if(pc, TokenIdKeywordInline);
     590         [ +  + ]:      99533 :     if (first == nullptr)
     591                 :      94116 :         first = eat_token_if(pc, TokenIdKeywordNoInline);
     592         [ +  + ]:      99533 :     if (first != nullptr) {
     593                 :       5417 :         Token *lib_name = nullptr;
     594         [ +  + ]:       5417 :         if (first->id == TokenIdKeywordExtern)
     595                 :       1792 :             lib_name = eat_token_if(pc, TokenIdStringLiteral);
     596                 :            : 
     597 [ +  + ][ +  - ]:       5417 :         if (first->id != TokenIdKeywordInline && first->id != TokenIdKeywordNoInline) {
     598                 :       5369 :             Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
     599                 :       5369 :             AstNode *var_decl = ast_parse_var_decl(pc);
     600         [ +  + ]:       5369 :             if (var_decl != nullptr) {
     601                 :         69 :                 assert(var_decl->type == NodeTypeVariableDeclaration);
     602                 :         69 :                 var_decl->line = first->start_line;
     603                 :         69 :                 var_decl->column = first->start_column;
     604                 :         69 :                 var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
     605                 :         69 :                 var_decl->data.variable_declaration.visib_mod = visib_mod;
     606                 :         69 :                 var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern;
     607                 :         69 :                 var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport;
     608                 :         69 :                 var_decl->data.variable_declaration.lib_name = token_buf(lib_name);
     609                 :         69 :                 return var_decl;
     610                 :            :             }
     611                 :            : 
     612         [ -  + ]:       5300 :             if (thread_local_kw != nullptr)
     613                 :       5300 :                 put_back_token(pc);
     614                 :            :         }
     615                 :            : 
     616                 :       5348 :         AstNode *fn_proto = ast_parse_fn_proto(pc);
     617         [ +  - ]:       5348 :         if (fn_proto != nullptr) {
     618                 :       5348 :             AstNode *body = ast_parse_block(pc);
     619         [ +  + ]:       5348 :             if (body == nullptr)
     620                 :       1211 :                 expect_token(pc, TokenIdSemicolon);
     621                 :            : 
     622                 :       5348 :             assert(fn_proto->type == NodeTypeFnProto);
     623                 :       5348 :             fn_proto->line = first->start_line;
     624                 :       5348 :             fn_proto->column = first->start_column;
     625                 :       5348 :             fn_proto->data.fn_proto.visib_mod = visib_mod;
     626                 :       5348 :             fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern;
     627                 :       5348 :             fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport;
     628      [ +  -  + ]:       5348 :             switch (first->id) {
     629                 :         48 :                 case TokenIdKeywordInline:
     630                 :         48 :                     fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
     631                 :         48 :                     break;
     632                 :          0 :                 case TokenIdKeywordNoInline:
     633                 :          0 :                     fn_proto->data.fn_proto.fn_inline = FnInlineNever;
     634                 :          0 :                     break;
     635                 :       5300 :                 default:
     636                 :       5300 :                     fn_proto->data.fn_proto.fn_inline = FnInlineAuto;
     637                 :       5300 :                     break;
     638                 :            :             }
     639                 :       5348 :             fn_proto->data.fn_proto.lib_name = token_buf(lib_name);
     640                 :            : 
     641                 :       5348 :             AstNode *res = fn_proto;
     642         [ +  + ]:       5348 :             if (body != nullptr) {
     643                 :       4137 :                 res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
     644                 :       4137 :                 res->data.fn_def.fn_proto = fn_proto;
     645                 :       4137 :                 res->data.fn_def.body = body;
     646                 :       4137 :                 fn_proto->data.fn_proto.fn_def_node = res;
     647                 :            :             }
     648                 :            : 
     649                 :       5348 :             return res;
     650                 :            :         }
     651                 :            : 
     652                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     653                 :            :     }
     654                 :            : 
     655                 :      94116 :     Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
     656                 :      94116 :     AstNode *var_decl = ast_parse_var_decl(pc);
     657         [ +  + ]:      94116 :     if (var_decl != nullptr) {
     658                 :      38301 :         assert(var_decl->type == NodeTypeVariableDeclaration);
     659                 :      38301 :         var_decl->data.variable_declaration.visib_mod = visib_mod;
     660                 :      38301 :         var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw;
     661                 :      38301 :         return var_decl;
     662                 :            :     }
     663                 :            : 
     664         [ -  + ]:      55815 :     if (thread_local_kw != nullptr)
     665                 :          0 :         put_back_token(pc);
     666                 :            : 
     667                 :      55815 :     AstNode *fn_proto = ast_parse_fn_proto(pc);
     668         [ +  + ]:      55815 :     if (fn_proto != nullptr) {
     669                 :      17366 :         AstNode *body = ast_parse_block(pc);
     670         [ -  + ]:      17366 :         if (body == nullptr)
     671                 :          0 :             expect_token(pc, TokenIdSemicolon);
     672                 :            : 
     673                 :      17366 :         assert(fn_proto->type == NodeTypeFnProto);
     674                 :      17366 :         fn_proto->data.fn_proto.visib_mod = visib_mod;
     675                 :      17366 :         AstNode *res = fn_proto;
     676         [ +  - ]:      17366 :         if (body != nullptr) {
     677                 :      17366 :             res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto);
     678                 :      17366 :             res->data.fn_def.fn_proto = fn_proto;
     679                 :      17366 :             res->data.fn_def.body = body;
     680                 :      17366 :             fn_proto->data.fn_proto.fn_def_node = res;
     681                 :            :         }
     682                 :            : 
     683                 :      17366 :         return res;
     684                 :            :     }
     685                 :            : 
     686                 :      38449 :     Token *usingnamespace = eat_token_if(pc, TokenIdKeywordUsingNamespace);
     687         [ +  + ]:      38449 :     if (usingnamespace != nullptr) {
     688                 :        141 :         AstNode *expr = ast_expect(pc, ast_parse_expr);
     689                 :        141 :         expect_token(pc, TokenIdSemicolon);
     690                 :            : 
     691                 :        141 :         AstNode *res = ast_create_node(pc, NodeTypeUsingNamespace, usingnamespace);
     692                 :        141 :         res->data.using_namespace.visib_mod = visib_mod;
     693                 :        141 :         res->data.using_namespace.expr = expr;
     694                 :        141 :         return res;
     695                 :            :     }
     696                 :            : 
     697                 :      38308 :     return nullptr;
     698                 :            : }
     699                 :            : 
     700                 :            : // FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
     701                 :     758983 : static AstNode *ast_parse_fn_proto(ParseContext *pc) {
     702                 :     758983 :     Token *first = peek_token(pc);
     703                 :            :     AstNodeFnProto fn_cc;
     704                 :            :     Token *fn;
     705         [ +  + ]:     758983 :     if (ast_parse_fn_cc(pc).unwrap(&fn_cc)) {
     706                 :            :         // The extern keyword for fn CC is also used for container decls.
     707                 :            :         // We therefore put it back, as allow container decl to consume it
     708                 :            :         // later.
     709         [ +  + ]:        604 :         if (fn_cc.cc == CallingConventionC) {
     710                 :        154 :             fn = eat_token_if(pc, TokenIdKeywordFn);
     711         [ -  + ]:        154 :             if (fn == nullptr) {
     712                 :          0 :                 put_back_token(pc);
     713                 :          0 :                 return nullptr;
     714                 :            :             }
     715                 :            :         } else {
     716                 :        604 :             fn = expect_token(pc, TokenIdKeywordFn);
     717                 :            :         }
     718                 :            :     } else {
     719                 :     758379 :         fn_cc = {};
     720                 :     758379 :         fn = eat_token_if(pc, TokenIdKeywordFn);
     721         [ +  + ]:     758379 :         if (fn == nullptr)
     722                 :     735457 :             return nullptr;
     723                 :            :     }
     724                 :            : 
     725                 :      23526 :     Token *identifier = eat_token_if(pc, TokenIdSymbol);
     726                 :      23526 :     expect_token(pc, TokenIdLParen);
     727                 :      23526 :     ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_param_decl);
     728                 :      23526 :     expect_token(pc, TokenIdRParen);
     729                 :            : 
     730                 :      23526 :     AstNode *align_expr = ast_parse_byte_align(pc);
     731                 :      23526 :     AstNode *section_expr = ast_parse_link_section(pc);
     732                 :      23526 :     Token *var = eat_token_if(pc, TokenIdKeywordVar);
     733                 :      23526 :     Token *exmark = nullptr;
     734                 :      23526 :     AstNode *return_type = nullptr;
     735         [ +  - ]:      23526 :     if (var == nullptr) {
     736                 :      23526 :         exmark = eat_token_if(pc, TokenIdBang);
     737                 :      23526 :         return_type = ast_expect(pc, ast_parse_type_expr);
     738                 :            :     }
     739                 :            : 
     740                 :      23526 :     AstNode *res = ast_create_node(pc, NodeTypeFnProto, first);
     741                 :      23526 :     res->data.fn_proto = fn_cc;
     742                 :      23526 :     res->data.fn_proto.name = token_buf(identifier);
     743                 :      23526 :     res->data.fn_proto.params = params;
     744                 :      23526 :     res->data.fn_proto.align_expr = align_expr;
     745                 :      23526 :     res->data.fn_proto.section_expr = section_expr;
     746                 :      23526 :     res->data.fn_proto.return_var_token = var;
     747                 :      23526 :     res->data.fn_proto.auto_err_set = exmark != nullptr;
     748                 :      23526 :     res->data.fn_proto.return_type = return_type;
     749                 :            : 
     750                 :            :     // It seems that the Zig compiler expects varargs to be the
     751                 :            :     // last parameter in the decl list. This is not encoded in
     752                 :            :     // the grammar, which allows varargs anywhere in the decl.
     753                 :            :     // Since varargs is gonna be removed at some point, I'm not
     754                 :            :     // gonna encode this "varargs is always last" rule in the
     755                 :            :     // grammar, and just enforce it here, until varargs is removed.
     756         [ +  + ]:      56652 :     for (size_t i = 0; i < params.length; i++) {
     757                 :      33126 :         AstNode *param_decl = params.at(i);
     758                 :      33126 :         assert(param_decl->type == NodeTypeParamDecl);
     759         [ +  + ]:      33126 :         if (param_decl->data.param_decl.is_var_args)
     760                 :        211 :             res->data.fn_proto.is_var_args = true;
     761 [ +  + ][ -  + ]:      33126 :         if (i != params.length - 1 && res->data.fn_proto.is_var_args)
     762                 :          0 :             ast_error(pc, first, "Function prototype have varargs as a none last paramter.");
     763                 :            :     }
     764                 :     758983 :     return res;
     765                 :            : }
     766                 :            : 
     767                 :            : // VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
     768                 :     300382 : static AstNode *ast_parse_var_decl(ParseContext *pc) {
     769                 :     300382 :     Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
     770         [ +  + ]:     300382 :     if (mut_kw == nullptr)
     771                 :     238870 :         mut_kw = eat_token_if(pc, TokenIdKeywordVar);
     772         [ +  + ]:     300382 :     if (mut_kw == nullptr)
     773                 :     224587 :         return nullptr;
     774                 :            : 
     775                 :      75795 :     Token *identifier = expect_token(pc, TokenIdSymbol);
     776                 :      75795 :     AstNode *type_expr = nullptr;
     777         [ +  + ]:      75795 :     if (eat_token_if(pc, TokenIdColon) != nullptr)
     778                 :      10183 :         type_expr = ast_expect(pc, ast_parse_type_expr);
     779                 :            : 
     780                 :      75795 :     AstNode *align_expr = ast_parse_byte_align(pc);
     781                 :      75795 :     AstNode *section_expr = ast_parse_link_section(pc);
     782                 :      75795 :     AstNode *expr = nullptr;
     783         [ +  + ]:      75795 :     if (eat_token_if(pc, TokenIdEq) != nullptr)
     784                 :      75755 :         expr = ast_expect(pc, ast_parse_expr);
     785                 :            : 
     786                 :      75795 :     expect_token(pc, TokenIdSemicolon);
     787                 :            : 
     788                 :      75795 :     AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
     789                 :      75795 :     res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
     790                 :      75795 :     res->data.variable_declaration.symbol = token_buf(identifier);
     791                 :      75795 :     res->data.variable_declaration.type = type_expr;
     792                 :      75795 :     res->data.variable_declaration.align_expr = align_expr;
     793                 :      75795 :     res->data.variable_declaration.section_expr = section_expr;
     794                 :      75795 :     res->data.variable_declaration.expr = expr;
     795                 :      75795 :     return res;
     796                 :            : }
     797                 :            : 
     798                 :            : // ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
     799                 :      38308 : static AstNode *ast_parse_container_field(ParseContext *pc) {
     800                 :      38308 :     Token *identifier = eat_token_if(pc, TokenIdSymbol);
     801         [ +  + ]:      38308 :     if (identifier == nullptr)
     802                 :       9298 :         return nullptr;
     803                 :            : 
     804                 :      29010 :     AstNode *type_expr = nullptr;
     805         [ +  + ]:      29010 :     if (eat_token_if(pc, TokenIdColon) != nullptr) {
     806                 :      15749 :         type_expr = ast_expect(pc, ast_parse_type_expr);
     807                 :            :     }
     808                 :      29010 :     AstNode *align_expr = ast_parse_byte_align(pc);
     809                 :      29010 :     AstNode *expr = nullptr;
     810         [ +  + ]:      29010 :     if (eat_token_if(pc, TokenIdEq) != nullptr)
     811                 :       2459 :         expr = ast_expect(pc, ast_parse_expr);
     812                 :            : 
     813                 :      29010 :     AstNode *res = ast_create_node(pc, NodeTypeStructField, identifier);
     814                 :      29010 :     res->data.struct_field.name = token_buf(identifier);
     815                 :      29010 :     res->data.struct_field.type = type_expr;
     816                 :      29010 :     res->data.struct_field.value = expr;
     817                 :      29010 :     res->data.struct_field.align_expr = align_expr;
     818                 :      29010 :     return res;
     819                 :            : }
     820                 :            : 
     821                 :            : // Statement
     822                 :            : //     <- KEYWORD_comptime? VarDecl
     823                 :            : //      / KEYWORD_comptime BlockExprStatement
     824                 :            : //      / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
     825                 :            : //      / KEYWORD_defer BlockExprStatement
     826                 :            : //      / KEYWORD_errdefer BlockExprStatement
     827                 :            : //      / IfStatement
     828                 :            : //      / LabeledStatement
     829                 :            : //      / SwitchExpr
     830                 :            : //      / AssignExpr SEMICOLON
     831                 :     200897 : static AstNode *ast_parse_statement(ParseContext *pc) {
     832                 :     200897 :     Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
     833                 :     200897 :     AstNode *var_decl = ast_parse_var_decl(pc);
     834         [ +  + ]:     200897 :     if (var_decl != nullptr) {
     835                 :      37425 :         assert(var_decl->type == NodeTypeVariableDeclaration);
     836                 :      37425 :         var_decl->data.variable_declaration.is_comptime = comptime != nullptr;
     837                 :      37425 :         return var_decl;
     838                 :            :     }
     839                 :            : 
     840         [ +  + ]:     163472 :     if (comptime != nullptr) {
     841                 :       2743 :         AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
     842                 :       2743 :         AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
     843                 :       2743 :         res->data.comptime_expr.expr = statement;
     844                 :       2743 :         return res;
     845                 :            :     }
     846                 :            : 
     847                 :     160729 :     Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
     848         [ +  + ]:     160729 :     if (suspend != nullptr) {
     849                 :        336 :         AstNode *statement = nullptr;
     850         [ +  + ]:        336 :         if (eat_token_if(pc, TokenIdSemicolon) == nullptr)
     851                 :        136 :             statement = ast_expect(pc, ast_parse_block_expr_statement);
     852                 :            : 
     853                 :        336 :         AstNode *res = ast_create_node(pc, NodeTypeSuspend, suspend);
     854                 :        336 :         res->data.suspend.block = statement;
     855                 :        336 :         return res;
     856                 :            :     }
     857                 :            : 
     858                 :     160393 :     Token *defer = eat_token_if(pc, TokenIdKeywordDefer);
     859         [ +  + ]:     160393 :     if (defer == nullptr)
     860                 :     159535 :         defer = eat_token_if(pc, TokenIdKeywordErrdefer);
     861         [ +  + ]:     160393 :     if (defer != nullptr) {
     862                 :       1197 :         AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
     863                 :       1197 :         AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);
     864                 :       1197 :         res->data.defer.kind = ReturnKindUnconditional;
     865                 :       1197 :         res->data.defer.expr = statement;
     866         [ +  + ]:       1197 :         if (defer->id == TokenIdKeywordErrdefer)
     867                 :        339 :             res->data.defer.kind = ReturnKindError;
     868                 :       1197 :         return res;
     869                 :            :     }
     870                 :            : 
     871                 :     159196 :     AstNode *if_statement = ast_parse_if_statement(pc);
     872         [ +  + ]:     159196 :     if (if_statement != nullptr)
     873                 :      13437 :         return if_statement;
     874                 :            : 
     875                 :     145759 :     AstNode *labeled_statement = ast_parse_labeled_statement(pc);
     876         [ +  + ]:     145759 :     if (labeled_statement != nullptr)
     877                 :       8093 :         return labeled_statement;
     878                 :            : 
     879                 :     137666 :     AstNode *switch_expr = ast_parse_switch_expr(pc);
     880         [ +  + ]:     137666 :     if (switch_expr != nullptr)
     881                 :       2393 :         return switch_expr;
     882                 :            : 
     883                 :     135273 :     AstNode *assign = ast_parse_assign_expr(pc);
     884         [ +  + ]:     135273 :     if (assign != nullptr) {
     885                 :      81930 :         expect_token(pc, TokenIdSemicolon);
     886                 :      81930 :         return assign;
     887                 :            :     }
     888                 :            : 
     889                 :      53343 :     return nullptr;
     890                 :            : }
     891                 :            : 
     892                 :            : // IfStatement
     893                 :            : //     <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
     894                 :            : //      / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
     895                 :     159196 : static AstNode *ast_parse_if_statement(ParseContext *pc) {
     896                 :     159196 :     AstNode *res = ast_parse_if_prefix(pc);
     897         [ +  + ]:     159196 :     if (res == nullptr)
     898                 :     145759 :         return nullptr;
     899                 :            : 
     900                 :      13437 :     AstNode *body = ast_parse_block_expr(pc);
     901                 :      13437 :     bool requires_semi = false;
     902         [ +  + ]:      13437 :     if (body == nullptr) {
     903                 :       3957 :         requires_semi = true;
     904                 :       3957 :         body = ast_parse_assign_expr(pc);
     905                 :            :     }
     906                 :            : 
     907         [ -  + ]:      13437 :     if (body == nullptr) {
     908                 :          0 :         Token *tok = eat_token(pc);
     909                 :          0 :         ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id));
     910                 :            :     }
     911                 :            : 
     912                 :      13437 :     Token *err_payload = nullptr;
     913                 :      13437 :     AstNode *else_body = nullptr;
     914         [ +  + ]:      13437 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
     915                 :       3481 :         err_payload = ast_parse_payload(pc);
     916                 :       3481 :         else_body = ast_expect(pc, ast_parse_statement);
     917                 :            :     }
     918                 :            : 
     919 [ +  + ][ +  + ]:      13437 :     if (requires_semi && else_body == nullptr)
     920                 :       3891 :         expect_token(pc, TokenIdSemicolon);
     921                 :            : 
     922                 :      13437 :     assert(res->type == NodeTypeIfOptional);
     923         [ +  + ]:      13437 :     if (err_payload != nullptr) {
     924                 :        320 :         AstNodeTestExpr old = res->data.test_expr;
     925                 :        320 :         res->type = NodeTypeIfErrorExpr;
     926                 :        320 :         res->data.if_err_expr.target_node = old.target_node;
     927                 :        320 :         res->data.if_err_expr.var_is_ptr = old.var_is_ptr;
     928                 :        320 :         res->data.if_err_expr.var_symbol = old.var_symbol;
     929                 :        320 :         res->data.if_err_expr.then_node = body;
     930                 :        320 :         res->data.if_err_expr.err_symbol = token_buf(err_payload);
     931                 :        320 :         res->data.if_err_expr.else_node = else_body;
     932                 :        320 :         return res;
     933                 :            :     }
     934                 :            : 
     935         [ +  + ]:      13117 :     if (res->data.test_expr.var_symbol != nullptr) {
     936                 :        883 :         res->data.test_expr.then_node = body;
     937                 :        883 :         res->data.test_expr.else_node = else_body;
     938                 :        883 :         return res;
     939                 :            :     }
     940                 :            : 
     941                 :      12234 :     AstNodeTestExpr old = res->data.test_expr;
     942                 :      12234 :     res->type = NodeTypeIfBoolExpr;
     943                 :      12234 :     res->data.if_bool_expr.condition = old.target_node;
     944                 :      12234 :     res->data.if_bool_expr.then_block = body;
     945                 :      12234 :     res->data.if_bool_expr.else_node = else_body;
     946                 :     159196 :     return res;
     947                 :            : }
     948                 :            : 
     949                 :            : // LabeledStatement <- BlockLabel? (Block / LoopStatement)
     950                 :     145759 : static AstNode *ast_parse_labeled_statement(ParseContext *pc) {
     951                 :     145759 :     Token *label = ast_parse_block_label(pc);
     952                 :     145759 :     AstNode *block = ast_parse_block(pc);
     953         [ +  + ]:     145759 :     if (block != nullptr) {
     954                 :       3583 :         assert(block->type == NodeTypeBlock);
     955                 :       3583 :         block->data.block.name = token_buf(label);
     956                 :       3583 :         return block;
     957                 :            :     }
     958                 :            : 
     959                 :     142176 :     AstNode *loop = ast_parse_loop_statement(pc);
     960         [ +  + ]:     142176 :     if (loop != nullptr) {
     961      [ +  +  - ]:       4510 :         switch (loop->type) {
     962                 :       1586 :             case NodeTypeForExpr:
     963                 :       1586 :                 loop->data.for_expr.name = token_buf(label);
     964                 :       1586 :                 break;
     965                 :       2924 :             case NodeTypeWhileExpr:
     966                 :       2924 :                 loop->data.while_expr.name = token_buf(label);
     967                 :       2924 :                 break;
     968                 :          0 :             default:
     969                 :          0 :                 zig_unreachable();
     970                 :            :         }
     971                 :       4510 :         return loop;
     972                 :            :     }
     973                 :            : 
     974         [ -  + ]:     137666 :     if (label != nullptr)
     975                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     976                 :     137666 :     return nullptr;
     977                 :            : }
     978                 :            : 
     979                 :            : // LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
     980                 :     142176 : static AstNode *ast_parse_loop_statement(ParseContext *pc) {
     981                 :     142176 :     Token *inline_token = eat_token_if(pc, TokenIdKeywordInline);
     982                 :     142176 :     AstNode *for_statement = ast_parse_for_statement(pc);
     983         [ +  + ]:     142176 :     if (for_statement != nullptr) {
     984                 :       1586 :         assert(for_statement->type == NodeTypeForExpr);
     985                 :       1586 :         for_statement->data.for_expr.is_inline = inline_token != nullptr;
     986                 :       1586 :         return for_statement;
     987                 :            :     }
     988                 :            : 
     989                 :     140590 :     AstNode *while_statement = ast_parse_while_statement(pc);
     990         [ +  + ]:     140590 :     if (while_statement != nullptr) {
     991                 :       2924 :         assert(while_statement->type == NodeTypeWhileExpr);
     992                 :       2924 :         while_statement->data.while_expr.is_inline = inline_token != nullptr;
     993                 :       2924 :         return while_statement;
     994                 :            :     }
     995                 :            : 
     996         [ -  + ]:     137666 :     if (inline_token != nullptr)
     997                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
     998                 :     137666 :     return nullptr;
     999                 :            : }
    1000                 :            : 
    1001                 :            : // ForStatement
    1002                 :            : //     <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
    1003                 :            : //      / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
    1004                 :     142176 : static AstNode *ast_parse_for_statement(ParseContext *pc) {
    1005                 :     142176 :     AstNode *res = ast_parse_for_prefix(pc);
    1006         [ +  + ]:     142176 :     if (res == nullptr)
    1007                 :     140590 :         return nullptr;
    1008                 :            : 
    1009                 :       1586 :     AstNode *body = ast_parse_block_expr(pc);
    1010                 :       1586 :     bool requires_semi = false;
    1011         [ +  + ]:       1586 :     if (body == nullptr) {
    1012                 :        141 :         requires_semi = true;
    1013                 :        141 :         body = ast_parse_assign_expr(pc);
    1014                 :            :     }
    1015                 :            : 
    1016         [ -  + ]:       1586 :     if (body == nullptr) {
    1017                 :          0 :         Token *tok = eat_token(pc);
    1018                 :          0 :         ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
    1019                 :            :     }
    1020                 :            : 
    1021                 :       1586 :     AstNode *else_body = nullptr;
    1022         [ -  + ]:       1586 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
    1023                 :          0 :         else_body = ast_expect(pc, ast_parse_statement);
    1024                 :            :     }
    1025                 :            : 
    1026 [ +  + ][ +  - ]:       1586 :     if (requires_semi && else_body == nullptr)
    1027                 :        141 :         expect_token(pc, TokenIdSemicolon);
    1028                 :            : 
    1029                 :       1586 :     assert(res->type == NodeTypeForExpr);
    1030                 :       1586 :     res->data.for_expr.body = body;
    1031                 :       1586 :     res->data.for_expr.else_node = else_body;
    1032                 :       1586 :     return res;
    1033                 :            : }
    1034                 :            : 
    1035                 :            : // WhileStatement
    1036                 :            : //     <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
    1037                 :            : //      / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
    1038                 :     140590 : static AstNode *ast_parse_while_statement(ParseContext *pc) {
    1039                 :     140590 :     AstNode *res = ast_parse_while_prefix(pc);
    1040         [ +  + ]:     140590 :     if (res == nullptr)
    1041                 :     137666 :         return nullptr;
    1042                 :            : 
    1043                 :       2924 :     AstNode *body = ast_parse_block_expr(pc);
    1044                 :       2924 :     bool requires_semi = false;
    1045         [ +  + ]:       2924 :     if (body == nullptr) {
    1046                 :         21 :         requires_semi = true;
    1047                 :         21 :         body = ast_parse_assign_expr(pc);
    1048                 :            :     }
    1049                 :            : 
    1050         [ -  + ]:       2924 :     if (body == nullptr) {
    1051                 :          0 :         Token *tok = eat_token(pc);
    1052                 :          0 :         ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
    1053                 :            :     }
    1054                 :            : 
    1055                 :       2924 :     Token *err_payload = nullptr;
    1056                 :       2924 :     AstNode *else_body = nullptr;
    1057         [ +  + ]:       2924 :     if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
    1058                 :         63 :         err_payload = ast_parse_payload(pc);
    1059                 :         63 :         else_body = ast_expect(pc, ast_parse_statement);
    1060                 :            :     }
    1061                 :            : 
    1062 [ +  + ][ +  - ]:       2924 :     if (requires_semi && else_body == nullptr)
    1063                 :         21 :         expect_token(pc, TokenIdSemicolon);
    1064                 :            : 
    1065                 :       2924 :     assert(res->type == NodeTypeWhileExpr);
    1066                 :       2924 :     res->data.while_expr.body = body;
    1067                 :       2924 :     res->data.while_expr.err_symbol = token_buf(err_payload);
    1068                 :       2924 :     res->data.while_expr.else_node = else_body;
    1069                 :       2924 :     return res;
    1070                 :            : }
    1071                 :            : 
    1072                 :            : 
    1073                 :            : // BlockExprStatement
    1074                 :            : //     <- BlockExpr
    1075                 :            : //      / AssignExpr SEMICOLON
    1076                 :       4076 : static AstNode *ast_parse_block_expr_statement(ParseContext *pc) {
    1077                 :       4076 :     AstNode *block = ast_parse_block_expr(pc);
    1078         [ +  + ]:       4076 :     if (block != nullptr)
    1079                 :        740 :         return block;
    1080                 :            : 
    1081                 :       3336 :     AstNode *assign_expr = ast_parse_assign_expr(pc);
    1082         [ +  - ]:       3336 :     if (assign_expr != nullptr) {
    1083                 :       3336 :         expect_token(pc, TokenIdSemicolon);
    1084                 :       3336 :         return assign_expr;
    1085                 :            :     }
    1086                 :            : 
    1087                 :          0 :     return nullptr;
    1088                 :            : }
    1089                 :            : 
    1090                 :            : // BlockExpr <- BlockLabel? Block
    1091                 :      22127 : static AstNode *ast_parse_block_expr(ParseContext *pc) {
    1092                 :      22127 :     Token *label = ast_parse_block_label(pc);
    1093         [ -  + ]:      22127 :     if (label != nullptr) {
    1094                 :          0 :         AstNode *res = ast_expect(pc, ast_parse_block);
    1095                 :          0 :         assert(res->type == NodeTypeBlock);
    1096                 :          0 :         res->data.block.name = token_buf(label);
    1097                 :          0 :         return res;
    1098                 :            :     }
    1099                 :            : 
    1100                 :      22127 :     return ast_parse_block(pc);
    1101                 :            : }
    1102                 :            : 
    1103                 :            : // AssignExpr <- Expr (AssignOp Expr)?
    1104                 :     161589 : static AstNode *ast_parse_assign_expr(ParseContext *pc) {
    1105                 :     161589 :     return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_assign_op, ast_parse_expr);
    1106                 :            : }
    1107                 :            : 
    1108                 :            : // Expr <- KEYWORD_try* BoolOrExpr
    1109                 :     651279 : static AstNode *ast_parse_expr(ParseContext *pc) {
    1110                 :    1302558 :     return ast_parse_prefix_op_expr(
    1111                 :            :         pc,
    1112                 :    1975605 :         [](ParseContext *context) {
    1113                 :     662163 :             Token *try_token = eat_token_if(context, TokenIdKeywordTry);
    1114         [ +  + ]:     662163 :             if (try_token != nullptr) {
    1115                 :      10884 :                 AstNode *res = ast_create_node(context, NodeTypeReturnExpr, try_token);
    1116                 :      10884 :                 res->data.return_expr.kind = ReturnKindError;
    1117                 :      10884 :                 return res;
    1118                 :            :             }
    1119                 :            : 
    1120                 :     651279 :             return (AstNode*)nullptr;
    1121                 :    1313442 :         },
    1122                 :            :         ast_parse_bool_or_expr
    1123                 :     651279 :     );
    1124                 :            : }
    1125                 :            : 
    1126                 :            : // BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
    1127                 :     651279 : static AstNode *ast_parse_bool_or_expr(ParseContext *pc) {
    1128                 :            :     return ast_parse_bin_op_expr(
    1129                 :            :         pc,
    1130                 :            :         BinOpChainInf,
    1131                 :            :         ast_parse_bin_op_simple<TokenIdKeywordOr, BinOpTypeBoolOr>,
    1132                 :            :         ast_parse_bool_and_expr
    1133                 :     651279 :     );
    1134                 :            : }
    1135                 :            : 
    1136                 :            : // BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
    1137                 :     652111 : static AstNode *ast_parse_bool_and_expr(ParseContext *pc) {
    1138                 :            :     return ast_parse_bin_op_expr(
    1139                 :            :         pc,
    1140                 :            :         BinOpChainInf,
    1141                 :            :         ast_parse_bin_op_simple<TokenIdKeywordAnd, BinOpTypeBoolAnd>,
    1142                 :            :         ast_parse_compare_expr
    1143                 :     652111 :     );
    1144                 :            : }
    1145                 :            : 
    1146                 :            : // CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
    1147                 :     653780 : static AstNode *ast_parse_compare_expr(ParseContext *pc) {
    1148                 :     653780 :     return ast_parse_bin_op_expr(pc, BinOpChainOnce, ast_parse_compare_op, ast_parse_bitwise_expr);
    1149                 :            : }
    1150                 :            : 
    1151                 :            : // BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
    1152                 :     687696 : static AstNode *ast_parse_bitwise_expr(ParseContext *pc) {
    1153                 :     687696 :     return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_bitwise_op, ast_parse_bit_shit_expr);
    1154                 :            : }
    1155                 :            : 
    1156                 :            : // BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
    1157                 :     694323 : static AstNode *ast_parse_bit_shit_expr(ParseContext *pc) {
    1158                 :     694323 :     return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_bit_shift_op, ast_parse_addition_expr);
    1159                 :            : }
    1160                 :            : 
    1161                 :            : // AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
    1162                 :     698235 : static AstNode *ast_parse_addition_expr(ParseContext *pc) {
    1163                 :     698235 :     return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_addition_op, ast_parse_multiply_expr);
    1164                 :            : }
    1165                 :            : 
    1166                 :            : // MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
    1167                 :     710256 : static AstNode *ast_parse_multiply_expr(ParseContext *pc) {
    1168                 :     710256 :     return ast_parse_bin_op_expr(pc, BinOpChainInf, ast_parse_multiply_op, ast_parse_prefix_expr);
    1169                 :            : }
    1170                 :            : 
    1171                 :            : // PrefixExpr <- PrefixOp* PrimaryExpr
    1172                 :     715110 : static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
    1173                 :            :     return ast_parse_prefix_op_expr(
    1174                 :            :         pc,
    1175                 :            :         ast_parse_prefix_op,
    1176                 :            :         ast_parse_primary_expr
    1177                 :     715110 :     );
    1178                 :            : }
    1179                 :            : 
    1180                 :            : // PrimaryExpr
    1181                 :            : //     <- AsmExpr
    1182                 :            : //      / IfExpr
    1183                 :            : //      / KEYWORD_break BreakLabel? Expr?
    1184                 :            : //      / KEYWORD_comptime Expr
    1185                 :            : //      / KEYWORD_continue BreakLabel?
    1186                 :            : //      / KEYWORD_resume Expr
    1187                 :            : //      / KEYWORD_return Expr?
    1188                 :            : //      / BlockLabel? LoopExpr
    1189                 :            : //      / Block
    1190                 :            : //      / CurlySuffixExpr
    1191                 :     715110 : static AstNode *ast_parse_primary_expr(ParseContext *pc) {
    1192                 :     715110 :     AstNode *asm_expr = ast_parse_asm_expr(pc);
    1193         [ +  + ]:     715110 :     if (asm_expr != nullptr)
    1194                 :        305 :         return asm_expr;
    1195                 :            : 
    1196                 :     714805 :     AstNode *if_expr = ast_parse_if_expr(pc);
    1197         [ +  + ]:     714805 :     if (if_expr != nullptr)
    1198                 :       1564 :         return if_expr;
    1199                 :            : 
    1200                 :     713241 :     Token *break_token = eat_token_if(pc, TokenIdKeywordBreak);
    1201         [ +  + ]:     713241 :     if (break_token != nullptr) {
    1202                 :       1689 :         Token *label = ast_parse_break_label(pc);
    1203                 :       1689 :         AstNode *expr = ast_parse_expr(pc);
    1204                 :            : 
    1205                 :       1689 :         AstNode *res = ast_create_node(pc, NodeTypeBreak, break_token);
    1206                 :       1689 :         res->data.break_expr.name = token_buf(label);
    1207                 :       1689 :         res->data.break_expr.expr = expr;
    1208                 :       1689 :         return res;
    1209                 :            :     }
    1210                 :            : 
    1211                 :     711552 :     Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
    1212         [ +  + ]:     711552 :     if (comptime != nullptr) {
    1213                 :        991 :         AstNode *expr = ast_expect(pc, ast_parse_expr);
    1214                 :        991 :         AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
    1215                 :        991 :         res->data.comptime_expr.expr = expr;
    1216                 :        991 :         return res;
    1217                 :            :     }
    1218                 :            : 
    1219                 :     710561 :     Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue);
    1220         [ +  + ]:     710561 :     if (continue_token != nullptr) {
    1221                 :        753 :         Token *label = ast_parse_break_label(pc);
    1222                 :        753 :         AstNode *res = ast_create_node(pc, NodeTypeContinue, continue_token);
    1223                 :        753 :         res->data.continue_expr.name = token_buf(label);
    1224                 :        753 :         return res;
    1225                 :            :     }
    1226                 :            : 
    1227                 :     709808 :     Token *resume = eat_token_if(pc, TokenIdKeywordResume);
    1228         [ +  + ]:     709808 :     if (resume != nullptr) {
    1229                 :        320 :         AstNode *expr = ast_expect(pc, ast_parse_expr);
    1230                 :        320 :         AstNode *res = ast_create_node(pc, NodeTypeResume, resume);
    1231                 :        320 :         res->data.resume_expr.expr = expr;
    1232                 :        320 :         return res;
    1233                 :            :     }
    1234                 :            : 
    1235                 :     709488 :     Token *return_token = eat_token_if(pc, TokenIdKeywordReturn);
    1236         [ +  + ]:     709488 :     if (return_token != nullptr) {
    1237                 :      26819 :         AstNode *expr = ast_parse_expr(pc);
    1238                 :      26819 :         AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, return_token);
    1239                 :      26819 :         res->data.return_expr.expr = expr;
    1240                 :      26819 :         return res;
    1241                 :            :     }
    1242                 :            : 
    1243                 :     682669 :     Token *label = ast_parse_block_label(pc);
    1244                 :     682669 :     AstNode *loop = ast_parse_loop_expr(pc);
    1245         [ +  + ]:     682669 :     if (loop != nullptr) {
    1246      [ +  +  - ]:        173 :         switch (loop->type) {
    1247                 :         43 :             case NodeTypeForExpr:
    1248                 :         43 :                 loop->data.for_expr.name = token_buf(label);
    1249                 :         43 :                 break;
    1250                 :        130 :             case NodeTypeWhileExpr:
    1251                 :        130 :                 loop->data.while_expr.name = token_buf(label);
    1252                 :        130 :                 break;
    1253                 :          0 :             default:
    1254                 :          0 :                 zig_unreachable();
    1255                 :            :         }
    1256                 :        173 :         return loop;
    1257         [ +  + ]:     682496 :     } else if (label != nullptr) {
    1258                 :            :         // Restore the tokens that we eaten by ast_parse_block_label.
    1259                 :        658 :         put_back_token(pc);
    1260                 :        658 :         put_back_token(pc);
    1261                 :            :     }
    1262                 :            : 
    1263                 :     682496 :     AstNode *block = ast_parse_block(pc);
    1264         [ +  + ]:     682496 :     if (block != nullptr)
    1265                 :       4141 :         return block;
    1266                 :            : 
    1267                 :     678355 :     AstNode *curly_suffix = ast_parse_curly_suffix_expr(pc);
    1268         [ +  + ]:     678355 :     if (curly_suffix != nullptr)
    1269                 :     591023 :         return curly_suffix;
    1270                 :            : 
    1271                 :      87332 :     return nullptr;
    1272                 :            : }
    1273                 :            : 
    1274                 :            : // IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
    1275                 :     714805 : static AstNode *ast_parse_if_expr(ParseContext *pc) {
    1276                 :     714805 :     return ast_parse_if_expr_helper(pc, ast_parse_expr);
    1277                 :            : }
    1278                 :            : 
    1279                 :            : // Block <- LBRACE Statement* RBRACE
    1280                 :     882540 : static AstNode *ast_parse_block(ParseContext *pc) {
    1281                 :     882540 :     Token *lbrace = eat_token_if(pc, TokenIdLBrace);
    1282         [ +  + ]:     882540 :     if (lbrace == nullptr)
    1283                 :     829197 :         return nullptr;
    1284                 :            : 
    1285                 :      53343 :     ZigList<AstNode *> statements = {};
    1286                 :            :     AstNode *statement;
    1287         [ +  + ]:     197353 :     while ((statement = ast_parse_statement(pc)) != nullptr)
    1288                 :     144010 :         statements.append(statement);
    1289                 :            : 
    1290                 :      53343 :     expect_token(pc, TokenIdRBrace);
    1291                 :            : 
    1292                 :      53343 :     AstNode *res = ast_create_node(pc, NodeTypeBlock, lbrace);
    1293                 :      53343 :     res->data.block.statements = statements;
    1294                 :     882540 :     return res;
    1295                 :            : }
    1296                 :            : 
    1297                 :            : // LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
    1298                 :     682669 : static AstNode *ast_parse_loop_expr(ParseContext *pc) {
    1299                 :            :     return ast_parse_loop_expr_helper(
    1300                 :            :         pc,
    1301                 :            :         ast_parse_for_expr,
    1302                 :            :         ast_parse_while_expr
    1303                 :     682669 :     );
    1304                 :            : }
    1305                 :            : 
    1306                 :            : // ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
    1307                 :     682669 : static AstNode *ast_parse_for_expr(ParseContext *pc) {
    1308                 :     682669 :     return ast_parse_for_expr_helper(pc, ast_parse_expr);
    1309                 :            : }
    1310                 :            : 
    1311                 :            : // WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
    1312                 :     682626 : static AstNode *ast_parse_while_expr(ParseContext *pc) {
    1313                 :     682626 :     return ast_parse_while_expr_helper(pc, ast_parse_expr);
    1314                 :            : }
    1315                 :            : 
    1316                 :            : // CurlySuffixExpr <- TypeExpr InitList?
    1317                 :     678355 : static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc) {
    1318                 :     678355 :     AstNode *type_expr = ast_parse_type_expr(pc);
    1319         [ +  + ]:     678355 :     if (type_expr == nullptr)
    1320                 :      87332 :         return nullptr;
    1321                 :            : 
    1322                 :     591023 :     AstNode *res = ast_parse_init_list(pc);
    1323         [ +  + ]:     591023 :     if (res == nullptr)
    1324                 :     577031 :         return type_expr;
    1325                 :            : 
    1326                 :      13992 :     assert(res->type == NodeTypeContainerInitExpr);
    1327                 :      13992 :     res->data.container_init_expr.type = type_expr;
    1328                 :      13992 :     return res;
    1329                 :            : }
    1330                 :            : 
    1331                 :            : // InitList
    1332                 :            : //     <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
    1333                 :            : //      / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
    1334                 :            : //      / LBRACE RBRACE
    1335                 :     591023 : static AstNode *ast_parse_init_list(ParseContext *pc) {
    1336                 :     591023 :     Token *lbrace = eat_token_if(pc, TokenIdLBrace);
    1337         [ +  + ]:     591023 :     if (lbrace == nullptr)
    1338                 :     577031 :         return nullptr;
    1339                 :            : 
    1340                 :      13992 :     AstNode *first = ast_parse_field_init(pc);
    1341         [ +  + ]:      13992 :     if (first != nullptr) {
    1342                 :       9084 :         AstNode *res = ast_create_node(pc, NodeTypeContainerInitExpr, lbrace);
    1343                 :       9084 :         res->data.container_init_expr.kind = ContainerInitKindStruct;
    1344                 :       9084 :         res->data.container_init_expr.entries.append(first);
    1345                 :            : 
    1346         [ +  + ]:      18332 :         while (eat_token_if(pc, TokenIdComma) != nullptr) {
    1347                 :      11352 :             AstNode *field_init = ast_parse_field_init(pc);
    1348         [ +  + ]:      11352 :             if (field_init == nullptr)
    1349                 :       2104 :                 break;
    1350                 :       9248 :             res->data.container_init_expr.entries.append(field_init);
    1351                 :            :         }
    1352                 :            : 
    1353                 :       9084 :         expect_token(pc, TokenIdRBrace);
    1354                 :       9084 :         return res;
    1355                 :            :     }
    1356                 :            : 
    1357                 :       4908 :     AstNode *res = ast_create_node(pc, NodeTypeContainerInitExpr, lbrace);
    1358                 :       4908 :     res->data.container_init_expr.kind = ContainerInitKindArray;
    1359                 :            : 
    1360                 :       4908 :     first = ast_parse_expr(pc);
    1361         [ +  + ]:       4908 :     if (first != nullptr) {
    1362                 :       4249 :         res->data.container_init_expr.entries.append(first);
    1363                 :            : 
    1364         [ +  + ]:      28931 :         while (eat_token_if(pc, TokenIdComma) != nullptr) {
    1365                 :      25990 :             AstNode *expr = ast_parse_expr(pc);
    1366         [ +  + ]:      25990 :             if (expr == nullptr)
    1367                 :       1308 :                 break;
    1368                 :      24682 :             res->data.container_init_expr.entries.append(expr);
    1369                 :            :         }
    1370                 :            : 
    1371                 :       4249 :         expect_token(pc, TokenIdRBrace);
    1372                 :       4249 :         return res;
    1373                 :            :     }
    1374                 :            : 
    1375                 :        659 :     expect_token(pc, TokenIdRBrace);
    1376                 :        659 :     return res;
    1377                 :            : }
    1378                 :            : 
    1379                 :            : // TypeExpr <- PrefixTypeOp* ErrorUnionExpr
    1380                 :     770100 : static AstNode *ast_parse_type_expr(ParseContext *pc) {
    1381                 :            :     return ast_parse_prefix_op_expr(
    1382                 :            :         pc,
    1383                 :            :         ast_parse_prefix_type_op,
    1384                 :            :         ast_parse_error_union_expr
    1385                 :     770100 :     );
    1386                 :            : }
    1387                 :            : 
    1388                 :            : // ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
    1389                 :     770100 : static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
    1390                 :     770100 :     AstNode *res = ast_parse_suffix_expr(pc);
    1391         [ +  + ]:     770100 :     if (res == nullptr)
    1392                 :      94930 :         return nullptr;
    1393                 :            : 
    1394                 :     675170 :     AstNode *op = ast_parse_bin_op_simple<TokenIdBang, BinOpTypeErrorUnion>(pc);
    1395         [ +  + ]:     675170 :     if (op == nullptr)
    1396                 :     672183 :         return res;
    1397                 :            : 
    1398                 :       2987 :     AstNode *right = ast_expect(pc, ast_parse_type_expr);
    1399                 :       2987 :     assert(op->type == NodeTypeBinOpExpr);
    1400                 :       2987 :     op->data.bin_op_expr.op1 = res;
    1401                 :       2987 :     op->data.bin_op_expr.op2 = right;
    1402                 :       2987 :     return op;
    1403                 :            : }
    1404                 :            : 
    1405                 :            : // SuffixExpr
    1406                 :            : //     <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
    1407                 :            : //      / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
    1408                 :     770100 : static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
    1409                 :     770100 :     Token *async_token = eat_token_if(pc, TokenIdKeywordAsync);
    1410         [ +  + ]:     770100 :     if (async_token != nullptr) {
    1411         [ +  + ]:        504 :         if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
    1412                 :            :             // HACK: If we see the keyword `fn`, then we assume that
    1413                 :            :             //       we are parsing an async fn proto, and not a call.
    1414                 :            :             //       We therefore put back all tokens consumed by the async
    1415                 :            :             //       prefix...
    1416                 :         56 :             put_back_token(pc);
    1417                 :         56 :             put_back_token(pc);
    1418                 :            : 
    1419                 :         56 :             return ast_parse_primary_type_expr(pc);
    1420                 :            :         }
    1421                 :            : 
    1422                 :        448 :         AstNode *child = ast_expect(pc, ast_parse_primary_type_expr);
    1423                 :            :         while (true) {
    1424                 :        536 :             AstNode *suffix = ast_parse_suffix_op(pc);
    1425         [ +  + ]:        536 :             if (suffix == nullptr)
    1426                 :        448 :                 break;
    1427                 :            : 
    1428   [ -  -  +  -  :         88 :             switch (suffix->type) {
                   -  - ]
    1429                 :          0 :                 case NodeTypeSliceExpr:
    1430                 :          0 :                     suffix->data.slice_expr.array_ref_expr = child;
    1431                 :          0 :                     break;
    1432                 :          0 :                 case NodeTypeArrayAccessExpr:
    1433                 :          0 :                     suffix->data.array_access_expr.array_ref_expr = child;
    1434                 :          0 :                     break;
    1435                 :         88 :                 case NodeTypeFieldAccessExpr:
    1436                 :         88 :                     suffix->data.field_access_expr.struct_expr = child;
    1437                 :         88 :                     break;
    1438                 :          0 :                 case NodeTypeUnwrapOptional:
    1439                 :          0 :                     suffix->data.unwrap_optional.expr = child;
    1440                 :          0 :                     break;
    1441                 :          0 :                 case NodeTypePtrDeref:
    1442                 :          0 :                     suffix->data.ptr_deref_expr.target = child;
    1443                 :          0 :                     break;
    1444                 :          0 :                 default:
    1445                 :          0 :                     zig_unreachable();
    1446                 :            :             }
    1447                 :         88 :             child = suffix;
    1448                 :         88 :         }
    1449                 :            : 
    1450                 :            :         // TODO: Both *_async_prefix and *_fn_call_argumnets returns an
    1451                 :            :         //       AstNode *. All we really want here is the arguments of
    1452                 :            :         //       the call we parse. We therefor "leak" the node for now.
    1453                 :            :         //       Wait till we get async rework to fix this.
    1454                 :        448 :         AstNode *args = ast_parse_fn_call_argumnets(pc);
    1455         [ -  + ]:        448 :         if (args == nullptr)
    1456                 :          0 :             ast_invalid_token_error(pc, peek_token(pc));
    1457                 :            : 
    1458                 :        448 :         assert(args->type == NodeTypeFnCallExpr);
    1459                 :            : 
    1460                 :        448 :         AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
    1461                 :        448 :         res->data.fn_call_expr.is_async = true;
    1462                 :        448 :         res->data.fn_call_expr.seen = false;
    1463                 :        448 :         res->data.fn_call_expr.fn_ref_expr = child;
    1464                 :        448 :         res->data.fn_call_expr.params = args->data.fn_call_expr.params;
    1465                 :        448 :         res->data.fn_call_expr.is_builtin = false;
    1466                 :        448 :         return res;
    1467                 :            :     }
    1468                 :            : 
    1469                 :     769596 :     AstNode *res = ast_parse_primary_type_expr(pc);
    1470         [ +  + ]:     769596 :     if (res == nullptr)
    1471                 :      94930 :         return nullptr;
    1472                 :            : 
    1473                 :            :     while (true) {
    1474                 :     912517 :         AstNode *suffix = ast_parse_suffix_op(pc);
    1475         [ +  + ]:     912517 :         if (suffix != nullptr) {
    1476   [ +  +  +  +  :     133143 :             switch (suffix->type) {
                   +  - ]
    1477                 :       5049 :                 case NodeTypeSliceExpr:
    1478                 :       5049 :                     suffix->data.slice_expr.array_ref_expr = res;
    1479                 :       5049 :                     break;
    1480                 :       8857 :                 case NodeTypeArrayAccessExpr:
    1481                 :       8857 :                     suffix->data.array_access_expr.array_ref_expr = res;
    1482                 :       8857 :                     break;
    1483                 :     115651 :                 case NodeTypeFieldAccessExpr:
    1484                 :     115651 :                     suffix->data.field_access_expr.struct_expr = res;
    1485                 :     115651 :                     break;
    1486                 :       1305 :                 case NodeTypeUnwrapOptional:
    1487                 :       1305 :                     suffix->data.unwrap_optional.expr = res;
    1488                 :       1305 :                     break;
    1489                 :       2281 :                 case NodeTypePtrDeref:
    1490                 :       2281 :                     suffix->data.ptr_deref_expr.target = res;
    1491                 :       2281 :                     break;
    1492                 :          0 :                 default:
    1493                 :          0 :                     zig_unreachable();
    1494                 :            :             }
    1495                 :     133143 :             res = suffix;
    1496                 :     133143 :             continue;
    1497                 :            :         }
    1498                 :            : 
    1499                 :     779374 :         AstNode * call = ast_parse_fn_call_argumnets(pc);
    1500         [ +  + ]:     779374 :         if (call != nullptr) {
    1501                 :     104708 :             assert(call->type == NodeTypeFnCallExpr);
    1502                 :     104708 :             call->data.fn_call_expr.fn_ref_expr = res;
    1503                 :     104708 :             res = call;
    1504                 :     104708 :             continue;
    1505                 :            :         }
    1506                 :            : 
    1507                 :     674666 :         break;
    1508                 :     237851 :     }
    1509                 :            : 
    1510                 :     674666 :     return res;
    1511                 :            : 
    1512                 :            : }
    1513                 :            : 
    1514                 :            : // PrimaryTypeExpr
    1515                 :            : //     <- BUILTINIDENTIFIER FnCallArguments
    1516                 :            : //      / CHAR_LITERAL
    1517                 :            : //      / ContainerDecl
    1518                 :            : //      / DOT IDENTIFIER
    1519                 :            : //      / ErrorSetDecl
    1520                 :            : //      / FLOAT
    1521                 :            : //      / FnProto
    1522                 :            : //      / GroupedExpr
    1523                 :            : //      / LabeledTypeExpr
    1524                 :            : //      / IDENTIFIER
    1525                 :            : //      / IfTypeExpr
    1526                 :            : //      / INTEGER
    1527                 :            : //      / KEYWORD_comptime TypeExpr
    1528                 :            : //      / KEYWORD_error DOT IDENTIFIER
    1529                 :            : //      / KEYWORD_false
    1530                 :            : //      / KEYWORD_null
    1531                 :            : //      / KEYWORD_promise
    1532                 :            : //      / KEYWORD_true
    1533                 :            : //      / KEYWORD_undefined
    1534                 :            : //      / KEYWORD_unreachable
    1535                 :            : //      / STRINGLITERAL
    1536                 :            : //      / SwitchExpr
    1537                 :     770100 : static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
    1538                 :            :     // TODO: This is not in line with the grammar.
    1539                 :            :     //       Because the prev stage 1 tokenizer does not parse
    1540                 :            :     //       @[a-zA-Z_][a-zA-Z0-9_] as one token, it has to do a
    1541                 :            :     //       hack, where it accepts '@' (IDENTIFIER / KEYWORD_export).
    1542                 :            :     //       I'd say that it's better if '@' is part of the builtin
    1543                 :            :     //       identifier token.
    1544                 :     770100 :     Token *at_sign = eat_token_if(pc, TokenIdAtSign);
    1545         [ +  + ]:     770100 :     if (at_sign != nullptr) {
    1546                 :            :         Buf *name;
    1547                 :      37320 :         Token *token = eat_token_if(pc, TokenIdKeywordExport);
    1548         [ +  + ]:      37320 :         if (token == nullptr) {
    1549                 :      36510 :             token = expect_token(pc, TokenIdSymbol);
    1550                 :      36510 :             name = token_buf(token);
    1551                 :            :         } else {
    1552                 :        810 :             name = buf_create_from_str("export");
    1553                 :            :         }
    1554                 :            : 
    1555                 :      37320 :         AstNode *res = ast_expect(pc, ast_parse_fn_call_argumnets);
    1556                 :      37320 :         AstNode *name_sym = ast_create_node(pc, NodeTypeSymbol, token);
    1557                 :      37320 :         name_sym->data.symbol_expr.symbol = name;
    1558                 :            : 
    1559                 :      37320 :         assert(res->type == NodeTypeFnCallExpr);
    1560                 :      37320 :         res->line = at_sign->start_line;
    1561                 :      37320 :         res->column = at_sign->start_column;
    1562                 :      37320 :         res->data.fn_call_expr.fn_ref_expr = name_sym;
    1563                 :      37320 :         res->data.fn_call_expr.is_builtin = true;
    1564                 :      37320 :         return res;
    1565                 :            :     }
    1566                 :            : 
    1567                 :     732780 :     Token *char_lit = eat_token_if(pc, TokenIdCharLiteral);
    1568         [ +  + ]:     732780 :     if (char_lit != nullptr) {
    1569                 :       4139 :         AstNode *res = ast_create_node(pc, NodeTypeCharLiteral, char_lit);
    1570                 :       4139 :         res->data.char_literal.value = char_lit->data.char_lit.c;
    1571                 :       4139 :         return res;
    1572                 :            :     }
    1573                 :            : 
    1574                 :     728641 :     AstNode *container_decl = ast_parse_container_decl(pc);
    1575         [ +  + ]:     728641 :     if (container_decl != nullptr)
    1576                 :       7526 :         return container_decl;
    1577                 :            : 
    1578                 :     721115 :     AstNode *enum_lit = ast_parse_enum_lit(pc);
    1579         [ +  + ]:     721115 :     if (enum_lit != nullptr)
    1580                 :       3545 :         return enum_lit;
    1581                 :            : 
    1582                 :     717570 :     AstNode *error_set_decl = ast_parse_error_set_decl(pc);
    1583         [ +  + ]:     717570 :     if (error_set_decl != nullptr)
    1584                 :       1215 :         return error_set_decl;
    1585                 :            : 
    1586                 :     716355 :     Token *float_lit = eat_token_if(pc, TokenIdFloatLiteral);
    1587         [ +  + ]:     716355 :     if (float_lit != nullptr) {
    1588                 :      18535 :         AstNode *res = ast_create_node(pc, NodeTypeFloatLiteral, float_lit);
    1589                 :      18535 :         res->data.float_literal.bigfloat = &float_lit->data.float_lit.bigfloat;
    1590                 :      18535 :         res->data.float_literal.overflow = float_lit->data.float_lit.overflow;
    1591                 :      18535 :         return res;
    1592                 :            :     }
    1593                 :            : 
    1594                 :     697820 :     AstNode *fn_proto = ast_parse_fn_proto(pc);
    1595         [ +  + ]:     697820 :     if (fn_proto != nullptr)
    1596                 :        812 :         return fn_proto;
    1597                 :            : 
    1598                 :     697008 :     AstNode *grouped_expr = ast_parse_grouped_expr(pc);
    1599         [ +  + ]:     697008 :     if (grouped_expr != nullptr)
    1600                 :       7310 :         return grouped_expr;
    1601                 :            : 
    1602                 :     689698 :     AstNode *labeled_type_expr = ast_parse_labeled_type_expr(pc);
    1603         [ +  + ]:     689698 :     if (labeled_type_expr != nullptr)
    1604                 :        707 :         return labeled_type_expr;
    1605                 :            : 
    1606                 :     688991 :     Token *identifier = eat_token_if(pc, TokenIdSymbol);
    1607         [ +  + ]:     688991 :     if (identifier != nullptr)
    1608                 :     426448 :         return token_symbol(pc, identifier);
    1609                 :            : 
    1610                 :     262543 :     AstNode *if_type_expr = ast_parse_if_type_expr(pc);
    1611         [ +  + ]:     262543 :     if (if_type_expr != nullptr)
    1612                 :         49 :         return if_type_expr;
    1613                 :            : 
    1614                 :     262494 :     Token *int_lit = eat_token_if(pc, TokenIdIntLiteral);
    1615         [ +  + ]:     262494 :     if (int_lit != nullptr) {
    1616                 :     108729 :         AstNode *res = ast_create_node(pc, NodeTypeIntLiteral, int_lit);
    1617                 :     108729 :         res->data.int_literal.bigint = &int_lit->data.int_lit.bigint;
    1618                 :     108729 :         return res;
    1619                 :            :     }
    1620                 :            : 
    1621                 :     153765 :     Token *comptime = eat_token_if(pc, TokenIdKeywordCompTime);
    1622         [ +  + ]:     153765 :     if (comptime != nullptr) {
    1623                 :          8 :         AstNode *expr = ast_expect(pc, ast_parse_type_expr);
    1624                 :          8 :         AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
    1625                 :          8 :         res->data.comptime_expr.expr = expr;
    1626                 :          8 :         return res;
    1627                 :            :     }
    1628                 :            : 
    1629                 :     153757 :     Token *error = eat_token_if(pc, TokenIdKeywordError);
    1630         [ +  + ]:     153757 :     if (error != nullptr) {
    1631                 :       8128 :         Token *dot = expect_token(pc, TokenIdDot);
    1632                 :       8128 :         Token *name = expect_token(pc, TokenIdSymbol);
    1633                 :       8128 :         AstNode *left = ast_create_node(pc, NodeTypeErrorType, error);
    1634                 :       8128 :         AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot);
    1635                 :       8128 :         res->data.field_access_expr.struct_expr = left;
    1636                 :       8128 :         res->data.field_access_expr.field_name = token_buf(name);
    1637                 :       8128 :         return res;
    1638                 :            :     }
    1639                 :            : 
    1640                 :     145629 :     Token *false_token = eat_token_if(pc, TokenIdKeywordFalse);
    1641         [ +  + ]:     145629 :     if (false_token != nullptr) {
    1642                 :       3173 :         AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, false_token);
    1643                 :       3173 :         res->data.bool_literal.value = false;
    1644                 :       3173 :         return res;
    1645                 :            :     }
    1646                 :            : 
    1647                 :     142456 :     Token *null = eat_token_if(pc, TokenIdKeywordNull);
    1648         [ +  + ]:     142456 :     if (null != nullptr)
    1649                 :       3267 :         return ast_create_node(pc, NodeTypeNullLiteral, null);
    1650                 :            : 
    1651                 :     139189 :     Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
    1652         [ +  + ]:     139189 :     if (anyframe != nullptr)
    1653                 :        176 :         return ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
    1654                 :            : 
    1655                 :     139013 :     Token *true_token = eat_token_if(pc, TokenIdKeywordTrue);
    1656         [ +  + ]:     139013 :     if (true_token != nullptr) {
    1657                 :       3234 :         AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token);
    1658                 :       3234 :         res->data.bool_literal.value = true;
    1659                 :       3234 :         return res;
    1660                 :            :     }
    1661                 :            : 
    1662                 :     135779 :     Token *undefined = eat_token_if(pc, TokenIdKeywordUndefined);
    1663         [ +  + ]:     135779 :     if (undefined != nullptr)
    1664                 :       3955 :         return ast_create_node(pc, NodeTypeUndefinedLiteral, undefined);
    1665                 :            : 
    1666                 :     131824 :     Token *unreachable = eat_token_if(pc, TokenIdKeywordUnreachable);
    1667         [ +  + ]:     131824 :     if (unreachable != nullptr)
    1668                 :       3649 :         return ast_create_node(pc, NodeTypeUnreachable, unreachable);
    1669                 :            : 
    1670                 :     128175 :     Token *string_lit = eat_token_if(pc, TokenIdStringLiteral);
    1671         [ +  + ]:     128175 :     if (string_lit != nullptr) {
    1672                 :      31576 :         AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);
    1673                 :      31576 :         res->data.string_literal.buf = token_buf(string_lit);
    1674                 :      31576 :         res->data.string_literal.c = string_lit->data.str_lit.is_c_str;
    1675                 :      31576 :         return res;
    1676                 :            :     }
    1677                 :            : 
    1678                 :      96599 :     AstNode *switch_expr = ast_parse_switch_expr(pc);
    1679         [ +  + ]:      96599 :     if (switch_expr != nullptr)
    1680                 :       1669 :         return switch_expr;
    1681                 :            : 
    1682                 :      94930 :     return nullptr;
    1683                 :            : }
    1684                 :            : 
    1685                 :            : // ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
    1686                 :     728641 : static AstNode *ast_parse_container_decl(ParseContext *pc) {
    1687                 :     728641 :     Token *layout_token = eat_token_if(pc, TokenIdKeywordExtern);
    1688         [ +  + ]:     728641 :     if (layout_token == nullptr)
    1689                 :     727246 :         layout_token = eat_token_if(pc, TokenIdKeywordPacked);
    1690                 :            : 
    1691                 :     728641 :     AstNode *res = ast_parse_container_decl_auto(pc);
    1692         [ +  + ]:     728641 :     if (res == nullptr) {
    1693         [ +  + ]:     721115 :         if (layout_token != nullptr)
    1694                 :        154 :             put_back_token(pc);
    1695                 :     721115 :         return nullptr;
    1696                 :            :     }
    1697                 :            : 
    1698                 :       7526 :     assert(res->type == NodeTypeContainerDecl);
    1699         [ +  + ]:       7526 :     if (layout_token != nullptr) {
    1700                 :       1772 :         res->line = layout_token->start_line;
    1701                 :       1772 :         res->column = layout_token->start_column;
    1702                 :       1772 :         res->data.container_decl.layout = layout_token->id == TokenIdKeywordExtern
    1703         [ +  + ]:       1772 :             ? ContainerLayoutExtern
    1704                 :            :             : ContainerLayoutPacked;
    1705                 :            :     }
    1706                 :       7526 :     return res;
    1707                 :            : }
    1708                 :            : 
    1709                 :            : // ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
    1710                 :     717570 : static AstNode *ast_parse_error_set_decl(ParseContext *pc) {
    1711                 :     717570 :     Token *first = eat_token_if(pc, TokenIdKeywordError);
    1712         [ +  + ]:     717570 :     if (first == nullptr)
    1713                 :     708227 :         return nullptr;
    1714         [ +  + ]:       9343 :     if (eat_token_if(pc, TokenIdLBrace) == nullptr) {
    1715                 :       8128 :         put_back_token(pc);
    1716                 :       8128 :         return nullptr;
    1717                 :            :     }
    1718                 :            : 
    1719                 :      10943 :     ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) {
    1720                 :       4864 :         Token *ident = eat_token_if(context, TokenIdSymbol);
    1721         [ +  + ]:       4864 :         if (ident == nullptr)
    1722                 :        730 :             return (AstNode*)nullptr;
    1723                 :            : 
    1724                 :       4134 :         return token_symbol(context, ident);
    1725                 :       7294 :     });
    1726                 :       1215 :     expect_token(pc, TokenIdRBrace);
    1727                 :            : 
    1728                 :       1215 :     AstNode *res = ast_create_node(pc, NodeTypeErrorSetDecl, first);
    1729                 :       1215 :     res->data.err_set_decl.decls = decls;
    1730                 :     717570 :     return res;
    1731                 :            : }
    1732                 :            : 
    1733                 :            : // GroupedExpr <- LPAREN Expr RPAREN
    1734                 :     697008 : static AstNode *ast_parse_grouped_expr(ParseContext *pc) {
    1735                 :     697008 :     Token *lparen = eat_token_if(pc, TokenIdLParen);
    1736         [ +  + ]:     697008 :     if (lparen == nullptr)
    1737                 :     689698 :         return nullptr;
    1738                 :            : 
    1739                 :       7310 :     AstNode *expr = ast_expect(pc, ast_parse_expr);
    1740                 :       7310 :     expect_token(pc, TokenIdRParen);
    1741                 :            : 
    1742                 :       7310 :     AstNode *res = ast_create_node(pc, NodeTypeGroupedExpr, lparen);
    1743                 :       7310 :     res->data.grouped_expr = expr;
    1744                 :       7310 :     return res;
    1745                 :            : }
    1746                 :            : 
    1747                 :            : // IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
    1748                 :     262543 : static AstNode *ast_parse_if_type_expr(ParseContext *pc) {
    1749                 :     262543 :     return ast_parse_if_expr_helper(pc, ast_parse_type_expr);
    1750                 :            : }
    1751                 :            : 
    1752                 :            : // LabeledTypeExpr
    1753                 :            : //     <- BlockLabel Block
    1754                 :            : //      / BlockLabel? LoopTypeExpr
    1755                 :     689698 : static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {
    1756                 :     689698 :     Token *label = ast_parse_block_label(pc);
    1757         [ +  + ]:     689698 :     if (label != nullptr) {
    1758                 :        691 :         AstNode *block = ast_parse_block(pc);
    1759         [ +  - ]:        691 :         if (block != nullptr) {
    1760                 :        691 :             assert(block->type == NodeTypeBlock);
    1761                 :        691 :             block->data.block.name = token_buf(label);
    1762                 :        691 :             return block;
    1763                 :            :         }
    1764                 :            :     }
    1765                 :            : 
    1766                 :     689007 :     AstNode *loop = ast_parse_loop_type_expr(pc);
    1767         [ +  + ]:     689007 :     if (loop != nullptr) {
    1768      [ +  +  - ]:         16 :         switch (loop->type) {
    1769                 :          8 :             case NodeTypeForExpr:
    1770                 :          8 :                 loop->data.for_expr.name = token_buf(label);
    1771                 :          8 :                 break;
    1772                 :          8 :             case NodeTypeWhileExpr:
    1773                 :          8 :                 loop->data.while_expr.name = token_buf(label);
    1774                 :          8 :                 break;
    1775                 :          0 :             default:
    1776                 :          0 :                 zig_unreachable();
    1777                 :            :         }
    1778                 :         16 :         return loop;
    1779                 :            :     }
    1780                 :            : 
    1781         [ -  + ]:     688991 :     if (label != nullptr)
    1782                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
    1783                 :     688991 :     return nullptr;
    1784                 :            : }
    1785                 :            : 
    1786                 :            : // LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
    1787                 :     689007 : static AstNode *ast_parse_loop_type_expr(ParseContext *pc) {
    1788                 :            :     return ast_parse_loop_expr_helper(
    1789                 :            :         pc,
    1790                 :            :         ast_parse_for_type_expr,
    1791                 :            :         ast_parse_while_type_expr
    1792                 :     689007 :     );
    1793                 :            : }
    1794                 :            : 
    1795                 :            : // ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
    1796                 :     689007 : static AstNode *ast_parse_for_type_expr(ParseContext *pc) {
    1797                 :     689007 :     return ast_parse_for_expr_helper(pc, ast_parse_type_expr);
    1798                 :            : }
    1799                 :            : 
    1800                 :            : // WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
    1801                 :     688999 : static AstNode *ast_parse_while_type_expr(ParseContext *pc) {
    1802                 :     688999 :     return ast_parse_while_expr_helper(pc, ast_parse_type_expr);
    1803                 :            : }
    1804                 :            : 
    1805                 :            : // SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
    1806                 :     234265 : static AstNode *ast_parse_switch_expr(ParseContext *pc) {
    1807                 :     234265 :     Token *switch_token = eat_token_if(pc, TokenIdKeywordSwitch);
    1808         [ +  + ]:     234265 :     if (switch_token == nullptr)
    1809                 :     230203 :         return nullptr;
    1810                 :            : 
    1811                 :       4062 :     expect_token(pc, TokenIdLParen);
    1812                 :       4062 :     AstNode *expr = ast_expect(pc, ast_parse_expr);
    1813                 :       4062 :     expect_token(pc, TokenIdRParen);
    1814                 :       4062 :     expect_token(pc, TokenIdLBrace);
    1815                 :       4062 :     ZigList<AstNode *> prongs = ast_parse_list(pc, TokenIdComma, ast_parse_switch_prong);
    1816                 :       4062 :     expect_token(pc, TokenIdRBrace);
    1817                 :            : 
    1818                 :       4062 :     AstNode *res = ast_create_node(pc, NodeTypeSwitchExpr, switch_token);
    1819                 :       4062 :     res->data.switch_expr.expr = expr;
    1820                 :       4062 :     res->data.switch_expr.prongs = prongs;
    1821                 :     234265 :     return res;
    1822                 :            : }
    1823                 :            : 
    1824                 :            : // AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
    1825                 :     715110 : static AstNode *ast_parse_asm_expr(ParseContext *pc) {
    1826                 :     715110 :     Token *asm_token = eat_token_if(pc, TokenIdKeywordAsm);
    1827         [ +  + ]:     715110 :     if (asm_token == nullptr)
    1828                 :     714805 :         return nullptr;
    1829                 :            : 
    1830                 :        305 :     Token *volatile_token = eat_token_if(pc, TokenIdKeywordVolatile);
    1831                 :        305 :     expect_token(pc, TokenIdLParen);
    1832                 :        305 :     Token *asm_template = expect_token(pc, TokenIdStringLiteral);
    1833                 :        305 :     AstNode *res = ast_parse_asm_output(pc);
    1834         [ +  + ]:        305 :     if (res == nullptr)
    1835                 :         91 :         res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
    1836                 :        305 :     expect_token(pc, TokenIdRParen);
    1837                 :            : 
    1838                 :        305 :     res->line = asm_token->start_line;
    1839                 :        305 :     res->column = asm_token->start_column;
    1840                 :        305 :     res->data.asm_expr.volatile_token = volatile_token;
    1841                 :        305 :     res->data.asm_expr.asm_template = asm_template;
    1842                 :        305 :     return res;
    1843                 :            : }
    1844                 :            : 
    1845                 :     721115 : static AstNode *ast_parse_enum_lit(ParseContext *pc) {
    1846                 :     721115 :     Token *period = eat_token_if(pc, TokenIdDot);
    1847         [ +  + ]:     721115 :     if (period == nullptr)
    1848                 :     717570 :         return nullptr;
    1849                 :            : 
    1850                 :       3545 :     Token *identifier = expect_token(pc, TokenIdSymbol);
    1851                 :       3545 :     AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period);
    1852                 :       3545 :     res->data.enum_literal.period = period;
    1853                 :       3545 :     res->data.enum_literal.identifier = identifier;
    1854                 :       3545 :     return res;
    1855                 :            : }
    1856                 :            : 
    1857                 :            : // AsmOutput <- COLON AsmOutputList AsmInput?
    1858                 :        305 : static AstNode *ast_parse_asm_output(ParseContext *pc) {
    1859         [ +  + ]:        305 :     if (eat_token_if(pc, TokenIdColon) == nullptr)
    1860                 :         91 :         return nullptr;
    1861                 :            : 
    1862                 :        214 :     ZigList<AsmOutput *> output_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_output_item);
    1863                 :        214 :     AstNode *res = ast_parse_asm_input(pc);
    1864         [ +  + ]:        214 :     if (res == nullptr)
    1865                 :         35 :         res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
    1866                 :            : 
    1867                 :        214 :     res->data.asm_expr.output_list = output_list;
    1868                 :        305 :     return res;
    1869                 :            : }
    1870                 :            : 
    1871                 :            : // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
    1872                 :        230 : static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
    1873                 :        230 :     Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
    1874         [ +  + ]:        230 :     if (sym_name == nullptr) {
    1875         [ +  + ]:        206 :         if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
    1876                 :        100 :             return nullptr;
    1877                 :            :         } else {
    1878                 :        106 :             sym_name = expect_token(pc, TokenIdSymbol);
    1879                 :        106 :             expect_token(pc, TokenIdRBracket);
    1880                 :            :         }
    1881                 :            :     }
    1882                 :            : 
    1883                 :        130 :     Token *str = expect_token(pc, TokenIdStringLiteral);
    1884                 :        130 :     expect_token(pc, TokenIdLParen);
    1885                 :            : 
    1886                 :        130 :     Token *var_name = eat_token_if(pc, TokenIdSymbol);
    1887                 :        130 :     AstNode *return_type = nullptr;
    1888         [ +  + ]:        130 :     if (var_name == nullptr) {
    1889                 :         98 :         expect_token(pc, TokenIdArrow);
    1890                 :         98 :         return_type = ast_expect(pc, ast_parse_type_expr);
    1891                 :            :     }
    1892                 :            : 
    1893                 :        130 :     expect_token(pc, TokenIdRParen);
    1894                 :            : 
    1895                 :        130 :     AsmOutput *res = allocate<AsmOutput>(1);
    1896         [ +  + ]:        130 :     res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
    1897                 :        130 :     res->constraint = token_buf(str);
    1898                 :        130 :     res->variable_name = token_buf(var_name);
    1899                 :        130 :     res->return_type = return_type;
    1900                 :        130 :     return res;
    1901                 :            : }
    1902                 :            : 
    1903                 :            : // AsmInput <- COLON AsmInputList AsmClobbers?
    1904                 :        214 : static AstNode *ast_parse_asm_input(ParseContext *pc) {
    1905         [ +  + ]:        214 :     if (eat_token_if(pc, TokenIdColon) == nullptr)
    1906                 :         35 :         return nullptr;
    1907                 :            : 
    1908                 :        179 :     ZigList<AsmInput *> input_list = ast_parse_list(pc, TokenIdComma, ast_parse_asm_input_item);
    1909                 :        179 :     AstNode *res = ast_parse_asm_clobbers(pc);
    1910         [ +  + ]:        179 :     if (res == nullptr)
    1911                 :         11 :         res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
    1912                 :            : 
    1913                 :        179 :     res->data.asm_expr.input_list = input_list;
    1914                 :        214 :     return res;
    1915                 :            : }
    1916                 :            : 
    1917                 :            : // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
    1918                 :        376 : static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
    1919                 :        376 :     Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
    1920         [ +  + ]:        376 :     if (sym_name == nullptr) {
    1921         [ +  + ]:        304 :         if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
    1922                 :         32 :             return nullptr;
    1923                 :            :         } else {
    1924                 :        272 :             sym_name = expect_token(pc, TokenIdSymbol);
    1925                 :        272 :             expect_token(pc, TokenIdRBracket);
    1926                 :            :         }
    1927                 :            :     }
    1928                 :            : 
    1929                 :        344 :     Token *constraint = expect_token(pc, TokenIdStringLiteral);
    1930                 :        344 :     expect_token(pc, TokenIdLParen);
    1931                 :        344 :     AstNode *expr = ast_expect(pc, ast_parse_expr);
    1932                 :        344 :     expect_token(pc, TokenIdRParen);
    1933                 :            : 
    1934                 :        344 :     AsmInput *res = allocate<AsmInput>(1);
    1935         [ +  + ]:        344 :     res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
    1936                 :        344 :     res->constraint = token_buf(constraint);
    1937                 :        344 :     res->expr = expr;
    1938                 :        344 :     return res;
    1939                 :            : }
    1940                 :            : 
    1941                 :            : // AsmClobbers <- COLON StringList
    1942                 :        179 : static AstNode *ast_parse_asm_clobbers(ParseContext *pc) {
    1943         [ +  + ]:        179 :     if (eat_token_if(pc, TokenIdColon) == nullptr)
    1944                 :         11 :         return nullptr;
    1945                 :            : 
    1946                 :        680 :     ZigList<Buf *> clobber_list = ast_parse_list<Buf>(pc, TokenIdComma, [](ParseContext *context) {
    1947                 :        256 :         Token *str = eat_token_if(context, TokenIdStringLiteral);
    1948         [ +  + ]:        256 :         if (str != nullptr)
    1949                 :        248 :             return token_buf(str);
    1950                 :          8 :         return (Buf*)nullptr;
    1951                 :        592 :     });
    1952                 :            : 
    1953                 :        168 :     AstNode *res = ast_create_node_no_line_info(pc, NodeTypeAsmExpr);
    1954                 :        168 :     res->data.asm_expr.clobber_list = clobber_list;
    1955                 :        179 :     return res;
    1956                 :            : }
    1957                 :            : 
    1958                 :            : // BreakLabel <- COLON IDENTIFIER
    1959                 :       2442 : static Token *ast_parse_break_label(ParseContext *pc) {
    1960         [ +  + ]:       2442 :     if (eat_token_if(pc, TokenIdColon) == nullptr)
    1961                 :       1372 :         return nullptr;
    1962                 :            : 
    1963                 :       1070 :     return expect_token(pc, TokenIdSymbol);
    1964                 :            : }
    1965                 :            : 
    1966                 :            : // BlockLabel <- IDENTIFIER COLON
    1967                 :    1540253 : static Token *ast_parse_block_label(ParseContext *pc) {
    1968                 :    1540253 :     Token *ident = eat_token_if(pc, TokenIdSymbol);
    1969         [ +  + ]:    1540253 :     if (ident == nullptr)
    1970                 :     717309 :         return nullptr;
    1971                 :            : 
    1972                 :            :     // We do 2 token lookahead here, as we don't want to error when
    1973                 :            :     // parsing identifiers.
    1974         [ +  + ]:     822944 :     if (eat_token_if(pc, TokenIdColon) == nullptr) {
    1975                 :     821484 :         put_back_token(pc);
    1976                 :     821484 :         return nullptr;
    1977                 :            :     }
    1978                 :            : 
    1979                 :       1460 :     return ident;
    1980                 :            : }
    1981                 :            : 
    1982                 :            : // FieldInit <- DOT IDENTIFIER EQUAL Expr
    1983                 :      25344 : static AstNode *ast_parse_field_init(ParseContext *pc) {
    1984                 :      25344 :     Token *first = eat_token_if(pc, TokenIdDot);
    1985         [ +  + ]:      25344 :     if (first == nullptr)
    1986                 :       7004 :         return nullptr;
    1987                 :            : 
    1988                 :      18340 :     Token *name = expect_token(pc, TokenIdSymbol);
    1989         [ +  + ]:      18340 :     if (eat_token_if(pc, TokenIdEq) == nullptr) {
    1990                 :            :         // Because ".Name" can also be intepreted as an enum literal, we should put back
    1991                 :            :         // those two tokens again so that the parser can try to parse them as the enum
    1992                 :            :         // literal later.
    1993                 :          8 :         put_back_token(pc);
    1994                 :          8 :         put_back_token(pc);
    1995                 :          8 :         return nullptr;
    1996                 :            :     }
    1997                 :      18332 :     AstNode *expr = ast_expect(pc, ast_parse_expr);
    1998                 :            : 
    1999                 :      18332 :     AstNode *res = ast_create_node(pc, NodeTypeStructValueField, first);
    2000                 :      18332 :     res->data.struct_val_field.name = token_buf(name);
    2001                 :      18332 :     res->data.struct_val_field.expr = expr;
    2002                 :      18332 :     return res;
    2003                 :            : }
    2004                 :            : 
    2005                 :            : // WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
    2006                 :       3062 : static AstNode *ast_parse_while_continue_expr(ParseContext *pc) {
    2007                 :       3062 :     Token *first = eat_token_if(pc, TokenIdColon);
    2008         [ +  + ]:       3062 :     if (first == nullptr)
    2009                 :       1702 :         return nullptr;
    2010                 :            : 
    2011                 :       1360 :     expect_token(pc, TokenIdLParen);
    2012                 :       1360 :     AstNode *expr = ast_expect(pc, ast_parse_assign_expr);
    2013                 :       1360 :     expect_token(pc, TokenIdRParen);
    2014                 :       1360 :     return expr;
    2015                 :            : }
    2016                 :            : 
    2017                 :            : // LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
    2018                 :      99321 : static AstNode *ast_parse_link_section(ParseContext *pc) {
    2019                 :      99321 :     Token *first = eat_token_if(pc, TokenIdKeywordLinkSection);
    2020         [ +  + ]:      99321 :     if (first == nullptr)
    2021                 :      99316 :         return nullptr;
    2022                 :            : 
    2023                 :          5 :     expect_token(pc, TokenIdLParen);
    2024                 :          5 :     AstNode *res = ast_expect(pc, ast_parse_expr);
    2025                 :          5 :     expect_token(pc, TokenIdRParen);
    2026                 :          5 :     return res;
    2027                 :            : }
    2028                 :            : 
    2029                 :            : // FnCC
    2030                 :            : //     <- KEYWORD_nakedcc
    2031                 :            : //      / KEYWORD_stdcallcc
    2032                 :            : //      / KEYWORD_extern
    2033                 :            : //      / KEYWORD_async
    2034                 :     758983 : static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {
    2035                 :     758983 :     AstNodeFnProto res = {};
    2036         [ +  + ]:     758983 :     if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) {
    2037                 :         64 :         res.cc = CallingConventionNaked;
    2038                 :         64 :         return Optional<AstNodeFnProto>::some(res);
    2039                 :            :     }
    2040         [ +  + ]:     758919 :     if (eat_token_if(pc, TokenIdKeywordStdcallCC) != nullptr) {
    2041                 :        202 :         res.cc = CallingConventionStdcall;
    2042                 :        202 :         return Optional<AstNodeFnProto>::some(res);
    2043                 :            :     }
    2044         [ +  + ]:     758717 :     if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) {
    2045                 :        154 :         res.cc = CallingConventionC;
    2046                 :        154 :         return Optional<AstNodeFnProto>::some(res);
    2047                 :            :     }
    2048         [ +  + ]:     758563 :     if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) {
    2049                 :        184 :         res.cc = CallingConventionAsync;
    2050                 :        184 :         return Optional<AstNodeFnProto>::some(res);
    2051                 :            :     }
    2052                 :            : 
    2053                 :     758983 :     return Optional<AstNodeFnProto>::none();
    2054                 :            : }
    2055                 :            : 
    2056                 :            : // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
    2057                 :      40724 : static AstNode *ast_parse_param_decl(ParseContext *pc) {
    2058                 :      40724 :     Token *first = eat_token_if(pc, TokenIdKeywordNoAlias);
    2059         [ +  + ]:      40724 :     if (first == nullptr)
    2060                 :      40412 :         first = eat_token_if(pc, TokenIdKeywordCompTime);
    2061                 :            : 
    2062                 :      40724 :     Token *name = eat_token_if(pc, TokenIdSymbol);
    2063         [ +  + ]:      40724 :     if (name != nullptr) {
    2064         [ +  + ]:      32587 :         if (eat_token_if(pc, TokenIdColon) != nullptr) {
    2065         [ +  + ]:      32234 :             if (first == nullptr)
    2066                 :      28456 :                 first = name;
    2067                 :            :         } else {
    2068                 :            :             // We put back the ident, so it can be parsed as a ParamType
    2069                 :            :             // later.
    2070                 :        353 :             put_back_token(pc);
    2071                 :      32587 :             name = nullptr;
    2072                 :            :         }
    2073                 :            :     }
    2074                 :            : 
    2075                 :            :     AstNode *res;
    2076         [ +  + ]:      40724 :     if (first == nullptr) {
    2077                 :       8490 :         first = peek_token(pc);
    2078                 :       8490 :         res = ast_parse_param_type(pc);
    2079                 :            :     } else {
    2080                 :      32234 :         res = ast_expect(pc, ast_parse_param_type);
    2081                 :            :     }
    2082                 :            : 
    2083         [ +  + ]:      40724 :     if (res == nullptr)
    2084                 :       7598 :         return nullptr;
    2085                 :            : 
    2086                 :      33126 :     assert(res->type == NodeTypeParamDecl);
    2087                 :      33126 :     res->line = first->start_line;
    2088                 :      33126 :     res->column = first->start_column;
    2089                 :      33126 :     res->data.param_decl.name = token_buf(name);
    2090                 :      33126 :     res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias;
    2091                 :      33126 :     res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime;
    2092                 :      33126 :     return res;
    2093                 :            : }
    2094                 :            : 
    2095                 :            : // ParamType
    2096                 :            : //     <- KEYWORD_var
    2097                 :            : //      / DOT3
    2098                 :            : //      / TypeExpr
    2099                 :      40724 : static AstNode *ast_parse_param_type(ParseContext *pc) {
    2100                 :      40724 :     Token *var_token = eat_token_if(pc, TokenIdKeywordVar);
    2101         [ +  + ]:      40724 :     if (var_token != nullptr) {
    2102                 :       1425 :         AstNode *res = ast_create_node(pc, NodeTypeParamDecl, var_token);
    2103                 :       1425 :         res->data.param_decl.var_token = var_token;
    2104                 :       1425 :         return res;
    2105                 :            :     }
    2106                 :            : 
    2107                 :      39299 :     Token *dots = eat_token_if(pc, TokenIdEllipsis3);
    2108         [ +  + ]:      39299 :     if (dots != nullptr) {
    2109                 :        211 :         AstNode *res = ast_create_node(pc, NodeTypeParamDecl, dots);
    2110                 :        211 :         res->data.param_decl.is_var_args = true;
    2111                 :        211 :         return res;
    2112                 :            :     }
    2113                 :            : 
    2114                 :      39088 :     AstNode *type_expr = ast_parse_type_expr(pc);
    2115         [ +  + ]:      39088 :     if (type_expr != nullptr) {
    2116                 :      31490 :         AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeParamDecl, type_expr);
    2117                 :      31490 :         res->data.param_decl.type = type_expr;
    2118                 :      31490 :         return res;
    2119                 :            :     }
    2120                 :            : 
    2121                 :       7598 :     return nullptr;
    2122                 :            : }
    2123                 :            : 
    2124                 :            : // IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
    2125                 :    1136544 : static AstNode *ast_parse_if_prefix(ParseContext *pc) {
    2126                 :    1136544 :     Token *first = eat_token_if(pc, TokenIdKeywordIf);
    2127         [ +  + ]:    1136544 :     if (first == nullptr)
    2128                 :    1121494 :         return nullptr;
    2129                 :            : 
    2130                 :      15050 :     expect_token(pc, TokenIdLParen);
    2131                 :      15050 :     AstNode *condition = ast_expect(pc, ast_parse_expr);
    2132                 :      15050 :     expect_token(pc, TokenIdRParen);
    2133                 :      15050 :     Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
    2134                 :            : 
    2135                 :            :     PtrPayload payload;
    2136                 :      15050 :     AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
    2137                 :      15050 :     res->data.test_expr.target_node = condition;
    2138         [ +  + ]:      15050 :     if (opt_payload.unwrap(&payload)) {
    2139                 :       1346 :         res->data.test_expr.var_symbol = token_buf(payload.payload);
    2140                 :       1346 :         res->data.test_expr.var_is_ptr = payload.asterisk != nullptr;
    2141                 :            :     }
    2142                 :    1136544 :     return res;
    2143                 :            : }
    2144                 :            : 
    2145                 :            : // WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
    2146                 :    1512215 : static AstNode *ast_parse_while_prefix(ParseContext *pc) {
    2147                 :    1512215 :     Token *while_token = eat_token_if(pc, TokenIdKeywordWhile);
    2148         [ +  + ]:    1512215 :     if (while_token == nullptr)
    2149                 :    1509153 :         return nullptr;
    2150                 :            : 
    2151                 :       3062 :     expect_token(pc, TokenIdLParen);
    2152                 :       3062 :     AstNode *condition = ast_expect(pc, ast_parse_expr);
    2153                 :       3062 :     expect_token(pc, TokenIdRParen);
    2154                 :       3062 :     Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
    2155                 :       3062 :     AstNode *continue_expr = ast_parse_while_continue_expr(pc);
    2156                 :            : 
    2157                 :            :     PtrPayload payload;
    2158                 :       3062 :     AstNode *res = ast_create_node(pc, NodeTypeWhileExpr, while_token);
    2159                 :       3062 :     res->data.while_expr.condition = condition;
    2160                 :       3062 :     res->data.while_expr.continue_expr = continue_expr;
    2161         [ +  + ]:       3062 :     if (opt_payload.unwrap(&payload)) {
    2162                 :        421 :         res->data.while_expr.var_symbol = token_buf(payload.payload);
    2163                 :        421 :         res->data.while_expr.var_is_ptr = payload.asterisk != nullptr;
    2164                 :            :     }
    2165                 :            : 
    2166                 :    1512215 :     return res;
    2167                 :            : }
    2168                 :            : 
    2169                 :            : // ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
    2170                 :    1513852 : static AstNode *ast_parse_for_prefix(ParseContext *pc) {
    2171                 :    1513852 :     Token *for_token = eat_token_if(pc, TokenIdKeywordFor);
    2172         [ +  + ]:    1513852 :     if (for_token == nullptr)
    2173                 :    1512215 :         return nullptr;
    2174                 :            : 
    2175                 :       1637 :     expect_token(pc, TokenIdLParen);
    2176                 :       1637 :     AstNode *array_expr = ast_expect(pc, ast_parse_expr);
    2177                 :       1637 :     expect_token(pc, TokenIdRParen);
    2178                 :            :     PtrIndexPayload payload;
    2179         [ -  + ]:       1637 :     if (!ast_parse_ptr_index_payload(pc).unwrap(&payload))
    2180                 :          0 :         ast_invalid_token_error(pc, peek_token(pc));
    2181                 :            : 
    2182                 :       1637 :     AstNode *res = ast_create_node(pc, NodeTypeForExpr, for_token);
    2183                 :       1637 :     res->data.for_expr.array_expr = array_expr;
    2184                 :       1637 :     res->data.for_expr.elem_node = token_symbol(pc, payload.payload);
    2185                 :       1637 :     res->data.for_expr.elem_is_ptr = payload.asterisk != nullptr;
    2186         [ +  + ]:       1637 :     if (payload.index != nullptr)
    2187                 :        522 :         res->data.for_expr.index_node = token_symbol(pc, payload.index);
    2188                 :            : 
    2189                 :    1513852 :     return res;
    2190                 :            : }
    2191                 :            : 
    2192                 :            : // Payload <- PIPE IDENTIFIER PIPE
    2193                 :       7364 : static Token *ast_parse_payload(ParseContext *pc) {
    2194         [ +  + ]:       7364 :     if (eat_token_if(pc, TokenIdBinOr) == nullptr)
    2195                 :       6602 :         return nullptr;
    2196                 :            : 
    2197                 :        762 :     Token *res = expect_token(pc, TokenIdSymbol);
    2198                 :        762 :     expect_token(pc, TokenIdBinOr);
    2199                 :        762 :     return res;
    2200                 :            : }
    2201                 :            : 
    2202                 :            : // PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
    2203                 :      35613 : static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc) {
    2204         [ +  + ]:      35613 :     if (eat_token_if(pc, TokenIdBinOr) == nullptr)
    2205                 :      32046 :         return Optional<PtrPayload>::none();
    2206                 :            : 
    2207                 :       3567 :     Token *asterisk = eat_token_if(pc, TokenIdStar);
    2208                 :       3567 :     Token *payload = expect_token(pc, TokenIdSymbol);
    2209                 :       3567 :     expect_token(pc, TokenIdBinOr);
    2210                 :            : 
    2211                 :            :     PtrPayload res;
    2212                 :       3567 :     res.asterisk = asterisk;
    2213                 :       3567 :     res.payload = payload;
    2214                 :      35613 :     return Optional<PtrPayload>::some(res);
    2215                 :            : }
    2216                 :            : 
    2217                 :            : // PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
    2218                 :       1637 : static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) {
    2219         [ -  + ]:       1637 :     if (eat_token_if(pc, TokenIdBinOr) == nullptr)
    2220                 :          0 :         return Optional<PtrIndexPayload>::none();
    2221                 :            : 
    2222                 :       1637 :     Token *asterisk = eat_token_if(pc, TokenIdStar);
    2223                 :       1637 :     Token *payload = expect_token(pc, TokenIdSymbol);
    2224                 :       1637 :     Token *index = nullptr;
    2225         [ +  + ]:       1637 :     if (eat_token_if(pc, TokenIdComma) != nullptr)
    2226                 :        522 :         index = expect_token(pc, TokenIdSymbol);
    2227                 :       1637 :     expect_token(pc, TokenIdBinOr);
    2228                 :            : 
    2229                 :            :     PtrIndexPayload res;
    2230                 :       1637 :     res.asterisk = asterisk;
    2231                 :       1637 :     res.payload = payload;
    2232                 :       1637 :     res.index = index;
    2233                 :       1637 :     return Optional<PtrIndexPayload>::some(res);
    2234                 :            : }
    2235                 :            : 
    2236                 :            : // SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
    2237                 :      21555 : static AstNode *ast_parse_switch_prong(ParseContext *pc) {
    2238                 :      21555 :     AstNode *res = ast_parse_switch_case(pc);
    2239         [ +  + ]:      21555 :     if (res == nullptr)
    2240                 :       4054 :         return nullptr;
    2241                 :            : 
    2242                 :      17501 :     expect_token(pc, TokenIdFatArrow);
    2243                 :      17501 :     Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
    2244                 :      17501 :     AstNode *expr = ast_expect(pc, ast_parse_assign_expr);
    2245                 :            : 
    2246                 :            :     PtrPayload payload;
    2247                 :      17501 :     assert(res->type == NodeTypeSwitchProng);
    2248                 :      17501 :     res->data.switch_prong.expr = expr;
    2249         [ +  + ]:      17501 :     if (opt_payload.unwrap(&payload)) {
    2250                 :       1800 :         res->data.switch_prong.var_symbol = token_symbol(pc, payload.payload);
    2251                 :       1800 :         res->data.switch_prong.var_is_ptr = payload.asterisk != nullptr;
    2252                 :            :     }
    2253                 :            : 
    2254                 :      21555 :     return res;
    2255                 :            : }
    2256                 :            : 
    2257                 :            : // SwitchCase
    2258                 :            : //     <- SwitchItem (COMMA SwitchItem)* COMMA?
    2259                 :            : //      / KEYWORD_else
    2260                 :      21555 : static AstNode *ast_parse_switch_case(ParseContext *pc) {
    2261                 :      21555 :     AstNode *first = ast_parse_switch_item(pc);
    2262         [ +  + ]:      21555 :     if (first != nullptr) {
    2263                 :      14254 :         AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeSwitchProng, first);
    2264                 :      14254 :         res->data.switch_prong.items.append(first);
    2265                 :      14254 :         res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange;
    2266                 :            : 
    2267         [ +  + ]:      16079 :         while (eat_token_if(pc, TokenIdComma) != nullptr) {
    2268                 :       1938 :             AstNode *item = ast_parse_switch_item(pc);
    2269         [ +  + ]:       1938 :             if (item == nullptr)
    2270                 :        113 :                 break;
    2271                 :            : 
    2272                 :       1825 :             res->data.switch_prong.items.append(item);
    2273                 :       1825 :             res->data.switch_prong.any_items_are_range |= item->type == NodeTypeSwitchRange;
    2274                 :            :         }
    2275                 :            : 
    2276                 :      14254 :         return res;
    2277                 :            :     }
    2278                 :            : 
    2279                 :       7301 :     Token *else_token = eat_token_if(pc, TokenIdKeywordElse);
    2280         [ +  + ]:       7301 :     if (else_token != nullptr)
    2281                 :       3247 :         return ast_create_node(pc, NodeTypeSwitchProng, else_token);
    2282                 :            : 
    2283                 :       4054 :     return nullptr;
    2284                 :            : }
    2285                 :            : 
    2286                 :            : // SwitchItem <- Expr (DOT3 Expr)?
    2287                 :      23493 : static AstNode *ast_parse_switch_item(ParseContext *pc) {
    2288                 :      23493 :     AstNode *expr = ast_parse_expr(pc);
    2289         [ +  + ]:      23493 :     if (expr == nullptr)
    2290                 :       7414 :         return nullptr;
    2291                 :            : 
    2292                 :      16079 :     Token *dots = eat_token_if(pc, TokenIdEllipsis3);
    2293         [ +  + ]:      16079 :     if (dots != nullptr) {
    2294                 :        171 :         AstNode *expr2 = ast_expect(pc, ast_parse_expr);
    2295                 :        171 :         AstNode *res = ast_create_node(pc, NodeTypeSwitchRange, dots);
    2296                 :        171 :         res->data.switch_range.start = expr;
    2297                 :        171 :         res->data.switch_range.end = expr2;
    2298                 :        171 :         return res;
    2299                 :            :     }
    2300                 :            : 
    2301                 :      15908 :     return expr;
    2302                 :            : }
    2303                 :            : 
    2304                 :            : // AssignOp
    2305                 :            : //     <- ASTERISKEQUAL
    2306                 :            : //      / SLASHEQUAL
    2307                 :            : //      / PERCENTEQUAL
    2308                 :            : //      / PLUSEQUAL
    2309                 :            : //      / MINUSEQUAL
    2310                 :            : //      / LARROW2EQUAL
    2311                 :            : //      / RARROW2EQUAL
    2312                 :            : //      / AMPERSANDEQUAL
    2313                 :            : //      / CARETEQUAL
    2314                 :            : //      / PIPEEQUAL
    2315                 :            : //      / ASTERISKPERCENTEQUAL
    2316                 :            : //      / PLUSPERCENTEQUAL
    2317                 :            : //      / MINUSPERCENTEQUAL
    2318                 :            : //      / EQUAL
    2319                 :     108246 : static AstNode *ast_parse_assign_op(ParseContext *pc) {
    2320                 :            :     // In C, we have `T arr[N] = {[i] = T{}};` but it doesn't
    2321                 :            :     // seem to work in C++...
    2322                 :     108246 :     BinOpType table[TokenIdCount] = {};
    2323                 :     108246 :     table[TokenIdBarBarEq] = BinOpTypeAssignMergeErrorSets;
    2324                 :     108246 :     table[TokenIdBitAndEq] = BinOpTypeAssignBitAnd;
    2325                 :     108246 :     table[TokenIdBitOrEq] = BinOpTypeAssignBitOr;
    2326                 :     108246 :     table[TokenIdBitShiftLeftEq] = BinOpTypeAssignBitShiftLeft;
    2327                 :     108246 :     table[TokenIdBitShiftRightEq] = BinOpTypeAssignBitShiftRight;
    2328                 :     108246 :     table[TokenIdBitXorEq] = BinOpTypeAssignBitXor;
    2329                 :     108246 :     table[TokenIdDivEq] = BinOpTypeAssignDiv;
    2330                 :     108246 :     table[TokenIdEq] = BinOpTypeAssign;
    2331                 :     108246 :     table[TokenIdMinusEq] = BinOpTypeAssignMinus;
    2332                 :     108246 :     table[TokenIdMinusPercentEq] = BinOpTypeAssignMinusWrap;
    2333                 :     108246 :     table[TokenIdModEq] = BinOpTypeAssignMod;
    2334                 :     108246 :     table[TokenIdPlusEq] = BinOpTypeAssignPlus;
    2335                 :     108246 :     table[TokenIdPlusPercentEq] = BinOpTypeAssignPlusWrap;
    2336                 :     108246 :     table[TokenIdTimesEq] = BinOpTypeAssignTimes;
    2337                 :     108246 :     table[TokenIdTimesPercentEq] = BinOpTypeAssignTimesWrap;
    2338                 :            : 
    2339                 :     108246 :     BinOpType op = table[peek_token(pc)->id];
    2340         [ +  + ]:     108246 :     if (op != BinOpTypeInvalid) {
    2341                 :      21474 :         Token *op_token = eat_token(pc);
    2342                 :      21474 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2343                 :      21474 :         res->data.bin_op_expr.bin_op = op;
    2344                 :      21474 :         return res;
    2345                 :            :     }
    2346                 :            : 
    2347                 :     108246 :     return nullptr;
    2348                 :            : 
    2349                 :            : }
    2350                 :            : 
    2351                 :            : // CompareOp
    2352                 :            : //     <- EQUALEQUAL
    2353                 :            : //      / EXCLAMATIONMARKEQUAL
    2354                 :            : //      / LARROW
    2355                 :            : //      / RARROW
    2356                 :            : //      / LARROWEQUAL
    2357                 :            : //      / RARROWEQUAL
    2358                 :     566448 : static AstNode *ast_parse_compare_op(ParseContext *pc) {
    2359                 :     566448 :     BinOpType table[TokenIdCount] = {};
    2360                 :     566448 :     table[TokenIdCmpEq] = BinOpTypeCmpEq;
    2361                 :     566448 :     table[TokenIdCmpNotEq] = BinOpTypeCmpNotEq;
    2362                 :     566448 :     table[TokenIdCmpLessThan] = BinOpTypeCmpLessThan;
    2363                 :     566448 :     table[TokenIdCmpGreaterThan] = BinOpTypeCmpGreaterThan;
    2364                 :     566448 :     table[TokenIdCmpLessOrEq] = BinOpTypeCmpLessOrEq;
    2365                 :     566448 :     table[TokenIdCmpGreaterOrEq] = BinOpTypeCmpGreaterOrEq;
    2366                 :            : 
    2367                 :     566448 :     BinOpType op = table[peek_token(pc)->id];
    2368         [ +  + ]:     566448 :     if (op != BinOpTypeInvalid) {
    2369                 :      33916 :         Token *op_token = eat_token(pc);
    2370                 :      33916 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2371                 :      33916 :         res->data.bin_op_expr.bin_op = op;
    2372                 :      33916 :         return res;
    2373                 :            :     }
    2374                 :            : 
    2375                 :     566448 :     return nullptr;
    2376                 :            : }
    2377                 :            : 
    2378                 :            : // BitwiseOp
    2379                 :            : //     <- AMPERSAND
    2380                 :            : //      / CARET
    2381                 :            : //      / PIPE
    2382                 :            : //      / KEYWORD_orelse
    2383                 :            : //      / KEYWORD_catch Payload?
    2384                 :     606991 : static AstNode *ast_parse_bitwise_op(ParseContext *pc) {
    2385                 :     606991 :     BinOpType table[TokenIdCount] = {};
    2386                 :     606991 :     table[TokenIdAmpersand] = BinOpTypeBinAnd;
    2387                 :     606991 :     table[TokenIdBinXor] = BinOpTypeBinXor;
    2388                 :     606991 :     table[TokenIdBinOr] = BinOpTypeBinOr;
    2389                 :     606991 :     table[TokenIdKeywordOrElse] = BinOpTypeUnwrapOptional;
    2390                 :            : 
    2391                 :     606991 :     BinOpType op = table[peek_token(pc)->id];
    2392         [ +  + ]:     606991 :     if (op != BinOpTypeInvalid) {
    2393                 :       4432 :         Token *op_token = eat_token(pc);
    2394                 :       4432 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2395                 :       4432 :         res->data.bin_op_expr.bin_op = op;
    2396                 :       4432 :         return res;
    2397                 :            :     }
    2398                 :            : 
    2399                 :     602559 :     Token *catch_token = eat_token_if(pc, TokenIdKeywordCatch);
    2400         [ +  + ]:     602559 :     if (catch_token != nullptr) {
    2401                 :       2195 :         Token *payload = ast_parse_payload(pc);
    2402                 :       2195 :         AstNode *res = ast_create_node(pc, NodeTypeCatchExpr, catch_token);
    2403         [ +  + ]:       2195 :         if (payload != nullptr)
    2404                 :        319 :             res->data.unwrap_err_expr.symbol = token_symbol(pc, payload);
    2405                 :            : 
    2406                 :       2195 :         return res;
    2407                 :            :     }
    2408                 :            : 
    2409                 :     606991 :     return nullptr;
    2410                 :            : }
    2411                 :            : 
    2412                 :            : // BitShiftOp
    2413                 :            : //     <- LARROW2
    2414                 :            : //      / RARROW2
    2415                 :     610903 : static AstNode *ast_parse_bit_shift_op(ParseContext *pc) {
    2416                 :     610903 :     BinOpType table[TokenIdCount] = {};
    2417                 :     610903 :     table[TokenIdBitShiftLeft] = BinOpTypeBitShiftLeft;
    2418                 :     610903 :     table[TokenIdBitShiftRight] = BinOpTypeBitShiftRight;
    2419                 :            : 
    2420                 :     610903 :     BinOpType op = table[peek_token(pc)->id];
    2421         [ +  + ]:     610903 :     if (op != BinOpTypeInvalid) {
    2422                 :       3912 :         Token *op_token = eat_token(pc);
    2423                 :       3912 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2424                 :       3912 :         res->data.bin_op_expr.bin_op = op;
    2425                 :       3912 :         return res;
    2426                 :            :     }
    2427                 :            : 
    2428                 :     610903 :     return nullptr;
    2429                 :            : }
    2430                 :            : 
    2431                 :            : // AdditionOp
    2432                 :            : //     <- PLUS
    2433                 :            : //      / MINUS
    2434                 :            : //      / PLUS2
    2435                 :            : //      / PLUSPERCENT
    2436                 :            : //      / MINUSPERCENT
    2437                 :     622924 : static AstNode *ast_parse_addition_op(ParseContext *pc) {
    2438                 :     622924 :     BinOpType table[TokenIdCount] = {};
    2439                 :     622924 :     table[TokenIdPlus] = BinOpTypeAdd;
    2440                 :     622924 :     table[TokenIdDash] = BinOpTypeSub;
    2441                 :     622924 :     table[TokenIdPlusPlus] = BinOpTypeArrayCat;
    2442                 :     622924 :     table[TokenIdPlusPercent] = BinOpTypeAddWrap;
    2443                 :     622924 :     table[TokenIdMinusPercent] = BinOpTypeSubWrap;
    2444                 :            : 
    2445                 :     622924 :     BinOpType op = table[peek_token(pc)->id];
    2446         [ +  + ]:     622924 :     if (op != BinOpTypeInvalid) {
    2447                 :      12021 :         Token *op_token = eat_token(pc);
    2448                 :      12021 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2449                 :      12021 :         res->data.bin_op_expr.bin_op = op;
    2450                 :      12021 :         return res;
    2451                 :            :     }
    2452                 :            : 
    2453                 :     622924 :     return nullptr;
    2454                 :            : }
    2455                 :            : 
    2456                 :            : // MultiplyOp
    2457                 :            : //     <- PIPE2
    2458                 :            : //      / ASTERISK
    2459                 :            : //      / SLASH
    2460                 :            : //      / PERCENT
    2461                 :            : //      / ASTERISK2
    2462                 :            : //      / ASTERISKPERCENT
    2463                 :     627778 : static AstNode *ast_parse_multiply_op(ParseContext *pc) {
    2464                 :     627778 :     BinOpType table[TokenIdCount] = {};
    2465                 :     627778 :     table[TokenIdBarBar] = BinOpTypeMergeErrorSets;
    2466                 :     627778 :     table[TokenIdStar] = BinOpTypeMult;
    2467                 :     627778 :     table[TokenIdSlash] = BinOpTypeDiv;
    2468                 :     627778 :     table[TokenIdPercent] = BinOpTypeMod;
    2469                 :     627778 :     table[TokenIdStarStar] = BinOpTypeArrayMult;
    2470                 :     627778 :     table[TokenIdTimesPercent] = BinOpTypeMultWrap;
    2471                 :            : 
    2472                 :     627778 :     BinOpType op = table[peek_token(pc)->id];
    2473         [ +  + ]:     627778 :     if (op != BinOpTypeInvalid) {
    2474                 :       4854 :         Token *op_token = eat_token(pc);
    2475                 :       4854 :         AstNode *res = ast_create_node(pc, NodeTypeBinOpExpr, op_token);
    2476                 :       4854 :         res->data.bin_op_expr.bin_op = op;
    2477                 :       4854 :         return res;
    2478                 :            :     }
    2479                 :            : 
    2480                 :     627778 :     return nullptr;
    2481                 :            : }
    2482                 :            : 
    2483                 :            : // PrefixOp
    2484                 :            : //     <- EXCLAMATIONMARK
    2485                 :            : //      / MINUS
    2486                 :            : //      / TILDE
    2487                 :            : //      / MINUSPERCENT
    2488                 :            : //      / AMPERSAND
    2489                 :            : //      / KEYWORD_try
    2490                 :            : //      / KEYWORD_await
    2491                 :     734240 : static AstNode *ast_parse_prefix_op(ParseContext *pc) {
    2492                 :     734240 :     PrefixOp table[TokenIdCount] = {};
    2493                 :     734240 :     table[TokenIdBang] = PrefixOpBoolNot;
    2494                 :     734240 :     table[TokenIdDash] = PrefixOpNegation;
    2495                 :     734240 :     table[TokenIdTilde] = PrefixOpBinNot;
    2496                 :     734240 :     table[TokenIdMinusPercent] = PrefixOpNegationWrap;
    2497                 :     734240 :     table[TokenIdAmpersand] = PrefixOpAddrOf;
    2498                 :            : 
    2499                 :     734240 :     PrefixOp op = table[peek_token(pc)->id];
    2500         [ +  + ]:     734240 :     if (op != PrefixOpInvalid) {
    2501                 :      18870 :         Token *op_token = eat_token(pc);
    2502                 :      18870 :         AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, op_token);
    2503                 :      18870 :         res->data.prefix_op_expr.prefix_op = op;
    2504                 :      18870 :         return res;
    2505                 :            :     }
    2506                 :            : 
    2507                 :     715370 :     Token *try_token = eat_token_if(pc, TokenIdKeywordTry);
    2508         [ +  + ]:     715370 :     if (try_token != nullptr) {
    2509                 :         44 :         AstNode *res = ast_create_node(pc, NodeTypeReturnExpr, try_token);
    2510                 :         44 :         res->data.return_expr.kind = ReturnKindError;
    2511                 :         44 :         return res;
    2512                 :            :     }
    2513                 :            : 
    2514                 :     715326 :     Token *await = eat_token_if(pc, TokenIdKeywordAwait);
    2515         [ +  + ]:     715326 :     if (await != nullptr) {
    2516                 :        216 :         AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
    2517                 :        216 :         return res;
    2518                 :            :     }
    2519                 :            : 
    2520                 :     734240 :     return nullptr;
    2521                 :            : }
    2522                 :            : 
    2523                 :            : // PrefixTypeOp
    2524                 :            : //     <- QUESTIONMARK
    2525                 :            : //      / KEYWORD_anyframe MINUSRARROW
    2526                 :            : //      / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)*
    2527                 :            : //      / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)*
    2528                 :     804189 : static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
    2529                 :     804189 :     Token *questionmark = eat_token_if(pc, TokenIdQuestion);
    2530         [ +  + ]:     804189 :     if (questionmark != nullptr) {
    2531                 :       3631 :         AstNode *res = ast_create_node(pc, NodeTypePrefixOpExpr, questionmark);
    2532                 :       3631 :         res->data.prefix_op_expr.prefix_op = PrefixOpOptional;
    2533                 :       3631 :         return res;
    2534                 :            :     }
    2535                 :            : 
    2536                 :     800558 :     Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
    2537         [ +  + ]:     800558 :     if (anyframe != nullptr) {
    2538         [ +  + ]:        240 :         if (eat_token_if(pc, TokenIdArrow) != nullptr) {
    2539                 :         64 :             AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
    2540                 :         64 :             return res;
    2541                 :            :         }
    2542                 :            : 
    2543                 :        176 :         put_back_token(pc);
    2544                 :            :     }
    2545                 :            : 
    2546                 :     800494 :     AstNode *array = ast_parse_array_type_start(pc);
    2547         [ +  + ]:     800494 :     if (array != nullptr) {
    2548                 :      10959 :         assert(array->type == NodeTypeArrayType);
    2549                 :            :         while (true) {
    2550                 :      16647 :             Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
    2551         [ +  + ]:      16647 :             if (allowzero_token != nullptr) {
    2552                 :         72 :                 array->data.array_type.allow_zero_token = allowzero_token;
    2553                 :         72 :                 continue;
    2554                 :            :             }
    2555                 :            : 
    2556                 :      16575 :             AstNode *align_expr = ast_parse_byte_align(pc);
    2557         [ +  + ]:      16575 :             if (align_expr != nullptr) {
    2558                 :        315 :                 array->data.array_type.align_expr = align_expr;
    2559                 :        315 :                 continue;
    2560                 :            :             }
    2561                 :            : 
    2562         [ +  + ]:      16260 :             if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
    2563                 :       5221 :                 array->data.array_type.is_const = true;
    2564                 :       5221 :                 continue;
    2565                 :            :             }
    2566                 :            : 
    2567         [ +  + ]:      11039 :             if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
    2568                 :         80 :                 array->data.array_type.is_volatile = true;
    2569                 :         80 :                 continue;
    2570                 :            :             }
    2571                 :      10959 :             break;
    2572                 :       5688 :         }
    2573                 :            : 
    2574                 :      10959 :         return array;
    2575                 :            :     }
    2576                 :            : 
    2577                 :     789535 :     AstNode *ptr = ast_parse_ptr_type_start(pc);
    2578         [ +  + ]:     789535 :     if (ptr != nullptr) {
    2579                 :      15208 :         assert(ptr->type == NodeTypePointerType);
    2580                 :            :         // We might get two pointers from *_ptr_type_start
    2581                 :      15208 :         AstNode *child = ptr->data.pointer_type.op_expr;
    2582         [ +  + ]:      15208 :         if (child == nullptr)
    2583                 :      15134 :             child = ptr;
    2584                 :            :         while (true) {
    2585                 :      20186 :             Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
    2586         [ +  + ]:      20186 :             if (allowzero_token != nullptr) {
    2587                 :        148 :                 child->data.pointer_type.allow_zero_token = allowzero_token;
    2588                 :        148 :                 continue;
    2589                 :            :             }
    2590                 :            : 
    2591         [ +  + ]:      20038 :             if (eat_token_if(pc, TokenIdKeywordAlign) != nullptr) {
    2592                 :        762 :                 expect_token(pc, TokenIdLParen);
    2593                 :        762 :                 AstNode *align_expr = ast_parse_expr(pc);
    2594                 :        762 :                 child->data.pointer_type.align_expr = align_expr;
    2595         [ +  + ]:        762 :                 if (eat_token_if(pc, TokenIdColon) != nullptr) {
    2596                 :         24 :                     Token *bit_offset_start = expect_token(pc, TokenIdIntLiteral);
    2597                 :         24 :                     expect_token(pc, TokenIdColon);
    2598                 :         24 :                     Token *host_int_bytes = expect_token(pc, TokenIdIntLiteral);
    2599                 :         24 :                     child->data.pointer_type.bit_offset_start = token_bigint(bit_offset_start);
    2600                 :         24 :                     child->data.pointer_type.host_int_bytes = token_bigint(host_int_bytes);
    2601                 :            :                 }
    2602                 :        762 :                 expect_token(pc, TokenIdRParen);
    2603                 :        762 :                 continue;
    2604                 :            :             }
    2605                 :            : 
    2606         [ +  + ]:      19276 :             if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
    2607                 :       3774 :                 child->data.pointer_type.is_const = true;
    2608                 :       3774 :                 continue;
    2609                 :            :             }
    2610                 :            : 
    2611         [ +  + ]:      15502 :             if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
    2612                 :        294 :                 child->data.pointer_type.is_volatile = true;
    2613                 :        294 :                 continue;
    2614                 :            :             }
    2615                 :            : 
    2616                 :      15208 :             break;
    2617                 :       4978 :         }
    2618                 :            : 
    2619                 :      15208 :         return ptr;
    2620                 :            :     }
    2621                 :            : 
    2622                 :     774327 :     Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
    2623         [ +  + ]:     774327 :     if (arr_init != nullptr) {
    2624                 :       4227 :         return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);
    2625                 :            :     }
    2626                 :            : 
    2627                 :            : 
    2628                 :     770100 :     return nullptr;
    2629                 :            : }
    2630                 :            : 
    2631                 :            : // SuffixOp
    2632                 :            : //     <- LBRACKET Expr (DOT2 Expr?)? RBRACKET
    2633                 :            : //      / DOT IDENTIFIER
    2634                 :            : //      / DOTASTERISK
    2635                 :            : //      / DOTQUESTIONMARK
    2636                 :     913053 : static AstNode *ast_parse_suffix_op(ParseContext *pc) {
    2637                 :     913053 :     Token *lbracket = eat_token_if(pc, TokenIdLBracket);
    2638         [ +  + ]:     913053 :     if (lbracket != nullptr) {
    2639                 :      13906 :         AstNode *start = ast_expect(pc, ast_parse_expr);
    2640                 :      13906 :         AstNode *end = nullptr;
    2641         [ +  + ]:      13906 :         if (eat_token_if(pc, TokenIdEllipsis2) != nullptr) {
    2642                 :       5049 :             end = ast_parse_expr(pc);
    2643                 :       5049 :             expect_token(pc, TokenIdRBracket);
    2644                 :            : 
    2645                 :       5049 :             AstNode *res = ast_create_node(pc, NodeTypeSliceExpr, lbracket);
    2646                 :       5049 :             res->data.slice_expr.start = start;
    2647                 :       5049 :             res->data.slice_expr.end = end;
    2648                 :       5049 :             return res;
    2649                 :            :         }
    2650                 :            : 
    2651                 :       8857 :         expect_token(pc, TokenIdRBracket);
    2652                 :            : 
    2653                 :       8857 :         AstNode *res = ast_create_node(pc, NodeTypeArrayAccessExpr, lbracket);
    2654                 :       8857 :         res->data.array_access_expr.subscript = start;
    2655                 :       8857 :         return res;
    2656                 :            :     }
    2657                 :            : 
    2658                 :     899147 :     Token *dot = eat_token_if(pc, TokenIdDot);
    2659         [ +  + ]:     899147 :     if (dot != nullptr) {
    2660         [ +  + ]:     119325 :         if (eat_token_if(pc, TokenIdStar) != nullptr)
    2661                 :       2281 :             return ast_create_node(pc, NodeTypePtrDeref, dot);
    2662         [ +  + ]:     117044 :         if (eat_token_if(pc, TokenIdQuestion) != nullptr)
    2663                 :       1305 :             return ast_create_node(pc, NodeTypeUnwrapOptional, dot);
    2664                 :            : 
    2665                 :     115739 :         Token *ident = expect_token(pc, TokenIdSymbol);
    2666                 :     115739 :         AstNode *res = ast_create_node(pc, NodeTypeFieldAccessExpr, dot);
    2667                 :     115739 :         res->data.field_access_expr.field_name = token_buf(ident);
    2668                 :     115739 :         return res;
    2669                 :            :     }
    2670                 :            : 
    2671                 :     779822 :     return nullptr;
    2672                 :            : }
    2673                 :            : 
    2674                 :            : // FnCallArguments <- LPAREN ExprList RPAREN
    2675                 :     817142 : static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
    2676                 :     817142 :     Token *paren = eat_token_if(pc, TokenIdLParen);
    2677         [ +  + ]:     817142 :     if (paren == nullptr)
    2678                 :     674666 :         return nullptr;
    2679                 :            : 
    2680                 :     142476 :     ZigList<AstNode *> params = ast_parse_list(pc, TokenIdComma, ast_parse_expr);
    2681                 :     142476 :     expect_token(pc, TokenIdRParen);
    2682                 :            : 
    2683                 :     142476 :     AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);
    2684                 :     142476 :     res->data.fn_call_expr.params = params;
    2685                 :     142476 :     res->data.fn_call_expr.seen = false;
    2686                 :     817142 :     return res;
    2687                 :            : }
    2688                 :            : 
    2689                 :            : // ArrayTypeStart <- LBRACKET Expr? RBRACKET
    2690                 :     800494 : static AstNode *ast_parse_array_type_start(ParseContext *pc) {
    2691                 :     800494 :     Token *lbracket = eat_token_if(pc, TokenIdLBracket);
    2692         [ +  + ]:     800494 :     if (lbracket == nullptr)
    2693                 :     789535 :         return nullptr;
    2694                 :            : 
    2695                 :      10959 :     AstNode *size = ast_parse_expr(pc);
    2696                 :      10959 :     expect_token(pc, TokenIdRBracket);
    2697                 :      10959 :     AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);
    2698                 :      10959 :     res->data.array_type.size = size;
    2699                 :      10959 :     return res;
    2700                 :            : }
    2701                 :            : 
    2702                 :            : // PtrTypeStart
    2703                 :            : //     <- ASTERISK
    2704                 :            : //      / ASTERISK2
    2705                 :            : //      / PTRUNKNOWN
    2706                 :            : //      / PTRC
    2707                 :     789535 : static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
    2708                 :     789535 :     Token *asterisk = eat_token_if(pc, TokenIdStar);
    2709         [ +  + ]:     789535 :     if (asterisk != nullptr) {
    2710                 :      11350 :         AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);
    2711                 :      11350 :         res->data.pointer_type.star_token = asterisk;
    2712                 :      11350 :         return res;
    2713                 :            :     }
    2714                 :            : 
    2715                 :     778185 :     Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);
    2716         [ +  + ]:     778185 :     if (asterisk2 != nullptr) {
    2717                 :         74 :         AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);
    2718                 :         74 :         AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);
    2719                 :         74 :         res->data.pointer_type.star_token = asterisk2;
    2720                 :         74 :         res2->data.pointer_type.star_token = asterisk2;
    2721                 :         74 :         res->data.pointer_type.op_expr = res2;
    2722                 :         74 :         return res;
    2723                 :            :     }
    2724                 :            : 
    2725                 :     778111 :     Token *multptr = eat_token_if(pc, TokenIdBracketStarBracket);
    2726         [ +  + ]:     778111 :     if (multptr != nullptr) {
    2727                 :       3536 :         AstNode *res = ast_create_node(pc, NodeTypePointerType, multptr);
    2728                 :       3536 :         res->data.pointer_type.star_token = multptr;
    2729                 :       3536 :         return res;
    2730                 :            :     }
    2731                 :            : 
    2732                 :     774575 :     Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
    2733         [ +  + ]:     774575 :     if (cptr != nullptr) {
    2734                 :        248 :         AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
    2735                 :        248 :         res->data.pointer_type.star_token = cptr;
    2736                 :        248 :         return res;
    2737                 :            :     }
    2738                 :            : 
    2739                 :     774327 :     return nullptr;
    2740                 :            : }
    2741                 :            : 
    2742                 :            : // ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
    2743                 :     728641 : static AstNode *ast_parse_container_decl_auto(ParseContext *pc) {
    2744                 :     728641 :     AstNode *res = ast_parse_container_decl_type(pc);
    2745         [ +  + ]:     728641 :     if (res == nullptr)
    2746                 :     721115 :         return nullptr;
    2747                 :            : 
    2748                 :       7526 :     expect_token(pc, TokenIdLBrace);
    2749                 :       7526 :     AstNodeContainerDecl members = ast_parse_container_members(pc);
    2750                 :       7526 :     expect_token(pc, TokenIdRBrace);
    2751                 :            : 
    2752                 :       7526 :     res->data.container_decl.fields = members.fields;
    2753                 :       7526 :     res->data.container_decl.decls = members.decls;
    2754                 :     728641 :     return res;
    2755                 :            : }
    2756                 :            : 
    2757                 :            : // ContainerDeclType
    2758                 :            : //     <- KEYWORD_struct
    2759                 :            : //      / KEYWORD_enum (LPAREN Expr RPAREN)?
    2760                 :            : //      / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
    2761                 :     728641 : static AstNode *ast_parse_container_decl_type(ParseContext *pc) {
    2762                 :     728641 :     Token *first = eat_token_if(pc, TokenIdKeywordStruct);
    2763         [ +  + ]:     728641 :     if (first != nullptr) {
    2764                 :       5586 :         AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
    2765                 :       5586 :         res->data.container_decl.init_arg_expr = nullptr;
    2766                 :       5586 :         res->data.container_decl.kind = ContainerKindStruct;
    2767                 :       5586 :         return res;
    2768                 :            :     }
    2769                 :            : 
    2770                 :     723055 :     first = eat_token_if(pc, TokenIdKeywordEnum);
    2771         [ +  + ]:     723055 :     if (first != nullptr) {
    2772                 :       1129 :         AstNode *init_arg_expr = nullptr;
    2773         [ +  + ]:       1129 :         if (eat_token_if(pc, TokenIdLParen) != nullptr) {
    2774                 :        158 :             init_arg_expr = ast_expect(pc, ast_parse_expr);
    2775                 :        158 :             expect_token(pc, TokenIdRParen);
    2776                 :            :         }
    2777                 :       1129 :         AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
    2778                 :       1129 :         res->data.container_decl.init_arg_expr = init_arg_expr;
    2779                 :       1129 :         res->data.container_decl.kind = ContainerKindEnum;
    2780                 :       1129 :         return res;
    2781                 :            :     }
    2782                 :            : 
    2783                 :     721926 :     first = eat_token_if(pc, TokenIdKeywordUnion);
    2784         [ +  + ]:     721926 :     if (first != nullptr) {
    2785                 :        811 :         AstNode *init_arg_expr = nullptr;
    2786                 :        811 :         bool auto_enum = false;
    2787         [ +  + ]:        811 :         if (eat_token_if(pc, TokenIdLParen) != nullptr) {
    2788         [ +  + ]:        515 :             if (eat_token_if(pc, TokenIdKeywordEnum) != nullptr) {
    2789                 :        435 :                 auto_enum = true;
    2790         [ +  + ]:        435 :                 if (eat_token_if(pc, TokenIdLParen) != nullptr) {
    2791                 :         16 :                     init_arg_expr = ast_expect(pc, ast_parse_expr);
    2792                 :         16 :                     expect_token(pc, TokenIdRParen);
    2793                 :            :                 }
    2794                 :            :             } else {
    2795                 :         80 :                 init_arg_expr = ast_expect(pc, ast_parse_expr);
    2796                 :            :             }
    2797                 :            : 
    2798                 :        515 :             expect_token(pc, TokenIdRParen);
    2799                 :            :         }
    2800                 :            : 
    2801                 :        811 :         AstNode *res = ast_create_node(pc, NodeTypeContainerDecl, first);
    2802                 :        811 :         res->data.container_decl.init_arg_expr = init_arg_expr;
    2803                 :        811 :         res->data.container_decl.auto_enum = auto_enum;
    2804                 :        811 :         res->data.container_decl.kind = ContainerKindUnion;
    2805                 :        811 :         return res;
    2806                 :            :     }
    2807                 :            : 
    2808                 :     721115 :     return nullptr;
    2809                 :            : }
    2810                 :            : 
    2811                 :            : // ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
    2812                 :     144906 : static AstNode *ast_parse_byte_align(ParseContext *pc) {
    2813         [ +  + ]:     144906 :     if (eat_token_if(pc, TokenIdKeywordAlign) == nullptr)
    2814                 :     144250 :         return nullptr;
    2815                 :            : 
    2816                 :        656 :     expect_token(pc, TokenIdLParen);
    2817                 :        656 :     AstNode *res = ast_expect(pc, ast_parse_expr);
    2818                 :        656 :     expect_token(pc, TokenIdRParen);
    2819                 :        656 :     return res;
    2820                 :            : }
    2821                 :            : 
    2822                 :          0 : static void visit_field(AstNode **node, void (*visit)(AstNode **, void *context), void *context) {
    2823         [ #  # ]:          0 :     if (*node) {
    2824                 :          0 :         visit(node, context);
    2825                 :            :     }
    2826                 :          0 : }
    2827                 :            : 
    2828                 :          0 : static void visit_node_list(ZigList<AstNode *> *list, void (*visit)(AstNode **, void *context), void *context) {
    2829         [ #  # ]:          0 :     if (list) {
    2830         [ #  # ]:          0 :         for (size_t i = 0; i < list->length; i += 1) {
    2831                 :          0 :             visit(&list->at(i), context);
    2832                 :            :         }
    2833                 :            :     }
    2834                 :          0 : }
    2835                 :            : 
    2836                 :          0 : void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context) {
    2837   [ #  #  #  #  :          0 :     switch (node->type) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    2838                 :          0 :         case NodeTypeFnProto:
    2839                 :          0 :             visit_field(&node->data.fn_proto.return_type, visit, context);
    2840                 :          0 :             visit_node_list(&node->data.fn_proto.params, visit, context);
    2841                 :          0 :             visit_field(&node->data.fn_proto.align_expr, visit, context);
    2842                 :          0 :             visit_field(&node->data.fn_proto.section_expr, visit, context);
    2843                 :          0 :             break;
    2844                 :          0 :         case NodeTypeFnDef:
    2845                 :          0 :             visit_field(&node->data.fn_def.fn_proto, visit, context);
    2846                 :          0 :             visit_field(&node->data.fn_def.body, visit, context);
    2847                 :          0 :             break;
    2848                 :          0 :         case NodeTypeParamDecl:
    2849                 :          0 :             visit_field(&node->data.param_decl.type, visit, context);
    2850                 :          0 :             break;
    2851                 :          0 :         case NodeTypeBlock:
    2852                 :          0 :             visit_node_list(&node->data.block.statements, visit, context);
    2853                 :          0 :             break;
    2854                 :          0 :         case NodeTypeGroupedExpr:
    2855                 :          0 :             visit_field(&node->data.grouped_expr, visit, context);
    2856                 :          0 :             break;
    2857                 :          0 :         case NodeTypeReturnExpr:
    2858                 :          0 :             visit_field(&node->data.return_expr.expr, visit, context);
    2859                 :          0 :             break;
    2860                 :          0 :         case NodeTypeDefer:
    2861                 :          0 :             visit_field(&node->data.defer.expr, visit, context);
    2862                 :          0 :             break;
    2863                 :          0 :         case NodeTypeVariableDeclaration:
    2864                 :          0 :             visit_field(&node->data.variable_declaration.type, visit, context);
    2865                 :          0 :             visit_field(&node->data.variable_declaration.expr, visit, context);
    2866                 :          0 :             visit_field(&node->data.variable_declaration.align_expr, visit, context);
    2867                 :          0 :             visit_field(&node->data.variable_declaration.section_expr, visit, context);
    2868                 :          0 :             break;
    2869                 :          0 :         case NodeTypeTestDecl:
    2870                 :          0 :             visit_field(&node->data.test_decl.body, visit, context);
    2871                 :          0 :             break;
    2872                 :          0 :         case NodeTypeBinOpExpr:
    2873                 :          0 :             visit_field(&node->data.bin_op_expr.op1, visit, context);
    2874                 :          0 :             visit_field(&node->data.bin_op_expr.op2, visit, context);
    2875                 :          0 :             break;
    2876                 :          0 :         case NodeTypeCatchExpr:
    2877                 :          0 :             visit_field(&node->data.unwrap_err_expr.op1, visit, context);
    2878                 :          0 :             visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
    2879                 :          0 :             visit_field(&node->data.unwrap_err_expr.op2, visit, context);
    2880                 :          0 :             break;
    2881                 :          0 :         case NodeTypeIntLiteral:
    2882                 :            :             // none
    2883                 :          0 :             break;
    2884                 :          0 :         case NodeTypeFloatLiteral:
    2885                 :            :             // none
    2886                 :          0 :             break;
    2887                 :          0 :         case NodeTypeStringLiteral:
    2888                 :            :             // none
    2889                 :          0 :             break;
    2890                 :          0 :         case NodeTypeCharLiteral:
    2891                 :            :             // none
    2892                 :          0 :             break;
    2893                 :          0 :         case NodeTypeSymbol:
    2894                 :            :             // none
    2895                 :          0 :             break;
    2896                 :          0 :         case NodeTypePrefixOpExpr:
    2897                 :          0 :             visit_field(&node->data.prefix_op_expr.primary_expr, visit, context);
    2898                 :          0 :             break;
    2899                 :          0 :         case NodeTypeFnCallExpr:
    2900                 :          0 :             visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context);
    2901                 :          0 :             visit_node_list(&node->data.fn_call_expr.params, visit, context);
    2902                 :          0 :             break;
    2903                 :          0 :         case NodeTypeArrayAccessExpr:
    2904                 :          0 :             visit_field(&node->data.array_access_expr.array_ref_expr, visit, context);
    2905                 :          0 :             visit_field(&node->data.array_access_expr.subscript, visit, context);
    2906                 :          0 :             break;
    2907                 :          0 :         case NodeTypeSliceExpr:
    2908                 :          0 :             visit_field(&node->data.slice_expr.array_ref_expr, visit, context);
    2909                 :          0 :             visit_field(&node->data.slice_expr.start, visit, context);
    2910                 :          0 :             visit_field(&node->data.slice_expr.end, visit, context);
    2911                 :          0 :             break;
    2912                 :          0 :         case NodeTypeFieldAccessExpr:
    2913                 :          0 :             visit_field(&node->data.field_access_expr.struct_expr, visit, context);
    2914                 :          0 :             break;
    2915                 :          0 :         case NodeTypePtrDeref:
    2916                 :          0 :             visit_field(&node->data.ptr_deref_expr.target, visit, context);
    2917                 :          0 :             break;
    2918                 :          0 :         case NodeTypeUnwrapOptional:
    2919                 :          0 :             visit_field(&node->data.unwrap_optional.expr, visit, context);
    2920                 :          0 :             break;
    2921                 :          0 :         case NodeTypeUsingNamespace:
    2922                 :          0 :             visit_field(&node->data.using_namespace.expr, visit, context);
    2923                 :          0 :             break;
    2924                 :          0 :         case NodeTypeBoolLiteral:
    2925                 :            :             // none
    2926                 :          0 :             break;
    2927                 :          0 :         case NodeTypeNullLiteral:
    2928                 :            :             // none
    2929                 :          0 :             break;
    2930                 :          0 :         case NodeTypeUndefinedLiteral:
    2931                 :            :             // none
    2932                 :          0 :             break;
    2933                 :          0 :         case NodeTypeIfBoolExpr:
    2934                 :          0 :             visit_field(&node->data.if_bool_expr.condition, visit, context);
    2935                 :          0 :             visit_field(&node->data.if_bool_expr.then_block, visit, context);
    2936                 :          0 :             visit_field(&node->data.if_bool_expr.else_node, visit, context);
    2937                 :          0 :             break;
    2938                 :          0 :         case NodeTypeIfErrorExpr:
    2939                 :          0 :             visit_field(&node->data.if_err_expr.target_node, visit, context);
    2940                 :          0 :             visit_field(&node->data.if_err_expr.then_node, visit, context);
    2941                 :          0 :             visit_field(&node->data.if_err_expr.else_node, visit, context);
    2942                 :          0 :             break;
    2943                 :          0 :         case NodeTypeIfOptional:
    2944                 :          0 :             visit_field(&node->data.test_expr.target_node, visit, context);
    2945                 :          0 :             visit_field(&node->data.test_expr.then_node, visit, context);
    2946                 :          0 :             visit_field(&node->data.test_expr.else_node, visit, context);
    2947                 :          0 :             break;
    2948                 :          0 :         case NodeTypeWhileExpr:
    2949                 :          0 :             visit_field(&node->data.while_expr.condition, visit, context);
    2950                 :          0 :             visit_field(&node->data.while_expr.body, visit, context);
    2951                 :          0 :             break;
    2952                 :          0 :         case NodeTypeForExpr:
    2953                 :          0 :             visit_field(&node->data.for_expr.elem_node, visit, context);
    2954                 :          0 :             visit_field(&node->data.for_expr.array_expr, visit, context);
    2955                 :          0 :             visit_field(&node->data.for_expr.index_node, visit, context);
    2956                 :          0 :             visit_field(&node->data.for_expr.body, visit, context);
    2957                 :          0 :             break;
    2958                 :          0 :         case NodeTypeSwitchExpr:
    2959                 :          0 :             visit_field(&node->data.switch_expr.expr, visit, context);
    2960                 :          0 :             visit_node_list(&node->data.switch_expr.prongs, visit, context);
    2961                 :          0 :             break;
    2962                 :          0 :         case NodeTypeSwitchProng:
    2963                 :          0 :             visit_node_list(&node->data.switch_prong.items, visit, context);
    2964                 :          0 :             visit_field(&node->data.switch_prong.var_symbol, visit, context);
    2965                 :          0 :             visit_field(&node->data.switch_prong.expr, visit, context);
    2966                 :          0 :             break;
    2967                 :          0 :         case NodeTypeSwitchRange:
    2968                 :          0 :             visit_field(&node->data.switch_range.start, visit, context);
    2969                 :          0 :             visit_field(&node->data.switch_range.end, visit, context);
    2970                 :          0 :             break;
    2971                 :          0 :         case NodeTypeCompTime:
    2972                 :          0 :             visit_field(&node->data.comptime_expr.expr, visit, context);
    2973                 :          0 :             break;
    2974                 :          0 :         case NodeTypeBreak:
    2975                 :            :             // none
    2976                 :          0 :             break;
    2977                 :          0 :         case NodeTypeContinue:
    2978                 :            :             // none
    2979                 :          0 :             break;
    2980                 :          0 :         case NodeTypeUnreachable:
    2981                 :            :             // none
    2982                 :          0 :             break;
    2983                 :          0 :         case NodeTypeAsmExpr:
    2984         [ #  # ]:          0 :             for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
    2985                 :          0 :                 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
    2986                 :          0 :                 visit_field(&asm_input->expr, visit, context);
    2987                 :            :             }
    2988         [ #  # ]:          0 :             for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
    2989                 :          0 :                 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
    2990                 :          0 :                 visit_field(&asm_output->return_type, visit, context);
    2991                 :            :             }
    2992                 :          0 :             break;
    2993                 :          0 :         case NodeTypeContainerDecl:
    2994                 :          0 :             visit_node_list(&node->data.container_decl.fields, visit, context);
    2995                 :          0 :             visit_node_list(&node->data.container_decl.decls, visit, context);
    2996                 :          0 :             visit_field(&node->data.container_decl.init_arg_expr, visit, context);
    2997                 :          0 :             break;
    2998                 :          0 :         case NodeTypeStructField:
    2999                 :          0 :             visit_field(&node->data.struct_field.type, visit, context);
    3000                 :          0 :             visit_field(&node->data.struct_field.value, visit, context);
    3001                 :          0 :             break;
    3002                 :          0 :         case NodeTypeContainerInitExpr:
    3003                 :          0 :             visit_field(&node->data.container_init_expr.type, visit, context);
    3004                 :          0 :             visit_node_list(&node->data.container_init_expr.entries, visit, context);
    3005                 :          0 :             break;
    3006                 :          0 :         case NodeTypeStructValueField:
    3007                 :          0 :             visit_field(&node->data.struct_val_field.expr, visit, context);
    3008                 :          0 :             break;
    3009                 :          0 :         case NodeTypeArrayType:
    3010                 :          0 :             visit_field(&node->data.array_type.size, visit, context);
    3011                 :          0 :             visit_field(&node->data.array_type.child_type, visit, context);
    3012                 :          0 :             visit_field(&node->data.array_type.align_expr, visit, context);
    3013                 :          0 :             break;
    3014                 :          0 :         case NodeTypeInferredArrayType:
    3015                 :          0 :             visit_field(&node->data.array_type.child_type, visit, context);
    3016                 :          0 :             break;
    3017                 :          0 :         case NodeTypeAnyFrameType:
    3018                 :          0 :             visit_field(&node->data.anyframe_type.payload_type, visit, context);
    3019                 :          0 :             break;
    3020                 :          0 :         case NodeTypeErrorType:
    3021                 :            :             // none
    3022                 :          0 :             break;
    3023                 :          0 :         case NodeTypePointerType:
    3024                 :          0 :             visit_field(&node->data.pointer_type.align_expr, visit, context);
    3025                 :          0 :             visit_field(&node->data.pointer_type.op_expr, visit, context);
    3026                 :          0 :             break;
    3027                 :          0 :         case NodeTypeErrorSetDecl:
    3028                 :          0 :             visit_node_list(&node->data.err_set_decl.decls, visit, context);
    3029                 :          0 :             break;
    3030                 :          0 :         case NodeTypeResume:
    3031                 :          0 :             visit_field(&node->data.resume_expr.expr, visit, context);
    3032                 :          0 :             break;
    3033                 :          0 :         case NodeTypeAwaitExpr:
    3034                 :          0 :             visit_field(&node->data.await_expr.expr, visit, context);
    3035                 :          0 :             break;
    3036                 :          0 :         case NodeTypeSuspend:
    3037                 :          0 :             visit_field(&node->data.suspend.block, visit, context);
    3038                 :          0 :             break;
    3039                 :          0 :         case NodeTypeEnumLiteral:
    3040                 :          0 :             break;
    3041                 :            :     }
    3042                 :          0 : }

Generated by: LCOV version 1.14