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 : }
|