authorgravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-12 02:10:27-07:00
committergravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-12 02:10:27-07:00
log0d629421c97f5be7a89102c0ae57916418e71243
treee438ce744be9567227a20c03cc309730e11b7805
parent3a3a73847812f03fa86fbcab4b3557a37f4c3536
signature Commit is signed but in an unrecognized format.

Recursive rewrite of stage2 parser, final sync


2 files changed, 0 insertions(+), 2671 deletions(-)

CMakeLists.txt-1
...@@ -723,7 +723,6 @@ set(ZIG_STD_FILES...@@ -723,7 +723,6 @@ set(ZIG_STD_FILES
723 "zig.zig"723 "zig.zig"
724 "zig/ast.zig"724 "zig/ast.zig"
725 "zig/parse.zig"725 "zig/parse.zig"
726 "zig/parse2.zig"
727 "zig/parse_string_literal.zig"726 "zig/parse_string_literal.zig"
728 "zig/render.zig"727 "zig/render.zig"
729 "zig/tokenizer.zig"728 "zig/tokenizer.zig"
std/zig/parse2.zig deleted-2670
...@@ -1,2670 +0,0 @@
1const std = @import("../std.zig");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4const ast = std.zig.ast;
5const Node = ast.Node;
6const Tree = ast.Tree;
7const Error = ast.Error;
8const TokenIndex = ast.TokenIndex;
9const Token = std.zig.Token;
10const TokenIterator = Tree.TokenList.Iterator;
11
12pub fn parse(allocator: *Allocator, source: []const u8) !Tree {
13 var tree_arena = std.heap.ArenaAllocator.init(allocator);
14 errdefer tree_arena.deinit();
15 const arena = &tree_arena.allocator;
16
17 var token_list = Tree.TokenList.init(arena);
18 var tokenizer = std.zig.Tokenizer.init(source);
19 while (true) {
20 const tree_token = try token_list.addOne();
21 tree_token.* = tokenizer.next();
22 if (tree_token.id == .Eof) break;
23 }
24 var it = token_list.iterator(0);
25
26 while (it.peek().?.id == .LineComment) _ = it.next();
27
28 var tree = Tree{
29 .source = source,
30 .root_node = undefined,
31 .tokens = token_list,
32 .errors = Tree.ErrorList.init(arena),
33 // TODO: Remove (not used/needed anywhere)
34 .arena_allocator = tree_arena,
35 };
36
37 tree.root_node = try parseRoot(&tree.arena_allocator.allocator, &it, &tree);
38
39 return tree;
40}
41
42// Root <- skip ContainerMembers eof
43fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) !*Node.Root {
44 const node = try arena.create(Node.Root);
45 node.* = Node.Root{
46 .base = Node{ .id = .Root },
47 .decls = undefined,
48 .doc_comments = null,
49 .shebang = null,
50 .eof_token = undefined,
51 };
52 node.decls = (try parseContainerMembers(arena, it, tree, .Keyword_struct)) orelse return node;
53 node.eof_token = eatToken(it, .Eof) orelse unreachable;
54 return node;
55}
56
57// ContainerMembers
58// <- TestDecl ContainerMembers
59// / TopLevelComptime ContainerMembers
60// / KEYWORD_pub? TopLevelDecl ContainerMembers
61// / KEYWORD_pub? ContainerField COMMA ContainerMembers
62// / KEYWORD_pub? ContainerField
63// /
64fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, kind: Token.Id) !?Node.Root.DeclList {
65 var list = Node.Root.DeclList.init(arena);
66
67 while (true) {
68 if (try parseTestDecl(arena, it, tree)) |node| {
69 try list.push(node);
70 continue;
71 }
72
73 if (try parseTopLevelComptime(arena, it, tree)) |node| {
74 try list.push(node);
75 continue;
76 }
77
78 const visibility_token = eatToken(it, .Keyword_pub);
79
80 if (try parseTopLevelDecl(arena, it, tree, visibility_token)) |node| {
81 try list.push(node);
82 continue;
83 }
84
85 if (try parseContainerField(arena, it, tree, kind)) |node| {
86 if (node.cast(Node.StructField)) |struct_field| struct_field.visib_token = visibility_token;
87 try list.push(node);
88 if (eatToken(it, .Comma)) |_| continue else break;
89 }
90
91 // Dangling pub
92 if (visibility_token != null) {
93 try tree.errors.push(Error{
94 .ExpectedPubItem = Error.ExpectedPubItem{ .token = it.peek().?.start },
95 });
96 return null;
97 }
98
99 break;
100 }
101
102 return list;
103}
104
105// TestDecl <- KEYWORD_test STRINGLITERAL Block
106fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
107 const test_token = eatToken(it, .Keyword_test) orelse return null;
108 const name_node = (try expectNode(arena, it, tree, parseStringLiteral, Error{
109 .ExpectedStringLiteral = Error.ExpectedStringLiteral{ .token = it.peek().?.start },
110 })) orelse return null;
111 const block_node = (try expectNode(
112 arena,
113 it,
114 tree,
115 parseBlock,
116 Error{ .ExpectedLBrace = Error.ExpectedLBrace{ .token = it.peek().?.start } },
117 )) orelse return null;
118
119 const test_node = try arena.create(Node.TestDecl);
120 test_node.* = Node.TestDecl{
121 .base = Node{ .id = .TestDecl },
122 .doc_comments = null,
123 .test_token = test_token,
124 .name = name_node,
125 .body_node = block_node,
126 };
127 return &test_node.base;
128}
129
130// TopLevelComptime <- KEYWORD_comptime BlockExpr
131fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
132 const tok = eatToken(it, .Keyword_comptime) orelse return null;
133 const block_node = (try expectNode(arena, it, tree, parseBlockExpr, Error{
134 .ExpectedLabelOrLBrace = Error.ExpectedLabelOrLBrace{ .token = it.peek().?.start },
135 })) orelse return null;
136
137 const comptime_node = try arena.create(Node.Comptime);
138 comptime_node.* = Node.Comptime{
139 .base = Node{ .id = .Comptime },
140 .doc_comments = null,
141 .comptime_token = tok,
142 .expr = block_node,
143 };
144 return &comptime_node.base;
145}
146
147// TopLevelDecl
148// <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
149// / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
150// / KEYWORD_use Expr SEMICOLON
151fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree, vis: ?TokenIndex) !?*Node {
152 const export_token = eatToken(it, .Keyword_export);
153 const extern_token = if (export_token == null) eatToken(it, .Keyword_extern) else null;
154 const lib_name = if (extern_token != null) try parseStringLiteral(arena, it, tree) else null;
155 const inline_token = if (extern_token == null) eatToken(it, .Keyword_inline) else null;
156
157 if (try parseFnProto(arena, it, tree)) |node| {
158 const fn_node = node.cast(Node.FnProto).?;
159
160 fn_node.*.visib_token = vis;
161 fn_node.*.extern_export_inline_token = export_token orelse extern_token orelse inline_token;
162 fn_node.*.lib_name = lib_name;
163
164 if (eatToken(it, .Semicolon)) |_| return node;
165 if (try parseBlock(arena, it, tree)) |body_node| {
166 fn_node.body_node = body_node;
167 return node;
168 }
169
170 try tree.errors.push(Error{
171 .ExpectedSemiOrLBrace = Error.ExpectedSemiOrLBrace{ .token = it.peek().?.start },
172 });
173 return null;
174 }
175
176 if (inline_token != null) return null;
177
178 const thread_local_token = eatToken(it, .Keyword_threadlocal);
179
180 if (try parseVarDecl(arena, it, tree)) |node| {
181 var var_decl = node.cast(Node.VarDecl).?;
182 var_decl.*.doc_comments = null;
183 var_decl.*.visib_token = vis;
184 var_decl.*.thread_local_token = thread_local_token;
185 var_decl.*.comptime_token = null;
186 var_decl.*.extern_export_token = export_token orelse extern_token;
187 var_decl.*.lib_name = lib_name;
188 return node;
189 }
190
191 const use_node = (try parseUse(arena, it, tree)) orelse return null;
192 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
193 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
194 })) orelse return null;
195 const semicolon_token = (try expectToken(it, tree, .Semicolon)) orelse return null;
196 const use_node_raw = use_node.cast(Node.Use).?;
197 use_node_raw.*.visib_token = vis;
198 use_node_raw.*.expr = expr_node;
199 use_node_raw.*.semicolon_token = semicolon_token;
200
201 return use_node;
202}
203
204// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
205fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
206 const cc = (try parseFnCC(arena, it, tree)) orelse return null; // null on parse error
207 const fn_token = eatToken(it, .Keyword_fn) orelse return null;
208 const name_token = eatToken(it, .Identifier);
209 const lparen = (try expectToken(it, tree, .LParen)) orelse return null;
210 const params = try parseParamDeclList(arena, it, tree);
211 const rparen = (try expectToken(it, tree, .RParen)) orelse return null;
212 const alignment_node = try parseByteAlign(arena, it, tree);
213 const section_expr = try parseLinkSection(arena, it, tree);
214 const exclamation_token = eatToken(it, .Bang);
215
216 const return_type_expr = blk: {
217 if (eatToken(it, .Keyword_var)) |var_token| {
218 const node = try arena.create(Node.VarType);
219 node.* = Node.VarType{
220 .base = Node{ .id = .VarType },
221 .token = var_token,
222 };
223 }
224 break :blk (try expectNode(arena, it, tree, parseTypeExpr, Error{
225 .ExpectedReturnType = Error.ExpectedReturnType{ .token = it.peek().?.start },
226 })) orelse return null;
227 };
228
229 // TODO: Based on this rule, `!var` is an acceptable return type, but there is no usage
230 // or coverage of that yet. The grammar also does not include `Keyword_var` as a choice
231 // for PrimaryTypeExpr, but the iterative stage2 parser treats it as one, which actually
232 // makes more sense given the return type rule above. Clarify this with @Hejsil.
233 // Alternative rule, if `var` were to be included in PrimaryTypeExpr (I think):
234 //
235 // - FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
236 // + FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? TypeExpr
237 const return_type = if (exclamation_token != null)
238 Node.FnProto.ReturnType{
239 .InferErrorSet = return_type_expr,
240 }
241 else
242 Node.FnProto.ReturnType{
243 .Explicit = return_type_expr,
244 };
245
246 const fn_proto_node = try arena.create(Node.FnProto);
247 fn_proto_node.* = Node.FnProto{
248 .base = Node{ .id = .FnProto },
249 .doc_comments = null,
250 .visib_token = null,
251 .fn_token = fn_token,
252 .name_token = name_token,
253 .params = params,
254 .return_type = return_type,
255 .var_args_token = undefined, // TODO ?TokenIndex
256 .extern_export_inline_token = null,
257 .cc_token = null,
258 .async_attr = null,
259 .body_node = null,
260 .lib_name = null,
261 .align_expr = null,
262 .section_expr = section_expr,
263 };
264
265 switch (cc) {
266 .CC => |token| fn_proto_node.cc_token = token,
267 .Extern => |token| fn_proto_node.extern_export_inline_token = token,
268 .Async => |node| fn_proto_node.async_attr = node,
269 .None => {},
270 }
271
272 return &fn_proto_node.base;
273}
274
275// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
276fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
277 const mut_token = eatToken(it, .Keyword_const) orelse
278 eatToken(it, .Keyword_var) orelse
279 return null;
280
281 const name_token = (try expectToken(it, tree, .Identifier)) orelse return null;
282 const type_node = blk: {
283 if (eatToken(it, .Colon)) |_| {
284 break :blk (try expectNode(arena, it, tree, parseTypeExpr, Error{
285 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
286 })) orelse return null;
287 } else break :blk null;
288 };
289 const align_node = try parseByteAlign(arena, it, tree);
290 const section_node = try parseLinkSection(arena, it, tree);
291 const eq_token = eatToken(it, .Equal);
292 const init_node = blk: {
293 if (eq_token) |_| {
294 break :blk (try expectNode(arena, it, tree, parseExpr, Error{
295 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
296 })) orelse return null;
297 } else break :blk null;
298 };
299 const semicolon_token = (try expectToken(it, tree, .Semicolon)) orelse return null;
300
301 const node = try arena.create(Node.VarDecl);
302 node.* = Node.VarDecl{
303 .base = Node{ .id = .VarDecl },
304 .mut_token = mut_token,
305 .name_token = name_token,
306 .eq_token = eq_token orelse 0,
307 .type_node = type_node,
308 .align_node = align_node,
309 .section_node = section_node,
310 .init_node = init_node,
311 .semicolon_token = semicolon_token,
312 // set by caller
313 .doc_comments = null,
314 .visib_token = null,
315 .thread_local_token = null,
316 .comptime_token = null,
317 .extern_export_token = null,
318 .lib_name = null,
319 };
320
321 return &node.base;
322}
323
324// ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)?
325fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree, kind: Token.Id) !?*Node {
326 const name_token = eatToken(it, .Identifier) orelse return null;
327
328 const type_expr = blk: {
329 if (eatToken(it, .Colon)) |_| {
330 break :blk (try expectNode(arena, it, tree, parseTypeExpr, Error{
331 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
332 })) orelse return null;
333 } else break :blk null;
334 };
335
336 // TODO: supply default value to struct field when ast.Node.StructField supports it
337 const default_value = blk: {
338 if (eatToken(it, .Equal)) |_| {
339 break :blk (try expectNode(arena, it, tree, parseExpr, Error{
340 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
341 }));
342 } else break :blk null;
343 };
344
345 switch (kind) {
346 .Keyword_struct => {
347 const node = try arena.create(Node.StructField);
348 node.* = Node.StructField{
349 .base = Node{ .id = .StructField },
350 .name_token = name_token,
351 .type_expr = type_expr orelse undefined,
352 .doc_comments = null,
353 .visib_token = null,
354 };
355 return &node.base;
356 },
357 .Keyword_union => {
358 const node = try arena.create(Node.UnionTag);
359 node.* = Node.UnionTag{
360 .base = Node{ .id = .UnionTag },
361 .doc_comments = null,
362 .name_token = name_token,
363 .type_expr = type_expr orelse undefined,
364 .value_expr = default_value,
365 };
366 return &node.base;
367 },
368 .Keyword_enum => {
369 const node = try arena.create(Node.EnumTag);
370 node.* = Node.EnumTag{
371 .base = Node{ .id = .EnumTag },
372 .doc_comments = null,
373 .name_token = name_token,
374 .value = default_value,
375 };
376 return &node.base;
377 },
378 else => unreachable,
379 }
380}
381
382// Statement
383// <- KEYWORD_comptime? VarDecl
384// / KEYWORD_comptime BlockExprStatement
385// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
386// / KEYWORD_defer BlockExprStatement
387// / KEYWORD_errdefer BlockExprStatement
388// / IfStatement
389// / LabeledStatement
390// / SwitchExpr
391// / AssignExpr SEMICOLON
392fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
393 const comptime_token = eatToken(it, .Keyword_comptime);
394
395 const var_decl_node = try parseVarDecl(arena, it, tree);
396 if (var_decl_node) |node| {
397 const var_decl = node.cast(Node.VarDecl).?;
398 var_decl.comptime_token = comptime_token;
399 return node;
400 }
401
402 if (comptime_token) |token| {
403 const block_expr = (try expectNode(arena, it, tree, parseBlockExprStatement, Error{
404 .ExpectedBlockOrAssignment = Error.ExpectedBlockOrAssignment{ .token = it.peek().?.start },
405 })) orelse return null;
406
407 const node = try arena.create(Node.Comptime);
408 node.* = Node.Comptime{
409 .base = Node{ .id = .Comptime },
410 .doc_comments = null,
411 .comptime_token = token,
412 .expr = block_expr,
413 };
414 return &node.base;
415 }
416
417 if (eatToken(it, .Keyword_suspend)) |suspend_token| {
418 const semicolon = eatToken(it, .Semicolon);
419
420 const body_node = if (semicolon == null) blk: {
421 break :blk (try expectNode(arena, it, tree, parseBlockExprStatement, Error{
422 // TODO: expected block or expression
423 .ExpectedBlockOrAssignment = Error.ExpectedBlockOrAssignment{ .token = it.peek().?.start },
424 })) orelse return null;
425 } else null;
426
427 const node = try arena.create(Node.Suspend);
428 node.* = Node.Suspend{
429 .base = Node{ .id = .Suspend },
430 .suspend_token = suspend_token,
431 .body = body_node,
432 };
433 return &node.base;
434 }
435
436 const defer_token = eatToken(it, .Keyword_defer) orelse eatToken(it, .Keyword_errdefer);
437 if (defer_token) |token| {
438 const expr_node = (try expectNode(arena, it, tree, parseBlockExprStatement, Error{
439 // TODO: expected block or expression
440 .ExpectedBlockOrAssignment = Error.ExpectedBlockOrAssignment{ .token = it.peek().?.start },
441 })) orelse return null;
442 const node = try arena.create(Node.Defer);
443 node.* = Node.Defer{
444 .base = Node{ .id = .Defer },
445 .defer_token = token,
446 .expr = expr_node,
447 };
448 return &node.base;
449 }
450
451 if (try parseIfStatement(arena, it, tree)) |node| return node;
452 if (try parseLabeledStatement(arena, it, tree)) |node| return node;
453 if (try parseSwitchExpr(arena, it, tree)) |node| return node;
454 if (try parseAssignExpr(arena, it, tree)) |node| {
455 _ = (try expectToken(it, tree, .Semicolon)) orelse return null;
456 return node;
457 }
458
459 return null;
460}
461
462// IfStatement
463// <- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
464// / IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
465fn parseIfStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
466 const if_node = if (try parseIfPrefix(arena, it, tree)) |node| node.cast(Node.If).? else return null;
467 const block_expr = (try parseBlockExpr(arena, it, tree));
468 const assign_expr = if (block_expr == null) blk: {
469 break :blk (try parseAssignExpr(arena, it, tree)) orelse null;
470 } else null;
471 const semicolon = if (assign_expr != null) eatToken(it, .Semicolon) else null;
472
473 const else_node = if (semicolon != null) blk: {
474 const else_token = eatToken(it, .Keyword_else) orelse break :blk null;
475 const payload = try parsePayload(arena, it, tree);
476 const else_body = (try expectNode(arena, it, tree, parseStatement, Error{
477 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
478 })) orelse return null;
479
480 const node = try arena.create(Node.Else);
481 node.* = Node.Else{
482 .base = Node{ .id = .Else },
483 .else_token = else_token,
484 .payload = payload,
485 .body = else_body,
486 };
487
488 break :blk node;
489 } else null;
490
491 if (block_expr) |body| {
492 if_node.body = body;
493 if_node.@"else" = else_node;
494 return &if_node.base;
495 }
496
497 if (assign_expr) |body| {
498 if_node.body = body;
499 if (semicolon != null) return &if_node.base;
500 if (else_node != null) {
501 if_node.@"else" = else_node;
502 return &if_node.base;
503 }
504 try tree.errors.push(Error{
505 .ExpectedSemiOrElse = Error.ExpectedSemiOrElse{ .token = it.peek().?.start },
506 });
507 }
508
509 return null;
510}
511
512// LabeledStatement <- BlockLabel? (Block / LoopStatement)
513fn parseLabeledStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) anyerror!?*Node {
514 const label_token = parseBlockLabel(arena, it, tree);
515
516 if (try parseBlock(arena, it, tree)) |node| {
517 node.cast(Node.Block).?.label = label_token;
518 return node;
519 }
520
521 if (try parseLoopStatement(arena, it, tree)) |node| {
522 if (node.cast(Node.For)) |for_node| {
523 for_node.label = label_token;
524 } else if (node.cast(Node.While)) |while_node| {
525 while_node.label = label_token;
526 } else unreachable;
527 return node;
528 }
529
530 return null;
531}
532
533// LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
534fn parseLoopStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
535 const inline_token = eatToken(it, .Keyword_inline);
536
537 if (try parseForStatement(arena, it, tree)) |node| {
538 node.cast(Node.For).?.inline_token = inline_token;
539 return node;
540 }
541
542 if (try parseWhileStatement(arena, it, tree)) |node| {
543 node.cast(Node.While).?.inline_token = inline_token;
544 return node;
545 }
546
547 return null;
548}
549
550// ForStatement
551// <- ForPrefix BlockExpr ( KEYWORD_else Statement )?
552// / ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
553fn parseForStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
554 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
555 const for_prefix = node.cast(Node.For).?;
556
557 if (try parseBlockExpr(arena, it, tree)) |block_expr_node| {
558 for_prefix.body = block_expr_node;
559
560 if (eatToken(it, .Keyword_else)) |else_token| {
561 const statement_node = (try expectNode(arena, it, tree, parseStatement, Error{
562 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
563 })) orelse return null;
564
565 const else_node = try arena.create(Node.Else);
566 else_node.* = Node.Else{
567 .base = Node{ .id = .Else },
568 .else_token = else_token,
569 .payload = null,
570 .body = statement_node,
571 };
572 for_prefix.@"else" = else_node;
573
574 return node;
575 }
576
577 return node;
578 }
579
580 if (try parseAssignExpr(arena, it, tree)) |assign_expr| {
581 for_prefix.body = assign_expr;
582
583 if (eatToken(it, .Semicolon) != null) return node;
584
585 if (eatToken(it, .Keyword_else)) |else_token| {
586 const statement_node = (try expectNode(arena, it, tree, parseStatement, Error{
587 .ExpectedStatement = Error.ExpectedStatement{ .token = it.peek().?.start },
588 })) orelse return null;
589
590 const else_node = try arena.create(Node.Else);
591 else_node.* = Node.Else{
592 .base = Node{ .id = .Else },
593 .else_token = else_token,
594 .payload = null,
595 .body = statement_node,
596 };
597 for_prefix.@"else" = else_node;
598 return node;
599 }
600
601 try tree.errors.push(Error{
602 .ExpectedSemiOrElse = Error.ExpectedSemiOrElse{ .token = it.peek().?.start },
603 });
604 return null;
605 }
606
607 return null;
608}
609
610// WhileStatement
611// <- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
612// / WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
613fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
614 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
615 const while_prefix = node.cast(Node.While).?;
616
617 if (try parseBlockExpr(arena, it, tree)) |block_expr_node| {
618 while_prefix.body = block_expr_node;
619
620 if (eatToken(it, .Keyword_else)) |else_token| {
621 const payload = try parsePayload(arena, it, tree);
622
623 const statement_node = (try expectNode(arena, it, tree, parseStatement, Error{
624 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
625 })) orelse return null;
626
627 const else_node = try arena.create(Node.Else);
628 else_node.* = Node.Else{
629 .base = Node{ .id = .Else },
630 .else_token = else_token,
631 .payload = payload,
632 .body = statement_node,
633 };
634 while_prefix.@"else" = else_node;
635
636 return node;
637 }
638
639 return node;
640 }
641
642 if (try parseAssignExpr(arena, it, tree)) |assign_expr_node| {
643 while_prefix.body = assign_expr_node;
644
645 if (eatToken(it, .Semicolon) != null) return node;
646
647 if (eatToken(it, .Keyword_else)) |else_token| {
648 const payload = try parsePayload(arena, it, tree);
649
650 const statement_node = (try expectNode(arena, it, tree, parseStatement, Error{
651 .ExpectedStatement = Error.ExpectedStatement{ .token = it.peek().?.start },
652 })) orelse return null;
653
654 const else_node = try arena.create(Node.Else);
655 else_node.* = Node.Else{
656 .base = Node{ .id = .Else },
657 .else_token = else_token,
658 .payload = payload,
659 .body = statement_node,
660 };
661 while_prefix.@"else" = else_node;
662 return node;
663 }
664
665 try tree.errors.push(Error{
666 .ExpectedSemiOrElse = Error.ExpectedSemiOrElse{ .token = it.peek().?.start },
667 });
668 return null;
669 }
670
671 return null;
672}
673
674// BlockExprStatement
675// <- BlockExpr
676// / AssignExpr SEMICOLON
677fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
678 if (try parseBlockExpr(arena, it, tree)) |node| return node;
679 if (try parseAssignExpr(arena, it, tree)) |node| {
680 _ = (try expectToken(it, tree, .Semicolon)) orelse return null;
681 return node;
682 }
683 return null;
684}
685
686// BlockExpr <- BlockLabel? Block
687fn parseBlockExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) anyerror!?*Node {
688 const label_token = parseBlockLabel(arena, it, tree) orelse return null;
689 const block_node = (parseBlock(arena, it, tree) catch return error.TodoFixRecursion) orelse return null;
690 block_node.cast(Node.Block).?.label = label_token;
691 return block_node;
692}
693
694// AssignExpr <- Expr (AssignOp Expr)?
695fn parseAssignExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
696 return parseBinOpExpr(arena, it, tree, parseAssignOp, parseExpr, .Once);
697}
698
699// Expr <- KEYWORD_try* BoolOrExpr
700fn parseExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
701 return parsePrefixOpExpr(arena, it, tree, parseTry, parseBoolOrExpr);
702}
703
704// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
705fn parseBoolOrExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
706 return parseBinOpExpr(
707 arena,
708 it,
709 tree,
710 SimpleBinOpParser(.Keyword_or, Node.InfixOp.Op.BoolOr).parse,
711 parseBoolAndExpr,
712 .Infinitely,
713 );
714}
715
716// BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
717fn parseBoolAndExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
718 return parseBinOpExpr(
719 arena,
720 it,
721 tree,
722 SimpleBinOpParser(.Keyword_and, Node.InfixOp.Op.BoolAnd).parse,
723 parseCompareExpr,
724 .Infinitely,
725 );
726}
727
728// CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
729fn parseCompareExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
730 return parseBinOpExpr(arena, it, tree, parseCompareOp, parseBitwiseExpr, .Once);
731 // TODO: stage1 supplies BinOpChainInf, not Once, but grammar uses `?`
732}
733
734// BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
735fn parseBitwiseExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
736 return parseBinOpExpr(arena, it, tree, parseBitwiseOp, parseBitShiftExpr, .Infinitely);
737}
738
739// BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
740fn parseBitShiftExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
741 return parseBinOpExpr(arena, it, tree, parseBitShiftOp, parseAdditionExpr, .Infinitely);
742}
743
744// AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
745fn parseAdditionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
746 return parseBinOpExpr(arena, it, tree, parseAdditionOp, parseMultiplyExpr, .Infinitely);
747}
748
749// MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
750fn parseMultiplyExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
751 return parseBinOpExpr(arena, it, tree, parseMultiplyOp, parsePrefixExpr, .Infinitely);
752}
753
754// PrefixExpr <- PrefixOp* PrimaryExpr
755fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
756 return parsePrefixOpExpr(arena, it, tree, parsePrefixOp, parsePrimaryExpr);
757}
758
759// PrimaryExpr
760// <- AsmExpr
761// / IfExpr
762// / KEYWORD_break BreakLabel? Expr?
763// / KEYWORD_cancel Expr
764// / KEYWORD_comptime Expr
765// / KEYWORD_continue BreakLabel?
766// / KEYWORD_resume Expr
767// / KEYWORD_return Expr?
768// / BlockLabel? LoopExpr
769// / Block
770// / CurlySuffixExpr
771fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
772 // TODO: enum literal not represented in grammar: https://github.com/ziglang/zig/issues/2235
773 if (try parseEnumLiteral(arena, it, tree)) |node| return node;
774 if (try parseAsmExpr(arena, it, tree)) |node| return node;
775 if (try parseIfExpr(arena, it, tree)) |node| return node;
776
777 if (eatToken(it, .Keyword_break)) |token| {
778 const label = parseBreakLabel(arena, it, tree);
779 const expr_node = try parseExpr(arena, it, tree);
780 const node = try arena.create(Node.ControlFlowExpression);
781 node.* = Node.ControlFlowExpression{
782 .base = Node{ .id = .ControlFlowExpression },
783 .ltoken = token,
784 .kind = Node.ControlFlowExpression.Kind{ .Break = null }, // TODO: what goes here?
785 .rhs = expr_node,
786 };
787 return &node.base;
788 }
789
790 if (eatToken(it, .Keyword_cancel)) |token| {
791 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
792 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
793 })) orelse return null;
794 const node = try arena.create(Node.PrefixOp);
795 node.* = Node.PrefixOp{
796 .base = Node{ .id = .PrefixOp },
797 .op_token = token,
798 .op = Node.PrefixOp.Op.Cancel,
799 .rhs = expr_node,
800 };
801 return &node.base;
802 }
803
804 if (eatToken(it, .Keyword_comptime)) |token| {
805 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
806 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
807 })) orelse return null;
808 const node = try arena.create(Node.Comptime);
809 node.* = Node.Comptime{
810 .base = Node{ .id = .Comptime },
811 .doc_comments = null,
812 .comptime_token = token,
813 .expr = expr_node,
814 };
815 return &node.base;
816 }
817
818 if (eatToken(it, .Keyword_continue)) |token| {
819 const label = parseBreakLabel(arena, it, tree);
820 const node = try arena.create(Node.ControlFlowExpression);
821 node.* = Node.ControlFlowExpression{
822 .base = Node{ .id = .ControlFlowExpression },
823 .ltoken = token,
824 .kind = Node.ControlFlowExpression.Kind{ .Continue = null }, // TODO: what goes here?
825 .rhs = null,
826 };
827 return &node.base;
828 }
829
830 if (eatToken(it, .Keyword_resume)) |token| {
831 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
832 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
833 })) orelse return null;
834 const node = try arena.create(Node.PrefixOp);
835 node.* = Node.PrefixOp{
836 .base = Node{ .id = .PrefixOp },
837 .op_token = token,
838 .op = Node.PrefixOp.Op.Resume,
839 .rhs = expr_node,
840 };
841 return &node.base;
842 }
843
844 if (eatToken(it, .Keyword_return)) |token| {
845 const expr_node = try parseExpr(arena, it, tree);
846 const node = try arena.create(Node.ControlFlowExpression);
847 node.* = Node.ControlFlowExpression{
848 .base = Node{ .id = .ControlFlowExpression },
849 .ltoken = token,
850 .kind = Node.ControlFlowExpression.Kind.Return,
851 .rhs = expr_node,
852 };
853 return &node.base;
854 }
855
856 const label = parseBlockLabel(arena, it, tree);
857 if (try parseLoopExpr(arena, it, tree)) |node| {
858 if (node.cast(Node.For)) |for_node| {
859 for_node.label = label;
860 } else if (node.cast(Node.While)) |while_node| {
861 while_node.label = label;
862 } else unreachable;
863 return node;
864 }
865
866 if (try parseBlock(arena, it, tree)) |node| return node;
867 if (try parseCurlySuffixExpr(arena, it, tree)) |node| return node;
868
869 return null;
870}
871
872// IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
873fn parseIfExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
874 const if_node = (try parseIfPrefix(arena, it, tree)) orelse return null;
875 const expr_node = (try parseExpr(arena, it, tree)) orelse return null;
876
877 const else_node = if (eatToken(it, .Keyword_else)) |else_token| blk: {
878 const payload = try parsePayload(arena, it, tree);
879 const else_expr = (try expectNode(arena, it, tree, parseExpr, Error{
880 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
881 })) orelse return null;
882
883 const node = try arena.create(Node.Else);
884 node.* = Node.Else{
885 .base = Node{ .id = .Else },
886 .else_token = else_token,
887 .payload = payload,
888 .body = else_expr,
889 };
890
891 break :blk node;
892 } else null;
893
894 const node = if_node.cast(Node.If).?;
895 node.*.body = expr_node;
896 node.*.@"else" = else_node;
897
898 return &node.base;
899}
900
901// Block <- LBRACE Statement* RBRACE
902fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
903 const lbrace = eatToken(it, .LBrace) orelse return null;
904
905 var statements = Node.Block.StatementList.init(arena);
906 while (true) {
907 const statement = (try parseStatement(arena, it, tree)) orelse break;
908 try statements.push(statement);
909 }
910
911 const rbrace = (try expectToken(it, tree, .RBrace)) orelse return null;
912
913 const block_node = try arena.create(Node.Block);
914 block_node.* = Node.Block{
915 .base = Node{ .id = .Block },
916 .label = null, // set by caller
917 .lbrace = lbrace,
918 .statements = statements,
919 .rbrace = rbrace,
920 };
921
922 return &block_node.base;
923}
924
925// LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
926fn parseLoopExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
927 const inline_token = eatToken(it, .Keyword_inline);
928
929 if (try parseForExpr(arena, it, tree)) |node| {
930 node.cast(Node.For).?.inline_token = inline_token;
931 return node;
932 }
933
934 if (try parseWhileExpr(arena, it, tree)) |node| {
935 node.cast(Node.While).?.inline_token = inline_token;
936 return node;
937 }
938
939 // TODO: error?
940
941 return null;
942}
943
944// ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
945fn parseForExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
946 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
947
948 const body_node = (try expectNode(arena, it, tree, parseExpr, Error{
949 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
950 })) orelse return null;
951 node.cast(Node.For).?.body = body_node;
952
953 if (eatToken(it, .Keyword_else)) |else_token| {
954 const body = (try expectNode(arena, it, tree, parseExpr, Error{
955 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
956 })) orelse return null;
957
958 const else_node = try arena.create(Node.Else);
959 else_node.* = Node.Else{
960 .base = Node{ .id = .Else },
961 .else_token = else_token,
962 .payload = null,
963 .body = body,
964 };
965
966 node.cast(Node.For).?.@"else" = else_node;
967 }
968
969 return node;
970}
971
972// WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
973fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
974 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
975
976 const body_node = (try expectNode(arena, it, tree, parseExpr, Error{
977 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
978 })) orelse return null;
979 node.cast(Node.For).?.body = body_node;
980
981 if (eatToken(it, .Keyword_else)) |else_token| {
982 const payload = try parsePayload(arena, it, tree);
983 const body = (try expectNode(arena, it, tree, parseExpr, Error{
984 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
985 })) orelse return null;
986
987 const else_node = try arena.create(Node.Else);
988 else_node.* = Node.Else{
989 .base = Node{ .id = .Else },
990 .else_token = else_token,
991 .payload = null,
992 .body = body,
993 };
994
995 node.cast(Node.While).?.@"else" = else_node;
996 }
997
998 return node;
999}
1000
1001// CurlySuffixExpr <- TypeExpr InitList?
1002fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1003 const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1004 const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr;
1005 init_list.cast(Node.SuffixOp).?.lhs = type_expr;
1006 return init_list;
1007}
1008
1009// InitList
1010// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
1011// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
1012// / LBRACE RBRACE
1013fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1014 const lbrace = eatToken(it, .LBrace) orelse return null;
1015 var init_list = Node.SuffixOp.Op.InitList.init(arena);
1016 const node = try arena.create(Node.SuffixOp);
1017 node.* = Node.SuffixOp{
1018 .base = Node{ .id = .SuffixOp },
1019 .lhs = undefined, // set by caller
1020 .op = Node.SuffixOp.Op{ .StructInitializer = init_list },
1021 .rtoken = undefined, // set below
1022 };
1023
1024 if (try parseFieldInit(arena, it, tree)) |field_init| {
1025 try init_list.push(field_init);
1026 while (eatToken(it, .Comma)) |_| {
1027 const next = (try parseFieldInit(arena, it, tree)) orelse break;
1028 try init_list.push(next);
1029 }
1030 } else if (try parseExpr(arena, it, tree)) |expr| {
1031 try init_list.push(expr);
1032 while (eatToken(it, .Comma)) |_| {
1033 const next = (try parseExpr(arena, it, tree)) orelse break;
1034 try init_list.push(next);
1035 }
1036 }
1037
1038 node.rtoken = (try expectToken(it, tree, .RBrace)) orelse return null;
1039 return &node.base;
1040}
1041
1042// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
1043fn parseTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1044 return parsePrefixOpExpr(arena, it, tree, parsePrefixTypeOp, parseErrorUnionExpr);
1045}
1046
1047// ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
1048fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1049 const suffix_expr = (try parseSuffixExpr(arena, it, tree)) orelse return null;
1050
1051 if (eatToken(it, .Bang)) |bang| {
1052 const type_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1053 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1054 })) orelse return null;
1055 const op_node = try arena.create(Node.InfixOp);
1056 op_node.* = Node.InfixOp{
1057 .base = Node{ .id = .InfixOp },
1058 .op_token = bang,
1059 .lhs = suffix_expr,
1060 .op = Node.InfixOp.Op.ErrorUnion,
1061 .rhs = type_expr,
1062 };
1063 return &op_node.base;
1064 }
1065
1066 return suffix_expr;
1067}
1068
1069// SuffixExpr
1070// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments
1071// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1072fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1073 if (try parseAsyncPrefix(arena, it, tree)) |async_node| {
1074 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
1075 var child = (try expectNode(arena, it, tree, parsePrimaryTypeExpr, Error{
1076 // TODO: different error?
1077 .ExpectedPrimaryExpr = Error.ExpectedPrimaryExpr{ .token = it.peek().?.start },
1078 })) orelse return null;
1079
1080 while (try parseSuffixOp(arena, it, tree)) |suffix| {
1081 // TODO: all of this, maybe
1082 switch (suffix.cast(Node.SuffixOp).?.op) {
1083 .Call => |op| {},
1084 .ArrayAccess => |op| {},
1085 .Slice => |op| {},
1086 .ArrayInitializer => |op| {},
1087 .StructInitializer => |op| {},
1088 .Deref => |op| {},
1089 .UnwrapOptional => |op| {},
1090 }
1091 child = suffix;
1092 }
1093
1094 const params = (try parseFnCallArguments(arena, it, tree)) orelse {
1095 try tree.errors.push(Error{
1096 .ExpectedParamList = Error.ExpectedParamList{ .token = it.peek().?.start },
1097 });
1098 return null;
1099 };
1100
1101 const node = try arena.create(Node.SuffixOp);
1102 node.* = Node.SuffixOp{
1103 .base = Node{ .id = .SuffixOp },
1104 .lhs = child,
1105 .op = Node.SuffixOp.Op{
1106 .Call = Node.SuffixOp.Op.Call{
1107 .params = params,
1108 .async_attr = async_node.cast(Node.AsyncAttribute).?,
1109 },
1110 },
1111 .rtoken = undefined, // TODO TokenIndex ehhhhhh????
1112 };
1113 return &node.base;
1114 }
1115
1116 if (try parsePrimaryTypeExpr(arena, it, tree)) |expr| {
1117 var res = expr;
1118
1119 while (true) {
1120 if (try parseSuffixOp(arena, it, tree)) |suffix| {
1121 suffix.cast(Node.SuffixOp).?.lhs = res;
1122 res = suffix;
1123 continue;
1124 } else if (try parseFnCallArguments(arena, it, tree)) |params| {
1125 const call = try arena.create(Node.SuffixOp);
1126 call.* = Node.SuffixOp{
1127 .base = Node{ .id = .SuffixOp },
1128 .lhs = res,
1129 .op = Node.SuffixOp.Op{
1130 .Call = Node.SuffixOp.Op.Call{
1131 .params = params,
1132 .async_attr = null,
1133 },
1134 },
1135 .rtoken = undefined, // TODO: TokenIndex HMMMMM.
1136 };
1137 res = &call.base;
1138 continue;
1139 }
1140 break;
1141 }
1142 // TODO
1143 return res;
1144 }
1145
1146 return null;
1147}
1148
1149// PrimaryTypeExpr
1150// <- BUILTINIDENTIFIER FnCallArguments
1151// / CHAR_LITERAL
1152// / ContainerDecl
1153// / ErrorSetDecl
1154// / FLOAT
1155// / FnProto
1156// / GroupedExpr
1157// / LabeledTypeExpr
1158// / IDENTIFIER
1159// / IfTypeExpr
1160// / INTEGER
1161// / KEYWORD_anyerror
1162// / KEYWORD_comptime TypeExpr
1163// / KEYWORD_error DOT IDENTIFIER
1164// / KEYWORD_false
1165// / KEYWORD_null
1166// / KEYWORD_promise
1167// / KEYWORD_true
1168// / KEYWORD_undefined
1169// / KEYWORD_unreachable
1170// / STRINGLITERAL
1171// / SwitchExpr
1172fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1173 // TODO: @[a-zA-Z_][a-zA-Z0-9]* (builtin identifier)
1174 if (eatToken(it, .CharLiteral)) |token| {
1175 const node = try arena.create(Node.CharLiteral);
1176 node.* = Node.CharLiteral{
1177 .base = Node{ .id = .CharLiteral },
1178 .token = token,
1179 };
1180 return &node.base;
1181 }
1182
1183 if (try parseContainerDecl(arena, it, tree)) |node| return node;
1184 if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
1185 if (try parseFloatLiteral(arena, it, tree)) |node| return node;
1186 if (try parseFnProto(arena, it, tree)) |node| return node;
1187 if (try parseGroupedExpr(arena, it, tree)) |node| return node;
1188 if (try parseLabeledTypeExpr(arena, it, tree)) |node| return node;
1189 if (try parseIdentifier(arena, it, tree)) |node| return node;
1190 if (try parseIfTypeExpr(arena, it, tree)) |node| return node;
1191 if (try parseIntegerLiteral(arena, it, tree)) |node| return node;
1192 if (eatToken(it, .Keyword_anyerror)) |token| return createLiteral(arena, Node.ErrorType, token);
1193 if (eatToken(it, .Keyword_comptime)) |token| {
1194 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1195 const node = try arena.create(Node.Comptime);
1196 node.* = Node.Comptime{
1197 .base = Node{ .id = .Comptime },
1198 .doc_comments = null,
1199 .comptime_token = token,
1200 .expr = expr,
1201 };
1202 return &node.base;
1203 }
1204 if (eatToken(it, .Keyword_error)) |token| {
1205 const period = (try expectToken(it, tree, .Period)) orelse return null;
1206 const identifier = (try expectNode(arena, it, tree, parseIdentifier, Error{
1207 .ExpectedIdentifier = Error.ExpectedIdentifier{ .token = it.peek().?.start },
1208 })) orelse return null;
1209 const global_error_set = try createLiteral(arena, Node.ErrorType, token);
1210 const node = try arena.create(Node.InfixOp);
1211 node.* = Node.InfixOp{
1212 .base = Node{ .id = .InfixOp },
1213 .op_token = period,
1214 .lhs = global_error_set,
1215 .op = Node.InfixOp.Op.Period,
1216 .rhs = identifier,
1217 };
1218 return &node.base;
1219 }
1220 if (eatToken(it, .Keyword_false)) |token| return createLiteral(arena, Node.BoolLiteral, token);
1221 if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token);
1222 if (eatToken(it, .Keyword_promise)) |token| {
1223 const node = try arena.create(Node.PromiseType);
1224 node.* = Node.PromiseType{
1225 .base = Node{ .id = .PromiseType },
1226 .promise_token = token,
1227 .result = null,
1228 };
1229 return &node.base;
1230 }
1231 if (eatToken(it, .Keyword_true)) |token| return createLiteral(arena, Node.BoolLiteral, token);
1232 if (eatToken(it, .Keyword_undefined)) |token| return createLiteral(arena, Node.UndefinedLiteral, token);
1233 if (eatToken(it, .Keyword_unreachable)) |token| return createLiteral(arena, Node.Unreachable, token);
1234 if (try parseStringLiteral(arena, it, tree)) |node| return node;
1235 if (try parseSwitchExpr(arena, it, tree)) |node| return node;
1236
1237 return null;
1238}
1239
1240// ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
1241fn parseContainerDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1242 const layout_token = eatToken(it, .Keyword_extern) orelse
1243 eatToken(it, .Keyword_packed);
1244
1245 const node = (try parseContainerDeclAuto(arena, it, tree)) orelse return null;
1246 node.cast(Node.ContainerDecl).?.*.layout_token = layout_token;
1247 return node;
1248}
1249
1250// ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
1251fn parseErrorSetDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1252 const error_token = eatToken(it, .Keyword_error) orelse return null;
1253 _ = (try expectToken(it, tree, .LBrace)) orelse return null;
1254 const decls = try parseIdentifierList(arena, it, tree);
1255 const rbrace = (try expectToken(it, tree, .RBrace)) orelse return null;
1256
1257 const node = try arena.create(Node.ErrorSetDecl);
1258 node.* = Node.ErrorSetDecl{
1259 .base = Node{ .id = .ErrorSetDecl },
1260 .error_token = error_token,
1261 .decls = decls,
1262 .rbrace_token = rbrace,
1263 };
1264 return &node.base;
1265}
1266
1267// GroupedExpr <- LPAREN Expr RPAREN
1268fn parseGroupedExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1269 const lparen = eatToken(it, .LParen) orelse return null;
1270 const expr = (try expectNode(arena, it, tree, parseExpr, Error{
1271 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1272 })) orelse return null;
1273 const rparen = (try expectToken(it, tree, .RParen)) orelse return null;
1274
1275 const node = try arena.create(Node.GroupedExpression);
1276 node.* = Node.GroupedExpression{
1277 .base = Node{ .id = .GroupedExpression },
1278 .lparen = lparen,
1279 .expr = expr,
1280 .rparen = rparen,
1281 };
1282 return &node.base;
1283}
1284
1285// IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
1286fn parseIfTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1287 const node = (try parseIfPrefix(arena, it, tree)) orelse return null;
1288 const type_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1289 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1290 })) orelse return null;
1291
1292 const if_prefix = node.cast(Node.If).?;
1293 if_prefix.body = type_expr;
1294
1295 if (eatToken(it, .Keyword_else)) |else_token| {
1296 const payload = (try parsePayload(arena, it, tree)) orelse return null;
1297 const else_body = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1298 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1299 })) orelse return null;
1300
1301 const else_node = try arena.create(Node.Else);
1302 else_node.* = Node.Else{
1303 .base = Node{ .id = .Else },
1304 .else_token = else_token,
1305 .payload = payload,
1306 .body = else_body,
1307 };
1308 if_prefix.@"else" = else_node;
1309 }
1310
1311 return node;
1312}
1313
1314// LabeledTypeExpr
1315// <- BlockLabel Block
1316// / BlockLabel? LoopTypeExpr
1317fn parseLabeledTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1318 const label = parseBlockLabel(arena, it, tree);
1319
1320 if (label) |token| {
1321 if (try parseBlock(arena, it, tree)) |node| {
1322 node.cast(Node.Block).?.label = token;
1323 return node;
1324 }
1325 }
1326
1327 const node = (try parseLoopTypeExpr(arena, it, tree)) orelse return null;
1328 switch (node.id) {
1329 .For => node.cast(Node.For).?.label = label,
1330 .While => node.cast(Node.While).?.label = label,
1331 else => unreachable,
1332 }
1333 return node;
1334}
1335
1336// LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
1337fn parseLoopTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1338 const inline_token = eatToken(it, .Keyword_inline);
1339
1340 if (try parseForTypeExpr(arena, it, tree)) |node| {
1341 node.cast(Node.For).?.inline_token = inline_token;
1342 return node;
1343 }
1344
1345 if (try parseWhileTypeExpr(arena, it, tree)) |node| {
1346 node.cast(Node.While).?.inline_token = inline_token;
1347 return node;
1348 }
1349
1350 return null;
1351}
1352
1353// ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
1354fn parseForTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1355 const node = (try parseForPrefix(arena, it, tree)) orelse return null;
1356 const for_prefix = node.cast(Node.For).?;
1357
1358 const type_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1359 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1360 })) orelse return null;
1361 for_prefix.body = type_expr;
1362
1363 if (eatToken(it, .Keyword_else)) |else_token| {
1364 const else_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1365 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1366 })) orelse return null;
1367
1368 const else_node = try arena.create(Node.Else);
1369 else_node.* = Node.Else{
1370 .base = Node{ .id = .Else },
1371 .else_token = else_token,
1372 .payload = null,
1373 .body = else_expr,
1374 };
1375
1376 for_prefix.@"else" = else_node;
1377 }
1378
1379 return node;
1380}
1381
1382// WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
1383fn parseWhileTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1384 const node = (try parseWhilePrefix(arena, it, tree)) orelse return null;
1385 const while_prefix = node.cast(Node.While).?;
1386
1387 const type_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1388 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1389 })) orelse return null;
1390 while_prefix.body = type_expr;
1391
1392 if (eatToken(it, .Keyword_else)) |else_token| {
1393 const payload = try parsePayload(arena, it, tree);
1394
1395 const else_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1396 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1397 })) orelse return null;
1398
1399 const else_node = try arena.create(Node.Else);
1400 else_node.* = Node.Else{
1401 .base = Node{ .id = .Else },
1402 .else_token = else_token,
1403 .payload = null,
1404 .body = else_expr,
1405 };
1406
1407 while_prefix.@"else" = else_node;
1408 }
1409
1410 return node;
1411}
1412
1413// SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
1414fn parseSwitchExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1415 const switch_token = eatToken(it, .Keyword_switch) orelse return null;
1416 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1417 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
1418 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1419 })) orelse return null;
1420 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1421 _ = (try expectToken(it, tree, .LBrace)) orelse return null;
1422 const cases = try parseSwitchProngList(arena, it, tree);
1423 const rbrace = (try expectToken(it, tree, .RBrace)) orelse return null;
1424
1425 const node = try arena.create(Node.Switch);
1426 node.* = Node.Switch{
1427 .base = Node{ .id = .Switch },
1428 .switch_token = switch_token,
1429 .expr = expr_node,
1430 .cases = cases,
1431 .rbrace = rbrace,
1432 };
1433 return &node.base;
1434}
1435
1436// AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN STRINGLITERAL AsmOutput? RPAREN
1437fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1438 const asm_token = eatToken(it, .Keyword_asm) orelse return null;
1439 const volatile_token = eatToken(it, .Keyword_volatile);
1440 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1441 const asm_output = try parseAsmOutput(arena, it, tree);
1442 const rparen = (try expectToken(it, tree, .RParen)) orelse return null;
1443
1444 const node = try arena.create(Node.Asm);
1445 node.* = Node.Asm{
1446 .base = Node{ .id = .Asm },
1447 .asm_token = asm_token,
1448 .volatile_token = volatile_token,
1449 .template = undefined, //TODO
1450 .outputs = undefined, // asm_output, // TODO
1451 .inputs = undefined, // TODO
1452 .clobbers = undefined, // TODO
1453 .rparen = rparen,
1454 };
1455 return &node.base;
1456}
1457
1458// TODO: enum literal not represented in grammar: https://github.com/ziglang/zig/issues/2235
1459fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1460 const dot = eatToken(it, .Period) orelse return null;
1461 const name = (try expectToken(it, tree, .Identifier)) orelse return null;
1462
1463 const node = try arena.create(Node.EnumLiteral);
1464 node.* = Node.EnumLiteral{
1465 .base = undefined, // TODO: ??
1466 .dot = dot,
1467 .name = name,
1468 };
1469 return &node.base;
1470}
1471
1472// AsmOutput <- COLON AsmOutputList AsmInput?
1473fn parseAsmOutput(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1474 return error.NotImplemented; // TODO
1475}
1476
1477// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
1478fn parseAsmOutputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1479 return error.NotImplemented; // TODO
1480}
1481
1482// AsmInput <- COLON AsmInputList AsmClobbers?
1483fn parseAsmInput(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1484 return error.NotImplemented; // TODO
1485}
1486
1487// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
1488fn parseAsmInputItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1489 return error.NotImplemented; // TODO
1490}
1491
1492// AsmClobbers <- COLON StringList
1493// StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL?
1494fn parseAsmClobbers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?Node.Asm.ClobberList {
1495 _ = eatToken(it, .Colon) orelse return null;
1496 return try ListParser(Node.Asm.ClobberList, parseStringLiteral).parse(arena, it, tree);
1497}
1498
1499// BreakLabel <- COLON IDENTIFIER
1500fn parseBreakLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenIndex {
1501 _ = eatToken(it, .Colon) orelse return null;
1502 return eatToken(it, .Identifier);
1503}
1504
1505// BlockLabel <- IDENTIFIER COLON
1506fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenIndex {
1507 const token = eatToken(it, .Identifier) orelse return null;
1508 _ = eatToken(it, .Colon) orelse return null;
1509 return token;
1510}
1511
1512// FieldInit <- DOT IDENTIFIER EQUAL Expr
1513fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1514 const period_token = eatToken(it, .Period) orelse return null;
1515 const name_token = (try expectToken(it, tree, .Identifier)) orelse return null;
1516 const eq_token = (try expectToken(it, tree, .Equal)) orelse return null;
1517 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
1518 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1519 })) orelse return null;
1520
1521 const node = try arena.create(Node.FieldInitializer);
1522 node.* = Node.FieldInitializer{
1523 .base = Node{ .id = .FieldInitializer },
1524 .period_token = period_token,
1525 .name_token = name_token,
1526 .expr = expr_node,
1527 };
1528 return &node.base;
1529}
1530
1531// WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
1532fn parseWhileContinueExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1533 _ = eatToken(it, .Colon) orelse return null;
1534 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1535 const node = (try expectNode(arena, it, tree, parseAssignExpr, Error{
1536 .ExpectedExprOrAssignment = Error.ExpectedExprOrAssignment{ .token = it.peek().?.start },
1537 })) orelse return null;
1538 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1539 return node;
1540}
1541
1542// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
1543fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1544 _ = eatToken(it, .Keyword_linksection) orelse return null;
1545 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1546 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
1547 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1548 })) orelse return null;
1549 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1550 return expr_node;
1551}
1552
1553// FnCC
1554// <- KEYWORD_nakedcc
1555// / KEYWORD_stdcallcc
1556// / KEYWORD_extern
1557// / KEYWORD_async (LARROW TypeExpr RARROW)?
1558fn parseFnCC(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?FnCC {
1559 if (eatToken(it, .Keyword_nakedcc)) |token| return FnCC{ .CC = token };
1560 if (eatToken(it, .Keyword_stdcallcc)) |token| return FnCC{ .CC = token };
1561 if (eatToken(it, .Keyword_extern)) |token| return FnCC{ .Extern = token };
1562 if (eatToken(it, .Keyword_async)) |token| {
1563 const node = try arena.create(Node.AsyncAttribute);
1564 node.* = Node.AsyncAttribute{
1565 .base = Node{ .id = .AsyncAttribute },
1566 .async_token = token,
1567 .allocator_type = null,
1568 .rangle_bracket = null,
1569 };
1570 if (eatToken(it, .AngleBracketLeft)) |_| {
1571 const type_expr = (try expectNode(arena, it, tree, parseTypeExpr, Error{
1572 .ExpectedTypeExpr = Error.ExpectedTypeExpr{ .token = it.peek().?.start },
1573 })) orelse return null;
1574 const rarrow = (try expectToken(it, tree, .AngleBracketRight)) orelse return null;
1575 node.allocator_type = type_expr;
1576 node.rangle_bracket = rarrow;
1577 }
1578 return FnCC{ .Async = node };
1579 }
1580 return FnCC{ .None = {} };
1581}
1582
1583const FnCC = union(enum) {
1584 CC: TokenIndex,
1585 Extern: TokenIndex,
1586 Async: *Node.AsyncAttribute,
1587 None,
1588};
1589
1590// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
1591fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1592 const noalias_token = eatToken(it, .Keyword_noalias);
1593 const comptime_token = if (noalias_token == null) eatToken(it, .Keyword_comptime) else null;
1594 const name_token = blk: {
1595 const identifier = eatToken(it, .Identifier) orelse break :blk null;
1596 if (eatToken(it, .Colon) != null) break :blk identifier;
1597 _ = rewindTokenIterator(it); // ParamType may also be an identifier
1598 break :blk null;
1599 };
1600 const param_type = (try parseParamType(arena, it, tree)) orelse return null;
1601
1602 switch (param_type) {
1603 .None => {
1604 if (name_token != null)
1605 try tree.errors.push(Error{
1606 .ExpectedParamType = Error.ExpectedParamType{ .token = it.peek().?.start },
1607 });
1608 return null;
1609 },
1610 else => {},
1611 }
1612
1613 const param_decl = try arena.create(Node.ParamDecl);
1614 param_decl.* = Node.ParamDecl{
1615 .base = Node{ .id = .ParamDecl },
1616 .doc_comments = null,
1617 .comptime_token = comptime_token,
1618 .noalias_token = noalias_token,
1619 .name_token = name_token,
1620 .type_node = undefined, // TODO: ok that this remains undefined when ... is found?
1621 .var_args_token = null,
1622 };
1623 switch (param_type) {
1624 .VarType => |node| param_decl.type_node = node,
1625 .TypeExpr => |node| param_decl.type_node = node,
1626 .VarArgs => |token| param_decl.var_args_token = token,
1627 else => unreachable,
1628 }
1629 return &param_decl.base;
1630}
1631
1632// ParamType
1633// <- KEYWORD_var
1634// / DOT3
1635// / TypeExpr
1636fn parseParamType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?ParamType {
1637 if (eatToken(it, .Keyword_var)) |token| {
1638 const node = try arena.create(Node.VarType);
1639 node.* = Node.VarType{
1640 .base = Node{ .id = .VarType },
1641 .token = token,
1642 };
1643 return ParamType{ .VarType = &node.base };
1644 }
1645 if (eatToken(it, .Ellipsis3)) |token| return ParamType{ .VarArgs = token };
1646 if (try parseTypeExpr(arena, it, tree)) |node| return ParamType{ .TypeExpr = node };
1647 return null;
1648}
1649
1650const ParamType = union(enum) {
1651 VarType: *Node,
1652 VarArgs: TokenIndex,
1653 TypeExpr: *Node,
1654 None,
1655};
1656
1657// IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
1658fn parseIfPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1659 const if_token = eatToken(it, .Keyword_if) orelse return null;
1660 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1661 const condition = (try expectNode(arena, it, tree, parseExpr, Error{
1662 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1663 })) orelse return null;
1664 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1665 const payload = try parsePtrPayload(arena, it, tree);
1666
1667 const node = try arena.create(Node.If);
1668 node.* = Node.If{
1669 .base = Node{ .id = .If },
1670 .if_token = if_token,
1671 .condition = condition,
1672 .payload = payload,
1673 .body = undefined, // set by caller
1674 .@"else" = null,
1675 };
1676 return &node.base;
1677}
1678
1679// WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
1680fn parseWhilePrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1681 const while_token = eatToken(it, .Keyword_while) orelse return null;
1682
1683 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1684 const condition = (try expectNode(arena, it, tree, parseExpr, Error{
1685 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1686 })) orelse return null;
1687 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1688
1689 const payload = try parsePtrPayload(arena, it, tree);
1690 const continue_expr = try parseWhileContinueExpr(arena, it, tree);
1691
1692 const node = try arena.create(Node.While);
1693 node.* = Node.While{
1694 .base = Node{ .id = .While },
1695 .label = null,
1696 .inline_token = null,
1697 .while_token = while_token,
1698 .condition = condition,
1699 .payload = payload,
1700 .continue_expr = continue_expr,
1701 .body = undefined, // set by caller
1702 .@"else" = null,
1703 };
1704 return &node.base;
1705}
1706
1707// ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
1708fn parseForPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1709 const for_token = eatToken(it, .Keyword_for) orelse return null;
1710
1711 _ = (try expectToken(it, tree, .LParen)) orelse return null;
1712 const array_expr = (try expectNode(arena, it, tree, parseExpr, Error{
1713 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1714 })) orelse return null;
1715 _ = (try expectToken(it, tree, .RParen)) orelse return null;
1716
1717 const payload = (try expectNode(arena, it, tree, parsePtrIndexPayload, Error{
1718 // TODO
1719 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
1720 })) orelse return null;
1721
1722 const node = try arena.create(Node.For);
1723 node.* = Node.For{
1724 .base = Node{ .id = .For },
1725 .label = null,
1726 .inline_token = null,
1727 .for_token = for_token,
1728 .array_expr = array_expr,
1729 .payload = payload, // TODO: why is this field optional?
1730 .body = undefined, // set by caller
1731 .@"else" = null,
1732 };
1733 return &node.base;
1734}
1735
1736// Payload <- PIPE IDENTIFIER PIPE
1737fn parsePayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1738 const lpipe = eatToken(it, .Pipe) orelse return null;
1739 const identifier = (try expectNode(arena, it, tree, parseIdentifier, Error{
1740 .ExpectedIdentifier = Error.ExpectedIdentifier{ .token = it.peek().?.start },
1741 })) orelse return null;
1742 const rpipe = (try expectToken(it, tree, .Pipe)) orelse return null;
1743
1744 const node = try arena.create(Node.Payload);
1745 node.* = Node.Payload{
1746 .base = Node{ .id = .Payload },
1747 .lpipe = lpipe,
1748 .error_symbol = identifier,
1749 .rpipe = rpipe,
1750 };
1751 return &node.base;
1752}
1753
1754// PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
1755fn parsePtrPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1756 const lpipe = eatToken(it, .Pipe) orelse return null;
1757 const asterisk = eatToken(it, .Asterisk);
1758 const identifier = (try expectNode(arena, it, tree, parseIdentifier, Error{
1759 .ExpectedIdentifier = Error.ExpectedIdentifier{ .token = it.peek().?.start },
1760 })) orelse return null;
1761 const rpipe = (try expectToken(it, tree, .Pipe)) orelse return null;
1762
1763 const node = try arena.create(Node.PointerPayload);
1764 node.* = Node.PointerPayload{
1765 .base = Node{ .id = .PointerPayload },
1766 .lpipe = lpipe,
1767 .ptr_token = asterisk,
1768 .value_symbol = identifier,
1769 .rpipe = rpipe,
1770 };
1771 return &node.base;
1772}
1773
1774// PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
1775fn parsePtrIndexPayload(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1776 const lpipe = eatToken(it, .Pipe) orelse return null;
1777 const asterisk = eatToken(it, .Asterisk);
1778 const index = blk: {
1779 if (eatToken(it, .Asterisk) == null) break :blk null;
1780 break :blk (try expectNode(arena, it, tree, parseIdentifier, Error{
1781 .ExpectedIdentifier = Error.ExpectedIdentifier{ .token = it.peek().?.start },
1782 })) orelse return null;
1783 };
1784 const identifier = (try expectNode(arena, it, tree, parseIdentifier, Error{
1785 .ExpectedIdentifier = Error.ExpectedIdentifier{ .token = it.peek().?.start },
1786 })) orelse return null;
1787 const rpipe = (try expectToken(it, tree, .Pipe)) orelse return null;
1788
1789 const node = try arena.create(Node.PointerIndexPayload);
1790 node.* = Node.PointerIndexPayload{
1791 .base = Node{ .id = .PointerIndexPayload },
1792 .lpipe = lpipe,
1793 .ptr_token = asterisk,
1794 .value_symbol = identifier,
1795 .index_symbol = index,
1796 .rpipe = rpipe,
1797 };
1798 return &node.base;
1799}
1800
1801// SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
1802fn parseSwitchProng(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1803 const node = (try parseSwitchCase(arena, it, tree)) orelse return null;
1804 const arrow = (try expectToken(it, tree, .EqualAngleBracketRight)) orelse return null;
1805 const payload = try parsePtrPayload(arena, it, tree);
1806 const expr = (try expectNode(arena, it, tree, parseAssignExpr, Error{
1807 .ExpectedExprOrAssignment = Error.ExpectedExprOrAssignment{ .token = it.peek().?.start },
1808 })) orelse return null;
1809
1810 const switch_case = node.cast(Node.SwitchCase).?;
1811 switch_case.arrow_token = arrow;
1812 switch_case.payload = payload;
1813 switch_case.expr = expr;
1814
1815 return node;
1816}
1817
1818// SwitchCase
1819// <- SwitchItem (COMMA SwitchItem)* COMMA?
1820// / KEYWORD_else
1821fn parseSwitchCase(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1822 var list = Node.SwitchCase.ItemList.init(arena);
1823
1824 if (try parseSwitchItem(arena, it, tree)) |first_item| {
1825 try list.push(first_item);
1826 while (eatToken(it, .Comma) != null) {
1827 const next_item = (try parseSwitchItem(arena, it, tree)) orelse break;
1828 try list.push(next_item);
1829 }
1830 } else if (eatToken(it, .Keyword_else)) |else_token| {
1831 const else_node = try arena.create(Node.SwitchElse);
1832 else_node.* = Node.SwitchElse{
1833 .base = Node{ .id = .SwitchElse },
1834 .token = else_token,
1835 };
1836 try list.push(&else_node.base);
1837 } else return null;
1838
1839 const node = try arena.create(Node.SwitchCase);
1840 node.* = Node.SwitchCase{
1841 .base = Node{ .id = .SwitchCase },
1842 .items = list,
1843 .arrow_token = undefined, // set by caller
1844 .payload = null,
1845 .expr = undefined, // set by caller
1846 };
1847 return &node.base;
1848}
1849
1850// SwitchItem <- Expr (DOT3 Expr)?
1851fn parseSwitchItem(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1852 const expr = (try parseExpr(arena, it, tree)) orelse return null;
1853 if (eatToken(it, .Ellipsis3)) |token| {
1854 const range_end = (try expectNode(arena, it, tree, parseExpr, Error{
1855 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
1856 })) orelse return null;
1857
1858 const node = try arena.create(Node.InfixOp);
1859 node.* = Node.InfixOp{
1860 .base = Node{ .id = .InfixOp },
1861 .op_token = token,
1862 .lhs = expr,
1863 .op = Node.InfixOp.Op{ .Range = {} },
1864 .rhs = range_end,
1865 };
1866 return &node.base;
1867 }
1868 return expr;
1869}
1870
1871// AssignOp
1872// <- ASTERISKEQUAL
1873// / SLASHEQUAL
1874// / PERCENTEQUAL
1875// / PLUSEQUAL
1876// / MINUSEQUAL
1877// / LARROW2EQUAL
1878// / RARROW2EQUAL
1879// / AMPERSANDEQUAL
1880// / CARETEQUAL
1881// / PIPEEQUAL
1882// / ASTERISKPERCENTEQUAL
1883// / PLUSPERCENTEQUAL
1884// / MINUSPERCENTEQUAL
1885// / EQUAL
1886fn parseAssignOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1887 return error.NotImplemented; // TODO
1888}
1889
1890// CompareOp
1891// <- EQUALEQUAL
1892// / EXCLAMATIONMARKEQUAL
1893// / LARROW
1894// / RARROW
1895// / LARROWEQUAL
1896// / RARROWEQUAL
1897fn parseCompareOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1898 const ops = Node.InfixOp.Op;
1899
1900 const token = nextNonCommentToken(it);
1901 const op = switch (token.ptr.id) {
1902 .EqualEqual => ops{ .EqualEqual = {} },
1903 .BangEqual => ops{ .BangEqual = {} },
1904 .AngleBracketLeft => ops{ .LessThan = {} },
1905 .AngleBracketRight => ops{ .GreaterThan = {} },
1906 .AngleBracketLeftEqual => ops{ .LessOrEqual = {} },
1907 .AngleBracketRightEqual => ops{ .GreaterOrEqual = {} },
1908 else => {
1909 _ = rewindTokenIterator(it);
1910 return null;
1911 },
1912 };
1913
1914 return try createInfixOp(arena, it.index, op);
1915}
1916
1917// BitwiseOp
1918// <- AMPERSAND
1919// / CARET
1920// / PIPE
1921// / KEYWORD_orelse
1922// / KEYWORD_catch Payload?
1923fn parseBitwiseOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1924 const ops = Node.InfixOp.Op;
1925
1926 const token = nextNonCommentToken(it);
1927 const op = switch (token.ptr.id) {
1928 .Ampersand => ops{ .BitAnd = {} },
1929 .Caret => ops{ .BitXor = {} },
1930 .Pipe => ops{ .BitOr = {} },
1931 .Keyword_orelse => ops{ .UnwrapOptional = {} },
1932 .Keyword_catch => ops{ .Catch = try parsePayload(arena, it, tree) },
1933 else => {
1934 _ = rewindTokenIterator(it);
1935 return null;
1936 },
1937 };
1938
1939 return try createInfixOp(arena, it.index, op);
1940}
1941
1942// BitShiftOp
1943// <- LARROW2
1944// / RARROW2
1945fn parseBitShiftOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1946 const ops = Node.InfixOp.Op;
1947
1948 const token = nextNonCommentToken(it);
1949 const op = switch (token.ptr.id) {
1950 .AngleBracketAngleBracketLeft => ops{ .BitShiftLeft = {} },
1951 .AngleBracketAngleBracketRight => ops{ .BitShiftRight = {} },
1952 else => {
1953 _ = rewindTokenIterator(it);
1954 return null;
1955 },
1956 };
1957
1958 return try createInfixOp(arena, it.index, op);
1959}
1960
1961// AdditionOp
1962// <- PLUS
1963// / MINUS
1964// / PLUS2
1965// / PLUSPERCENT
1966// / MINUSPERCENT
1967fn parseAdditionOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1968 const ops = Node.InfixOp.Op;
1969
1970 const token = nextNonCommentToken(it);
1971 const op = switch (token.ptr.id) {
1972 .Plus => ops{ .Add = {} },
1973 .Minus => ops{ .Sub = {} },
1974 .PlusPlus => ops{ .ArrayCat = {} },
1975 .PlusPercent => ops{ .AddWrap = {} },
1976 .MinusPercent => ops{ .SubWrap = {} },
1977 else => {
1978 _ = rewindTokenIterator(it);
1979 return null;
1980 },
1981 };
1982
1983 return try createInfixOp(arena, it.index, op);
1984}
1985
1986// MultiplyOp
1987// <- PIPE2
1988// / ASTERISK
1989// / SLASH
1990// / PERCENT
1991// / ASTERISK2
1992// / ASTERISKPERCENT
1993fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1994 const ops = Node.InfixOp.Op;
1995
1996 const token = nextNonCommentToken(it);
1997 const op = switch (token.ptr.id) {
1998 .PipePipe => ops{ .BoolOr = {} },
1999 .Asterisk => ops{ .Mult = {} },
2000 .Slash => ops{ .Div = {} },
2001 .Percent => ops{ .Mod = {} },
2002 .AsteriskAsterisk => ops{ .ArrayMult = {} },
2003 .AsteriskPercent => ops{ .MultWrap = {} },
2004 else => {
2005 _ = rewindTokenIterator(it);
2006 return null;
2007 },
2008 };
2009
2010 return try createInfixOp(arena, it.index, op);
2011}
2012
2013// PrefixOp
2014// <- EXCLAMATIONMARK
2015// / MINUS
2016// / TILDE
2017// / MINUSPERCENT
2018// / AMPERSAND
2019// / KEYWORD_try
2020// / KEYWORD_await
2021fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2022 const ops = Node.PrefixOp.Op;
2023
2024 const token = nextNonCommentToken(it);
2025 const op = switch (token.ptr.id) {
2026 .Bang => ops{ .BoolNot = {} },
2027 .Minus => ops{ .Negation = {} },
2028 .Tilde => ops{ .BitNot = {} },
2029 .MinusPercent => ops{ .NegationWrap = {} },
2030 .Ampersand => ops{ .AddressOf = {} },
2031 .Keyword_try => ops{ .Try = {} },
2032 .Keyword_await => ops{ .Await = {} },
2033 else => {
2034 _ = rewindTokenIterator(it);
2035 return null;
2036 },
2037 };
2038
2039 const node = try arena.create(Node.PrefixOp);
2040 node.* = Node.PrefixOp{
2041 .base = Node{ .id = .PrefixOp },
2042 .op_token = it.index,
2043 .op = op,
2044 .rhs = undefined,
2045 };
2046 return &node.base;
2047}
2048
2049// TODO: last choice allows for `*const volatile volatile const`, `*align(4) align(8) align(4)` etc.
2050// PrefixTypeOp
2051// <- QUESTIONMARK
2052// / KEYWORD_promise MINUSRARROW
2053// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)*
2054// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)*
2055fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2056 if (eatToken(it, .QuestionMark)) |token| {
2057 const node = try arena.create(Node.PrefixOp);
2058 node.* = Node.PrefixOp{
2059 .base = Node{ .id = .PrefixOp },
2060 .op_token = token,
2061 .op = Node.PrefixOp.Op.OptionalType,
2062 .rhs = undefined, // set by caller
2063 };
2064 return &node.base;
2065 }
2066
2067 if (eatToken(it, .Keyword_promise)) |token| {
2068 const arrow = (try expectToken(it, tree, .Arrow)) orelse return null;
2069 const node = try arena.create(Node.PromiseType);
2070 node.* = Node.PromiseType{
2071 .base = Node{ .id = .PromiseType },
2072 .promise_token = token,
2073 .result = null,
2074 };
2075 return &node.base;
2076 }
2077
2078 if (try parseArrayTypeStart(arena, it, tree)) |node| {
2079 // TODO: Set node.rhs
2080 while (true) {
2081 if (try parseByteAlign(arena, it, tree)) |byte_align| {
2082 // TODO
2083 continue;
2084 }
2085
2086 if (eatToken(it, .Keyword_const)) |const_token| {
2087 // TODO
2088 continue;
2089 }
2090
2091 if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2092 // TODO
2093 continue;
2094 }
2095
2096 break;
2097 }
2098 // return null;
2099 return error.NotImplemented;
2100 }
2101
2102 if (try parsePtrTypeStart(arena, it, tree)) |node| {
2103 while (true) {
2104 // TODO: allowzero
2105 if (eatToken(it, .Keyword_align)) |align_token| {
2106 const lparen = (try expectToken(it, tree, .LParen)) orelse return null;
2107 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
2108 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2109 })) orelse return null;
2110
2111 // Optional bit range
2112 const bit_range = if (eatToken(it, .Colon)) |_| bit_range_value: {
2113 const range_start = (try expectNode(arena, it, tree, parseIntegerLiteral, Error{
2114 .ExpectedIntegerLiteral = Error.ExpectedIntegerLiteral{ .token = it.peek().?.start },
2115 })) orelse return null;
2116 _ = (try expectToken(it, tree, .Colon)) orelse return null;
2117 const range_end = (try expectNode(arena, it, tree, parseIntegerLiteral, Error{
2118 .ExpectedIntegerLiteral = Error.ExpectedIntegerLiteral{ .token = it.peek().?.start },
2119 })) orelse return null;
2120
2121 break :bit_range_value Node.PrefixOp.PtrInfo.Align.BitRange{
2122 .start = range_start,
2123 .end = range_end,
2124 };
2125 } else null;
2126 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2127
2128 node.cast(Node.PrefixOp).?.op.PtrType.align_info = Node.PrefixOp.PtrInfo.Align{
2129 .node = expr_node,
2130 .bit_range = bit_range,
2131 };
2132
2133 continue;
2134 } else if (eatToken(it, .Keyword_const)) |const_token| ptr_info_value: {
2135 node.cast(Node.PrefixOp).?.op.PtrType.const_token = const_token;
2136 continue;
2137 } else if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2138 node.cast(Node.PrefixOp).?.op.PtrType.volatile_token = volatile_token;
2139 continue;
2140 }
2141 break;
2142 }
2143 }
2144
2145 return null;
2146}
2147
2148// SuffixOp
2149// <- LBRACKET Expr (DOT2 Expr?)? RBRACKET
2150// / DOT IDENTIFIER
2151// / DOTASTERISK
2152// / DOTQUESTIONMARK
2153fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2154 if (eatToken(it, .LBracket)) |_| {
2155 const expr_node = (try expectNode(arena, it, tree, parseExpr, Error{
2156 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2157 })) orelse return null;
2158 const dots = eatToken(it, .Ellipsis2);
2159 const expr = if (dots) |_| try parseExpr(arena, it, tree) else null;
2160 _ = (try expectToken(it, tree, .RBracket)) orelse return null;
2161 return error.NotImplemented; // TODO
2162 }
2163
2164 if (eatToken(it, .Period)) |_| {
2165 const identifier = (try expectToken(it, tree, .Identifier)) orelse return null;
2166 return error.NotImplemented; // TODO
2167 }
2168
2169 if (eatToken(it, .Period)) |period| {
2170 if (eatToken(it, .Asterisk)) |asterisk| {
2171 const node = try arena.create(Node.SuffixOp);
2172 node.* = Node.SuffixOp{
2173 .base = Node{ .id = .SuffixOp },
2174 .lhs = undefined, // TODO
2175 .op = Node.SuffixOp.Op.Deref,
2176 .rtoken = undefined, // TODO
2177 };
2178 return &node.base;
2179 }
2180 if (eatToken(it, .QuestionMark)) |question_mark| {
2181 const node = try arena.create(Node.SuffixOp);
2182 node.* = Node.SuffixOp{
2183 .base = Node{ .id = .SuffixOp },
2184 .lhs = undefined, // TODO
2185 .op = Node.SuffixOp.Op.UnwrapOptional,
2186 .rtoken = undefined, // TODO
2187 };
2188 return &node.base;
2189 }
2190 try tree.errors.push(Error{
2191 .ExpectedDerefOrUnwrap = Error.ExpectedDerefOrUnwrap{ .token = it.peek().?.start },
2192 });
2193 return null;
2194 }
2195
2196 return null;
2197}
2198
2199// AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
2200fn parseAsyncPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2201 const async_token = eatToken(it, .Keyword_async) orelse return null;
2202 var rangle_bracket: ?TokenIndex = null;
2203 const expr_node = if (eatToken(it, .AngleBracketLeft)) |_| blk: {
2204 const prefix_expr = (try expectNode(arena, it, tree, parsePrefixExpr, Error{
2205 .ExpectedPrefixExpr = Error.ExpectedPrefixExpr{ .token = it.peek().?.start },
2206 })) orelse return null;
2207 rangle_bracket = (try expectToken(it, tree, .AngleBracketRight)) orelse return null;
2208 break :blk prefix_expr;
2209 } else null;
2210
2211 const node = try arena.create(Node.AsyncAttribute);
2212 node.* = Node.AsyncAttribute{
2213 .base = Node{ .id = .AsyncAttribute },
2214 .async_token = async_token,
2215 .allocator_type = expr_node,
2216 .rangle_bracket = rangle_bracket,
2217 };
2218 return &node.base;
2219}
2220
2221// FnCallArguments <- LPAREN ExprList RPAREN
2222// ExprList <- (Expr COMMA)* Expr?
2223fn parseFnCallArguments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?Node.SuffixOp.Op.Call.ParamList {
2224 if (eatToken(it, .LParen) == null) return null;
2225 const list = try ListParser(Node.SuffixOp.Op.Call.ParamList, parseExpr).parse(arena, it, tree);
2226 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2227 return list;
2228}
2229
2230// ArrayTypeStart <- LBRACKET Expr? RBRACKET
2231fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2232 const lbracket = eatToken(it, .LBracket) orelse return null;
2233 const expr = (try parseExpr(arena, it, tree)) orelse return null;
2234 const rbracket = (try expectToken(it, tree, .RBracket)) orelse return null;
2235
2236 const node = try arena.create(Node.PrefixOp);
2237 node.* = Node.PrefixOp{
2238 .base = Node{ .id = .PrefixOp },
2239 .op_token = lbracket,
2240 .op = Node.PrefixOp.Op{ .ArrayType = expr },
2241 .rhs = undefined, // set by caller
2242 };
2243 return &node.base;
2244}
2245
2246// PtrTypeStart
2247// <- ASTERISK
2248// / ASTERISK2
2249// / PTRUNKNOWN
2250// / PTRC
2251fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2252 const token = eatToken(it, .Asterisk) orelse
2253 eatToken(it, .AsteriskAsterisk) orelse
2254 eatToken(it, .BracketStarBracket) orelse
2255 eatToken(it, .BracketStarCBracket) orelse
2256 null;
2257
2258 if (token) |op_token| {
2259 const node = try arena.create(Node.PrefixOp);
2260 node.* = Node.PrefixOp{
2261 .base = Node{ .id = .PrefixOp },
2262 .op_token = op_token,
2263 .op = Node.PrefixOp.Op{
2264 .PtrType = Node.PrefixOp.PtrInfo{
2265 .allowzero_token = null,
2266 .align_info = null,
2267 .const_token = null,
2268 .volatile_token = null,
2269 },
2270 },
2271 .rhs = undefined, // set by caller
2272 };
2273 return &node.base;
2274 } else return null;
2275 // TODO: zig fmt allows expression body of `if` on its own line, but forces the expression
2276 // body of an `else if` to be all on the same line
2277}
2278
2279// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
2280fn parseContainerDeclAuto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2281 const node = (try parseContainerDeclType(arena, it, tree)) orelse return null;
2282 const lbrace = (try expectToken(it, tree, .LBrace)) orelse return null;
2283 const kind = it.list.at(node.cast(Node.ContainerDecl).?.kind_token).id;
2284 const members = (try parseContainerMembers(arena, it, tree, kind)) orelse return null;
2285 const rbrace = (try expectToken(it, tree, .RBrace)) orelse return null;
2286
2287 const decl_type = node.cast(Node.ContainerDecl).?;
2288 decl_type.fields_and_decls = members;
2289 decl_type.lbrace_token = lbrace;
2290 decl_type.rbrace_token = rbrace;
2291
2292 return node;
2293}
2294
2295// ContainerDeclType
2296// <- (KEYWORD_struct / KEYWORD_enum) (LPAREN Expr RPAREN)?
2297// / KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
2298fn parseContainerDeclType(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2299 const container_type = eatToken(it, .Keyword_struct) orelse eatToken(it, .Keyword_enum);
2300 if (container_type) |kind_token| {
2301 // TODO: https://github.com/ziglang/zig/issues/2330
2302 const init_arg_expr = if (eatToken(it, .LParen) != null) blk: {
2303 const expr = (try expectNode(arena, it, tree, parseExpr, Error{
2304 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2305 })) orelse return null;
2306 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2307 break :blk Node.ContainerDecl.InitArg{ .Type = expr };
2308 } else Node.ContainerDecl.InitArg{ .None = {} };
2309
2310 const node = try arena.create(Node.ContainerDecl);
2311 node.* = Node.ContainerDecl{
2312 .base = Node{ .id = .ContainerDecl },
2313 .layout_token = null,
2314 .kind_token = kind_token,
2315 .init_arg_expr = init_arg_expr,
2316 .fields_and_decls = undefined, // set by caller
2317 .lbrace_token = undefined, // set by caller
2318 .rbrace_token = undefined, // set by caller
2319 };
2320 return &node.base;
2321 }
2322
2323 if (eatToken(it, .Keyword_union)) |kind_token| {
2324 const init_arg_expr = if (eatToken(it, .LParen) != null) set_init_arg: {
2325 if (eatToken(it, .Keyword_enum) != null) {
2326 const enum_expr = if (eatToken(it, .LParen) != null) set_enum_expr: {
2327 const expr = (try expectNode(arena, it, tree, parseExpr, Error{
2328 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2329 })) orelse return null;
2330 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2331 break :set_enum_expr expr;
2332 } else null;
2333 break :set_init_arg Node.ContainerDecl.InitArg{ .Enum = enum_expr };
2334 }
2335
2336 const expr = (try expectNode(arena, it, tree, parseExpr, Error{
2337 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2338 })) orelse return null;
2339 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2340 break :set_init_arg Node.ContainerDecl.InitArg{ .Type = expr };
2341 } else Node.ContainerDecl.InitArg{ .None = {} };
2342
2343 const node = try arena.create(Node.ContainerDecl);
2344 node.* = Node.ContainerDecl{
2345 .base = Node{ .id = .ContainerDecl },
2346 .layout_token = null,
2347 .kind_token = kind_token,
2348 .init_arg_expr = init_arg_expr,
2349 .fields_and_decls = undefined, // set by caller
2350 .lbrace_token = undefined, // set by caller
2351 .rbrace_token = undefined, // set by caller
2352 };
2353 return &node.base;
2354 }
2355
2356 return null;
2357}
2358
2359// ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
2360fn parseByteAlign(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2361 const align_token = eatToken(it, .Keyword_align) orelse return null;
2362 _ = (try expectToken(it, tree, .LParen)) orelse return null;
2363 const align_expr = (try expectNode(arena, it, tree, parseExpr, Error{
2364 .ExpectedExpr = Error.ExpectedExpr{ .token = it.peek().?.start },
2365 })) orelse return null;
2366 _ = (try expectToken(it, tree, .RParen)) orelse return null;
2367
2368 const node = try arena.create(Node.PrefixOp);
2369 node.* = Node.PrefixOp{
2370 .base = Node{ .id = .PrefixOp },
2371 .op_token = align_token,
2372 .op = Node.PrefixOp.Op{
2373 .PtrType = Node.PrefixOp.PtrInfo{
2374 .allowzero_token = null,
2375 .align_info = Node.PrefixOp.PtrInfo.Align{
2376 .node = align_expr,
2377 .bit_range = null,
2378 },
2379 .const_token = null,
2380 .volatile_token = null,
2381 },
2382 },
2383 .rhs = undefined, // set by caller
2384 };
2385
2386 return &node.base;
2387}
2388
2389// IdentifierList <- (IDENTIFIER COMMA)* IDENTIFIER?
2390fn parseIdentifierList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.ErrorSetDecl.DeclList {
2391 // ErrorSetDecl.DeclList is used since ErrorSetDecl is the only caller of this function.
2392 return try ListParser(Node.ErrorSetDecl.DeclList, parseIdentifier).parse(arena, it, tree);
2393}
2394
2395// SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
2396fn parseSwitchProngList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Switch.CaseList {
2397 return try ListParser(Node.Switch.CaseList, parseSwitchProng).parse(arena, it, tree);
2398}
2399
2400// AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem?
2401fn parseAsmOutputList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2402 return try ListParser(Node.Asm.OutputList, parseAsmOutputItem).parse(arena, it, tree);
2403}
2404
2405// AsmInputList <- (AsmInputItem COMMA)* AsmInputItem?
2406fn parseAsmInputList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2407 return try ListParser(Node.Asm.InputList, parseAsmInputItem).parse(arena, it, tree);
2408}
2409
2410// ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
2411fn parseParamDeclList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.FnProto.ParamList {
2412 return try ListParser(Node.FnProto.ParamList, parseParamDecl).parse(arena, it, tree);
2413}
2414
2415// TODO: don't use anyerror
2416const ParseFn = fn (*Allocator, *TokenIterator, *Tree) anyerror!?*Node;
2417
2418// Helper parsers not included in the grammar
2419
2420fn parseIdentifier(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2421 const token = eatToken(it, .Identifier) orelse return null;
2422 const node = try arena.create(Node.Identifier);
2423 node.* = Node.Identifier{
2424 .base = Node{ .id = .Identifier },
2425 .token = token,
2426 };
2427 return &node.base;
2428}
2429
2430fn createLiteral(arena: *Allocator, comptime T: type, token: TokenIndex) !*Node {
2431 const result = try arena.create(T);
2432 result.* = T{
2433 .base = Node{ .id = Node.typeToId(T) },
2434 .token = token,
2435 };
2436 return &result.base;
2437}
2438
2439// string literal or multiline string literal
2440fn parseStringLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2441 if (eatToken(it, .StringLiteral)) |token| {
2442 const node = try arena.create(Node.StringLiteral);
2443 node.* = Node.StringLiteral{
2444 .base = Node{ .id = .StringLiteral },
2445 .token = token,
2446 };
2447 return &node.base;
2448 }
2449
2450 if (eatToken(it, .MultilineStringLiteralLine)) |first_line| {
2451 const node = try arena.create(Node.MultilineStringLiteral);
2452 node.* = Node.MultilineStringLiteral{
2453 .base = Node{ .id = .MultilineStringLiteral },
2454 .lines = Node.MultilineStringLiteral.LineList.init(arena),
2455 };
2456 try node.lines.push(first_line);
2457 while (eatToken(it, .MultilineStringLiteralLine)) |line|
2458 try node.lines.push(line);
2459
2460 return &node.base;
2461 }
2462
2463 return null;
2464}
2465
2466fn parseIntegerLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2467 const token = eatToken(it, .IntegerLiteral) orelse return null;
2468 const node = try arena.create(Node.IntegerLiteral);
2469 node.* = Node.IntegerLiteral{
2470 .base = Node{ .id = .IntegerLiteral },
2471 .token = token,
2472 };
2473 return &node.base;
2474}
2475
2476fn parseFloatLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2477 const token = eatToken(it, .FloatLiteral) orelse return null;
2478 const node = try arena.create(Node.FloatLiteral);
2479 node.* = Node.FloatLiteral{
2480 .base = Node{ .id = .FloatLiteral },
2481 .token = token,
2482 };
2483 return &node.base;
2484}
2485
2486fn parseTry(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2487 const token = eatToken(it, .Keyword_try) orelse return null;
2488 const node = try arena.create(Node.PrefixOp);
2489 node.* = Node.PrefixOp{
2490 .base = Node{ .id = .PrefixOp },
2491 .op_token = token,
2492 .op = Node.PrefixOp.Op.Try,
2493 .rhs = undefined, // set by caller
2494 };
2495 return &node.base;
2496}
2497
2498fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2499 const token = eatToken(it, .Keyword_use) orelse return null;
2500 const node = try arena.create(Node.Use);
2501 node.* = Node.Use{
2502 .base = Node{ .id = .PrefixOp },
2503 .doc_comments = null,
2504 .visib_token = null,
2505 .use_token = token,
2506 .expr = undefined,
2507 .semicolon_token = undefined,
2508 };
2509 return &node.base;
2510}
2511
2512// Op* Child
2513fn parsePrefixOpExpr(
2514 arena: *Allocator,
2515 it: *TokenIterator,
2516 tree: *Tree,
2517 opParseFn: ParseFn,
2518 childParseFn: ParseFn,
2519) !?*Node {
2520 if (try opParseFn(arena, it, tree)) |op| {
2521 const child = (try expectNode(
2522 arena,
2523 it,
2524 tree,
2525 childParseFn,
2526 Error{
2527 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
2528 },
2529 )) orelse return null;
2530 op.cast(Node.PrefixOp).?.rhs = child;
2531 return op;
2532 }
2533 return childParseFn(arena, it, tree);
2534}
2535
2536// Child (Op Child)(*/?)
2537fn parseBinOpExpr(
2538 arena: *Allocator,
2539 it: *TokenIterator,
2540 tree: *Tree,
2541 opParseFn: ParseFn,
2542 childParseFn: ParseFn,
2543 chain: BinOpChain,
2544) !?*Node {
2545 var res = (try childParseFn(arena, it, tree)) orelse return null;
2546
2547 while (try opParseFn(arena, it, tree)) |node| {
2548 const right = (try expectNode(arena, it, tree, childParseFn, Error{
2549 .InvalidToken = Error.InvalidToken{ .token = it.peek().?.start },
2550 })) orelse return null;
2551 const left = res;
2552 res = node;
2553
2554 const op = node.cast(Node.InfixOp).?;
2555 op.*.lhs = left;
2556 op.*.rhs = right;
2557
2558 switch (chain) {
2559 .Once => break,
2560 .Infinitely => continue,
2561 }
2562 }
2563
2564 return res;
2565}
2566
2567fn SimpleBinOpParser(token: Token.Id, op: Node.InfixOp.Op) type {
2568 return struct {
2569 pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2570 const op_token = eatToken(it, token) orelse return null;
2571 const node = try arena.create(Node.InfixOp);
2572 node.* = Node.InfixOp{
2573 .base = Node{ .id = .InfixOp },
2574 .op_token = op_token,
2575 .lhs = undefined, // set by caller
2576 .op = op,
2577 .rhs = undefined, // set by caller
2578 };
2579 return &node.base;
2580 }
2581 };
2582}
2583
2584const BinOpChain = enum {
2585 Once,
2586 Infinitely,
2587};
2588
2589fn createInfixOp(arena: *Allocator, index: TokenIndex, op: Node.InfixOp.Op) !*Node {
2590 const node = try arena.create(Node.InfixOp);
2591 node.* = Node.InfixOp{
2592 .base = Node{ .id = .InfixOp },
2593 .op_token = index,
2594 .lhs = undefined,
2595 .op = op,
2596 .rhs = undefined,
2597 };
2598 return &node.base;
2599}
2600
2601fn eatToken(it: *TokenIterator, id: Token.Id) ?TokenIndex {
2602 return if (it.peek().?.id == id) nextNonCommentToken(it).index else null;
2603}
2604
2605fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) !?TokenIndex {
2606 const token = nextNonCommentToken(it);
2607 if (token.ptr.id != id) {
2608 try tree.errors.push(Error{
2609 .ExpectedToken = Error.ExpectedToken{ .token = token.index, .expected_id = id },
2610 });
2611 return null;
2612 }
2613 return token.index;
2614}
2615
2616fn nextNonCommentToken(it: *TokenIterator) AnnotatedToken {
2617 const result = AnnotatedToken{
2618 .index = it.index,
2619 .ptr = it.next().?,
2620 };
2621 assert(result.ptr.id != .LineComment);
2622
2623 while (true) {
2624 const next_tok = it.peek() orelse return result;
2625 if (next_tok.id != .LineComment) return result;
2626 _ = it.next();
2627 }
2628}
2629
2630fn rewindTokenIterator(it: *TokenIterator) void {
2631 while (true) {
2632 const prev_tok = it.prev() orelse return;
2633 if (prev_tok.id == .LineComment) continue;
2634 return;
2635 }
2636}
2637
2638const AnnotatedToken = struct {
2639 index: TokenIndex,
2640 ptr: *Token,
2641};
2642
2643fn expectNode(
2644 arena: *Allocator,
2645 it: *TokenIterator,
2646 tree: *Tree,
2647 parseFn: ParseFn,
2648 err: Error, // if parsing fails
2649) !?*Node {
2650 const node = try parseFn(arena, it, tree);
2651 if (node == null) try tree.errors.push(err);
2652 return node;
2653}
2654
2655fn ListParser(comptime L: type, comptime nodeParseFn: var) type {
2656 return struct {
2657 pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !L {
2658 var list = L.init(arena);
2659 while (try nodeParseFn(arena, it, tree)) |node| {
2660 try list.push(node);
2661 if (eatToken(it, .Colon) == null) break;
2662 }
2663 return list;
2664 }
2665 };
2666}
2667
2668test "std.zig.parser" {
2669 _ = @import("parser_test.zig");
2670}