authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-13 10:15:12+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-13 10:15:12+02:00
log44c53c9979e30653a109b07ee90ba57e3bc8a7df
tree8748ef5e8b26492c7bcb17ba2428a2a4e2f16768
parentfad54e62bb58937e82e5ca9c58b8b2066559e849

std.zig.parser: Refactor round 2

* More work on ensuring that each state only eat one token * VarDecl parsing now constructs its node * Handling all fn parsing in the same case * Using eatToken instead of getNextToken where possible * All tokenIdTo* now takes @TagType(Token.Id) * Added a createToCtxLiteral function

1 files changed, 410 insertions(+), 439 deletions(-)

std/zig/parser.zig+410-439
...@@ -59,12 +59,26 @@ pub const Parser = struct {...@@ -59,12 +59,26 @@ pub const Parser = struct {
59 lib_name: ?&ast.Node,59 lib_name: ?&ast.Node,
60 };60 };
6161
62 const VarDeclCtx = struct {
63 mut_token: Token,
64 visib_token: ?Token,
65 comptime_token: ?Token,
66 extern_export_token: ?Token,
67 lib_name: ?&ast.Node,
68 list: &ArrayList(&ast.Node),
69 };
70
62 const TopLevelExternOrFieldCtx = struct {71 const TopLevelExternOrFieldCtx = struct {
63 visib_token: Token,72 visib_token: Token,
64 container_decl: &ast.NodeContainerDecl,73 container_decl: &ast.NodeContainerDecl,
65 };74 };
6675
67 const ContainerExternCtx = struct {76 const ExternTypeCtx = struct {
77 opt_ctx: OptionalCtx,
78 extern_token: Token,
79 };
80
81 const ContainerKindCtx = struct {
68 opt_ctx: OptionalCtx,82 opt_ctx: OptionalCtx,
69 ltoken: Token,83 ltoken: Token,
70 layout: ast.NodeContainerDecl.Layout,84 layout: ast.NodeContainerDecl.Layout,
...@@ -80,15 +94,6 @@ pub const Parser = struct {...@@ -80,15 +94,6 @@ pub const Parser = struct {
80 ptr: &?Token,94 ptr: &?Token,
81 };95 };
8296
83 const RevertState = struct {
84 parser: Parser,
85 tokenizer: Tokenizer,
86
87 // We expect, that if something is optional, then there is a field,
88 // that needs to be set to null, when we revert.
89 ptr: &?&ast.Node,
90 };
91
92 const ExprListCtx = struct {97 const ExprListCtx = struct {
93 list: &ArrayList(&ast.Node),98 list: &ArrayList(&ast.Node),
94 end: Token.Id,99 end: Token.Id,
...@@ -102,6 +107,11 @@ pub const Parser = struct {...@@ -102,6 +107,11 @@ pub const Parser = struct {
102 };107 };
103 }108 }
104109
110 const MaybeLabeledExpressionCtx = struct {
111 label: Token,
112 opt_ctx: OptionalCtx,
113 };
114
105 const LabelCtx = struct {115 const LabelCtx = struct {
106 label: ?Token,116 label: ?Token,
107 opt_ctx: OptionalCtx,117 opt_ctx: OptionalCtx,
...@@ -179,12 +189,12 @@ pub const Parser = struct {...@@ -179,12 +189,12 @@ pub const Parser = struct {
179 TopLevelDecl: TopLevelDeclCtx,189 TopLevelDecl: TopLevelDeclCtx,
180 TopLevelExternOrField: TopLevelExternOrFieldCtx,190 TopLevelExternOrField: TopLevelExternOrFieldCtx,
181191
182 ContainerExtern: ContainerExternCtx,192 ContainerKind: ContainerKindCtx,
183 ContainerInitArgStart: &ast.NodeContainerDecl,193 ContainerInitArgStart: &ast.NodeContainerDecl,
184 ContainerInitArg: &ast.NodeContainerDecl,194 ContainerInitArg: &ast.NodeContainerDecl,
185 ContainerDecl: &ast.NodeContainerDecl,195 ContainerDecl: &ast.NodeContainerDecl,
186196
187 VarDecl: &ast.NodeVarDecl,197 VarDecl: VarDeclCtx,
188 VarDeclAlign: &ast.NodeVarDecl,198 VarDeclAlign: &ast.NodeVarDecl,
189 VarDeclEq: &ast.NodeVarDecl,199 VarDeclEq: &ast.NodeVarDecl,
190200
...@@ -199,6 +209,7 @@ pub const Parser = struct {...@@ -199,6 +209,7 @@ pub const Parser = struct {
199 ParamDeclEnd: ParamDeclEndCtx,209 ParamDeclEnd: ParamDeclEndCtx,
200 ParamDeclComma: &ast.NodeFnProto,210 ParamDeclComma: &ast.NodeFnProto,
201211
212 MaybeLabeledExpression: MaybeLabeledExpressionCtx,
202 LabeledExpression: LabelCtx,213 LabeledExpression: LabelCtx,
203 Inline: InlineCtx,214 Inline: InlineCtx,
204 While: LoopCtx,215 While: LoopCtx,
...@@ -209,7 +220,7 @@ pub const Parser = struct {...@@ -209,7 +220,7 @@ pub const Parser = struct {
209 Block: &ast.NodeBlock,220 Block: &ast.NodeBlock,
210 Statement: &ast.NodeBlock,221 Statement: &ast.NodeBlock,
211 ComptimeStatement: ComptimeStatementCtx,222 ComptimeStatement: ComptimeStatementCtx,
212 Semicolon: &const &const ast.Node,223 Semicolon: &&ast.Node,
213224
214 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),225 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
215 AsmOutputReturnOrType: &ast.NodeAsmOutput,226 AsmOutputReturnOrType: &ast.NodeAsmOutput,
...@@ -233,6 +244,7 @@ pub const Parser = struct {...@@ -233,6 +244,7 @@ pub const Parser = struct {
233 AsyncAllocator: &ast.NodeAsyncAttribute,244 AsyncAllocator: &ast.NodeAsyncAttribute,
234 AsyncEnd: AsyncEndCtx,245 AsyncEnd: AsyncEndCtx,
235246
247 ExternType: ExternTypeCtx,
236 SliceOrArrayAccess: &ast.NodeSuffixOp,248 SliceOrArrayAccess: &ast.NodeSuffixOp,
237 SliceOrArrayType: &ast.NodePrefixOp,249 SliceOrArrayType: &ast.NodePrefixOp,
238 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,250 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
...@@ -491,6 +503,7 @@ pub const Parser = struct {...@@ -491,6 +503,7 @@ pub const Parser = struct {
491 .lib_name = lib_name,503 .lib_name = lib_name,
492 },504 },
493 }) catch unreachable;505 }) catch unreachable;
506 continue;
494 },507 },
495 State.TopLevelDecl => |ctx| {508 State.TopLevelDecl => |ctx| {
496 const token = self.getNextToken();509 const token = self.getNextToken();
...@@ -524,49 +537,20 @@ pub const Parser = struct {...@@ -524,49 +537,20 @@ pub const Parser = struct {
524 }537 }
525 }538 }
526539
527 const var_decl_node = try self.createAttachNode(arena, ctx.decls, ast.NodeVarDecl,540 stack.append(State {
528 ast.NodeVarDecl {541 .VarDecl = VarDeclCtx {
529 .base = undefined,
530 .visib_token = ctx.visib_token,542 .visib_token = ctx.visib_token,
531 .mut_token = token,543 .lib_name = ctx.lib_name,
532 .comptime_token = null,544 .comptime_token = null,
533 .extern_export_token = ctx.extern_export_inline_token,545 .extern_export_token = ctx.extern_export_inline_token,
534 .type_node = null,546 .mut_token = token,
535 .align_node = null,547 .list = ctx.decls
536 .init_node = null,
537 .lib_name = ctx.lib_name,
538 // initialized later
539 .name_token = undefined,
540 .eq_token = undefined,
541 .semicolon_token = undefined,
542 }
543 );
544 stack.append(State { .VarDecl = var_decl_node }) catch unreachable;
545 continue;
546 },
547 Token.Id.Keyword_fn => {
548 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,
549 ast.NodeFnProto {
550 .base = undefined,
551 .visib_token = ctx.visib_token,
552 .name_token = null,
553 .fn_token = token,
554 .params = ArrayList(&ast.Node).init(arena),
555 .return_type = undefined,
556 .var_args_token = null,
557 .extern_export_inline_token = ctx.extern_export_inline_token,
558 .cc_token = null,
559 .async_attr = null,
560 .body_node = null,
561 .lib_name = ctx.lib_name,
562 .align_expr = null,
563 }548 }
564 );549 }) catch unreachable;
565 stack.append(State { .FnDef = fn_proto }) catch unreachable;
566 try stack.append(State { .FnProto = fn_proto });
567 continue;550 continue;
568 },551 },
569 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {552 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc,
553 Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {
570 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,554 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,
571 ast.NodeFnProto {555 ast.NodeFnProto {
572 .base = undefined,556 .base = undefined,
...@@ -577,7 +561,7 @@ pub const Parser = struct {...@@ -577,7 +561,7 @@ pub const Parser = struct {
577 .return_type = undefined,561 .return_type = undefined,
578 .var_args_token = null,562 .var_args_token = null,
579 .extern_export_inline_token = ctx.extern_export_inline_token,563 .extern_export_inline_token = ctx.extern_export_inline_token,
580 .cc_token = token,564 .cc_token = null,
581 .async_attr = null,565 .async_attr = null,
582 .body_node = null,566 .body_node = null,
583 .lib_name = ctx.lib_name,567 .lib_name = ctx.lib_name,
...@@ -586,52 +570,44 @@ pub const Parser = struct {...@@ -586,52 +570,44 @@ pub const Parser = struct {
586 );570 );
587 stack.append(State { .FnDef = fn_proto }) catch unreachable;571 stack.append(State { .FnDef = fn_proto }) catch unreachable;
588 try stack.append(State { .FnProto = fn_proto });572 try stack.append(State { .FnProto = fn_proto });
589 try stack.append(State {
590 .ExpectTokenSave = ExpectTokenSave {
591 .id = Token.Id.Keyword_fn,
592 .ptr = &fn_proto.fn_token,
593 }
594 });
595 continue;
596 },
597 Token.Id.Keyword_async => {
598 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
599 ast.NodeAsyncAttribute {
600 .base = undefined,
601 .async_token = token,
602 .allocator_type = null,
603 .rangle_bracket = null,
604 }
605 );
606573
607 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,574 switch (token.id) {
608 ast.NodeFnProto {575 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
609 .base = undefined,576 fn_proto.cc_token = token;
610 .visib_token = ctx.visib_token,577 try stack.append(State {
611 .name_token = null,578 .ExpectTokenSave = ExpectTokenSave {
612 .fn_token = undefined,579 .id = Token.Id.Keyword_fn,
613 .params = ArrayList(&ast.Node).init(arena),580 .ptr = &fn_proto.fn_token,
614 .return_type = undefined,581 }
615 .var_args_token = null,582 });
616 .extern_export_inline_token = ctx.extern_export_inline_token,583 continue;
617 .cc_token = null,584 },
618 .async_attr = async_node,585 Token.Id.Keyword_async => {
619 .body_node = null,586 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
620 .lib_name = ctx.lib_name,587 ast.NodeAsyncAttribute {
621 .align_expr = null,588 .base = undefined,
622 }589 .async_token = token,
623 );590 .allocator_type = null,
624 stack.append(State { .FnDef = fn_proto }) catch unreachable;591 .rangle_bracket = null,
625 try stack.append(State { .FnProto = fn_proto });592 }
626 try stack.append(State {593 );
627 .ExpectTokenSave = ExpectTokenSave {594 fn_proto.async_attr = async_node;
628 .id = Token.Id.Keyword_fn,
629 .ptr = &fn_proto.fn_token,
630 }
631 });
632595
633 try stack.append(State { .AsyncAllocator = async_node });596 try stack.append(State {
634 continue;597 .ExpectTokenSave = ExpectTokenSave {
598 .id = Token.Id.Keyword_fn,
599 .ptr = &fn_proto.fn_token,
600 }
601 });
602 try stack.append(State { .AsyncAllocator = async_node });
603 continue;
604 },
605 Token.Id.Keyword_fn => {
606 fn_proto.fn_token = token;
607 continue;
608 },
609 else => unreachable,
610 }
635 },611 },
636 else => {612 else => {
637 return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id));613 return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id));
...@@ -669,7 +645,7 @@ pub const Parser = struct {...@@ -669,7 +645,7 @@ pub const Parser = struct {
669 },645 },
670646
671647
672 State.ContainerExtern => |ctx| {648 State.ContainerKind => |ctx| {
673 const token = self.getNextToken();649 const token = self.getNextToken();
674 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeContainerDecl,650 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeContainerDecl,
675 ast.NodeContainerDecl {651 ast.NodeContainerDecl {
...@@ -697,6 +673,7 @@ pub const Parser = struct {...@@ -697,6 +673,7 @@ pub const Parser = struct {
697 stack.append(State { .ContainerDecl = node }) catch unreachable;673 stack.append(State { .ContainerDecl = node }) catch unreachable;
698 try stack.append(State { .ExpectToken = Token.Id.LBrace });674 try stack.append(State { .ExpectToken = Token.Id.LBrace });
699 try stack.append(State { .ContainerInitArgStart = node });675 try stack.append(State { .ContainerInitArgStart = node });
676 continue;
700 },677 },
701678
702 State.ContainerInitArgStart => |container_decl| {679 State.ContainerInitArgStart => |container_decl| {
...@@ -706,6 +683,7 @@ pub const Parser = struct {...@@ -706,6 +683,7 @@ pub const Parser = struct {
706683
707 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;684 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
708 try stack.append(State { .ContainerInitArg = container_decl });685 try stack.append(State { .ContainerInitArg = container_decl });
686 continue;
709 },687 },
710688
711 State.ContainerInitArg => |container_decl| {689 State.ContainerInitArg => |container_decl| {
...@@ -781,6 +759,7 @@ pub const Parser = struct {...@@ -781,6 +759,7 @@ pub const Parser = struct {
781 .container_decl = container_decl,759 .container_decl = container_decl,
782 }760 }
783 });761 });
762 continue;
784 },763 },
785 else => {764 else => {
786 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;765 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
...@@ -792,6 +771,7 @@ pub const Parser = struct {...@@ -792,6 +771,7 @@ pub const Parser = struct {
792 .lib_name = null,771 .lib_name = null,
793 }772 }
794 });773 });
774 continue;
795 }775 }
796 }776 }
797 },777 },
...@@ -828,7 +808,25 @@ pub const Parser = struct {...@@ -828,7 +808,25 @@ pub const Parser = struct {
828 },808 },
829809
830810
831 State.VarDecl => |var_decl| {811 State.VarDecl => |ctx| {
812 const var_decl = try self.createAttachNode(arena, ctx.list, ast.NodeVarDecl,
813 ast.NodeVarDecl {
814 .base = undefined,
815 .visib_token = ctx.visib_token,
816 .mut_token = ctx.mut_token,
817 .comptime_token = ctx.comptime_token,
818 .extern_export_token = ctx.extern_export_token,
819 .type_node = null,
820 .align_node = null,
821 .init_node = null,
822 .lib_name = ctx.lib_name,
823 // initialized later
824 .name_token = undefined,
825 .eq_token = undefined,
826 .semicolon_token = undefined,
827 }
828 );
829
832 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;830 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
833 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });831 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });
834 try stack.append(State { .IfToken = Token.Id.Colon });832 try stack.append(State { .IfToken = Token.Id.Colon });
...@@ -907,12 +905,9 @@ pub const Parser = struct {...@@ -907,12 +905,9 @@ pub const Parser = struct {
907 try stack.append(State { .ParamDecl = fn_proto });905 try stack.append(State { .ParamDecl = fn_proto });
908 try stack.append(State { .ExpectToken = Token.Id.LParen });906 try stack.append(State { .ExpectToken = Token.Id.LParen });
909907
910 const next_token = self.getNextToken();908 if (self.eatToken(Token.Id.Identifier)) |name_token| {
911 if (next_token.id == Token.Id.Identifier) {909 fn_proto.name_token = name_token;
912 fn_proto.name_token = next_token;
913 continue;
914 }910 }
915 self.putBackToken(next_token);
916 continue;911 continue;
917 },912 },
918 State.FnProtoAlign => |fn_proto| {913 State.FnProtoAlign => |fn_proto| {
...@@ -923,7 +918,6 @@ pub const Parser = struct {...@@ -923,7 +918,6 @@ pub const Parser = struct {
923 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } });918 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } });
924 try stack.append(State { .ExpectToken = Token.Id.LParen });919 try stack.append(State { .ExpectToken = Token.Id.LParen });
925 }920 }
926
927 continue;921 continue;
928 },922 },
929 State.FnProtoReturnType => |fn_proto| {923 State.FnProtoReturnType => |fn_proto| {
...@@ -987,6 +981,7 @@ pub const Parser = struct {...@@ -987,6 +981,7 @@ pub const Parser = struct {
987 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {981 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {
988 param_decl.noalias_token = noalias_token;982 param_decl.noalias_token = noalias_token;
989 }983 }
984 continue;
990 },985 },
991 State.ParamDeclName => |param_decl| {986 State.ParamDeclName => |param_decl| {
992 // TODO: Here, we eat two tokens in one state. This means that we can't have987 // TODO: Here, we eat two tokens in one state. This means that we can't have
...@@ -998,6 +993,7 @@ pub const Parser = struct {...@@ -998,6 +993,7 @@ pub const Parser = struct {
998 self.putBackToken(ident_token);993 self.putBackToken(ident_token);
999 }994 }
1000 }995 }
996 continue;
1001 },997 },
1002 State.ParamDeclEnd => |ctx| {998 State.ParamDeclEnd => |ctx| {
1003 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {999 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
...@@ -1010,6 +1006,7 @@ pub const Parser = struct {...@@ -1010,6 +1006,7 @@ pub const Parser = struct {
1010 try stack.append(State {1006 try stack.append(State {
1011 .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node }1007 .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node }
1012 });1008 });
1009 continue;
1013 },1010 },
1014 State.ParamDeclComma => |fn_proto| {1011 State.ParamDeclComma => |fn_proto| {
1015 if ((try self.expectCommaOrEnd(Token.Id.RParen)) == null) {1012 if ((try self.expectCommaOrEnd(Token.Id.RParen)) == null) {
...@@ -1018,7 +1015,20 @@ pub const Parser = struct {...@@ -1018,7 +1015,20 @@ pub const Parser = struct {
1018 continue;1015 continue;
1019 },1016 },
10201017
1018 State.MaybeLabeledExpression => |ctx| {
1019 if (self.eatToken(Token.Id.Colon)) |_| {
1020 stack.append(State {
1021 .LabeledExpression = LabelCtx {
1022 .label = ctx.label,
1023 .opt_ctx = ctx.opt_ctx,
1024 }
1025 }) catch unreachable;
1026 continue;
1027 }
10211028
1029 _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeIdentifier, ctx.label);
1030 continue;
1031 },
1022 State.LabeledExpression => |ctx| {1032 State.LabeledExpression => |ctx| {
1023 const token = self.getNextToken();1033 const token = self.getNextToken();
1024 switch (token.id) {1034 switch (token.id) {
...@@ -1134,11 +1144,13 @@ pub const Parser = struct {...@@ -1134,11 +1144,13 @@ pub const Parser = struct {
1134 try stack.append(State { .ExpectToken = Token.Id.RParen });1144 try stack.append(State { .ExpectToken = Token.Id.RParen });
1135 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });1145 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
1136 try stack.append(State { .ExpectToken = Token.Id.LParen });1146 try stack.append(State { .ExpectToken = Token.Id.LParen });
1147 continue;
1137 },1148 },
1138 State.WhileContinueExpr => |dest| {1149 State.WhileContinueExpr => |dest| {
1139 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;1150 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
1140 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } });1151 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } });
1141 try stack.append(State { .ExpectToken = Token.Id.LParen });1152 try stack.append(State { .ExpectToken = Token.Id.LParen });
1153 continue;
1142 },1154 },
1143 State.For => |ctx| {1155 State.For => |ctx| {
1144 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFor,1156 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFor,
...@@ -1159,26 +1171,26 @@ pub const Parser = struct {...@@ -1159,26 +1171,26 @@ pub const Parser = struct {
1159 try stack.append(State { .ExpectToken = Token.Id.RParen });1171 try stack.append(State { .ExpectToken = Token.Id.RParen });
1160 try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } });1172 try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } });
1161 try stack.append(State { .ExpectToken = Token.Id.LParen });1173 try stack.append(State { .ExpectToken = Token.Id.LParen });
1174 continue;
1162 },1175 },
1163 State.Else => |dest| {1176 State.Else => |dest| {
1164 const else_token = self.getNextToken();1177 if (self.eatToken(Token.Id.Keyword_else)) |else_token| {
1165 if (else_token.id != Token.Id.Keyword_else) {1178 const node = try self.createNode(arena, ast.NodeElse,
1166 self.putBackToken(else_token);1179 ast.NodeElse {
1180 .base = undefined,
1181 .else_token = else_token,
1182 .payload = null,
1183 .body = undefined,
1184 }
1185 );
1186 *dest = node;
1187
1188 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
1189 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
1190 continue;
1191 } else {
1167 continue;1192 continue;
1168 }1193 }
1169
1170 const node = try self.createNode(arena, ast.NodeElse,
1171 ast.NodeElse {
1172 .base = undefined,
1173 .else_token = else_token,
1174 .payload = null,
1175 .body = undefined,
1176 }
1177 );
1178 *dest = node;
1179
1180 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
1181 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
1182 },1194 },
11831195
11841196
...@@ -1207,26 +1219,19 @@ pub const Parser = struct {...@@ -1207,26 +1219,19 @@ pub const Parser = struct {
1207 .block = block,1219 .block = block,
1208 }1220 }
1209 }) catch unreachable;1221 }) catch unreachable;
1222 continue;
1210 },1223 },
1211 Token.Id.Keyword_var, Token.Id.Keyword_const => {1224 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1212 const var_decl = try self.createAttachNode(arena, &block.statements, ast.NodeVarDecl,1225 stack.append(State {
1213 ast.NodeVarDecl {1226 .VarDecl = VarDeclCtx {
1214 .base = undefined,
1215 .visib_token = null,1227 .visib_token = null,
1216 .mut_token = token,
1217 .comptime_token = null,1228 .comptime_token = null,
1218 .extern_export_token = null,1229 .extern_export_token = null,
1219 .type_node = null,
1220 .align_node = null,
1221 .init_node = null,
1222 .lib_name = null,1230 .lib_name = null,
1223 // initialized later1231 .mut_token = token,
1224 .name_token = undefined,1232 .list = &block.statements,
1225 .eq_token = undefined,
1226 .semicolon_token = undefined,
1227 }1233 }
1228 );1234 }) catch unreachable;
1229 stack.append(State { .VarDecl = var_decl }) catch unreachable;
1230 continue;1235 continue;
1231 },1236 },
1232 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {1237 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
...@@ -1242,7 +1247,7 @@ pub const Parser = struct {...@@ -1242,7 +1247,7 @@ pub const Parser = struct {
1242 .expr = undefined,1247 .expr = undefined,
1243 }1248 }
1244 );1249 );
1245 stack.append(State { .Semicolon = &node.base }) catch unreachable;1250 stack.append(State { .Semicolon = &&node.base }) catch unreachable;
1246 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });1251 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
1247 continue;1252 continue;
1248 },1253 },
...@@ -1270,40 +1275,37 @@ pub const Parser = struct {...@@ -1270,40 +1275,37 @@ pub const Parser = struct {
1270 },1275 },
1271 State.ComptimeStatement => |ctx| {1276 State.ComptimeStatement => |ctx| {
1272 const token = self.getNextToken();1277 const token = self.getNextToken();
1273 if (token.id == Token.Id.Keyword_var or token.id == Token.Id.Keyword_const) {1278 switch (token.id) {
1274 const var_decl = try self.createAttachNode(arena, &ctx.block.statements, ast.NodeVarDecl,1279 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1275 ast.NodeVarDecl {1280 stack.append(State {
1276 .base = undefined,1281 .VarDecl = VarDeclCtx {
1277 .visib_token = null,1282 .visib_token = null,
1278 .mut_token = token,1283 .comptime_token = ctx.comptime_token,
1279 .comptime_token = ctx.comptime_token,1284 .extern_export_token = null,
1280 .extern_export_token = null,1285 .lib_name = null,
1281 .type_node = null,1286 .mut_token = token,
1282 .align_node = null,1287 .list = &ctx.block.statements,
1283 .init_node = null,1288 }
1284 .lib_name = null,1289 }) catch unreachable;
1285 // initialized later1290 continue;
1286 .name_token = undefined,1291 },
1287 .eq_token = undefined,1292 else => {
1288 .semicolon_token = undefined,1293 self.putBackToken(token);
1289 }1294 self.putBackToken(ctx.comptime_token);
1290 );1295 const statememt = try ctx.block.statements.addOne();
1291 stack.append(State { .VarDecl = var_decl }) catch unreachable;1296 stack.append(State { .Semicolon = statememt }) catch unreachable;
1292 continue;1297 try stack.append(State { .Expression = OptionalCtx { .Required = statememt } });
1293 } else {1298 continue;
1294 self.putBackToken(token);1299 }
1295 self.putBackToken(ctx.comptime_token);
1296 const statememt = try ctx.block.statements.addOne();
1297 stack.append(State { .Semicolon = statememt }) catch unreachable;
1298 try stack.append(State { .Expression = OptionalCtx { .Required = statememt } });
1299 continue;
1300 }1300 }
1301 },1301 },
1302 State.Semicolon => |node_ptr| {1302 State.Semicolon => |node_ptr| {
1303 const node = *node_ptr;1303 const node = *node_ptr;
1304 if (requireSemiColon(node)) {1304 if (requireSemiColon(node)) {
1305 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;1305 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1306 continue;
1306 }1307 }
1308 continue;
1307 },1309 },
13081310
13091311
...@@ -1332,6 +1334,7 @@ pub const Parser = struct {...@@ -1332,6 +1334,7 @@ pub const Parser = struct {
1332 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });1334 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1333 try stack.append(State { .ExpectToken = Token.Id.RBracket });1335 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1334 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });1336 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1337 continue;
1335 },1338 },
1336 State.AsmOutputReturnOrType => |node| {1339 State.AsmOutputReturnOrType => |node| {
1337 const token = self.getNextToken();1340 const token = self.getNextToken();
...@@ -1377,11 +1380,13 @@ pub const Parser = struct {...@@ -1377,11 +1380,13 @@ pub const Parser = struct {
1377 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });1380 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1378 try stack.append(State { .ExpectToken = Token.Id.RBracket });1381 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1379 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });1382 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1383 continue;
1380 },1384 },
1381 State.AsmClopperItems => |items| {1385 State.AsmClopperItems => |items| {
1382 stack.append(State { .AsmClopperItems = items }) catch unreachable;1386 stack.append(State { .AsmClopperItems = items }) catch unreachable;
1383 try stack.append(State { .IfToken = Token.Id.Comma });1387 try stack.append(State { .IfToken = Token.Id.Comma });
1384 try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } });1388 try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } });
1389 continue;
1385 },1390 },
13861391
13871392
...@@ -1393,14 +1398,16 @@ pub const Parser = struct {...@@ -1393,14 +1398,16 @@ pub const Parser = struct {
13931398
1394 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;1399 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1395 try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } });1400 try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } });
1401 continue;
1396 },1402 },
1397 State.ExprListCommaOrEnd => |list_state| {1403 State.ExprListCommaOrEnd => |list_state| {
1398 if (try self.expectCommaOrEnd(list_state.end)) |end| {1404 if (try self.expectCommaOrEnd(list_state.end)) |end| {
1399 *list_state.ptr = end;1405 *list_state.ptr = end;
1406 continue;
1400 } else {1407 } else {
1401 stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable;1408 stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable;
1409 continue;
1402 }1410 }
1403 continue;
1404 },1411 },
1405 State.FieldInitListItemOrEnd => |list_state| {1412 State.FieldInitListItemOrEnd => |list_state| {
1406 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1413 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
...@@ -1433,22 +1440,25 @@ pub const Parser = struct {...@@ -1433,22 +1440,25 @@ pub const Parser = struct {
1433 .ptr = &node.period_token,1440 .ptr = &node.period_token,
1434 }1441 }
1435 });1442 });
1443 continue;
1436 },1444 },
1437 State.FieldInitListCommaOrEnd => |list_state| {1445 State.FieldInitListCommaOrEnd => |list_state| {
1438 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {1446 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1439 *list_state.ptr = end;1447 *list_state.ptr = end;
1448 continue;
1440 } else {1449 } else {
1441 stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable;1450 stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable;
1451 continue;
1442 }1452 }
1443 continue;
1444 },1453 },
1445 State.FieldListCommaOrEnd => |container_decl| {1454 State.FieldListCommaOrEnd => |container_decl| {
1446 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {1455 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1447 container_decl.rbrace_token = end;1456 container_decl.rbrace_token = end;
1457 continue;
1448 } else {1458 } else {
1449 stack.append(State { .ContainerDecl = container_decl }) catch unreachable;1459 stack.append(State { .ContainerDecl = container_decl }) catch unreachable;
1460 continue;
1450 }1461 }
1451 continue;
1452 },1462 },
1453 State.IdentifierListItemOrEnd => |list_state| {1463 State.IdentifierListItemOrEnd => |list_state| {
1454 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1464 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
...@@ -1458,14 +1468,16 @@ pub const Parser = struct {...@@ -1458,14 +1468,16 @@ pub const Parser = struct {
14581468
1459 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;1469 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;
1460 try stack.append(State { .Identifier = OptionalCtx { .Required = try list_state.list.addOne() } });1470 try stack.append(State { .Identifier = OptionalCtx { .Required = try list_state.list.addOne() } });
1471 continue;
1461 },1472 },
1462 State.IdentifierListCommaOrEnd => |list_state| {1473 State.IdentifierListCommaOrEnd => |list_state| {
1463 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {1474 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1464 *list_state.ptr = end;1475 *list_state.ptr = end;
1476 continue;
1465 } else {1477 } else {
1466 stack.append(State { .IdentifierListItemOrEnd = list_state }) catch unreachable;1478 stack.append(State { .IdentifierListItemOrEnd = list_state }) catch unreachable;
1479 continue;
1467 }1480 }
1468 continue;
1469 },1481 },
1470 State.SwitchCaseOrEnd => |list_state| {1482 State.SwitchCaseOrEnd => |list_state| {
1471 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1483 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
...@@ -1486,15 +1498,16 @@ pub const Parser = struct {...@@ -1486,15 +1498,16 @@ pub const Parser = struct {
1486 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } });1498 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } });
1487 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });1499 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
1488 try stack.append(State { .SwitchCaseFirstItem = &node.items });1500 try stack.append(State { .SwitchCaseFirstItem = &node.items });
14891501 continue;
1490 },1502 },
1491 State.SwitchCaseCommaOrEnd => |list_state| {1503 State.SwitchCaseCommaOrEnd => |list_state| {
1492 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {1504 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1493 *list_state.ptr = end;1505 *list_state.ptr = end;
1506 continue;
1494 } else {1507 } else {
1495 stack.append(State { .SwitchCaseOrEnd = list_state }) catch unreachable;1508 stack.append(State { .SwitchCaseOrEnd = list_state }) catch unreachable;
1509 continue;
1496 }1510 }
1497 continue;
1498 },1511 },
1499 State.SwitchCaseFirstItem => |case_items| {1512 State.SwitchCaseFirstItem => |case_items| {
1500 const token = self.getNextToken();1513 const token = self.getNextToken();
...@@ -1544,6 +1557,7 @@ pub const Parser = struct {...@@ -1544,6 +1557,7 @@ pub const Parser = struct {
1544 }1557 }
1545 });1558 });
1546 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } });1559 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } });
1560 continue;
1547 },1561 },
1548 State.AsyncEnd => |ctx| {1562 State.AsyncEnd => |ctx| {
1549 const node = ctx.ctx.get() ?? continue;1563 const node = ctx.ctx.get() ?? continue;
...@@ -1552,6 +1566,7 @@ pub const Parser = struct {...@@ -1552,6 +1566,7 @@ pub const Parser = struct {
1552 ast.Node.Id.FnProto => {1566 ast.Node.Id.FnProto => {
1553 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);1567 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);
1554 fn_proto.async_attr = ctx.attribute;1568 fn_proto.async_attr = ctx.attribute;
1569 continue;
1555 },1570 },
1556 ast.Node.Id.SuffixOp => {1571 ast.Node.Id.SuffixOp => {
1557 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);1572 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);
...@@ -1574,6 +1589,38 @@ pub const Parser = struct {...@@ -1574,6 +1589,38 @@ pub const Parser = struct {
1574 },1589 },
15751590
15761591
1592 State.ExternType => |ctx| {
1593 if (self.eatToken(Token.Id.Keyword_fn)) |fn_token| {
1594 const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFnProto,
1595 ast.NodeFnProto {
1596 .base = undefined,
1597 .visib_token = null,
1598 .name_token = null,
1599 .fn_token = fn_token,
1600 .params = ArrayList(&ast.Node).init(arena),
1601 .return_type = undefined,
1602 .var_args_token = null,
1603 .extern_export_inline_token = ctx.extern_token,
1604 .cc_token = null,
1605 .async_attr = null,
1606 .body_node = null,
1607 .lib_name = null,
1608 .align_expr = null,
1609 }
1610 );
1611 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1612 continue;
1613 }
1614
1615 stack.append(State {
1616 .ContainerKind = ContainerKindCtx {
1617 .opt_ctx = ctx.opt_ctx,
1618 .ltoken = ctx.extern_token,
1619 .layout = ast.NodeContainerDecl.Layout.Extern,
1620 },
1621 }) catch unreachable;
1622 continue;
1623 },
1577 State.SliceOrArrayAccess => |node| {1624 State.SliceOrArrayAccess => |node| {
1578 var token = self.getNextToken();1625 var token = self.getNextToken();
1579 switch (token.id) {1626 switch (token.id) {
...@@ -1692,6 +1739,7 @@ pub const Parser = struct {...@@ -1692,6 +1739,7 @@ pub const Parser = struct {
1692 }1739 }
1693 }) catch unreachable;1740 }) catch unreachable;
1694 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } });1741 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } });
1742 continue;
1695 },1743 },
1696 State.PointerPayload => |opt_ctx| {1744 State.PointerPayload => |opt_ctx| {
1697 const token = self.getNextToken();1745 const token = self.getNextToken();
...@@ -1729,6 +1777,7 @@ pub const Parser = struct {...@@ -1729,6 +1777,7 @@ pub const Parser = struct {
1729 .ptr = &node.ptr_token,1777 .ptr = &node.ptr_token,
1730 }1778 }
1731 });1779 });
1780 continue;
1732 },1781 },
1733 State.PointerIndexPayload => |opt_ctx| {1782 State.PointerIndexPayload => |opt_ctx| {
1734 const token = self.getNextToken();1783 const token = self.getNextToken();
...@@ -1769,26 +1818,14 @@ pub const Parser = struct {...@@ -1769,26 +1818,14 @@ pub const Parser = struct {
1769 .ptr = &node.ptr_token,1818 .ptr = &node.ptr_token,
1770 }1819 }
1771 });1820 });
1821 continue;
1772 },1822 },
17731823
17741824
1775 State.Expression => |opt_ctx| {1825 State.Expression => |opt_ctx| {
1776 const token = self.getNextToken();1826 const token = self.getNextToken();
1777 switch (token.id) {1827 switch (token.id) {
1778 Token.Id.Keyword_return => {1828 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1779 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,
1780 ast.NodeControlFlowExpression {
1781 .base = undefined,
1782 .ltoken = token,
1783 .kind = ast.NodeControlFlowExpression.Kind.Return,
1784 .rhs = null,
1785 }
1786 );
1787
1788 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
1789 continue;
1790 },
1791 Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1792 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,1829 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,
1793 ast.NodeControlFlowExpression {1830 ast.NodeControlFlowExpression {
1794 .base = undefined,1831 .base = undefined,
...@@ -1811,6 +1848,9 @@ pub const Parser = struct {...@@ -1811,6 +1848,9 @@ pub const Parser = struct {
1811 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } });1848 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } });
1812 try stack.append(State { .IfToken = Token.Id.Colon });1849 try stack.append(State { .IfToken = Token.Id.Colon });
1813 },1850 },
1851 Token.Id.Keyword_return => {
1852 node.kind = ast.NodeControlFlowExpression.Kind.Return;
1853 },
1814 else => unreachable,1854 else => unreachable,
1815 }1855 }
1816 continue;1856 continue;
...@@ -1861,9 +1901,8 @@ pub const Parser = struct {...@@ -1861,9 +1901,8 @@ pub const Parser = struct {
1861 }1901 }
1862 );1902 );
1863 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;1903 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1904 continue;
1864 }1905 }
1865
1866 continue;
1867 },1906 },
1868 State.AssignmentExpressionBegin => |opt_ctx| {1907 State.AssignmentExpressionBegin => |opt_ctx| {
1869 stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable;1908 stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable;
...@@ -1904,34 +1943,27 @@ pub const Parser = struct {...@@ -1904,34 +1943,27 @@ pub const Parser = struct {
1904 const lhs = opt_ctx.get() ?? continue;1943 const lhs = opt_ctx.get() ?? continue;
19051944
1906 const token = self.getNextToken();1945 const token = self.getNextToken();
1907 switch (token.id) {1946 if (tokenIdToUnwrapExpr(token.id)) |unwrap_id| {
1908 Token.Id.Keyword_catch, Token.Id.QuestionMarkQuestionMark => {1947 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1909 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,1948 ast.NodeInfixOp {
1910 ast.NodeInfixOp {1949 .base = undefined,
1911 .base = undefined,1950 .lhs = lhs,
1912 .lhs = lhs,1951 .op_token = token,
1913 .op_token = token,1952 .op = unwrap_id,
1914 .op = switch (token.id) {1953 .rhs = undefined,
1915 Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null },1954 }
1916 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} },1955 );
1917 else => unreachable,
1918 },
1919 .rhs = undefined,
1920 }
1921 );
19221956
1923 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;1957 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1924 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });1958 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
19251959
1926 if (node.op == ast.NodeInfixOp.InfixOp.Catch) {1960 if (node.op == ast.NodeInfixOp.InfixOp.Catch) {
1927 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } });1961 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } });
1928 }1962 }
1929 continue;1963 continue;
1930 },1964 } else {
1931 else => {1965 self.putBackToken(token);
1932 self.putBackToken(token);1966 continue;
1933 continue;
1934 },
1935 }1967 }
1936 },1968 },
19371969
...@@ -1944,26 +1976,19 @@ pub const Parser = struct {...@@ -1944,26 +1976,19 @@ pub const Parser = struct {
1944 State.BoolOrExpressionEnd => |opt_ctx| {1976 State.BoolOrExpressionEnd => |opt_ctx| {
1945 const lhs = opt_ctx.get() ?? continue;1977 const lhs = opt_ctx.get() ?? continue;
19461978
1947 const token = self.getNextToken();1979 if (self.eatToken(Token.Id.Keyword_or)) |or_token| {
1948 switch (token.id) {1980 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1949 Token.Id.Keyword_or => {1981 ast.NodeInfixOp {
1950 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,1982 .base = undefined,
1951 ast.NodeInfixOp {1983 .lhs = lhs,
1952 .base = undefined,1984 .op_token = or_token,
1953 .lhs = lhs,1985 .op = ast.NodeInfixOp.InfixOp.BoolOr,
1954 .op_token = token,1986 .rhs = undefined,
1955 .op = ast.NodeInfixOp.InfixOp.BoolOr,1987 }
1956 .rhs = undefined,1988 );
1957 }1989 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1958 );1990 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1959 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;1991 continue;
1960 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1961 continue;
1962 },
1963 else => {
1964 self.putBackToken(token);
1965 continue;
1966 },
1967 }1992 }
1968 },1993 },
19691994
...@@ -1976,26 +2001,19 @@ pub const Parser = struct {...@@ -1976,26 +2001,19 @@ pub const Parser = struct {
1976 State.BoolAndExpressionEnd => |opt_ctx| {2001 State.BoolAndExpressionEnd => |opt_ctx| {
1977 const lhs = opt_ctx.get() ?? continue;2002 const lhs = opt_ctx.get() ?? continue;
19782003
1979 const token = self.getNextToken();2004 if (self.eatToken(Token.Id.Keyword_and)) |and_token| {
1980 switch (token.id) {2005 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1981 Token.Id.Keyword_and => {2006 ast.NodeInfixOp {
1982 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,2007 .base = undefined,
1983 ast.NodeInfixOp {2008 .lhs = lhs,
1984 .base = undefined,2009 .op_token = and_token,
1985 .lhs = lhs,2010 .op = ast.NodeInfixOp.InfixOp.BoolAnd,
1986 .op_token = token,2011 .rhs = undefined,
1987 .op = ast.NodeInfixOp.InfixOp.BoolAnd,2012 }
1988 .rhs = undefined,2013 );
1989 }2014 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1990 );2015 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1991 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2016 continue;
1992 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1993 continue;
1994 },
1995 else => {
1996 self.putBackToken(token);
1997 continue;
1998 },
1999 }2017 }
2000 },2018 },
20012019
...@@ -2037,26 +2055,19 @@ pub const Parser = struct {...@@ -2037,26 +2055,19 @@ pub const Parser = struct {
2037 State.BinaryOrExpressionEnd => |opt_ctx| {2055 State.BinaryOrExpressionEnd => |opt_ctx| {
2038 const lhs = opt_ctx.get() ?? continue;2056 const lhs = opt_ctx.get() ?? continue;
20392057
2040 const token = self.getNextToken();2058 if (self.eatToken(Token.Id.Pipe)) |pipe| {
2041 switch (token.id) {2059 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2042 Token.Id.Pipe => {2060 ast.NodeInfixOp {
2043 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,2061 .base = undefined,
2044 ast.NodeInfixOp {2062 .lhs = lhs,
2045 .base = undefined,2063 .op_token = pipe,
2046 .lhs = lhs,2064 .op = ast.NodeInfixOp.InfixOp.BitOr,
2047 .op_token = token,2065 .rhs = undefined,
2048 .op = ast.NodeInfixOp.InfixOp.BitOr,2066 }
2049 .rhs = undefined,2067 );
2050 }2068 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2051 );2069 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2052 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2070 continue;
2053 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2054 continue;
2055 },
2056 else => {
2057 self.putBackToken(token);
2058 continue;
2059 },
2060 }2071 }
2061 },2072 },
20622073
...@@ -2069,26 +2080,19 @@ pub const Parser = struct {...@@ -2069,26 +2080,19 @@ pub const Parser = struct {
2069 State.BinaryXorExpressionEnd => |opt_ctx| {2080 State.BinaryXorExpressionEnd => |opt_ctx| {
2070 const lhs = opt_ctx.get() ?? continue;2081 const lhs = opt_ctx.get() ?? continue;
20712082
2072 const token = self.getNextToken();2083 if (self.eatToken(Token.Id.Caret)) |caret| {
2073 switch (token.id) {2084 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2074 Token.Id.Caret => {2085 ast.NodeInfixOp {
2075 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,2086 .base = undefined,
2076 ast.NodeInfixOp {2087 .lhs = lhs,
2077 .base = undefined,2088 .op_token = caret,
2078 .lhs = lhs,2089 .op = ast.NodeInfixOp.InfixOp.BitXor,
2079 .op_token = token,2090 .rhs = undefined,
2080 .op = ast.NodeInfixOp.InfixOp.BitXor,2091 }
2081 .rhs = undefined,2092 );
2082 }2093 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2083 );2094 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2084 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2095 continue;
2085 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2086 continue;
2087 },
2088 else => {
2089 self.putBackToken(token);
2090 continue;
2091 },
2092 }2096 }
2093 },2097 },
20942098
...@@ -2101,26 +2105,19 @@ pub const Parser = struct {...@@ -2101,26 +2105,19 @@ pub const Parser = struct {
2101 State.BinaryAndExpressionEnd => |opt_ctx| {2105 State.BinaryAndExpressionEnd => |opt_ctx| {
2102 const lhs = opt_ctx.get() ?? continue;2106 const lhs = opt_ctx.get() ?? continue;
21032107
2104 const token = self.getNextToken();2108 if (self.eatToken(Token.Id.Ampersand)) |ampersand| {
2105 switch (token.id) {2109 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2106 Token.Id.Ampersand => {2110 ast.NodeInfixOp {
2107 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,2111 .base = undefined,
2108 ast.NodeInfixOp {2112 .lhs = lhs,
2109 .base = undefined,2113 .op_token = ampersand,
2110 .lhs = lhs,2114 .op = ast.NodeInfixOp.InfixOp.BitAnd,
2111 .op_token = token,2115 .rhs = undefined,
2112 .op = ast.NodeInfixOp.InfixOp.BitAnd,2116 }
2113 .rhs = undefined,2117 );
2114 }2118 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2115 );2119 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2116 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2120 continue;
2117 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2118 continue;
2119 },
2120 else => {
2121 self.putBackToken(token);
2122 continue;
2123 },
2124 }2121 }
2125 },2122 },
21262123
...@@ -2241,28 +2238,28 @@ pub const Parser = struct {...@@ -2241,28 +2238,28 @@ pub const Parser = struct {
2241 }2238 }
2242 });2239 });
2243 continue;2240 continue;
2244 } else {
2245 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2246 ast.NodeSuffixOp {
2247 .base = undefined,
2248 .lhs = lhs,
2249 .op = ast.NodeSuffixOp.SuffixOp {
2250 .ArrayInitializer = ArrayList(&ast.Node).init(arena),
2251 },
2252 .rtoken = undefined,
2253 }
2254 );
2255 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2256 try stack.append(State { .IfToken = Token.Id.LBrace });
2257 try stack.append(State {
2258 .ExprListItemOrEnd = ExprListCtx {
2259 .list = &node.op.ArrayInitializer,
2260 .end = Token.Id.RBrace,
2261 .ptr = &node.rtoken,
2262 }
2263 });
2264 continue;
2265 }2241 }
2242
2243 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2244 ast.NodeSuffixOp {
2245 .base = undefined,
2246 .lhs = lhs,
2247 .op = ast.NodeSuffixOp.SuffixOp {
2248 .ArrayInitializer = ArrayList(&ast.Node).init(arena),
2249 },
2250 .rtoken = undefined,
2251 }
2252 );
2253 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2254 try stack.append(State { .IfToken = Token.Id.LBrace });
2255 try stack.append(State {
2256 .ExprListItemOrEnd = ExprListCtx {
2257 .list = &node.op.ArrayInitializer,
2258 .end = Token.Id.RBrace,
2259 .ptr = &node.rtoken,
2260 }
2261 });
2262 continue;
2266 },2263 },
22672264
2268 State.TypeExprBegin => |opt_ctx| {2265 State.TypeExprBegin => |opt_ctx| {
...@@ -2274,26 +2271,19 @@ pub const Parser = struct {...@@ -2274,26 +2271,19 @@ pub const Parser = struct {
2274 State.TypeExprEnd => |opt_ctx| {2271 State.TypeExprEnd => |opt_ctx| {
2275 const lhs = opt_ctx.get() ?? continue;2272 const lhs = opt_ctx.get() ?? continue;
22762273
2277 const token = self.getNextToken();2274 if (self.eatToken(Token.Id.Bang)) |bang| {
2278 switch (token.id) {2275 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2279 Token.Id.Bang => {2276 ast.NodeInfixOp {
2280 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,2277 .base = undefined,
2281 ast.NodeInfixOp {2278 .lhs = lhs,
2282 .base = undefined,2279 .op_token = bang,
2283 .lhs = lhs,2280 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,
2284 .op_token = token,2281 .rhs = undefined,
2285 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,2282 }
2286 .rhs = undefined,2283 );
2287 }2284 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2288 );2285 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
2289 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;2286 continue;
2290 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
2291 continue;
2292 },
2293 else => {
2294 self.putBackToken(token);
2295 continue;
2296 },
2297 }2287 }
2298 },2288 },
22992289
...@@ -2309,6 +2299,7 @@ pub const Parser = struct {...@@ -2309,6 +2299,7 @@ pub const Parser = struct {
2309 }2299 }
2310 );2300 );
23112301
2302 // Treat '**' token as two derefs
2312 if (token.id == Token.Id.AsteriskAsterisk) {2303 if (token.id == Token.Id.AsteriskAsterisk) {
2313 const child = try self.createNode(arena, ast.NodePrefixOp,2304 const child = try self.createNode(arena, ast.NodePrefixOp,
2314 ast.NodePrefixOp {2305 ast.NodePrefixOp {
...@@ -2335,35 +2326,30 @@ pub const Parser = struct {...@@ -2335,35 +2326,30 @@ pub const Parser = struct {
2335 },2326 },
23362327
2337 State.SuffixOpExpressionBegin => |opt_ctx| {2328 State.SuffixOpExpressionBegin => |opt_ctx| {
2338 const token = self.getNextToken();2329 if (self.eatToken(Token.Id.Keyword_async)) |async_token| {
2339 switch (token.id) {2330 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
2340 Token.Id.Keyword_async => {2331 ast.NodeAsyncAttribute {
2341 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,2332 .base = undefined,
2342 ast.NodeAsyncAttribute {2333 .async_token = async_token,
2343 .base = undefined,2334 .allocator_type = null,
2344 .async_token = token,2335 .rangle_bracket = null,
2345 .allocator_type = null,2336 }
2346 .rangle_bracket = null,2337 );
2347 }2338 stack.append(State {
2348 );2339 .AsyncEnd = AsyncEndCtx {
2349 stack.append(State {2340 .ctx = opt_ctx,
2350 .AsyncEnd = AsyncEndCtx {2341 .attribute = async_node,
2351 .ctx = opt_ctx,2342 }
2352 .attribute = async_node,2343 }) catch unreachable;
2353 }2344 try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() });
2354 }) catch unreachable;2345 try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() });
2355 try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() });2346 try stack.append(State { .AsyncAllocator = async_node });
2356 try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() });2347 continue;
2357 try stack.append(State { .AsyncAllocator = async_node });
2358 continue;
2359 },
2360 else => {
2361 self.putBackToken(token);
2362 stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2363 try stack.append(State { .PrimaryExpression = opt_ctx });
2364 continue;
2365 }
2366 }2348 }
2349
2350 stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2351 try stack.append(State { .PrimaryExpression = opt_ctx });
2352 continue;
2367 },2353 },
23682354
2369 State.SuffixOpExpressionEnd => |opt_ctx| {2355 State.SuffixOpExpressionEnd => |opt_ctx| {
...@@ -2436,43 +2422,44 @@ pub const Parser = struct {...@@ -2436,43 +2422,44 @@ pub const Parser = struct {
2436 const token = self.getNextToken();2422 const token = self.getNextToken();
2437 switch (token.id) {2423 switch (token.id) {
2438 Token.Id.IntegerLiteral => {2424 Token.Id.IntegerLiteral => {
2439 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeStringLiteral, token)).base);2425 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeStringLiteral, token);
2440 continue;2426 continue;
2441 },2427 },
2442 Token.Id.FloatLiteral => {2428 Token.Id.FloatLiteral => {
2443 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeFloatLiteral, token)).base);2429 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeFloatLiteral, token);
2444 continue;2430 continue;
2445 },2431 },
2446 Token.Id.CharLiteral => {2432 Token.Id.CharLiteral => {
2447 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeCharLiteral, token)).base);2433 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeCharLiteral, token);
2448 continue;2434 continue;
2449 },2435 },
2450 Token.Id.Keyword_undefined => {2436 Token.Id.Keyword_undefined => {
2451 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeUndefinedLiteral, token)).base);2437 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUndefinedLiteral, token);
2452 continue;2438 continue;
2453 },2439 },
2454 Token.Id.Keyword_true, Token.Id.Keyword_false => {2440 Token.Id.Keyword_true, Token.Id.Keyword_false => {
2455 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeBoolLiteral, token)).base);2441 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeBoolLiteral, token);
2456 continue;2442 continue;
2457 },2443 },
2458 Token.Id.Keyword_null => {2444 Token.Id.Keyword_null => {
2459 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeNullLiteral, token)).base);2445 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeNullLiteral, token);
2460 continue;2446 continue;
2461 },2447 },
2462 Token.Id.Keyword_this => {2448 Token.Id.Keyword_this => {
2463 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeThisLiteral, token)).base);2449 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeThisLiteral, token);
2464 continue;2450 continue;
2465 },2451 },
2466 Token.Id.Keyword_var => {2452 Token.Id.Keyword_var => {
2467 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeVarType, token)).base);2453 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeVarType, token);
2468 continue;2454 continue;
2469 },2455 },
2470 Token.Id.Keyword_unreachable => {2456 Token.Id.Keyword_unreachable => {
2471 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeUnreachable, token)).base);2457 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUnreachable, token);
2472 continue;2458 continue;
2473 },2459 },
2474 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {2460 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
2475 opt_ctx.store((try self.parseStringLiteral(arena, token)) ?? unreachable);2461 opt_ctx.store((try self.parseStringLiteral(arena, token)) ?? unreachable);
2462 continue;
2476 },2463 },
2477 Token.Id.LParen => {2464 Token.Id.LParen => {
2478 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeGroupedExpression,2465 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeGroupedExpression,
...@@ -2521,6 +2508,7 @@ pub const Parser = struct {...@@ -2521,6 +2508,7 @@ pub const Parser = struct {
2521 }2508 }
2522 );2509 );
2523 stack.append(State { .SliceOrArrayType = node }) catch unreachable;2510 stack.append(State { .SliceOrArrayType = node }) catch unreachable;
2511 continue;
2524 },2512 },
2525 Token.Id.Keyword_error => {2513 Token.Id.Keyword_error => {
2526 stack.append(State {2514 stack.append(State {
...@@ -2529,73 +2517,41 @@ pub const Parser = struct {...@@ -2529,73 +2517,41 @@ pub const Parser = struct {
2529 .opt_ctx = opt_ctx2517 .opt_ctx = opt_ctx
2530 }2518 }
2531 }) catch unreachable;2519 }) catch unreachable;
2520 continue;
2532 },2521 },
2533 Token.Id.Keyword_packed => {2522 Token.Id.Keyword_packed => {
2534 stack.append(State {2523 stack.append(State {
2535 .ContainerExtern = ContainerExternCtx {2524 .ContainerKind = ContainerKindCtx {
2536 .opt_ctx = opt_ctx,2525 .opt_ctx = opt_ctx,
2537 .ltoken = token,2526 .ltoken = token,
2538 .layout = ast.NodeContainerDecl.Layout.Packed,2527 .layout = ast.NodeContainerDecl.Layout.Packed,
2539 },2528 },
2540 }) catch unreachable;2529 }) catch unreachable;
2530 continue;
2541 },2531 },
2542 Token.Id.Keyword_extern => {2532 Token.Id.Keyword_extern => {
2543 // TODO: Here, we eat two tokens in the same state. This prevents comments
2544 // from being between these two tokens.
2545 const next = self.getNextToken();
2546 if (next.id == Token.Id.Keyword_fn) {
2547 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2548 ast.NodeFnProto {
2549 .base = undefined,
2550 .visib_token = null,
2551 .name_token = null,
2552 .fn_token = next,
2553 .params = ArrayList(&ast.Node).init(arena),
2554 .return_type = undefined,
2555 .var_args_token = null,
2556 .extern_export_inline_token = token,
2557 .cc_token = null,
2558 .async_attr = null,
2559 .body_node = null,
2560 .lib_name = null,
2561 .align_expr = null,
2562 }
2563 );
2564 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2565 continue;
2566 }
2567
2568 self.putBackToken(next);
2569 stack.append(State {2533 stack.append(State {
2570 .ContainerExtern = ContainerExternCtx {2534 .ExternType = ExternTypeCtx {
2571 .opt_ctx = opt_ctx,2535 .opt_ctx = opt_ctx,
2572 .ltoken = token,2536 .extern_token = token,
2573 .layout = ast.NodeContainerDecl.Layout.Extern,
2574 },2537 },
2575 }) catch unreachable;2538 }) catch unreachable;
2539 continue;
2576 },2540 },
2577 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {2541 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
2578 self.putBackToken(token);2542 self.putBackToken(token);
2579 stack.append(State {2543 stack.append(State {
2580 .ContainerExtern = ContainerExternCtx {2544 .ContainerKind = ContainerKindCtx {
2581 .opt_ctx = opt_ctx,2545 .opt_ctx = opt_ctx,
2582 .ltoken = token,2546 .ltoken = token,
2583 .layout = ast.NodeContainerDecl.Layout.Auto,2547 .layout = ast.NodeContainerDecl.Layout.Auto,
2584 },2548 },
2585 }) catch unreachable;2549 }) catch unreachable;
2550 continue;
2586 },2551 },
2587 Token.Id.Identifier => {2552 Token.Id.Identifier => {
2588 // TODO: Here, we eat two tokens in the same state. This prevents comments
2589 // from being between these two tokens.
2590 const next = self.getNextToken();
2591 if (next.id != Token.Id.Colon) {
2592 self.putBackToken(next);
2593 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeIdentifier, token)).base);
2594 continue;
2595 }
2596
2597 stack.append(State {2553 stack.append(State {
2598 .LabeledExpression = LabelCtx {2554 .MaybeLabeledExpression = MaybeLabeledExpressionCtx {
2599 .label = token,2555 .label = token,
2600 .opt_ctx = opt_ctx2556 .opt_ctx = opt_ctx
2601 }2557 }
...@@ -2710,7 +2666,7 @@ pub const Parser = struct {...@@ -2710,7 +2666,7 @@ pub const Parser = struct {
27102666
2711 State.ErrorTypeOrSetDecl => |ctx| {2667 State.ErrorTypeOrSetDecl => |ctx| {
2712 if (self.eatToken(Token.Id.LBrace) == null) {2668 if (self.eatToken(Token.Id.LBrace) == null) {
2713 ctx.opt_ctx.store(&(try self.createLiteral(arena, ast.NodeErrorType, ctx.error_token)).base);2669 _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeErrorType, ctx.error_token);
2714 continue;2670 continue;
2715 }2671 }
27162672
...@@ -2746,7 +2702,7 @@ pub const Parser = struct {...@@ -2746,7 +2702,7 @@ pub const Parser = struct {
2746 },2702 },
2747 State.Identifier => |opt_ctx| {2703 State.Identifier => |opt_ctx| {
2748 if (self.eatToken(Token.Id.Identifier)) |ident_token| {2704 if (self.eatToken(Token.Id.Identifier)) |ident_token| {
2749 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeIdentifier, ident_token)).base);2705 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeIdentifier, ident_token);
2750 continue;2706 continue;
2751 }2707 }
27522708
...@@ -3044,8 +3000,16 @@ pub const Parser = struct {...@@ -3044,8 +3000,16 @@ pub const Parser = struct {
3044 };3000 };
3045 }3001 }
30463002
3047 fn tokenIdToComparison(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3003 fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
3048 return switch (*id) {3004 return switch (id) {
3005 Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null },
3006 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} },
3007 else => null,
3008 };
3009 }
3010
3011 fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
3012 return switch (id) {
3049 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp { .BangEqual = void{} },3013 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp { .BangEqual = void{} },
3050 Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp { .EqualEqual = void{} },3014 Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp { .EqualEqual = void{} },
3051 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp { .LessThan = void{} },3015 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp { .LessThan = void{} },
...@@ -3056,16 +3020,16 @@ pub const Parser = struct {...@@ -3056,16 +3020,16 @@ pub const Parser = struct {
3056 };3020 };
3057 }3021 }
30583022
3059 fn tokenIdToBitShift(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3023 fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
3060 return switch (*id) {3024 return switch (id) {
3061 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp { .BitShiftLeft = void{} },3025 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp { .BitShiftLeft = void{} },
3062 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp { .BitShiftRight = void{} },3026 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp { .BitShiftRight = void{} },
3063 else => null,3027 else => null,
3064 };3028 };
3065 }3029 }
30663030
3067 fn tokenIdToAddition(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3031 fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
3068 return switch (*id) {3032 return switch (id) {
3069 Token.Id.Minus => ast.NodeInfixOp.InfixOp { .Sub = void{} },3033 Token.Id.Minus => ast.NodeInfixOp.InfixOp { .Sub = void{} },
3070 Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp { .SubWrap = void{} },3034 Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp { .SubWrap = void{} },
3071 Token.Id.Plus => ast.NodeInfixOp.InfixOp { .Add = void{} },3035 Token.Id.Plus => ast.NodeInfixOp.InfixOp { .Add = void{} },
...@@ -3075,8 +3039,8 @@ pub const Parser = struct {...@@ -3075,8 +3039,8 @@ pub const Parser = struct {
3075 };3039 };
3076 }3040 }
30773041
3078 fn tokenIdToMultiply(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3042 fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
3079 return switch (*id) {3043 return switch (id) {
3080 Token.Id.Slash => ast.NodeInfixOp.InfixOp { .Div = void{} },3044 Token.Id.Slash => ast.NodeInfixOp.InfixOp { .Div = void{} },
3081 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp { .Mult = void{} },3045 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp { .Mult = void{} },
3082 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp { .ArrayMult = void{} },3046 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp { .ArrayMult = void{} },
...@@ -3087,8 +3051,8 @@ pub const Parser = struct {...@@ -3087,8 +3051,8 @@ pub const Parser = struct {
3087 };3051 };
3088 }3052 }
30893053
3090 fn tokenIdToPrefixOp(id: &const Token.Id) ?ast.NodePrefixOp.PrefixOp {3054 fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.NodePrefixOp.PrefixOp {
3091 return switch (*id) {3055 return switch (id) {
3092 Token.Id.Bang => ast.NodePrefixOp.PrefixOp { .BoolNot = void{} },3056 Token.Id.Bang => ast.NodePrefixOp.PrefixOp { .BoolNot = void{} },
3093 Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} },3057 Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} },
3094 Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} },3058 Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} },
...@@ -3149,6 +3113,13 @@ pub const Parser = struct {...@@ -3149,6 +3113,13 @@ pub const Parser = struct {
3149 );3113 );
3150 }3114 }
31513115
3116 fn createToCtxLiteral(self: &Parser, arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, token: &const Token) !&T {
3117 const node = try self.createLiteral(arena, T, token);
3118 opt_ctx.store(&node.base);
3119
3120 return node;
3121 }
3122
3152 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {3123 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
3153 const loc = self.tokenizer.getTokenLocation(0, token);3124 const loc = self.tokenizer.getTokenLocation(0, token);
3154 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);3125 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);