authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-13 11:17:09-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-04-13 11:17:09-04:00
log4662fd4d92b216708390a2056a201c91773b9bc6
tree15edb79059e5a4695287a78a6293c0b015dc0727
parent30c5f3c441e6090f29c0540b1fa8a20d6bd2fc0d
parenta498993fd102c649c3d24f73f064c5bbafb9b3ec
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #919 from zig-lang/self-hosted-parser-refactor

Self-hosted parser refactor

2 files changed, 1996 insertions(+), 1942 deletions(-)

std/zig/ast.zig+55-39
...@@ -283,13 +283,13 @@ pub const NodeUse = struct {...@@ -283,13 +283,13 @@ pub const NodeUse = struct {
283pub const NodeErrorSetDecl = struct {283pub const NodeErrorSetDecl = struct {
284 base: Node,284 base: Node,
285 error_token: Token,285 error_token: Token,
286 decls: ArrayList(&NodeIdentifier),286 decls: ArrayList(&Node),
287 rbrace_token: Token,287 rbrace_token: Token,
288288
289 pub fn iterate(self: &NodeErrorSetDecl, index: usize) ?&Node {289 pub fn iterate(self: &NodeErrorSetDecl, index: usize) ?&Node {
290 var i = index;290 var i = index;
291291
292 if (i < self.decls.len) return &self.decls.at(i).base;292 if (i < self.decls.len) return self.decls.at(i);
293 i -= self.decls.len;293 i -= self.decls.len;
294294
295 return null;295 return null;
...@@ -676,13 +676,13 @@ pub const NodeComptime = struct {...@@ -676,13 +676,13 @@ pub const NodeComptime = struct {
676pub const NodePayload = struct {676pub const NodePayload = struct {
677 base: Node,677 base: Node,
678 lpipe: Token,678 lpipe: Token,
679 error_symbol: &NodeIdentifier,679 error_symbol: &Node,
680 rpipe: Token,680 rpipe: Token,
681681
682 pub fn iterate(self: &NodePayload, index: usize) ?&Node {682 pub fn iterate(self: &NodePayload, index: usize) ?&Node {
683 var i = index;683 var i = index;
684684
685 if (i < 1) return &self.error_symbol.base;685 if (i < 1) return self.error_symbol;
686 i -= 1;686 i -= 1;
687687
688 return null;688 return null;
...@@ -700,14 +700,14 @@ pub const NodePayload = struct {...@@ -700,14 +700,14 @@ pub const NodePayload = struct {
700pub const NodePointerPayload = struct {700pub const NodePointerPayload = struct {
701 base: Node,701 base: Node,
702 lpipe: Token,702 lpipe: Token,
703 is_ptr: bool,703 ptr_token: ?Token,
704 value_symbol: &NodeIdentifier,704 value_symbol: &Node,
705 rpipe: Token,705 rpipe: Token,
706706
707 pub fn iterate(self: &NodePointerPayload, index: usize) ?&Node {707 pub fn iterate(self: &NodePointerPayload, index: usize) ?&Node {
708 var i = index;708 var i = index;
709709
710 if (i < 1) return &self.value_symbol.base;710 if (i < 1) return self.value_symbol;
711 i -= 1;711 i -= 1;
712712
713 return null;713 return null;
...@@ -725,19 +725,19 @@ pub const NodePointerPayload = struct {...@@ -725,19 +725,19 @@ pub const NodePointerPayload = struct {
725pub const NodePointerIndexPayload = struct {725pub const NodePointerIndexPayload = struct {
726 base: Node,726 base: Node,
727 lpipe: Token,727 lpipe: Token,
728 is_ptr: bool,728 ptr_token: ?Token,
729 value_symbol: &NodeIdentifier,729 value_symbol: &Node,
730 index_symbol: ?&NodeIdentifier,730 index_symbol: ?&Node,
731 rpipe: Token,731 rpipe: Token,
732732
733 pub fn iterate(self: &NodePointerIndexPayload, index: usize) ?&Node {733 pub fn iterate(self: &NodePointerIndexPayload, index: usize) ?&Node {
734 var i = index;734 var i = index;
735735
736 if (i < 1) return &self.value_symbol.base;736 if (i < 1) return self.value_symbol;
737 i -= 1;737 i -= 1;
738738
739 if (self.index_symbol) |index_symbol| {739 if (self.index_symbol) |index_symbol| {
740 if (i < 1) return &index_symbol.base;740 if (i < 1) return index_symbol;
741 i -= 1;741 i -= 1;
742 }742 }
743743
...@@ -756,14 +756,14 @@ pub const NodePointerIndexPayload = struct {...@@ -756,14 +756,14 @@ pub const NodePointerIndexPayload = struct {
756pub const NodeElse = struct {756pub const NodeElse = struct {
757 base: Node,757 base: Node,
758 else_token: Token,758 else_token: Token,
759 payload: ?&NodePayload,759 payload: ?&Node,
760 body: &Node,760 body: &Node,
761761
762 pub fn iterate(self: &NodeElse, index: usize) ?&Node {762 pub fn iterate(self: &NodeElse, index: usize) ?&Node {
763 var i = index;763 var i = index;
764764
765 if (self.payload) |payload| {765 if (self.payload) |payload| {
766 if (i < 1) return &payload.base;766 if (i < 1) return payload;
767 i -= 1;767 i -= 1;
768 }768 }
769769
...@@ -813,7 +813,7 @@ pub const NodeSwitch = struct {...@@ -813,7 +813,7 @@ pub const NodeSwitch = struct {
813pub const NodeSwitchCase = struct {813pub const NodeSwitchCase = struct {
814 base: Node,814 base: Node,
815 items: ArrayList(&Node),815 items: ArrayList(&Node),
816 payload: ?&NodePointerPayload,816 payload: ?&Node,
817 expr: &Node,817 expr: &Node,
818818
819 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {819 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
...@@ -823,7 +823,7 @@ pub const NodeSwitchCase = struct {...@@ -823,7 +823,7 @@ pub const NodeSwitchCase = struct {
823 i -= self.items.len;823 i -= self.items.len;
824824
825 if (self.payload) |payload| {825 if (self.payload) |payload| {
826 if (i < 1) return &payload.base;826 if (i < 1) return payload;
827 i -= 1;827 i -= 1;
828 }828 }
829829
...@@ -865,7 +865,7 @@ pub const NodeWhile = struct {...@@ -865,7 +865,7 @@ pub const NodeWhile = struct {
865 inline_token: ?Token,865 inline_token: ?Token,
866 while_token: Token,866 while_token: Token,
867 condition: &Node,867 condition: &Node,
868 payload: ?&NodePointerPayload,868 payload: ?&Node,
869 continue_expr: ?&Node,869 continue_expr: ?&Node,
870 body: &Node,870 body: &Node,
871 @"else": ?&NodeElse,871 @"else": ?&NodeElse,
...@@ -877,7 +877,7 @@ pub const NodeWhile = struct {...@@ -877,7 +877,7 @@ pub const NodeWhile = struct {
877 i -= 1;877 i -= 1;
878878
879 if (self.payload) |payload| {879 if (self.payload) |payload| {
880 if (i < 1) return &payload.base;880 if (i < 1) return payload;
881 i -= 1;881 i -= 1;
882 }882 }
883883
...@@ -924,7 +924,7 @@ pub const NodeFor = struct {...@@ -924,7 +924,7 @@ pub const NodeFor = struct {
924 inline_token: ?Token,924 inline_token: ?Token,
925 for_token: Token,925 for_token: Token,
926 array_expr: &Node,926 array_expr: &Node,
927 payload: ?&NodePointerIndexPayload,927 payload: ?&Node,
928 body: &Node,928 body: &Node,
929 @"else": ?&NodeElse,929 @"else": ?&NodeElse,
930930
...@@ -935,7 +935,7 @@ pub const NodeFor = struct {...@@ -935,7 +935,7 @@ pub const NodeFor = struct {
935 i -= 1;935 i -= 1;
936936
937 if (self.payload) |payload| {937 if (self.payload) |payload| {
938 if (i < 1) return &payload.base;938 if (i < 1) return payload;
939 i -= 1;939 i -= 1;
940 }940 }
941941
...@@ -975,7 +975,7 @@ pub const NodeIf = struct {...@@ -975,7 +975,7 @@ pub const NodeIf = struct {
975 base: Node,975 base: Node,
976 if_token: Token,976 if_token: Token,
977 condition: &Node,977 condition: &Node,
978 payload: ?&NodePointerPayload,978 payload: ?&Node,
979 body: &Node,979 body: &Node,
980 @"else": ?&NodeElse,980 @"else": ?&NodeElse,
981981
...@@ -986,7 +986,7 @@ pub const NodeIf = struct {...@@ -986,7 +986,7 @@ pub const NodeIf = struct {
986 i -= 1;986 i -= 1;
987987
988 if (self.payload) |payload| {988 if (self.payload) |payload| {
989 if (i < 1) return &payload.base;989 if (i < 1) return payload;
990 i -= 1;990 i -= 1;
991 }991 }
992992
...@@ -1048,7 +1048,7 @@ pub const NodeInfixOp = struct {...@@ -1048,7 +1048,7 @@ pub const NodeInfixOp = struct {
1048 BitXor,1048 BitXor,
1049 BoolAnd,1049 BoolAnd,
1050 BoolOr,1050 BoolOr,
1051 Catch: ?&NodePayload,1051 Catch: ?&Node,
1052 Div,1052 Div,
1053 EqualEqual,1053 EqualEqual,
1054 ErrorUnion,1054 ErrorUnion,
...@@ -1076,7 +1076,7 @@ pub const NodeInfixOp = struct {...@@ -1076,7 +1076,7 @@ pub const NodeInfixOp = struct {
1076 switch (self.op) {1076 switch (self.op) {
1077 InfixOp.Catch => |maybe_payload| {1077 InfixOp.Catch => |maybe_payload| {
1078 if (maybe_payload) |payload| {1078 if (maybe_payload) |payload| {
1079 if (i < 1) return &payload.base;1079 if (i < 1) return payload;
1080 i -= 1;1080 i -= 1;
1081 }1081 }
1082 },1082 },
...@@ -1344,14 +1344,30 @@ pub const NodeControlFlowExpression = struct {...@@ -1344,14 +1344,30 @@ pub const NodeControlFlowExpression = struct {
1344 rhs: ?&Node,1344 rhs: ?&Node,
13451345
1346 const Kind = union(enum) {1346 const Kind = union(enum) {
1347 Break: ?Token,1347 Break: ?&Node,
1348 Continue: ?Token,1348 Continue: ?&Node,
1349 Return,1349 Return,
1350 };1350 };
13511351
1352 pub fn iterate(self: &NodeControlFlowExpression, index: usize) ?&Node {1352 pub fn iterate(self: &NodeControlFlowExpression, index: usize) ?&Node {
1353 var i = index;1353 var i = index;
13541354
1355 switch (self.kind) {
1356 Kind.Break => |maybe_label| {
1357 if (maybe_label) |label| {
1358 if (i < 1) return label;
1359 i -= 1;
1360 }
1361 },
1362 Kind.Continue => |maybe_label| {
1363 if (maybe_label) |label| {
1364 if (i < 1) return label;
1365 i -= 1;
1366 }
1367 },
1368 Kind.Return => {},
1369 }
1370
1355 if (self.rhs) |rhs| {1371 if (self.rhs) |rhs| {
1356 if (i < 1) return rhs;1372 if (i < 1) return rhs;
1357 i -= 1;1373 i -= 1;
...@@ -1370,14 +1386,14 @@ pub const NodeControlFlowExpression = struct {...@@ -1370,14 +1386,14 @@ pub const NodeControlFlowExpression = struct {
1370 }1386 }
13711387
1372 switch (self.kind) {1388 switch (self.kind) {
1373 Kind.Break => |maybe_blk_token| {1389 Kind.Break => |maybe_label| {
1374 if (maybe_blk_token) |blk_token| {1390 if (maybe_label) |label| {
1375 return blk_token;1391 return label.lastToken();
1376 }1392 }
1377 },1393 },
1378 Kind.Continue => |maybe_blk_token| {1394 Kind.Continue => |maybe_label| {
1379 if (maybe_blk_token) |blk_token| {1395 if (maybe_label) |label| {
1380 return blk_token;1396 return label.lastToken();
1381 }1397 }
1382 },1398 },
1383 Kind.Return => return self.ltoken,1399 Kind.Return => return self.ltoken,
...@@ -1390,14 +1406,14 @@ pub const NodeControlFlowExpression = struct {...@@ -1390,14 +1406,14 @@ pub const NodeControlFlowExpression = struct {
1390pub const NodeSuspend = struct {1406pub const NodeSuspend = struct {
1391 base: Node,1407 base: Node,
1392 suspend_token: Token,1408 suspend_token: Token,
1393 payload: ?&NodePayload,1409 payload: ?&Node,
1394 body: ?&Node,1410 body: ?&Node,
13951411
1396 pub fn iterate(self: &NodeSuspend, index: usize) ?&Node {1412 pub fn iterate(self: &NodeSuspend, index: usize) ?&Node {
1397 var i = index;1413 var i = index;
13981414
1399 if (self.payload) |payload| {1415 if (self.payload) |payload| {
1400 if (i < 1) return &payload.base;1416 if (i < 1) return payload;
1401 i -= 1;1417 i -= 1;
1402 }1418 }
14031419
...@@ -1605,7 +1621,7 @@ pub const NodeThisLiteral = struct {...@@ -1605,7 +1621,7 @@ pub const NodeThisLiteral = struct {
16051621
1606pub const NodeAsmOutput = struct {1622pub const NodeAsmOutput = struct {
1607 base: Node,1623 base: Node,
1608 symbolic_name: &NodeIdentifier,1624 symbolic_name: &Node,
1609 constraint: &Node,1625 constraint: &Node,
1610 kind: Kind,1626 kind: Kind,
16111627
...@@ -1617,7 +1633,7 @@ pub const NodeAsmOutput = struct {...@@ -1617,7 +1633,7 @@ pub const NodeAsmOutput = struct {
1617 pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node {1633 pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node {
1618 var i = index;1634 var i = index;
16191635
1620 if (i < 1) return &self.symbolic_name.base;1636 if (i < 1) return self.symbolic_name;
1621 i -= 1;1637 i -= 1;
16221638
1623 if (i < 1) return self.constraint;1639 if (i < 1) return self.constraint;
...@@ -1651,14 +1667,14 @@ pub const NodeAsmOutput = struct {...@@ -1651,14 +1667,14 @@ pub const NodeAsmOutput = struct {
16511667
1652pub const NodeAsmInput = struct {1668pub const NodeAsmInput = struct {
1653 base: Node,1669 base: Node,
1654 symbolic_name: &NodeIdentifier,1670 symbolic_name: &Node,
1655 constraint: &Node,1671 constraint: &Node,
1656 expr: &Node,1672 expr: &Node,
16571673
1658 pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node {1674 pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node {
1659 var i = index;1675 var i = index;
16601676
1661 if (i < 1) return &self.symbolic_name.base;1677 if (i < 1) return self.symbolic_name;
1662 i -= 1;1678 i -= 1;
16631679
1664 if (i < 1) return self.constraint;1680 if (i < 1) return self.constraint;
...@@ -1682,7 +1698,7 @@ pub const NodeAsmInput = struct {...@@ -1682,7 +1698,7 @@ pub const NodeAsmInput = struct {
1682pub const NodeAsm = struct {1698pub const NodeAsm = struct {
1683 base: Node,1699 base: Node,
1684 asm_token: Token,1700 asm_token: Token,
1685 is_volatile: bool,1701 volatile_token: ?Token,
1686 template: &Node,1702 template: &Node,
1687 //tokens: ArrayList(AsmToken),1703 //tokens: ArrayList(AsmToken),
1688 outputs: ArrayList(&NodeAsmOutput),1704 outputs: ArrayList(&NodeAsmOutput),
std/zig/parser.zig+1941-1903
...@@ -59,29 +59,29 @@ pub const Parser = struct {...@@ -59,29 +59,29 @@ pub const Parser = struct {
59 lib_name: ?&ast.Node,59 lib_name: ?&ast.Node,
60 };60 };
6161
62 const ContainerExternCtx = struct {62 const VarDeclCtx = struct {
63 dest_ptr: DestPtr,63 mut_token: Token,
64 ltoken: Token,64 visib_token: ?Token,
65 layout: ast.NodeContainerDecl.Layout,65 comptime_token: ?Token,
66 extern_export_token: ?Token,
67 lib_name: ?&ast.Node,
68 list: &ArrayList(&ast.Node),
66 };69 };
6770
68 const DestPtr = union(enum) {71 const TopLevelExternOrFieldCtx = struct {
69 Field: &&ast.Node,72 visib_token: Token,
70 NullableField: &?&ast.Node,73 container_decl: &ast.NodeContainerDecl,
74 };
7175
72 pub fn store(self: &const DestPtr, value: &ast.Node) void {76 const ExternTypeCtx = struct {
73 switch (*self) {77 opt_ctx: OptionalCtx,
74 DestPtr.Field => |ptr| *ptr = value,78 extern_token: Token,
75 DestPtr.NullableField => |ptr| *ptr = value,79 };
76 }
77 }
7880
79 pub fn get(self: &const DestPtr) &ast.Node {81 const ContainerKindCtx = struct {
80 switch (*self) {82 opt_ctx: OptionalCtx,
81 DestPtr.Field => |ptr| return *ptr,83 ltoken: Token,
82 DestPtr.NullableField => |ptr| return ??*ptr,84 layout: ast.NodeContainerDecl.Layout,
83 }
84 }
85 };85 };
8686
87 const ExpectTokenSave = struct {87 const ExpectTokenSave = struct {
...@@ -89,13 +89,9 @@ pub const Parser = struct {...@@ -89,13 +89,9 @@ pub const Parser = struct {
89 ptr: &Token,89 ptr: &Token,
90 };90 };
9191
92 const RevertState = struct {92 const OptionalTokenSave = struct {
93 parser: Parser,93 id: Token.Id,
94 tokenizer: Tokenizer,94 ptr: &?Token,
95
96 // We expect, that if something is optional, then there is a field,
97 // that needs to be set to null, when we revert.
98 ptr: &?&ast.Node,
99 };95 };
10096
101 const ExprListCtx = struct {97 const ExprListCtx = struct {
...@@ -104,11 +100,6 @@ pub const Parser = struct {...@@ -104,11 +100,6 @@ pub const Parser = struct {
104 ptr: &Token,100 ptr: &Token,
105 };101 };
106102
107 const ElseCtx = struct {
108 payload: ?DestPtr,
109 body: DestPtr,
110 };
111
112 fn ListSave(comptime T: type) type {103 fn ListSave(comptime T: type) type {
113 return struct {104 return struct {
114 list: &ArrayList(T),105 list: &ArrayList(T),
...@@ -116,120 +107,196 @@ pub const Parser = struct {...@@ -116,120 +107,196 @@ pub const Parser = struct {
116 };107 };
117 }108 }
118109
110 const MaybeLabeledExpressionCtx = struct {
111 label: Token,
112 opt_ctx: OptionalCtx,
113 };
114
119 const LabelCtx = struct {115 const LabelCtx = struct {
120 label: ?Token,116 label: ?Token,
121 dest_ptr: DestPtr,117 opt_ctx: OptionalCtx,
122 };118 };
123119
124 const InlineCtx = struct {120 const InlineCtx = struct {
125 label: ?Token,121 label: ?Token,
126 inline_token: ?Token,122 inline_token: ?Token,
127 dest_ptr: DestPtr,123 opt_ctx: OptionalCtx,
128 };124 };
129125
130 const LoopCtx = struct {126 const LoopCtx = struct {
131 label: ?Token,127 label: ?Token,
132 inline_token: ?Token,128 inline_token: ?Token,
133 loop_token: Token,129 loop_token: Token,
134 dest_ptr: DestPtr,130 opt_ctx: OptionalCtx,
135 };131 };
136132
137 const AsyncEndCtx = struct {133 const AsyncEndCtx = struct {
138 dest_ptr: DestPtr,134 ctx: OptionalCtx,
139 attribute: &ast.NodeAsyncAttribute,135 attribute: &ast.NodeAsyncAttribute,
140 };136 };
141137
138 const ErrorTypeOrSetDeclCtx = struct {
139 opt_ctx: OptionalCtx,
140 error_token: Token,
141 };
142
143 const ParamDeclEndCtx = struct {
144 fn_proto: &ast.NodeFnProto,
145 param_decl: &ast.NodeParamDecl,
146 };
147
148 const ComptimeStatementCtx = struct {
149 comptime_token: Token,
150 block: &ast.NodeBlock,
151 };
152
153 const OptionalCtx = union(enum) {
154 Optional: &?&ast.Node,
155 RequiredNull: &?&ast.Node,
156 Required: &&ast.Node,
157
158 pub fn store(self: &const OptionalCtx, value: &ast.Node) void {
159 switch (*self) {
160 OptionalCtx.Optional => |ptr| *ptr = value,
161 OptionalCtx.RequiredNull => |ptr| *ptr = value,
162 OptionalCtx.Required => |ptr| *ptr = value,
163 }
164 }
165
166 pub fn get(self: &const OptionalCtx) ?&ast.Node {
167 switch (*self) {
168 OptionalCtx.Optional => |ptr| return *ptr,
169 OptionalCtx.RequiredNull => |ptr| return ??*ptr,
170 OptionalCtx.Required => |ptr| return *ptr,
171 }
172 }
173
174 pub fn toRequired(self: &const OptionalCtx) OptionalCtx {
175 switch (*self) {
176 OptionalCtx.Optional => |ptr| {
177 return OptionalCtx { .RequiredNull = ptr };
178 },
179 OptionalCtx.RequiredNull => |ptr| return *self,
180 OptionalCtx.Required => |ptr| return *self,
181 }
182 }
183 };
184
142 const State = union(enum) {185 const State = union(enum) {
143 TopLevel,186 TopLevel,
144 TopLevelExtern: TopLevelDeclCtx,187 TopLevelExtern: TopLevelDeclCtx,
145 TopLevelLibname: TopLevelDeclCtx,188 TopLevelLibname: TopLevelDeclCtx,
146 TopLevelDecl: TopLevelDeclCtx,189 TopLevelDecl: TopLevelDeclCtx,
147 ContainerExtern: ContainerExternCtx,190 TopLevelExternOrField: TopLevelExternOrFieldCtx,
191
192 ContainerKind: ContainerKindCtx,
193 ContainerInitArgStart: &ast.NodeContainerDecl,
194 ContainerInitArg: &ast.NodeContainerDecl,
148 ContainerDecl: &ast.NodeContainerDecl,195 ContainerDecl: &ast.NodeContainerDecl,
149 SliceOrArrayAccess: &ast.NodeSuffixOp,196
150 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,197 VarDecl: VarDeclCtx,
151 VarDecl: &ast.NodeVarDecl,
152 VarDeclAlign: &ast.NodeVarDecl,198 VarDeclAlign: &ast.NodeVarDecl,
153 VarDeclEq: &ast.NodeVarDecl,199 VarDeclEq: &ast.NodeVarDecl,
154 IfToken: @TagType(Token.Id),200
155 IfTokenSave: ExpectTokenSave,201 FnDef: &ast.NodeFnProto,
156 ExpectToken: @TagType(Token.Id),
157 ExpectTokenSave: ExpectTokenSave,
158 FnProto: &ast.NodeFnProto,202 FnProto: &ast.NodeFnProto,
159 FnProtoAlign: &ast.NodeFnProto,203 FnProtoAlign: &ast.NodeFnProto,
160 FnProtoReturnType: &ast.NodeFnProto,204 FnProtoReturnType: &ast.NodeFnProto,
205
161 ParamDecl: &ast.NodeFnProto,206 ParamDecl: &ast.NodeFnProto,
162 ParamDeclComma,207 ParamDeclAliasOrComptime: &ast.NodeParamDecl,
163 FnDef: &ast.NodeFnProto,208 ParamDeclName: &ast.NodeParamDecl,
209 ParamDeclEnd: ParamDeclEndCtx,
210 ParamDeclComma: &ast.NodeFnProto,
211
212 MaybeLabeledExpression: MaybeLabeledExpressionCtx,
164 LabeledExpression: LabelCtx,213 LabeledExpression: LabelCtx,
165 Inline: InlineCtx,214 Inline: InlineCtx,
166 While: LoopCtx,215 While: LoopCtx,
216 WhileContinueExpr: &?&ast.Node,
167 For: LoopCtx,217 For: LoopCtx,
168 Block: &ast.NodeBlock,
169 Else: &?&ast.NodeElse,218 Else: &?&ast.NodeElse,
170 WhileContinueExpr: &?&ast.Node,219
220 Block: &ast.NodeBlock,
171 Statement: &ast.NodeBlock,221 Statement: &ast.NodeBlock,
172 Semicolon: &const &const ast.Node,222 ComptimeStatement: ComptimeStatementCtx,
223 Semicolon: &&ast.Node,
224
173 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),225 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
226 AsmOutputReturnOrType: &ast.NodeAsmOutput,
174 AsmInputItems: &ArrayList(&ast.NodeAsmInput),227 AsmInputItems: &ArrayList(&ast.NodeAsmInput),
175 AsmClopperItems: &ArrayList(&ast.Node),228 AsmClopperItems: &ArrayList(&ast.Node),
229
176 ExprListItemOrEnd: ExprListCtx,230 ExprListItemOrEnd: ExprListCtx,
177 ExprListCommaOrEnd: ExprListCtx,231 ExprListCommaOrEnd: ExprListCtx,
178 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),232 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
179 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),233 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
180 FieldListCommaOrEnd: &ast.NodeContainerDecl,234 FieldListCommaOrEnd: &ast.NodeContainerDecl,
181 IdentifierListItemOrEnd: ListSave(&ast.NodeIdentifier),235 IdentifierListItemOrEnd: ListSave(&ast.Node),
182 IdentifierListCommaOrEnd: ListSave(&ast.NodeIdentifier),236 IdentifierListCommaOrEnd: ListSave(&ast.Node),
183 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),237 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
184 SuspendBody: &ast.NodeSuspend,
185 AsyncEnd: AsyncEndCtx,
186 Payload: &?&ast.NodePayload,
187 PointerPayload: &?&ast.NodePointerPayload,
188 PointerIndexPayload: &?&ast.NodePointerIndexPayload,
189 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),238 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
239 SwitchCaseFirstItem: &ArrayList(&ast.Node),
190 SwitchCaseItem: &ArrayList(&ast.Node),240 SwitchCaseItem: &ArrayList(&ast.Node),
191 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),241 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
192242
193 /// A state that can be appended before any other State. If an error occures,243 SuspendBody: &ast.NodeSuspend,
194 /// the parser will first try looking for the closest optional state. If an244 AsyncAllocator: &ast.NodeAsyncAttribute,
195 /// optional state is found, the parser will revert to the state it was in245 AsyncEnd: AsyncEndCtx,
196 /// when the optional was added. This will polute the arena allocator with246
197 /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes.247 ExternType: ExternTypeCtx,
198 Optional: RevertState,248 SliceOrArrayAccess: &ast.NodeSuffixOp,
199249 SliceOrArrayType: &ast.NodePrefixOp,
200 Expression: DestPtr,250 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
201 RangeExpressionBegin: DestPtr,251
202 RangeExpressionEnd: DestPtr,252 Payload: OptionalCtx,
203 AssignmentExpressionBegin: DestPtr,253 PointerPayload: OptionalCtx,
204 AssignmentExpressionEnd: DestPtr,254 PointerIndexPayload: OptionalCtx,
205 UnwrapExpressionBegin: DestPtr,255
206 UnwrapExpressionEnd: DestPtr,256 Expression: OptionalCtx,
207 BoolOrExpressionBegin: DestPtr,257 RangeExpressionBegin: OptionalCtx,
208 BoolOrExpressionEnd: DestPtr,258 RangeExpressionEnd: OptionalCtx,
209 BoolAndExpressionBegin: DestPtr,259 AssignmentExpressionBegin: OptionalCtx,
210 BoolAndExpressionEnd: DestPtr,260 AssignmentExpressionEnd: OptionalCtx,
211 ComparisonExpressionBegin: DestPtr,261 UnwrapExpressionBegin: OptionalCtx,
212 ComparisonExpressionEnd: DestPtr,262 UnwrapExpressionEnd: OptionalCtx,
213 BinaryOrExpressionBegin: DestPtr,263 BoolOrExpressionBegin: OptionalCtx,
214 BinaryOrExpressionEnd: DestPtr,264 BoolOrExpressionEnd: OptionalCtx,
215 BinaryXorExpressionBegin: DestPtr,265 BoolAndExpressionBegin: OptionalCtx,
216 BinaryXorExpressionEnd: DestPtr,266 BoolAndExpressionEnd: OptionalCtx,
217 BinaryAndExpressionBegin: DestPtr,267 ComparisonExpressionBegin: OptionalCtx,
218 BinaryAndExpressionEnd: DestPtr,268 ComparisonExpressionEnd: OptionalCtx,
219 BitShiftExpressionBegin: DestPtr,269 BinaryOrExpressionBegin: OptionalCtx,
220 BitShiftExpressionEnd: DestPtr,270 BinaryOrExpressionEnd: OptionalCtx,
221 AdditionExpressionBegin: DestPtr,271 BinaryXorExpressionBegin: OptionalCtx,
222 AdditionExpressionEnd: DestPtr,272 BinaryXorExpressionEnd: OptionalCtx,
223 MultiplyExpressionBegin: DestPtr,273 BinaryAndExpressionBegin: OptionalCtx,
224 MultiplyExpressionEnd: DestPtr,274 BinaryAndExpressionEnd: OptionalCtx,
225 CurlySuffixExpressionBegin: DestPtr,275 BitShiftExpressionBegin: OptionalCtx,
226 CurlySuffixExpressionEnd: DestPtr,276 BitShiftExpressionEnd: OptionalCtx,
227 TypeExprBegin: DestPtr,277 AdditionExpressionBegin: OptionalCtx,
228 TypeExprEnd: DestPtr,278 AdditionExpressionEnd: OptionalCtx,
229 PrefixOpExpression: DestPtr,279 MultiplyExpressionBegin: OptionalCtx,
230 SuffixOpExpressionBegin: DestPtr,280 MultiplyExpressionEnd: OptionalCtx,
231 SuffixOpExpressionEnd: DestPtr,281 CurlySuffixExpressionBegin: OptionalCtx,
232 PrimaryExpression: DestPtr,282 CurlySuffixExpressionEnd: OptionalCtx,
283 TypeExprBegin: OptionalCtx,
284 TypeExprEnd: OptionalCtx,
285 PrefixOpExpression: OptionalCtx,
286 SuffixOpExpressionBegin: OptionalCtx,
287 SuffixOpExpressionEnd: OptionalCtx,
288 PrimaryExpression: OptionalCtx,
289
290 ErrorTypeOrSetDecl: ErrorTypeOrSetDeclCtx,
291 StringLiteral: OptionalCtx,
292 Identifier: OptionalCtx,
293
294
295 IfToken: @TagType(Token.Id),
296 IfTokenSave: ExpectTokenSave,
297 ExpectToken: @TagType(Token.Id),
298 ExpectTokenSave: ExpectTokenSave,
299 OptionalTokenSave: OptionalTokenSave,
233 };300 };
234301
235 /// Returns an AST tree, allocated with the parser's allocator.302 /// Returns an AST tree, allocated with the parser's allocator.
...@@ -302,31 +369,31 @@ pub const Parser = struct {...@@ -302,31 +369,31 @@ pub const Parser = struct {
302 Token.Id.Keyword_test => {369 Token.Id.Keyword_test => {
303 stack.append(State.TopLevel) catch unreachable;370 stack.append(State.TopLevel) catch unreachable;
304371
305 const name_token = self.getNextToken();
306 const name = (try self.parseStringLiteral(arena, name_token)) ?? {
307 try self.parseError(&stack, name_token, "expected string literal, found {}", @tagName(name_token.id));
308 continue;
309 };
310 const lbrace = (try self.expectToken(&stack, Token.Id.LBrace)) ?? continue;
311
312 const block = try self.createNode(arena, ast.NodeBlock,372 const block = try self.createNode(arena, ast.NodeBlock,
313 ast.NodeBlock {373 ast.NodeBlock {
314 .base = undefined,374 .base = undefined,
315 .label = null,375 .label = null,
316 .lbrace = lbrace,376 .lbrace = undefined,
317 .statements = ArrayList(&ast.Node).init(arena),377 .statements = ArrayList(&ast.Node).init(arena),
318 .rbrace = undefined,378 .rbrace = undefined,
319 }379 }
320 );380 );
321 _ = try self.createAttachNode(arena, &root_node.decls, ast.NodeTestDecl,381 const test_node = try self.createAttachNode(arena, &root_node.decls, ast.NodeTestDecl,
322 ast.NodeTestDecl {382 ast.NodeTestDecl {
323 .base = undefined,383 .base = undefined,
324 .test_token = token,384 .test_token = token,
325 .name = name,385 .name = undefined,
326 .body_node = &block.base,386 .body_node = &block.base,
327 }387 }
328 );388 );
329 stack.append(State { .Block = block }) catch unreachable;389 stack.append(State { .Block = block }) catch unreachable;
390 try stack.append(State {
391 .ExpectTokenSave = ExpectTokenSave {
392 .id = Token.Id.LBrace,
393 .ptr = &block.rbrace,
394 }
395 });
396 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &test_node.name } });
330 continue;397 continue;
331 },398 },
332 Token.Id.Eof => {399 Token.Id.Eof => {
...@@ -346,15 +413,30 @@ pub const Parser = struct {...@@ -346,15 +413,30 @@ pub const Parser = struct {
346 continue;413 continue;
347 },414 },
348 Token.Id.Keyword_comptime => {415 Token.Id.Keyword_comptime => {
416 const block = try self.createNode(arena, ast.NodeBlock,
417 ast.NodeBlock {
418 .base = undefined,
419 .label = null,
420 .lbrace = undefined,
421 .statements = ArrayList(&ast.Node).init(arena),
422 .rbrace = undefined,
423 }
424 );
349 const node = try self.createAttachNode(arena, &root_node.decls, ast.NodeComptime,425 const node = try self.createAttachNode(arena, &root_node.decls, ast.NodeComptime,
350 ast.NodeComptime {426 ast.NodeComptime {
351 .base = undefined,427 .base = undefined,
352 .comptime_token = token,428 .comptime_token = token,
353 .expr = undefined,429 .expr = &block.base,
354 }430 }
355 );431 );
356 stack.append(State.TopLevel) catch unreachable;432 stack.append(State.TopLevel) catch unreachable;
357 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });433 try stack.append(State { .Block = block });
434 try stack.append(State {
435 .ExpectTokenSave = ExpectTokenSave {
436 .id = Token.Id.LBrace,
437 .ptr = &block.rbrace,
438 }
439 });
358 continue;440 continue;
359 },441 },
360 else => {442 else => {
...@@ -404,7 +486,6 @@ pub const Parser = struct {...@@ -404,7 +486,6 @@ pub const Parser = struct {
404 }486 }
405 }487 }
406 },488 },
407
408 State.TopLevelLibname => |ctx| {489 State.TopLevelLibname => |ctx| {
409 const lib_name = blk: {490 const lib_name = blk: {
410 const lib_name_token = self.getNextToken();491 const lib_name_token = self.getNextToken();
...@@ -422,15 +503,14 @@ pub const Parser = struct {...@@ -422,15 +503,14 @@ pub const Parser = struct {
422 .lib_name = lib_name,503 .lib_name = lib_name,
423 },504 },
424 }) catch unreachable;505 }) catch unreachable;
506 continue;
425 },507 },
426
427 State.TopLevelDecl => |ctx| {508 State.TopLevelDecl => |ctx| {
428 const token = self.getNextToken();509 const token = self.getNextToken();
429 switch (token.id) {510 switch (token.id) {
430 Token.Id.Keyword_use => {511 Token.Id.Keyword_use => {
431 if (ctx.extern_export_inline_token != null) {512 if (ctx.extern_export_inline_token != null) {
432 try self.parseError(&stack, token, "Invalid token {}", @tagName((??ctx.extern_export_inline_token).id));513 return self.parseError(token, "Invalid token {}", @tagName((??ctx.extern_export_inline_token).id));
433 continue;
434 }514 }
435515
436 const node = try self.createAttachNode(arena, ctx.decls, ast.NodeUse,516 const node = try self.createAttachNode(arena, ctx.decls, ast.NodeUse,
...@@ -447,60 +527,30 @@ pub const Parser = struct {...@@ -447,60 +527,30 @@ pub const Parser = struct {
447 .ptr = &node.semicolon_token,527 .ptr = &node.semicolon_token,
448 }528 }
449 }) catch unreachable;529 }) catch unreachable;
450 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });530 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
451 continue;531 continue;
452 },532 },
453 Token.Id.Keyword_var, Token.Id.Keyword_const => {533 Token.Id.Keyword_var, Token.Id.Keyword_const => {
454 if (ctx.extern_export_inline_token) |extern_export_inline_token| {534 if (ctx.extern_export_inline_token) |extern_export_inline_token| {
455 if (extern_export_inline_token.id == Token.Id.Keyword_inline) {535 if (extern_export_inline_token.id == Token.Id.Keyword_inline) {
456 try self.parseError(&stack, token, "Invalid token {}", @tagName(extern_export_inline_token.id));536 return self.parseError(token, "Invalid token {}", @tagName(extern_export_inline_token.id));
457 continue;
458 }537 }
459 }538 }
460539
461 const var_decl_node = try self.createAttachNode(arena, ctx.decls, ast.NodeVarDecl,540 stack.append(State {
462 ast.NodeVarDecl {541 .VarDecl = VarDeclCtx {
463 .base = undefined,
464 .visib_token = ctx.visib_token,542 .visib_token = ctx.visib_token,
465 .mut_token = token,543 .lib_name = ctx.lib_name,
466 .comptime_token = null,544 .comptime_token = null,
467 .extern_export_token = ctx.extern_export_inline_token,545 .extern_export_token = ctx.extern_export_inline_token,
468 .type_node = null,546 .mut_token = token,
469 .align_node = null,547 .list = ctx.decls
470 .init_node = null,
471 .lib_name = ctx.lib_name,
472 // initialized later
473 .name_token = undefined,
474 .eq_token = undefined,
475 .semicolon_token = undefined,
476 }
477 );
478 stack.append(State { .VarDecl = var_decl_node }) catch unreachable;
479 continue;
480 },
481 Token.Id.Keyword_fn => {
482 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,
483 ast.NodeFnProto {
484 .base = undefined,
485 .visib_token = ctx.visib_token,
486 .name_token = null,
487 .fn_token = token,
488 .params = ArrayList(&ast.Node).init(arena),
489 .return_type = undefined,
490 .var_args_token = null,
491 .extern_export_inline_token = ctx.extern_export_inline_token,
492 .cc_token = null,
493 .async_attr = null,
494 .body_node = null,
495 .lib_name = ctx.lib_name,
496 .align_expr = null,
497 }548 }
498 );549 }) catch unreachable;
499 stack.append(State { .FnDef = fn_proto }) catch unreachable;
500 try stack.append(State { .FnProto = fn_proto });
501 continue;550 continue;
502 },551 },
503 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 => {
504 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,554 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,
505 ast.NodeFnProto {555 ast.NodeFnProto {
506 .base = undefined,556 .base = undefined,
...@@ -511,7 +561,7 @@ pub const Parser = struct {...@@ -511,7 +561,7 @@ pub const Parser = struct {
511 .return_type = undefined,561 .return_type = undefined,
512 .var_args_token = null,562 .var_args_token = null,
513 .extern_export_inline_token = ctx.extern_export_inline_token,563 .extern_export_inline_token = ctx.extern_export_inline_token,
514 .cc_token = token,564 .cc_token = null,
515 .async_attr = null,565 .async_attr = null,
516 .body_node = null,566 .body_node = null,
517 .lib_name = ctx.lib_name,567 .lib_name = ctx.lib_name,
...@@ -520,126 +570,84 @@ pub const Parser = struct {...@@ -520,126 +570,84 @@ pub const Parser = struct {
520 );570 );
521 stack.append(State { .FnDef = fn_proto }) catch unreachable;571 stack.append(State { .FnDef = fn_proto }) catch unreachable;
522 try stack.append(State { .FnProto = fn_proto });572 try stack.append(State { .FnProto = fn_proto });
523 try stack.append(State {
524 .ExpectTokenSave = ExpectTokenSave {
525 .id = Token.Id.Keyword_fn,
526 .ptr = &fn_proto.fn_token,
527 }
528 });
529 continue;
530 },
531 Token.Id.Keyword_async => {
532 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
533 ast.NodeAsyncAttribute {
534 .base = undefined,
535 .async_token = token,
536 .allocator_type = null,
537 .rangle_bracket = null,
538 }
539 );
540573
541 const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto,574 switch (token.id) {
542 ast.NodeFnProto {575 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
543 .base = undefined,576 fn_proto.cc_token = token;
544 .visib_token = ctx.visib_token,577 try stack.append(State {
545 .name_token = null,578 .ExpectTokenSave = ExpectTokenSave {
546 .fn_token = undefined,579 .id = Token.Id.Keyword_fn,
547 .params = ArrayList(&ast.Node).init(arena),580 .ptr = &fn_proto.fn_token,
548 .return_type = undefined,581 }
549 .var_args_token = null,582 });
550 .extern_export_inline_token = ctx.extern_export_inline_token,583 continue;
551 .cc_token = null,584 },
552 .async_attr = async_node,585 Token.Id.Keyword_async => {
553 .body_node = null,586 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
554 .lib_name = ctx.lib_name,587 ast.NodeAsyncAttribute {
555 .align_expr = null,588 .base = undefined,
556 }589 .async_token = token,
557 );590 .allocator_type = null,
558 stack.append(State { .FnDef = fn_proto }) catch unreachable;591 .rangle_bracket = null,
559 try stack.append(State { .FnProto = fn_proto });592 }
560 try stack.append(State {593 );
561 .ExpectTokenSave = ExpectTokenSave {594 fn_proto.async_attr = async_node;
562 .id = Token.Id.Keyword_fn,
563 .ptr = &fn_proto.fn_token,
564 }
565 });
566595
567 const langle_bracket = self.getNextToken();596 try stack.append(State {
568 if (langle_bracket.id != Token.Id.AngleBracketLeft) {597 .ExpectTokenSave = ExpectTokenSave {
569 self.putBackToken(langle_bracket);598 .id = Token.Id.Keyword_fn,
570 continue;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,
571 }610 }
572
573 async_node.rangle_bracket = Token(undefined);
574 try stack.append(State {
575 .ExpectTokenSave = ExpectTokenSave {
576 .id = Token.Id.AngleBracketRight,
577 .ptr = &??async_node.rangle_bracket,
578 }
579 });
580 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } });
581 continue;
582 },611 },
583 else => {612 else => {
584 try self.parseError(&stack, token, "expected variable declaration or function, found {}", @tagName(token.id));613 return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id));
585 continue;
586 },614 },
587 }615 }
588 },616 },
589 State.VarDecl => |var_decl| {617 State.TopLevelExternOrField => |ctx| {
590 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;618 if (self.eatToken(Token.Id.Identifier)) |identifier| {
591 try stack.append(State { .TypeExprBegin = DestPtr {.NullableField = &var_decl.type_node} });619 std.debug.assert(ctx.container_decl.kind == ast.NodeContainerDecl.Kind.Struct);
592 try stack.append(State { .IfToken = Token.Id.Colon });620 const node = try self.createAttachNode(arena, &ctx.container_decl.fields_and_decls, ast.NodeStructField,
593 try stack.append(State {621 ast.NodeStructField {
594 .ExpectTokenSave = ExpectTokenSave {622 .base = undefined,
595 .id = Token.Id.Identifier,623 .visib_token = ctx.visib_token,
596 .ptr = &var_decl.name_token,624 .name_token = identifier,
597 }625 .type_expr = undefined,
598 });626 }
599 continue;627 );
600 },
601 State.VarDeclAlign => |var_decl| {
602 stack.append(State { .VarDeclEq = var_decl }) catch unreachable;
603628
604 const next_token = self.getNextToken();629 stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
605 if (next_token.id == Token.Id.Keyword_align) {630 try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } });
606 try stack.append(State { .ExpectToken = Token.Id.RParen });631 try stack.append(State { .ExpectToken = Token.Id.Colon });
607 try stack.append(State { .Expression = DestPtr{.NullableField = &var_decl.align_node} });
608 try stack.append(State { .ExpectToken = Token.Id.LParen });
609 continue;632 continue;
610 }633 }
611634
612 self.putBackToken(next_token);635 stack.append(State{ .ContainerDecl = ctx.container_decl }) catch unreachable;
613 continue;636 try stack.append(State {
614 },637 .TopLevelExtern = TopLevelDeclCtx {
615 State.VarDeclEq => |var_decl| {638 .decls = &ctx.container_decl.fields_and_decls,
616 const token = self.getNextToken();639 .visib_token = ctx.visib_token,
617 switch (token.id) {640 .extern_export_inline_token = null,
618 Token.Id.Equal => {641 .lib_name = null,
619 var_decl.eq_token = token;
620 stack.append(State {
621 .ExpectTokenSave = ExpectTokenSave {
622 .id = Token.Id.Semicolon,
623 .ptr = &var_decl.semicolon_token,
624 },
625 }) catch unreachable;
626 try stack.append(State { .Expression = DestPtr {.NullableField = &var_decl.init_node} });
627 continue;
628 },
629 Token.Id.Semicolon => {
630 var_decl.semicolon_token = token;
631 continue;
632 },
633 else => {
634 try self.parseError(&stack, token, "expected '=' or ';', found {}", @tagName(token.id));
635 continue;
636 }642 }
637 }643 });
644 continue;
638 },645 },
639646
640 State.ContainerExtern => |ctx| {647
648 State.ContainerKind => |ctx| {
641 const token = self.getNextToken();649 const token = self.getNextToken();
642 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeContainerDecl,650 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeContainerDecl,
643 ast.NodeContainerDecl {651 ast.NodeContainerDecl {
644 .base = undefined,652 .base = undefined,
645 .ltoken = ctx.ltoken,653 .ltoken = ctx.ltoken,
...@@ -649,15 +657,14 @@ pub const Parser = struct {...@@ -649,15 +657,14 @@ pub const Parser = struct {
649 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,657 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,
650 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,658 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,
651 else => {659 else => {
652 try self.parseError(&stack, token, "expected {}, {} or {}, found {}",660 return self.parseError(token, "expected {}, {} or {}, found {}",
653 @tagName(Token.Id.Keyword_struct),661 @tagName(Token.Id.Keyword_struct),
654 @tagName(Token.Id.Keyword_union),662 @tagName(Token.Id.Keyword_union),
655 @tagName(Token.Id.Keyword_enum),663 @tagName(Token.Id.Keyword_enum),
656 @tagName(token.id));664 @tagName(token.id));
657 continue;
658 },665 },
659 },666 },
660 .init_arg_expr = undefined,667 .init_arg_expr = ast.NodeContainerDecl.InitArg.None,
661 .fields_and_decls = ArrayList(&ast.Node).init(arena),668 .fields_and_decls = ArrayList(&ast.Node).init(arena),
662 .rbrace_token = undefined,669 .rbrace_token = undefined,
663 }670 }
...@@ -665,37 +672,36 @@ pub const Parser = struct {...@@ -665,37 +672,36 @@ pub const Parser = struct {
665672
666 stack.append(State { .ContainerDecl = node }) catch unreachable;673 stack.append(State { .ContainerDecl = node }) catch unreachable;
667 try stack.append(State { .ExpectToken = Token.Id.LBrace });674 try stack.append(State { .ExpectToken = Token.Id.LBrace });
675 try stack.append(State { .ContainerInitArgStart = node });
676 continue;
677 },
668678
669 const lparen = self.getNextToken();679 State.ContainerInitArgStart => |container_decl| {
670 if (lparen.id != Token.Id.LParen) {680 if (self.eatToken(Token.Id.LParen) == null) {
671 self.putBackToken(lparen);
672 node.init_arg_expr = ast.NodeContainerDecl.InitArg.None;
673 continue;681 continue;
674 }682 }
675683
676 try stack.append(State { .ExpectToken = Token.Id.RParen });684 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
685 try stack.append(State { .ContainerInitArg = container_decl });
686 continue;
687 },
677688
689 State.ContainerInitArg => |container_decl| {
678 const init_arg_token = self.getNextToken();690 const init_arg_token = self.getNextToken();
679 switch (init_arg_token.id) {691 switch (init_arg_token.id) {
680 Token.Id.Keyword_enum => {692 Token.Id.Keyword_enum => {
681 node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;693 container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;
682 },694 },
683 else => {695 else => {
684 self.putBackToken(init_arg_token);696 self.putBackToken(init_arg_token);
685 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };697 container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };
686 try stack.append(State {698 stack.append(State { .Expression = OptionalCtx { .Required = &container_decl.init_arg_expr.Type } }) catch unreachable;
687 .Expression = DestPtr {
688 .Field = &node.init_arg_expr.Type
689 }
690 });
691 },699 },
692 }700 }
693 continue;701 continue;
694 },702 },
695
696 State.ContainerDecl => |container_decl| {703 State.ContainerDecl => |container_decl| {
697 const token = self.getNextToken();704 const token = self.getNextToken();
698
699 switch (token.id) {705 switch (token.id) {
700 Token.Id.Identifier => {706 Token.Id.Identifier => {
701 switch (container_decl.kind) {707 switch (container_decl.kind) {
...@@ -710,7 +716,7 @@ pub const Parser = struct {...@@ -710,7 +716,7 @@ pub const Parser = struct {
710 );716 );
711717
712 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;718 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
713 try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } });719 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } });
714 try stack.append(State { .ExpectToken = Token.Id.Colon });720 try stack.append(State { .ExpectToken = Token.Id.Colon });
715 continue;721 continue;
716 },722 },
...@@ -724,14 +730,8 @@ pub const Parser = struct {...@@ -724,14 +730,8 @@ pub const Parser = struct {
724 );730 );
725731
726 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;732 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
727733 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &node.type_expr } });
728 const next = self.getNextToken();734 try stack.append(State { .IfToken = Token.Id.Colon });
729 if (next.id != Token.Id.Colon) {
730 self.putBackToken(next);
731 continue;
732 }
733
734 try stack.append(State { .Expression = DestPtr { .NullableField = &node.type_expr } });
735 continue;735 continue;
736 },736 },
737 ast.NodeContainerDecl.Kind.Enum => {737 ast.NodeContainerDecl.Kind.Enum => {
...@@ -744,52 +744,36 @@ pub const Parser = struct {...@@ -744,52 +744,36 @@ pub const Parser = struct {
744 );744 );
745745
746 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;746 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
747747 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &node.value } });
748 const next = self.getNextToken();748 try stack.append(State { .IfToken = Token.Id.Equal });
749 if (next.id != Token.Id.Equal) {
750 self.putBackToken(next);
751 continue;
752 }
753
754 try stack.append(State { .Expression = DestPtr { .NullableField = &node.value } });
755 continue;749 continue;
756 },750 },
757 }751 }
758 },752 },
759 Token.Id.Keyword_pub => {753 Token.Id.Keyword_pub => {
760 if (self.eatToken(Token.Id.Identifier)) |identifier| {754 switch (container_decl.kind) {
761 switch (container_decl.kind) {755 ast.NodeContainerDecl.Kind.Struct => {
762 ast.NodeContainerDecl.Kind.Struct => {756 try stack.append(State {
763 const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeStructField,757 .TopLevelExternOrField = TopLevelExternOrFieldCtx {
764 ast.NodeStructField {758 .visib_token = token,
765 .base = undefined,759 .container_decl = container_decl,
766 .visib_token = token,760 }
767 .name_token = identifier,761 });
768 .type_expr = undefined,762 continue;
769 }763 },
770 );764 else => {
771765 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
772 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;766 try stack.append(State {
773 try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } });767 .TopLevelExtern = TopLevelDeclCtx {
774 try stack.append(State { .ExpectToken = Token.Id.Colon });768 .decls = &container_decl.fields_and_decls,
775 continue;769 .visib_token = token,
776 },770 .extern_export_inline_token = null,
777 else => {771 .lib_name = null,
778 self.putBackToken(identifier);772 }
779 }773 });
774 continue;
780 }775 }
781 }776 }
782
783 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
784 try stack.append(State {
785 .TopLevelExtern = TopLevelDeclCtx {
786 .decls = &container_decl.fields_and_decls,
787 .visib_token = token,
788 .extern_export_inline_token = null,
789 .lib_name = null,
790 }
791 });
792 continue;
793 },777 },
794 Token.Id.Keyword_export => {778 Token.Id.Keyword_export => {
795 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;779 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
...@@ -823,1118 +807,554 @@ pub const Parser = struct {...@@ -823,1118 +807,554 @@ pub const Parser = struct {
823 }807 }
824 },808 },
825809
826 State.ExpectToken => |token_id| {
827 _ = (try self.expectToken(&stack, token_id)) ?? continue;
828 continue;
829 },
830810
831 State.ExpectTokenSave => |expect_token_save| {811 State.VarDecl => |ctx| {
832 *expect_token_save.ptr = (try self.expectToken(&stack, expect_token_save.id)) ?? continue;812 const var_decl = try self.createAttachNode(arena, ctx.list, ast.NodeVarDecl,
833 continue;813 ast.NodeVarDecl {
834 },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 );
835829
836 State.IfToken => |token_id| {830 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
837 const token = self.getNextToken();831 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });
838 if (@TagType(Token.Id)(token.id) != token_id) {832 try stack.append(State { .IfToken = Token.Id.Colon });
839 self.putBackToken(token);833 try stack.append(State {
840 _ = stack.pop();834 .ExpectTokenSave = ExpectTokenSave {
841 continue;835 .id = Token.Id.Identifier,
842 }836 .ptr = &var_decl.name_token,
837 }
838 });
843 continue;839 continue;
844 },840 },
841 State.VarDeclAlign => |var_decl| {
842 stack.append(State { .VarDeclEq = var_decl }) catch unreachable;
845843
846 State.IfTokenSave => |if_token_save| {844 const next_token = self.getNextToken();
847 const token = self.getNextToken();845 if (next_token.id == Token.Id.Keyword_align) {
848 if (@TagType(Token.Id)(token.id) != if_token_save.id) {846 try stack.append(State { .ExpectToken = Token.Id.RParen });
849 self.putBackToken(token);847 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.align_node} });
850 _ = stack.pop();848 try stack.append(State { .ExpectToken = Token.Id.LParen });
851 continue;849 continue;
852 }850 }
853851
854 *if_token_save.ptr = token;852 self.putBackToken(next_token);
855 continue;853 continue;
856 },854 },
857855 State.VarDeclEq => |var_decl| {
858 State.Optional => { },
859
860 State.Expression => |dest_ptr| {
861 const token = self.getNextToken();856 const token = self.getNextToken();
862 switch (token.id) {857 switch (token.id) {
863 Token.Id.Keyword_return => {858 Token.Id.Equal => {
864 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeControlFlowExpression,859 var_decl.eq_token = token;
865 ast.NodeControlFlowExpression {
866 .base = undefined,
867 .ltoken = token,
868 .kind = ast.NodeControlFlowExpression.Kind.Return,
869 .rhs = undefined,
870 }
871 );
872
873 // TODO: Find another way to do optional expressions
874 stack.append(State {
875 .Optional = RevertState {
876 .parser = *self,
877 .tokenizer = *self.tokenizer,
878 .ptr = &node.rhs,
879 }
880 }) catch unreachable;
881 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });
882 continue;
883 },
884 Token.Id.Keyword_break, Token.Id.Keyword_continue => {
885 const label = blk: {
886 const colon = self.getNextToken();
887 if (colon.id != Token.Id.Colon) {
888 self.putBackToken(colon);
889 break :blk null;
890 }
891
892 break :blk (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
893 };
894
895 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeControlFlowExpression,
896 ast.NodeControlFlowExpression {
897 .base = undefined,
898 .ltoken = token,
899 .kind = switch (token.id) {
900 Token.Id.Keyword_break => ast.NodeControlFlowExpression.Kind { .Break = label },
901 Token.Id.Keyword_continue => ast.NodeControlFlowExpression.Kind { .Continue = label },
902 else => unreachable,
903 },
904 .rhs = undefined,
905 }
906 );
907
908 // TODO: Find another way to do optional expressions
909 stack.append(State {860 stack.append(State {
910 .Optional = RevertState {861 .ExpectTokenSave = ExpectTokenSave {
911 .parser = *self,862 .id = Token.Id.Semicolon,
912 .tokenizer = *self.tokenizer,863 .ptr = &var_decl.semicolon_token,
913 .ptr = &node.rhs,864 },
914 }
915 }) catch unreachable;865 }) catch unreachable;
916 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });866 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } });
917 continue;867 continue;
918 },868 },
919 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {869 Token.Id.Semicolon => {
920 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,870 var_decl.semicolon_token = token;
921 ast.NodePrefixOp {
922 .base = undefined,
923 .op_token = token,
924 .op = switch (token.id) {
925 Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{} },
926 Token.Id.Keyword_cancel => ast.NodePrefixOp.PrefixOp { .Cancel = void{} },
927 Token.Id.Keyword_resume => ast.NodePrefixOp.PrefixOp { .Resume = void{} },
928 else => unreachable,
929 },
930 .rhs = undefined,
931 }
932 );
933
934 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
935 continue;871 continue;
936 },872 },
937 else => {873 else => {
938 if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) {874 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));
939 self.putBackToken(token);
940 stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable;
941 }
942 continue;
943 }875 }
944 }876 }
945 },877 },
946878
947 State.RangeExpressionBegin => |dest_ptr| {
948 stack.append(State { .RangeExpressionEnd = dest_ptr }) catch unreachable;
949 try stack.append(State { .Expression = dest_ptr });
950 continue;
951 },
952
953 State.RangeExpressionEnd => |dest_ptr| {
954 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
955 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
956 ast.NodeInfixOp {
957 .base = undefined,
958 .lhs = dest_ptr.get(),
959 .op_token = ellipsis3,
960 .op = ast.NodeInfixOp.InfixOp.Range,
961 .rhs = undefined,
962 }
963 );
964 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
965 }
966
967 continue;
968 },
969
970 State.AssignmentExpressionBegin => |dest_ptr| {
971 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
972 try stack.append(State { .Expression = dest_ptr });
973 continue;
974 },
975
976 State.AssignmentExpressionEnd => |dest_ptr| {
977 const token = self.getNextToken();
978 if (tokenIdToAssignment(token.id)) |ass_id| {
979 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
980 ast.NodeInfixOp {
981 .base = undefined,
982 .lhs = dest_ptr.get(),
983 .op_token = token,
984 .op = ass_id,
985 .rhs = undefined,
986 }
987 );
988 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
989 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
990 continue;
991 } else {
992 self.putBackToken(token);
993 continue;
994 }
995 },
996
997 State.UnwrapExpressionBegin => |dest_ptr| {
998 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
999 try stack.append(State { .BoolOrExpressionBegin = dest_ptr });
1000 continue;
1001 },
1002879
1003 State.UnwrapExpressionEnd => |dest_ptr| {880 State.FnDef => |fn_proto| {
1004 const token = self.getNextToken();881 const token = self.getNextToken();
1005 switch (token.id) {882 switch(token.id) {
1006 Token.Id.Keyword_catch, Token.Id.QuestionMarkQuestionMark => {883 Token.Id.LBrace => {
1007 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,884 const block = try self.createNode(arena, ast.NodeBlock,
1008 ast.NodeInfixOp {885 ast.NodeBlock {
1009 .base = undefined,886 .base = undefined,
1010 .lhs = dest_ptr.get(),887 .label = null,
1011 .op_token = token,888 .lbrace = token,
1012 .op = switch (token.id) {889 .statements = ArrayList(&ast.Node).init(arena),
1013 Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null },890 .rbrace = undefined,
1014 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} },
1015 else => unreachable,
1016 },
1017 .rhs = undefined,
1018 }891 }
1019 );892 );
1020893 fn_proto.body_node = &block.base;
1021 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;894 stack.append(State { .Block = block }) catch unreachable;
1022 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
1023
1024 if (node.op == ast.NodeInfixOp.InfixOp.Catch) {
1025 try stack.append(State { .Payload = &node.op.Catch });
1026 }
1027 continue;895 continue;
1028 },896 },
897 Token.Id.Semicolon => continue,
1029 else => {898 else => {
1030 self.putBackToken(token);899 return self.parseError(token, "expected ';' or '{{', found {}", @tagName(token.id));
1031 continue;
1032 },900 },
1033 }901 }
1034 },902 },
903 State.FnProto => |fn_proto| {
904 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
905 try stack.append(State { .ParamDecl = fn_proto });
906 try stack.append(State { .ExpectToken = Token.Id.LParen });
1035907
1036 State.BoolOrExpressionBegin => |dest_ptr| {908 if (self.eatToken(Token.Id.Identifier)) |name_token| {
1037 stack.append(State { .BoolOrExpressionEnd = dest_ptr }) catch unreachable;909 fn_proto.name_token = name_token;
1038 try stack.append(State { .BoolAndExpressionBegin = dest_ptr });910 }
1039 continue;911 continue;
1040 },912 },
913 State.FnProtoAlign => |fn_proto| {
914 stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable;
1041915
1042 State.BoolOrExpressionEnd => |dest_ptr| {916 if (self.eatToken(Token.Id.Keyword_align)) |align_token| {
1043 const token = self.getNextToken();917 try stack.append(State { .ExpectToken = Token.Id.RParen });
1044 switch (token.id) {918 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } });
1045 Token.Id.Keyword_or => {919 try stack.append(State { .ExpectToken = Token.Id.LParen });
1046 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1047 ast.NodeInfixOp {
1048 .base = undefined,
1049 .lhs = dest_ptr.get(),
1050 .op_token = token,
1051 .op = ast.NodeInfixOp.InfixOp.BoolOr,
1052 .rhs = undefined,
1053 }
1054 );
1055 stack.append(State { .BoolOrExpressionEnd = dest_ptr }) catch unreachable;
1056 try stack.append(State { .BoolAndExpressionBegin = DestPtr { .Field = &node.rhs } });
1057 continue;
1058 },
1059 else => {
1060 self.putBackToken(token);
1061 continue;
1062 },
1063 }920 }
1064 },
1065
1066 State.BoolAndExpressionBegin => |dest_ptr| {
1067 stack.append(State { .BoolAndExpressionEnd = dest_ptr }) catch unreachable;
1068 try stack.append(State { .ComparisonExpressionBegin = dest_ptr });
1069 continue;921 continue;
1070 },922 },
1071923 State.FnProtoReturnType => |fn_proto| {
1072 State.BoolAndExpressionEnd => |dest_ptr| {
1073 const token = self.getNextToken();924 const token = self.getNextToken();
1074 switch (token.id) {925 switch (token.id) {
1075 Token.Id.Keyword_and => {926 Token.Id.Bang => {
1076 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,927 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };
1077 ast.NodeInfixOp {928 stack.append(State {
1078 .base = undefined,929 .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet },
1079 .lhs = dest_ptr.get(),930 }) catch unreachable;
1080 .op_token = token,
1081 .op = ast.NodeInfixOp.InfixOp.BoolAnd,
1082 .rhs = undefined,
1083 }
1084 );
1085 stack.append(State { .BoolAndExpressionEnd = dest_ptr }) catch unreachable;
1086 try stack.append(State { .ComparisonExpressionBegin = DestPtr { .Field = &node.rhs } });
1087 continue;931 continue;
1088 },932 },
1089 else => {933 else => {
934 // TODO: this is a special case. Remove this when #760 is fixed
935 if (token.id == Token.Id.Keyword_error) {
936 if (self.isPeekToken(Token.Id.LBrace)) {
937 fn_proto.return_type = ast.NodeFnProto.ReturnType {
938 .Explicit = &(try self.createLiteral(arena, ast.NodeErrorType, token)).base
939 };
940 continue;
941 }
942 }
943
1090 self.putBackToken(token);944 self.putBackToken(token);
945 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
946 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable;
1091 continue;947 continue;
1092 },948 },
1093 }949 }
1094 },950 },
1095951
1096 State.ComparisonExpressionBegin => |dest_ptr| {
1097 stack.append(State { .ComparisonExpressionEnd = dest_ptr }) catch unreachable;
1098 try stack.append(State { .BinaryOrExpressionBegin = dest_ptr });
1099 continue;
1100 },
1101952
1102 State.ComparisonExpressionEnd => |dest_ptr| {953 State.ParamDecl => |fn_proto| {
1103 const token = self.getNextToken();954 if (self.eatToken(Token.Id.RParen)) |_| {
1104 if (tokenIdToComparison(token.id)) |comp_id| {
1105 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1106 ast.NodeInfixOp {
1107 .base = undefined,
1108 .lhs = dest_ptr.get(),
1109 .op_token = token,
1110 .op = comp_id,
1111 .rhs = undefined,
1112 }
1113 );
1114 stack.append(State { .ComparisonExpressionEnd = dest_ptr }) catch unreachable;
1115 try stack.append(State { .BinaryOrExpressionBegin = DestPtr { .Field = &node.rhs } });
1116 continue;
1117 } else {
1118 self.putBackToken(token);
1119 continue;955 continue;
1120 }956 }
1121 },957 const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.NodeParamDecl,
958 ast.NodeParamDecl {
959 .base = undefined,
960 .comptime_token = null,
961 .noalias_token = null,
962 .name_token = null,
963 .type_node = undefined,
964 .var_args_token = null,
965 },
966 );
1122967
1123 State.BinaryOrExpressionBegin => |dest_ptr| {968 stack.append(State {
1124 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;969 .ParamDeclEnd = ParamDeclEndCtx {
1125 try stack.append(State { .BinaryXorExpressionBegin = dest_ptr });970 .param_decl = param_decl,
971 .fn_proto = fn_proto,
972 }
973 }) catch unreachable;
974 try stack.append(State { .ParamDeclName = param_decl });
975 try stack.append(State { .ParamDeclAliasOrComptime = param_decl });
1126 continue;976 continue;
1127 },977 },
1128978 State.ParamDeclAliasOrComptime => |param_decl| {
1129 State.BinaryOrExpressionEnd => |dest_ptr| {979 if (self.eatToken(Token.Id.Keyword_comptime)) |comptime_token| {
1130 const token = self.getNextToken();980 param_decl.comptime_token = comptime_token;
1131 switch (token.id) {981 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {
1132 Token.Id.Pipe => {982 param_decl.noalias_token = noalias_token;
1133 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,983 }
1134 ast.NodeInfixOp {984 continue;
1135 .base = undefined,985 },
1136 .lhs = dest_ptr.get(),986 State.ParamDeclName => |param_decl| {
1137 .op_token = token,987 // TODO: Here, we eat two tokens in one state. This means that we can't have
1138 .op = ast.NodeInfixOp.InfixOp.BitOr,988 // comments between these two tokens.
1139 .rhs = undefined,989 if (self.eatToken(Token.Id.Identifier)) |ident_token| {
1140 }990 if (self.eatToken(Token.Id.Colon)) |_| {
1141 );991 param_decl.name_token = ident_token;
1142 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;992 } else {
1143 try stack.append(State { .BinaryXorExpressionBegin = DestPtr { .Field = &node.rhs } });993 self.putBackToken(ident_token);
1144 continue;994 }
1145 },
1146 else => {
1147 self.putBackToken(token);
1148 continue;
1149 },
1150 }995 }
996 continue;
1151 },997 },
998 State.ParamDeclEnd => |ctx| {
999 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
1000 ctx.param_decl.var_args_token = ellipsis3;
1001 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
1002 continue;
1003 }
11521004
1153 State.BinaryXorExpressionBegin => |dest_ptr| {1005 try stack.append(State { .ParamDeclComma = ctx.fn_proto });
1154 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;1006 try stack.append(State {
1155 try stack.append(State { .BinaryAndExpressionBegin = dest_ptr });1007 .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node }
1008 });
1009 continue;
1010 },
1011 State.ParamDeclComma => |fn_proto| {
1012 if ((try self.expectCommaOrEnd(Token.Id.RParen)) == null) {
1013 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;
1014 }
1156 continue;1015 continue;
1157 },1016 },
11581017
1159 State.BinaryXorExpressionEnd => |dest_ptr| {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 }
1028
1029 _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeIdentifier, ctx.label);
1030 continue;
1031 },
1032 State.LabeledExpression => |ctx| {
1160 const token = self.getNextToken();1033 const token = self.getNextToken();
1161 switch (token.id) {1034 switch (token.id) {
1162 Token.Id.Caret => {1035 Token.Id.LBrace => {
1163 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1036 const block = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeBlock,
1164 ast.NodeInfixOp {1037 ast.NodeBlock {
1165 .base = undefined,1038 .base = undefined,
1166 .lhs = dest_ptr.get(),1039 .label = ctx.label,
1167 .op_token = token,1040 .lbrace = token,
1168 .op = ast.NodeInfixOp.InfixOp.BitXor,1041 .statements = ArrayList(&ast.Node).init(arena),
1169 .rhs = undefined,1042 .rbrace = undefined,
1170 }1043 }
1171 );1044 );
1172 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;1045 stack.append(State { .Block = block }) catch unreachable;
1173 try stack.append(State { .BinaryAndExpressionBegin = DestPtr { .Field = &node.rhs } });1046 continue;
1047 },
1048 Token.Id.Keyword_while => {
1049 stack.append(State {
1050 .While = LoopCtx {
1051 .label = ctx.label,
1052 .inline_token = null,
1053 .loop_token = token,
1054 .opt_ctx = ctx.opt_ctx.toRequired(),
1055 }
1056 }) catch unreachable;
1057 continue;
1058 },
1059 Token.Id.Keyword_for => {
1060 stack.append(State {
1061 .For = LoopCtx {
1062 .label = ctx.label,
1063 .inline_token = null,
1064 .loop_token = token,
1065 .opt_ctx = ctx.opt_ctx.toRequired(),
1066 }
1067 }) catch unreachable;
1068 continue;
1069 },
1070 Token.Id.Keyword_inline => {
1071 stack.append(State {
1072 .Inline = InlineCtx {
1073 .label = ctx.label,
1074 .inline_token = token,
1075 .opt_ctx = ctx.opt_ctx.toRequired(),
1076 }
1077 }) catch unreachable;
1174 continue;1078 continue;
1175 },1079 },
1176 else => {1080 else => {
1081 if (ctx.opt_ctx != OptionalCtx.Optional) {
1082 return self.parseError(token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id));
1083 }
1084
1177 self.putBackToken(token);1085 self.putBackToken(token);
1178 continue;1086 continue;
1179 },1087 },
1180 }1088 }
1181 },1089 },
11821090 State.Inline => |ctx| {
1183 State.BinaryAndExpressionBegin => |dest_ptr| {
1184 stack.append(State { .BinaryAndExpressionEnd = dest_ptr }) catch unreachable;
1185 try stack.append(State { .BitShiftExpressionBegin = dest_ptr });
1186 continue;
1187 },
1188
1189 State.BinaryAndExpressionEnd => |dest_ptr| {
1190 const token = self.getNextToken();1091 const token = self.getNextToken();
1191 switch (token.id) {1092 switch (token.id) {
1192 Token.Id.Ampersand => {1093 Token.Id.Keyword_while => {
1193 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1094 stack.append(State {
1194 ast.NodeInfixOp {1095 .While = LoopCtx {
1195 .base = undefined,1096 .inline_token = ctx.inline_token,
1196 .lhs = dest_ptr.get(),1097 .label = ctx.label,
1197 .op_token = token,1098 .loop_token = token,
1198 .op = ast.NodeInfixOp.InfixOp.BitAnd,1099 .opt_ctx = ctx.opt_ctx.toRequired(),
1199 .rhs = undefined,
1200 }1100 }
1201 );1101 }) catch unreachable;
1202 stack.append(State { .BinaryAndExpressionEnd = dest_ptr }) catch unreachable;1102 continue;
1203 try stack.append(State { .BitShiftExpressionBegin = DestPtr { .Field = &node.rhs } });1103 },
1104 Token.Id.Keyword_for => {
1105 stack.append(State {
1106 .For = LoopCtx {
1107 .inline_token = ctx.inline_token,
1108 .label = ctx.label,
1109 .loop_token = token,
1110 .opt_ctx = ctx.opt_ctx.toRequired(),
1111 }
1112 }) catch unreachable;
1204 continue;1113 continue;
1205 },1114 },
1206 else => {1115 else => {
1116 if (ctx.opt_ctx != OptionalCtx.Optional) {
1117 return self.parseError(token, "expected 'while' or 'for', found {}", @tagName(token.id));
1118 }
1119
1207 self.putBackToken(token);1120 self.putBackToken(token);
1208 continue;1121 continue;
1209 },1122 },
1210 }1123 }
1211 },1124 },
12121125 State.While => |ctx| {
1213 State.BitShiftExpressionBegin => |dest_ptr| {1126 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeWhile,
1214 stack.append(State { .BitShiftExpressionEnd = dest_ptr }) catch unreachable;1127 ast.NodeWhile {
1215 try stack.append(State { .AdditionExpressionBegin = dest_ptr });1128 .base = undefined,
1129 .label = ctx.label,
1130 .inline_token = ctx.inline_token,
1131 .while_token = ctx.loop_token,
1132 .condition = undefined,
1133 .payload = null,
1134 .continue_expr = null,
1135 .body = undefined,
1136 .@"else" = null,
1137 }
1138 );
1139 stack.append(State { .Else = &node.@"else" }) catch unreachable;
1140 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
1141 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
1142 try stack.append(State { .IfToken = Token.Id.Colon });
1143 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
1144 try stack.append(State { .ExpectToken = Token.Id.RParen });
1145 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
1146 try stack.append(State { .ExpectToken = Token.Id.LParen });
1216 continue;1147 continue;
1217 },1148 },
12181149 State.WhileContinueExpr => |dest| {
1219 State.BitShiftExpressionEnd => |dest_ptr| {1150 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
1220 const token = self.getNextToken();1151 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } });
1221 if (tokenIdToBitShift(token.id)) |bitshift_id| {1152 try stack.append(State { .ExpectToken = Token.Id.LParen });
1222 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1223 ast.NodeInfixOp {
1224 .base = undefined,
1225 .lhs = dest_ptr.get(),
1226 .op_token = token,
1227 .op = bitshift_id,
1228 .rhs = undefined,
1229 }
1230 );
1231 stack.append(State { .BitShiftExpressionEnd = dest_ptr }) catch unreachable;
1232 try stack.append(State { .AdditionExpressionBegin = DestPtr { .Field = &node.rhs } });
1233 continue;
1234 } else {
1235 self.putBackToken(token);
1236 continue;
1237 }
1238 },
1239
1240 State.AdditionExpressionBegin => |dest_ptr| {
1241 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;
1242 try stack.append(State { .MultiplyExpressionBegin = dest_ptr });
1243 continue;1153 continue;
1244 },1154 },
12451155 State.For => |ctx| {
1246 State.AdditionExpressionEnd => |dest_ptr| {1156 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFor,
1247 const token = self.getNextToken();1157 ast.NodeFor {
1248 if (tokenIdToAddition(token.id)) |add_id| {1158 .base = undefined,
1249 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1159 .label = ctx.label,
1250 ast.NodeInfixOp {1160 .inline_token = ctx.inline_token,
1251 .base = undefined,1161 .for_token = ctx.loop_token,
1252 .lhs = dest_ptr.get(),1162 .array_expr = undefined,
1253 .op_token = token,1163 .payload = null,
1254 .op = add_id,1164 .body = undefined,
1255 .rhs = undefined,1165 .@"else" = null,
1256 }1166 }
1257 );1167 );
1258 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;1168 stack.append(State { .Else = &node.@"else" }) catch unreachable;
1259 try stack.append(State { .MultiplyExpressionBegin = DestPtr { .Field = &node.rhs } });1169 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
1260 continue;1170 try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } });
1261 } else {1171 try stack.append(State { .ExpectToken = Token.Id.RParen });
1262 self.putBackToken(token);1172 try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } });
1263 continue;1173 try stack.append(State { .ExpectToken = Token.Id.LParen });
1264 }
1265 },
1266
1267 State.MultiplyExpressionBegin => |dest_ptr| {
1268 stack.append(State { .MultiplyExpressionEnd = dest_ptr }) catch unreachable;
1269 try stack.append(State { .CurlySuffixExpressionBegin = dest_ptr });
1270 continue;1174 continue;
1271 },1175 },
12721176 State.Else => |dest| {
1273 State.MultiplyExpressionEnd => |dest_ptr| {1177 if (self.eatToken(Token.Id.Keyword_else)) |else_token| {
1274 const token = self.getNextToken();1178 const node = try self.createNode(arena, ast.NodeElse,
1275 if (tokenIdToMultiply(token.id)) |mult_id| {1179 ast.NodeElse {
1276 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1277 ast.NodeInfixOp {
1278 .base = undefined,1180 .base = undefined,
1279 .lhs = dest_ptr.get(),1181 .else_token = else_token,
1280 .op_token = token,1182 .payload = null,
1281 .op = mult_id,1183 .body = undefined,
1282 .rhs = undefined,
1283 }1184 }
1284 );1185 );
1285 stack.append(State { .MultiplyExpressionEnd = dest_ptr }) catch unreachable;1186 *dest = node;
1286 try stack.append(State { .CurlySuffixExpressionBegin = DestPtr { .Field = &node.rhs } });
1287 continue;
1288 } else {
1289 self.putBackToken(token);
1290 continue;
1291 }
1292 },
1293
1294 State.CurlySuffixExpressionBegin => |dest_ptr| {
1295 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
1296 try stack.append(State { .TypeExprBegin = dest_ptr });
1297 continue;
1298 },
1299
1300 State.CurlySuffixExpressionEnd => |dest_ptr| {
1301 if (self.eatToken(Token.Id.LBrace) == null) {
1302 continue;
1303 }
13041187
1305 if (self.isPeekToken(Token.Id.Period)) {1188 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
1306 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,1189 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
1307 ast.NodeSuffixOp {
1308 .base = undefined,
1309 .lhs = dest_ptr.get(),
1310 .op = ast.NodeSuffixOp.SuffixOp {
1311 .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),
1312 },
1313 .rtoken = undefined,
1314 }
1315 );
1316 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
1317 try stack.append(State {
1318 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
1319 .list = &node.op.StructInitializer,
1320 .ptr = &node.rtoken,
1321 }
1322 });
1323 continue;1190 continue;
1324 } else {1191 } else {
1325 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,
1326 ast.NodeSuffixOp {
1327 .base = undefined,
1328 .lhs = dest_ptr.get(),
1329 .op = ast.NodeSuffixOp.SuffixOp {
1330 .ArrayInitializer = ArrayList(&ast.Node).init(arena),
1331 },
1332 .rtoken = undefined,
1333 }
1334 );
1335 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
1336 try stack.append(State {
1337 .ExprListItemOrEnd = ExprListCtx {
1338 .list = &node.op.ArrayInitializer,
1339 .end = Token.Id.RBrace,
1340 .ptr = &node.rtoken,
1341 }
1342 });
1343 continue;1192 continue;
1344 }1193 }
1345 },1194 },
13461195
1347 State.TypeExprBegin => |dest_ptr| {
1348 stack.append(State { .TypeExprEnd = dest_ptr }) catch unreachable;
1349 try stack.append(State { .PrefixOpExpression = dest_ptr });
1350 continue;
1351 },
13521196
1353 State.TypeExprEnd => |dest_ptr| {1197 State.Block => |block| {
1354 const token = self.getNextToken();1198 const token = self.getNextToken();
1355 switch (token.id) {1199 switch (token.id) {
1356 Token.Id.Bang => {1200 Token.Id.RBrace => {
1357 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1201 block.rbrace = token;
1358 ast.NodeInfixOp {
1359 .base = undefined,
1360 .lhs = dest_ptr.get(),
1361 .op_token = token,
1362 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,
1363 .rhs = undefined,
1364 }
1365 );
1366 stack.append(State { .TypeExprEnd = dest_ptr }) catch unreachable;
1367 try stack.append(State { .PrefixOpExpression = DestPtr { .Field = &node.rhs } });
1368 continue;1202 continue;
1369 },1203 },
1370 else => {1204 else => {
1371 self.putBackToken(token);1205 self.putBackToken(token);
1206 stack.append(State { .Block = block }) catch unreachable;
1207 try stack.append(State { .Statement = block });
1372 continue;1208 continue;
1373 },1209 },
1374 }1210 }
1375 },1211 },
13761212 State.Statement => |block| {
1377 State.PrefixOpExpression => |dest_ptr| {
1378 const token = self.getNextToken();
1379 if (tokenIdToPrefixOp(token.id)) |prefix_id| {
1380 var node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,
1381 ast.NodePrefixOp {
1382 .base = undefined,
1383 .op_token = token,
1384 .op = prefix_id,
1385 .rhs = undefined,
1386 }
1387 );
1388
1389 if (token.id == Token.Id.AsteriskAsterisk) {
1390 const child = try self.createNode(arena, ast.NodePrefixOp,
1391 ast.NodePrefixOp {
1392 .base = undefined,
1393 .op_token = token,
1394 .op = prefix_id,
1395 .rhs = undefined,
1396 }
1397 );
1398 node.rhs = &child.base;
1399 node = child;
1400 }
1401
1402 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1403 if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) {
1404 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });
1405 }
1406 continue;
1407 } else {
1408 self.putBackToken(token);
1409 stack.append(State { .SuffixOpExpressionBegin = dest_ptr }) catch unreachable;
1410 continue;
1411 }
1412 },
1413
1414 State.SuffixOpExpressionBegin => |dest_ptr| {
1415 const token = self.getNextToken();1213 const token = self.getNextToken();
1416 switch (token.id) {1214 switch (token.id) {
1417 Token.Id.Keyword_async => {1215 Token.Id.Keyword_comptime => {
1418 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
1419 ast.NodeAsyncAttribute {
1420 .base = undefined,
1421 .async_token = token,
1422 .allocator_type = null,
1423 .rangle_bracket = null,
1424 }
1425 );
1426 stack.append(State {1216 stack.append(State {
1427 .AsyncEnd = AsyncEndCtx {1217 .ComptimeStatement = ComptimeStatementCtx {
1428 .dest_ptr = dest_ptr,1218 .comptime_token = token,
1429 .attribute = async_node,1219 .block = block,
1430 }1220 }
1431 }) catch unreachable;1221 }) catch unreachable;
1432 try stack.append(State { .SuffixOpExpressionEnd = dest_ptr });
1433 try stack.append(State { .PrimaryExpression = dest_ptr });
1434
1435 const langle_bracket = self.getNextToken();
1436 if (langle_bracket.id != Token.Id.AngleBracketLeft) {
1437 self.putBackToken(langle_bracket);
1438 continue;
1439 }
1440
1441 async_node.rangle_bracket = Token(undefined);
1442 try stack.append(State {
1443 .ExpectTokenSave = ExpectTokenSave {
1444 .id = Token.Id.AngleBracketRight,
1445 .ptr = &??async_node.rangle_bracket,
1446 }
1447 });
1448 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } });
1449 continue;1222 continue;
1450 },1223 },
1451 else => {1224 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1452 self.putBackToken(token);1225 stack.append(State {
1453 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1226 .VarDecl = VarDeclCtx {
1454 try stack.append(State { .PrimaryExpression = dest_ptr });1227 .visib_token = null,
1455 continue;1228 .comptime_token = null,
1456 }1229 .extern_export_token = null,
1457 }1230 .lib_name = null,
1458 },1231 .mut_token = token,
14591232 .list = &block.statements,
1460 State.SuffixOpExpressionEnd => |dest_ptr| {
1461 const token = self.getNextToken();
1462 switch (token.id) {
1463 Token.Id.LParen => {
1464 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,
1465 ast.NodeSuffixOp {
1466 .base = undefined,
1467 .lhs = dest_ptr.get(),
1468 .op = ast.NodeSuffixOp.SuffixOp {
1469 .Call = ast.NodeSuffixOp.CallInfo {
1470 .params = ArrayList(&ast.Node).init(arena),
1471 .async_attr = null,
1472 }
1473 },
1474 .rtoken = undefined,
1475 }
1476 );
1477 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1478 try stack.append(State {
1479 .ExprListItemOrEnd = ExprListCtx {
1480 .list = &node.op.Call.params,
1481 .end = Token.Id.RParen,
1482 .ptr = &node.rtoken,
1483 }1233 }
1484 });1234 }) catch unreachable;
1485 continue;1235 continue;
1486 },1236 },
1487 Token.Id.LBracket => {1237 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1488 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,1238 const node = try self.createAttachNode(arena, &block.statements, ast.NodeDefer,
1489 ast.NodeSuffixOp {1239 ast.NodeDefer {
1490 .base = undefined,1240 .base = undefined,
1491 .lhs = dest_ptr.get(),1241 .defer_token = token,
1492 .op = ast.NodeSuffixOp.SuffixOp {1242 .kind = switch (token.id) {
1493 .ArrayAccess = undefined,1243 Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional,
1244 Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error,
1245 else => unreachable,
1494 },1246 },
1495 .rtoken = undefined1247 .expr = undefined,
1496 }1248 }
1497 );1249 );
1498 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1250 stack.append(State { .Semicolon = &&node.base }) catch unreachable;
1499 try stack.append(State { .SliceOrArrayAccess = node });1251 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
1500 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }});
1501 continue;1252 continue;
1502 },1253 },
1503 Token.Id.Period => {1254 Token.Id.LBrace => {
1504 const identifier = try self.createLiteral(arena, ast.NodeIdentifier, Token(undefined));1255 const inner_block = try self.createAttachNode(arena, &block.statements, ast.NodeBlock,
1505 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1256 ast.NodeBlock {
1506 ast.NodeInfixOp {
1507 .base = undefined,1257 .base = undefined,
1508 .lhs = dest_ptr.get(),1258 .label = null,
1509 .op_token = token,1259 .lbrace = token,
1510 .op = ast.NodeInfixOp.InfixOp.Period,1260 .statements = ArrayList(&ast.Node).init(arena),
1511 .rhs = &identifier.base,1261 .rbrace = undefined,
1512 }1262 }
1513 );1263 );
1514 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1264 stack.append(State { .Block = inner_block }) catch unreachable;
1515 try stack.append(State {
1516 .ExpectTokenSave = ExpectTokenSave {
1517 .id = Token.Id.Identifier,
1518 .ptr = &identifier.token
1519 }
1520 });
1521 continue;1265 continue;
1522 },1266 },
1523 else => {1267 else => {
1524 self.putBackToken(token);1268 self.putBackToken(token);
1269 const statememt = try block.statements.addOne();
1270 stack.append(State { .Semicolon = statememt }) catch unreachable;
1271 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statememt } });
1525 continue;1272 continue;
1526 },1273 }
1527 }1274 }
1528 },1275 },
15291276 State.ComptimeStatement => |ctx| {
1530 State.PrimaryExpression => |dest_ptr| {
1531 const token = self.getNextToken();1277 const token = self.getNextToken();
1532 switch (token.id) {1278 switch (token.id) {
1533 Token.Id.IntegerLiteral => {1279 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1534 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeStringLiteral, token)).base);
1535 continue;
1536 },
1537 Token.Id.FloatLiteral => {
1538 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeFloatLiteral, token)).base);
1539 continue;
1540 },
1541 Token.Id.CharLiteral => {
1542 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeCharLiteral, token)).base);
1543 continue;
1544 },
1545 Token.Id.Keyword_undefined => {
1546 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeUndefinedLiteral, token)).base);
1547 continue;
1548 },
1549 Token.Id.Keyword_true, Token.Id.Keyword_false => {
1550 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeBoolLiteral, token)).base);
1551 continue;
1552 },
1553 Token.Id.Keyword_null => {
1554 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeNullLiteral, token)).base);
1555 continue;
1556 },
1557 Token.Id.Keyword_this => {
1558 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeThisLiteral, token)).base);
1559 continue;
1560 },
1561 Token.Id.Keyword_var => {
1562 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeVarType, token)).base);
1563 continue;
1564 },
1565 Token.Id.Keyword_unreachable => {
1566 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeUnreachable, token)).base);
1567 continue;
1568 },
1569 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
1570 dest_ptr.store((try self.parseStringLiteral(arena, token)) ?? unreachable);
1571 },
1572 Token.Id.LParen => {
1573 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeGroupedExpression,
1574 ast.NodeGroupedExpression {
1575 .base = undefined,
1576 .lparen = token,
1577 .expr = undefined,
1578 .rparen = undefined,
1579 }
1580 );
1581 stack.append(State {1280 stack.append(State {
1582 .ExpectTokenSave = ExpectTokenSave {1281 .VarDecl = VarDeclCtx {
1583 .id = Token.Id.RParen,1282 .visib_token = null,
1584 .ptr = &node.rparen,1283 .comptime_token = ctx.comptime_token,
1284 .extern_export_token = null,
1285 .lib_name = null,
1286 .mut_token = token,
1287 .list = &ctx.block.statements,
1585 }1288 }
1586 }) catch unreachable;1289 }) catch unreachable;
1587 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1588 continue;1290 continue;
1589 },1291 },
1590 Token.Id.Builtin => {1292 else => {
1591 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeBuiltinCall,1293 self.putBackToken(token);
1592 ast.NodeBuiltinCall {1294 self.putBackToken(ctx.comptime_token);
1593 .base = undefined,1295 const statememt = try ctx.block.statements.addOne();
1594 .builtin_token = token,1296 stack.append(State { .Semicolon = statememt }) catch unreachable;
1595 .params = ArrayList(&ast.Node).init(arena),1297 try stack.append(State { .Expression = OptionalCtx { .Required = statememt } });
1596 .rparen_token = undefined,
1597 }
1598 );
1599 stack.append(State {
1600 .ExprListItemOrEnd = ExprListCtx {
1601 .list = &node.params,
1602 .end = Token.Id.RParen,
1603 .ptr = &node.rparen_token,
1604 }
1605 }) catch unreachable;
1606 try stack.append(State { .ExpectToken = Token.Id.LParen, });
1607 continue;1298 continue;
1608 },1299 }
1609 Token.Id.LBracket => {1300 }
1610 const rbracket_token = self.getNextToken();1301 },
1611 if (rbracket_token.id == Token.Id.RBracket) {1302 State.Semicolon => |node_ptr| {
1612 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,1303 const node = *node_ptr;
1613 ast.NodePrefixOp {1304 if (requireSemiColon(node)) {
1614 .base = undefined,1305 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1615 .op_token = token,1306 continue;
1616 .op = ast.NodePrefixOp.PrefixOp{1307 }
1617 .SliceType = ast.NodePrefixOp.AddrOfInfo {1308 continue;
1618 .align_expr = null,1309 },
1619 .bit_offset_start_token = null,
1620 .bit_offset_end_token = null,
1621 .const_token = null,
1622 .volatile_token = null,
1623 }
1624 },
1625 .rhs = undefined,
1626 }
1627 );
1628 dest_ptr.store(&node.base);
1629 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1630 try stack.append(State { .AddrOfModifiers = &node.op.SliceType });
1631 continue;
1632 }
1633
1634 self.putBackToken(rbracket_token);
16351310
1636 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,
1637 ast.NodePrefixOp {
1638 .base = undefined,
1639 .op_token = token,
1640 .op = ast.NodePrefixOp.PrefixOp{
1641 .ArrayType = undefined,
1642 },
1643 .rhs = undefined,
1644 }
1645 );
1646 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1647 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1648 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayType } });
16491311
1650 },1312 State.AsmOutputItems => |items| {
1651 Token.Id.Keyword_error => {1313 const lbracket = self.getNextToken();
1652 if (self.eatToken(Token.Id.LBrace) == null) {1314 if (lbracket.id != Token.Id.LBracket) {
1653 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeErrorType, token)).base);1315 self.putBackToken(lbracket);
1654 continue;1316 continue;
1655 }1317 }
16561318
1657 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeErrorSetDecl,1319 const node = try self.createNode(arena, ast.NodeAsmOutput,
1658 ast.NodeErrorSetDecl {1320 ast.NodeAsmOutput {
1659 .base = undefined,1321 .base = undefined,
1660 .error_token = token,1322 .symbolic_name = undefined,
1661 .decls = ArrayList(&ast.NodeIdentifier).init(arena),1323 .constraint = undefined,
1662 .rbrace_token = undefined,1324 .kind = undefined,
1663 }1325 }
1664 );1326 );
1327 try items.append(node);
16651328
1666 stack.append(State {1329 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1667 .IdentifierListItemOrEnd = ListSave(&ast.NodeIdentifier) {1330 try stack.append(State { .IfToken = Token.Id.Comma });
1668 .list = &node.decls,1331 try stack.append(State { .ExpectToken = Token.Id.RParen });
1669 .ptr = &node.rbrace_token,1332 try stack.append(State { .AsmOutputReturnOrType = node });
1670 }1333 try stack.append(State { .ExpectToken = Token.Id.LParen });
1671 }) catch unreachable;1334 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1335 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1336 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1337 continue;
1338 },
1339 State.AsmOutputReturnOrType => |node| {
1340 const token = self.getNextToken();
1341 switch (token.id) {
1342 Token.Id.Identifier => {
1343 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.NodeIdentifier, token) };
1672 continue;1344 continue;
1673 },1345 },
1674 Token.Id.Keyword_packed => {1346 Token.Id.Arrow => {
1675 stack.append(State {1347 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
1676 .ContainerExtern = ContainerExternCtx {1348 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } });
1677 .dest_ptr = dest_ptr,1349 continue;
1678 .ltoken = token,
1679 .layout = ast.NodeContainerDecl.Layout.Packed,
1680 },
1681 }) catch unreachable;
1682 },
1683 Token.Id.Keyword_extern => {
1684 const next = self.getNextToken();
1685 if (next.id == Token.Id.Keyword_fn) {
1686 const fn_proto = try self.createToDestNode(arena, dest_ptr, ast.NodeFnProto,
1687 ast.NodeFnProto {
1688 .base = undefined,
1689 .visib_token = null,
1690 .name_token = null,
1691 .fn_token = next,
1692 .params = ArrayList(&ast.Node).init(arena),
1693 .return_type = undefined,
1694 .var_args_token = null,
1695 .extern_export_inline_token = token,
1696 .cc_token = null,
1697 .async_attr = null,
1698 .body_node = null,
1699 .lib_name = null,
1700 .align_expr = null,
1701 }
1702 );
1703 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1704 continue;
1705 }
1706
1707 self.putBackToken(next);
1708 stack.append(State {
1709 .ContainerExtern = ContainerExternCtx {
1710 .dest_ptr = dest_ptr,
1711 .ltoken = token,
1712 .layout = ast.NodeContainerDecl.Layout.Extern,
1713 },
1714 }) catch unreachable;
1715 },1350 },
1716 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {1351 else => {
1717 self.putBackToken(token);1352 return self.parseError(token, "expected '->' or {}, found {}",
1718 stack.append(State {1353 @tagName(Token.Id.Identifier),
1719 .ContainerExtern = ContainerExternCtx {1354 @tagName(token.id));
1720 .dest_ptr = dest_ptr,
1721 .ltoken = token,
1722 .layout = ast.NodeContainerDecl.Layout.Auto,
1723 },
1724 }) catch unreachable;
1725 },
1726 Token.Id.Identifier => {
1727 const next = self.getNextToken();
1728 if (next.id != Token.Id.Colon) {
1729 self.putBackToken(next);
1730 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeIdentifier, token)).base);
1731 continue;
1732 }
1733
1734 stack.append(State {
1735 .LabeledExpression = LabelCtx {
1736 .label = token,
1737 .dest_ptr = dest_ptr
1738 }
1739 }) catch unreachable;
1740 continue;
1741 },
1742 Token.Id.Keyword_fn => {
1743 const fn_proto = try self.createToDestNode(arena, dest_ptr, ast.NodeFnProto,
1744 ast.NodeFnProto {
1745 .base = undefined,
1746 .visib_token = null,
1747 .name_token = null,
1748 .fn_token = token,
1749 .params = ArrayList(&ast.Node).init(arena),
1750 .return_type = undefined,
1751 .var_args_token = null,
1752 .extern_export_inline_token = null,
1753 .cc_token = null,
1754 .async_attr = null,
1755 .body_node = null,
1756 .lib_name = null,
1757 .align_expr = null,
1758 }
1759 );
1760 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1761 continue;
1762 },
1763 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
1764 const fn_token = (try self.expectToken(&stack, Token.Id.Keyword_fn)) ?? continue;
1765 const fn_proto = try self.createToDestNode(arena, dest_ptr, ast.NodeFnProto,
1766 ast.NodeFnProto {
1767 .base = undefined,
1768 .visib_token = null,
1769 .name_token = null,
1770 .fn_token = fn_token,
1771 .params = ArrayList(&ast.Node).init(arena),
1772 .return_type = undefined,
1773 .var_args_token = null,
1774 .extern_export_inline_token = null,
1775 .cc_token = token,
1776 .async_attr = null,
1777 .body_node = null,
1778 .lib_name = null,
1779 .align_expr = null,
1780 }
1781 );
1782 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1783 continue;
1784 },
1785 Token.Id.Keyword_asm => {
1786 const is_volatile = blk: {
1787 const volatile_token = self.getNextToken();
1788 if (volatile_token.id != Token.Id.Keyword_volatile) {
1789 self.putBackToken(volatile_token);
1790 break :blk false;
1791 }
1792 break :blk true;
1793 };
1794 _ = (try self.expectToken(&stack, Token.Id.LParen)) ?? continue;
1795
1796 const template_token = self.getNextToken();
1797 const template = (try self.parseStringLiteral(arena, template_token)) ?? {
1798 try self.parseError(&stack, template_token, "expected string literal, found {}", @tagName(template_token.id));
1799 continue;
1800 };
1801 // TODO parse template
1802
1803 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeAsm,
1804 ast.NodeAsm {
1805 .base = undefined,
1806 .asm_token = token,
1807 .is_volatile = is_volatile,
1808 .template = template,
1809 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
1810 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
1811 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
1812 .cloppers = ArrayList(&ast.Node).init(arena),
1813 .rparen = undefined,
1814 }
1815 );
1816 stack.append(State {
1817 .ExpectTokenSave = ExpectTokenSave {
1818 .id = Token.Id.RParen,
1819 .ptr = &node.rparen,
1820 }
1821 }) catch unreachable;
1822 try stack.append(State { .AsmClopperItems = &node.cloppers });
1823 try stack.append(State { .IfToken = Token.Id.Colon });
1824 try stack.append(State { .AsmInputItems = &node.inputs });
1825 try stack.append(State { .IfToken = Token.Id.Colon });
1826 try stack.append(State { .AsmOutputItems = &node.outputs });
1827 try stack.append(State { .IfToken = Token.Id.Colon });
1828 },
1829 Token.Id.Keyword_inline => {
1830 stack.append(State {
1831 .Inline = InlineCtx {
1832 .label = null,
1833 .inline_token = token,
1834 .dest_ptr = dest_ptr,
1835 }
1836 }) catch unreachable;
1837 continue;
1838 },
1839 else => {
1840 if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) {
1841 try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
1842 }
1843 continue;
1844 }
1845 }
1846 },
1847
1848 State.SliceOrArrayAccess => |node| {
1849 var token = self.getNextToken();
1850
1851 switch (token.id) {
1852 Token.Id.Ellipsis2 => {
1853 const start = node.op.ArrayAccess;
1854 node.op = ast.NodeSuffixOp.SuffixOp {
1855 .Slice = ast.NodeSuffixOp.SliceRange {
1856 .start = start,
1857 .end = undefined,
1858 }
1859 };
1860
1861 const rbracket_token = self.getNextToken();
1862 if (rbracket_token.id != Token.Id.RBracket) {
1863 self.putBackToken(rbracket_token);
1864 stack.append(State {
1865 .ExpectTokenSave = ExpectTokenSave {
1866 .id = Token.Id.RBracket,
1867 .ptr = &node.rtoken,
1868 }
1869 }) catch unreachable;
1870 try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } });
1871 } else {
1872 node.rtoken = rbracket_token;
1873 }
1874 continue;
1875 },
1876 Token.Id.RBracket => {
1877 node.rtoken = token;
1878 continue;
1879 },
1880 else => {
1881 try self.parseError(&stack, token, "expected ']' or '..', found {}", @tagName(token.id));
1882 continue;
1883 }
1884 }
1885 },
1886
1887
1888 State.AsmOutputItems => |items| {
1889 const lbracket = self.getNextToken();
1890 if (lbracket.id != Token.Id.LBracket) {
1891 self.putBackToken(lbracket);
1892 continue;
1893 }
1894
1895 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1896 try stack.append(State { .IfToken = Token.Id.Comma });
1897
1898 const symbolic_name = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
1899 _ = (try self.expectToken(&stack, Token.Id.RBracket)) ?? continue;
1900
1901 const constraint_token = self.getNextToken();
1902 const constraint = (try self.parseStringLiteral(arena, constraint_token)) ?? {
1903 try self.parseError(&stack, constraint_token, "expected string literal, found {}", @tagName(constraint_token.id));
1904 continue;
1905 };
1906
1907 _ = (try self.expectToken(&stack, Token.Id.LParen)) ?? continue;
1908 try stack.append(State { .ExpectToken = Token.Id.RParen });
1909
1910 const node = try self.createNode(arena, ast.NodeAsmOutput,
1911 ast.NodeAsmOutput {
1912 .base = undefined,
1913 .symbolic_name = try self.createLiteral(arena, ast.NodeIdentifier, symbolic_name),
1914 .constraint = constraint,
1915 .kind = undefined,
1916 }
1917 );
1918 try items.append(node);
1919
1920 const symbol_or_arrow = self.getNextToken();
1921 switch (symbol_or_arrow.id) {
1922 Token.Id.Identifier => {
1923 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.NodeIdentifier, symbol_or_arrow) };
1924 },
1925 Token.Id.Arrow => {
1926 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
1927 try stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.kind.Return } });
1928 },
1929 else => {
1930 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
1931 @tagName(Token.Id.Identifier),
1932 @tagName(symbol_or_arrow.id));
1933 continue;
1934 },1355 },
1935 }1356 }
1936 },1357 },
1937
1938 State.AsmInputItems => |items| {1358 State.AsmInputItems => |items| {
1939 const lbracket = self.getNextToken();1359 const lbracket = self.getNextToken();
1940 if (lbracket.id != Token.Id.LBracket) {1360 if (lbracket.id != Token.Id.LBracket) {
...@@ -1942,59 +1362,53 @@ pub const Parser = struct {...@@ -1942,59 +1362,53 @@ pub const Parser = struct {
1942 continue;1362 continue;
1943 }1363 }
19441364
1945 stack.append(State { .AsmInputItems = items }) catch unreachable;
1946 try stack.append(State { .IfToken = Token.Id.Comma });
1947
1948 const symbolic_name = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
1949 _ = (try self.expectToken(&stack, Token.Id.RBracket)) ?? continue;
1950
1951 const constraint_token = self.getNextToken();
1952 const constraint = (try self.parseStringLiteral(arena, constraint_token)) ?? {
1953 try self.parseError(&stack, constraint_token, "expected string literal, found {}", @tagName(constraint_token.id));
1954 continue;
1955 };
1956
1957 _ = (try self.expectToken(&stack, Token.Id.LParen)) ?? continue;
1958 try stack.append(State { .ExpectToken = Token.Id.RParen });
1959
1960 const node = try self.createNode(arena, ast.NodeAsmInput,1365 const node = try self.createNode(arena, ast.NodeAsmInput,
1961 ast.NodeAsmInput {1366 ast.NodeAsmInput {
1962 .base = undefined,1367 .base = undefined,
1963 .symbolic_name = try self.createLiteral(arena, ast.NodeIdentifier, symbolic_name),1368 .symbolic_name = undefined,
1964 .constraint = constraint,1369 .constraint = undefined,
1965 .expr = undefined,1370 .expr = undefined,
1966 }1371 }
1967 );1372 );
1968 try items.append(node);1373 try items.append(node);
1969 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1970 },
19711374
1375 stack.append(State { .AsmInputItems = items }) catch unreachable;
1376 try stack.append(State { .IfToken = Token.Id.Comma });
1377 try stack.append(State { .ExpectToken = Token.Id.RParen });
1378 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
1379 try stack.append(State { .ExpectToken = Token.Id.LParen });
1380 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1381 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1382 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1383 continue;
1384 },
1972 State.AsmClopperItems => |items| {1385 State.AsmClopperItems => |items| {
1973 const string_token = self.getNextToken();
1974 const string = (try self.parseStringLiteral(arena, string_token)) ?? {
1975 self.putBackToken(string_token);
1976 continue;
1977 };
1978 try items.append(string);
1979
1980 stack.append(State { .AsmClopperItems = items }) catch unreachable;1386 stack.append(State { .AsmClopperItems = items }) catch unreachable;
1981 try stack.append(State { .IfToken = Token.Id.Comma });1387 try stack.append(State { .IfToken = Token.Id.Comma });
1388 try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } });
1389 continue;
1982 },1390 },
19831391
1984 State.ExprListItemOrEnd => |list_state| {
1985 var token = self.getNextToken();
19861392
1987 const IdTag = @TagType(Token.Id);1393 State.ExprListItemOrEnd => |list_state| {
1988 if (IdTag(list_state.end) == token.id) {1394 if (self.eatToken(list_state.end)) |token| {
1989 *list_state.ptr = token;1395 *list_state.ptr = token;
1990 continue;1396 continue;
1991 }1397 }
19921398
1993 self.putBackToken(token);
1994 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;1399 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1995 try stack.append(State { .Expression = DestPtr{ .Field = try list_state.list.addOne() } });1400 try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } });
1401 continue;
1402 },
1403 State.ExprListCommaOrEnd => |list_state| {
1404 if (try self.expectCommaOrEnd(list_state.end)) |end| {
1405 *list_state.ptr = end;
1406 continue;
1407 } else {
1408 stack.append(State { .ExprListItemOrEnd = list_state }) catch unreachable;
1409 continue;
1410 }
1996 },1411 },
1997
1998 State.FieldInitListItemOrEnd => |list_state| {1412 State.FieldInitListItemOrEnd => |list_state| {
1999 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1413 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
2000 *list_state.ptr = rbrace;1414 *list_state.ptr = rbrace;
...@@ -2012,7 +1426,7 @@ pub const Parser = struct {...@@ -2012,7 +1426,7 @@ pub const Parser = struct {
2012 try list_state.list.append(node);1426 try list_state.list.append(node);
20131427
2014 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;1428 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
2015 try stack.append(State { .Expression = DestPtr{.Field = &node.expr} });1429 try stack.append(State { .Expression = OptionalCtx{ .Required = &node.expr } });
2016 try stack.append(State { .ExpectToken = Token.Id.Equal });1430 try stack.append(State { .ExpectToken = Token.Id.Equal });
2017 try stack.append(State {1431 try stack.append(State {
2018 .ExpectTokenSave = ExpectTokenSave {1432 .ExpectTokenSave = ExpectTokenSave {
...@@ -2026,26 +1440,45 @@ pub const Parser = struct {...@@ -2026,26 +1440,45 @@ pub const Parser = struct {
2026 .ptr = &node.period_token,1440 .ptr = &node.period_token,
2027 }1441 }
2028 });1442 });
1443 continue;
1444 },
1445 State.FieldInitListCommaOrEnd => |list_state| {
1446 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1447 *list_state.ptr = end;
1448 continue;
1449 } else {
1450 stack.append(State { .FieldInitListItemOrEnd = list_state }) catch unreachable;
1451 continue;
1452 }
1453 },
1454 State.FieldListCommaOrEnd => |container_decl| {
1455 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1456 container_decl.rbrace_token = end;
1457 continue;
1458 } else {
1459 stack.append(State { .ContainerDecl = container_decl }) catch unreachable;
1460 continue;
1461 }
2029 },1462 },
2030
2031 State.IdentifierListItemOrEnd => |list_state| {1463 State.IdentifierListItemOrEnd => |list_state| {
2032 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1464 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
2033 *list_state.ptr = rbrace;1465 *list_state.ptr = rbrace;
2034 continue;1466 continue;
2035 }1467 }
20361468
2037 const node = try self.createLiteral(arena, ast.NodeIdentifier, Token(undefined));
2038 try list_state.list.append(node);
2039
2040 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;1469 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;
2041 try stack.append(State {1470 try stack.append(State { .Identifier = OptionalCtx { .Required = try list_state.list.addOne() } });
2042 .ExpectTokenSave = ExpectTokenSave {1471 continue;
2043 .id = Token.Id.Identifier,1472 },
2044 .ptr = &node.token,1473 State.IdentifierListCommaOrEnd => |list_state| {
2045 }1474 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
2046 });1475 *list_state.ptr = end;
1476 continue;
1477 } else {
1478 stack.append(State { .IdentifierListItemOrEnd = list_state }) catch unreachable;
1479 continue;
1480 }
2047 },1481 },
2048
2049 State.SwitchCaseOrEnd => |list_state| {1482 State.SwitchCaseOrEnd => |list_state| {
2050 if (self.eatToken(Token.Id.RBrace)) |rbrace| {1483 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
2051 *list_state.ptr = rbrace;1484 *list_state.ptr = rbrace;
...@@ -2062,109 +1495,78 @@ pub const Parser = struct {...@@ -2062,109 +1495,78 @@ pub const Parser = struct {
2062 );1495 );
2063 try list_state.list.append(node);1496 try list_state.list.append(node);
2064 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;1497 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
2065 try stack.append(State { .AssignmentExpressionBegin = DestPtr{ .Field = &node.expr } });1498 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } });
2066 try stack.append(State { .PointerPayload = &node.payload });1499 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
20671500 try stack.append(State { .SwitchCaseFirstItem = &node.items });
2068 const maybe_else = self.getNextToken();1501 continue;
2069 if (maybe_else.id == Token.Id.Keyword_else) {1502 },
2070 const else_node = try self.createAttachNode(arena, &node.items, ast.NodeSwitchElse,1503 State.SwitchCaseCommaOrEnd => |list_state| {
1504 if (try self.expectCommaOrEnd(Token.Id.RBrace)) |end| {
1505 *list_state.ptr = end;
1506 continue;
1507 } else {
1508 stack.append(State { .SwitchCaseOrEnd = list_state }) catch unreachable;
1509 continue;
1510 }
1511 },
1512 State.SwitchCaseFirstItem => |case_items| {
1513 const token = self.getNextToken();
1514 if (token.id == Token.Id.Keyword_else) {
1515 const else_node = try self.createAttachNode(arena, case_items, ast.NodeSwitchElse,
2071 ast.NodeSwitchElse {1516 ast.NodeSwitchElse {
2072 .base = undefined,1517 .base = undefined,
2073 .token = maybe_else,1518 .token = token,
2074 }1519 }
2075 );1520 );
2076 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });1521 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
2077 continue;1522 continue;
2078 } else {1523 } else {
2079 self.putBackToken(maybe_else);1524 self.putBackToken(token);
2080 try stack.append(State { .SwitchCaseItem = &node.items });1525 try stack.append(State { .SwitchCaseItem = case_items });
2081 continue;1526 continue;
2082 }1527 }
2083 },1528 },
2084
2085 State.SwitchCaseItem => |case_items| {1529 State.SwitchCaseItem => |case_items| {
2086 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;1530 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
2087 try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });1531 try stack.append(State { .RangeExpressionBegin = OptionalCtx { .Required = try case_items.addOne() } });
2088 },
2089
2090 State.ExprListCommaOrEnd => |list_state| {
2091 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
2092 continue;
2093 },
2094
2095 State.FieldInitListCommaOrEnd => |list_state| {
2096 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
2097 continue;
2098 },1532 },
20991533 State.SwitchCaseItemCommaOrEnd => |case_items| {
2100 State.FieldListCommaOrEnd => |container_decl| {1534 if ((try self.expectCommaOrEnd(Token.Id.EqualAngleBracketRight)) == null) {
2101 try self.commaOrEnd(&stack, Token.Id.RBrace, &container_decl.rbrace_token,1535 stack.append(State { .SwitchCaseItem = case_items }) catch unreachable;
2102 State { .ContainerDecl = container_decl });1536 }
2103 continue;1537 continue;
2104 },1538 },
21051539
2106 State.IdentifierListCommaOrEnd => |list_state| {
2107 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .IdentifierListItemOrEnd = list_state });
2108 continue;
2109 },
21101540
2111 State.SwitchCaseCommaOrEnd => |list_state| {1541 State.SuspendBody => |suspend_node| {
2112 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });1542 if (suspend_node.payload != null) {
1543 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = &suspend_node.body } });
1544 }
2113 continue;1545 continue;
2114 },1546 },
1547 State.AsyncAllocator => |async_node| {
1548 if (self.eatToken(Token.Id.AngleBracketLeft) == null) {
1549 continue;
1550 }
21151551
2116 State.SwitchCaseItemCommaOrEnd => |case_items| {1552 async_node.rangle_bracket = Token(undefined);
2117 try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });1553 try stack.append(State {
1554 .ExpectTokenSave = ExpectTokenSave {
1555 .id = Token.Id.AngleBracketRight,
1556 .ptr = &??async_node.rangle_bracket,
1557 }
1558 });
1559 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } });
2118 continue;1560 continue;
2119 },1561 },
21201562 State.AsyncEnd => |ctx| {
2121 State.Else => |dest| {1563 const node = ctx.ctx.get() ?? continue;
2122 const else_token = self.getNextToken();
2123 if (else_token.id != Token.Id.Keyword_else) {
2124 self.putBackToken(else_token);
2125 continue;
2126 }
2127
2128 const node = try self.createNode(arena, ast.NodeElse,
2129 ast.NodeElse {
2130 .base = undefined,
2131 .else_token = else_token,
2132 .payload = null,
2133 .body = undefined,
2134 }
2135 );
2136 *dest = node;
2137
2138 stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable;
2139 try stack.append(State { .Payload = &node.payload });
2140 },
2141
2142 State.WhileContinueExpr => |dest| {
2143 const colon = self.getNextToken();
2144 if (colon.id != Token.Id.Colon) {
2145 self.putBackToken(colon);
2146 continue;
2147 }
2148
2149 _ = (try self.expectToken(&stack, Token.Id.LParen)) ?? continue;
2150 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
2151 try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = dest } });
2152 },
2153
2154 State.SuspendBody => |suspend_node| {
2155 if (suspend_node.payload != null) {
2156 try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = &suspend_node.body } });
2157 }
2158 continue;
2159 },
2160
2161 State.AsyncEnd => |ctx| {
2162 const node = ctx.dest_ptr.get();
21631564
2164 switch (node.id) {1565 switch (node.id) {
2165 ast.Node.Id.FnProto => {1566 ast.Node.Id.FnProto => {
2166 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);1567 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);
2167 fn_proto.async_attr = ctx.attribute;1568 fn_proto.async_attr = ctx.attribute;
1569 continue;
2168 },1570 },
2169 ast.Node.Id.SuffixOp => {1571 ast.Node.Id.SuffixOp => {
2170 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);1572 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);
...@@ -2173,128 +1575,121 @@ pub const Parser = struct {...@@ -2173,128 +1575,121 @@ pub const Parser = struct {
2173 continue;1575 continue;
2174 }1576 }
21751577
2176 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",1578 return self.parseError(node.firstToken(), "expected {}, found {}.",
1579 @tagName(ast.NodeSuffixOp.SuffixOp.Call),
2177 @tagName(suffix_op.op));1580 @tagName(suffix_op.op));
2178 continue;
2179 },1581 },
2180 else => {1582 else => {
2181 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",1583 return self.parseError(node.firstToken(), "expected {} or {}, found {}.",
1584 @tagName(ast.NodeSuffixOp.SuffixOp.Call),
1585 @tagName(ast.Node.Id.FnProto),
2182 @tagName(node.id));1586 @tagName(node.id));
2183 continue;
2184 }1587 }
2185 }1588 }
2186 },1589 },
21871590
2188 State.Payload => |dest| {
2189 const lpipe = self.getNextToken();
2190 if (lpipe.id != Token.Id.Pipe) {
2191 self.putBackToken(lpipe);
2192 continue;
2193 }
2194
2195 const error_symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
2196 const rpipe = (try self.expectToken(&stack, Token.Id.Pipe)) ?? continue;
2197 *dest = try self.createNode(arena, ast.NodePayload,
2198 ast.NodePayload {
2199 .base = undefined,
2200 .lpipe = lpipe,
2201 .error_symbol = try self.createLiteral(arena, ast.NodeIdentifier, error_symbol),
2202 .rpipe = rpipe
2203 }
2204 );
2205 },
22061591
2207 State.PointerPayload => |dest| {1592 State.ExternType => |ctx| {
2208 const lpipe = self.getNextToken();1593 if (self.eatToken(Token.Id.Keyword_fn)) |fn_token| {
2209 if (lpipe.id != Token.Id.Pipe) {1594 const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFnProto,
2210 self.putBackToken(lpipe);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;
2211 continue;1612 continue;
2212 }1613 }
22131614
2214 const is_ptr = blk: {1615 stack.append(State {
2215 const asterik = self.getNextToken();1616 .ContainerKind = ContainerKindCtx {
2216 if (asterik.id == Token.Id.Asterisk) {1617 .opt_ctx = ctx.opt_ctx,
2217 break :blk true;1618 .ltoken = ctx.extern_token,
2218 } else {1619 .layout = ast.NodeContainerDecl.Layout.Extern,
2219 self.putBackToken(asterik);1620 },
2220 break :blk false;1621 }) catch unreachable;
2221 }1622 continue;
2222 };1623 },
1624 State.SliceOrArrayAccess => |node| {
1625 var token = self.getNextToken();
1626 switch (token.id) {
1627 Token.Id.Ellipsis2 => {
1628 const start = node.op.ArrayAccess;
1629 node.op = ast.NodeSuffixOp.SuffixOp {
1630 .Slice = ast.NodeSuffixOp.SliceRange {
1631 .start = start,
1632 .end = null,
1633 }
1634 };
22231635
2224 const value_symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;1636 stack.append(State {
2225 const rpipe = (try self.expectToken(&stack, Token.Id.Pipe)) ?? continue;1637 .ExpectTokenSave = ExpectTokenSave {
2226 *dest = try self.createNode(arena, ast.NodePointerPayload,1638 .id = Token.Id.RBracket,
2227 ast.NodePointerPayload {1639 .ptr = &node.rtoken,
2228 .base = undefined,1640 }
2229 .lpipe = lpipe,1641 }) catch unreachable;
2230 .is_ptr = is_ptr,1642 try stack.append(State { .Expression = OptionalCtx { .Optional = &node.op.Slice.end } });
2231 .value_symbol = try self.createLiteral(arena, ast.NodeIdentifier, value_symbol),1643 continue;
2232 .rpipe = rpipe1644 },
1645 Token.Id.RBracket => {
1646 node.rtoken = token;
1647 continue;
1648 },
1649 else => {
1650 return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id));
2233 }1651 }
2234 );1652 }
2235 },1653 },
22361654 State.SliceOrArrayType => |node| {
2237 State.PointerIndexPayload => |dest| {1655 if (self.eatToken(Token.Id.RBracket)) |_| {
2238 const lpipe = self.getNextToken();1656 node.op = ast.NodePrefixOp.PrefixOp {
2239 if (lpipe.id != Token.Id.Pipe) {1657 .SliceType = ast.NodePrefixOp.AddrOfInfo {
2240 self.putBackToken(lpipe);1658 .align_expr = null,
1659 .bit_offset_start_token = null,
1660 .bit_offset_end_token = null,
1661 .const_token = null,
1662 .volatile_token = null,
1663 }
1664 };
1665 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1666 try stack.append(State { .AddrOfModifiers = &node.op.SliceType });
2241 continue;1667 continue;
2242 }1668 }
22431669
2244 const is_ptr = blk: {1670 node.op = ast.NodePrefixOp.PrefixOp { .ArrayType = undefined };
2245 const asterik = self.getNextToken();1671 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
2246 if (asterik.id == Token.Id.Asterisk) {1672 try stack.append(State { .ExpectToken = Token.Id.RBracket });
2247 break :blk true;1673 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } });
2248 } else {1674 continue;
2249 self.putBackToken(asterik);
2250 break :blk false;
2251 }
2252 };
2253
2254 const value_symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
2255 const index_symbol = blk: {
2256 const comma = self.getNextToken();
2257 if (comma.id != Token.Id.Comma) {
2258 self.putBackToken(comma);
2259 break :blk null;
2260 }
2261
2262 const symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
2263 break :blk try self.createLiteral(arena, ast.NodeIdentifier, symbol);
2264 };
2265
2266 const rpipe = (try self.expectToken(&stack, Token.Id.Pipe)) ?? continue;
2267 *dest = try self.createNode(arena, ast.NodePointerIndexPayload,
2268 ast.NodePointerIndexPayload {
2269 .base = undefined,
2270 .lpipe = lpipe,
2271 .is_ptr = is_ptr,
2272 .value_symbol = try self.createLiteral(arena, ast.NodeIdentifier, value_symbol),
2273 .index_symbol = index_symbol,
2274 .rpipe = rpipe
2275 }
2276 );
2277 },1675 },
2278
2279 State.AddrOfModifiers => |addr_of_info| {1676 State.AddrOfModifiers => |addr_of_info| {
2280 var token = self.getNextToken();1677 var token = self.getNextToken();
2281 switch (token.id) {1678 switch (token.id) {
2282 Token.Id.Keyword_align => {1679 Token.Id.Keyword_align => {
2283 stack.append(state) catch unreachable;1680 stack.append(state) catch unreachable;
2284 if (addr_of_info.align_expr != null) {1681 if (addr_of_info.align_expr != null) {
2285 try self.parseError(&stack, token, "multiple align qualifiers");1682 return self.parseError(token, "multiple align qualifiers");
2286 continue;
2287 }1683 }
2288 try stack.append(State { .ExpectToken = Token.Id.RParen });1684 try stack.append(State { .ExpectToken = Token.Id.RParen });
2289 try stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });1685 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &addr_of_info.align_expr} });
2290 try stack.append(State { .ExpectToken = Token.Id.LParen });1686 try stack.append(State { .ExpectToken = Token.Id.LParen });
2291 continue;1687 continue;
2292 },1688 },
2293 Token.Id.Keyword_const => {1689 Token.Id.Keyword_const => {
2294 stack.append(state) catch unreachable;1690 stack.append(state) catch unreachable;
2295 if (addr_of_info.const_token != null) {1691 if (addr_of_info.const_token != null) {
2296 try self.parseError(&stack, token, "duplicate qualifier: const");1692 return self.parseError(token, "duplicate qualifier: const");
2297 continue;
2298 }1693 }
2299 addr_of_info.const_token = token;1694 addr_of_info.const_token = token;
2300 continue;1695 continue;
...@@ -2302,8 +1697,7 @@ pub const Parser = struct {...@@ -2302,8 +1697,7 @@ pub const Parser = struct {
2302 Token.Id.Keyword_volatile => {1697 Token.Id.Keyword_volatile => {
2303 stack.append(state) catch unreachable;1698 stack.append(state) catch unreachable;
2304 if (addr_of_info.volatile_token != null) {1699 if (addr_of_info.volatile_token != null) {
2305 try self.parseError(&stack, token, "duplicate qualifier: volatile");1700 return self.parseError(token, "duplicate qualifier: volatile");
2306 continue;
2307 }1701 }
2308 addr_of_info.volatile_token = token;1702 addr_of_info.volatile_token = token;
2309 continue;1703 continue;
...@@ -2315,391 +1709,1043 @@ pub const Parser = struct {...@@ -2315,391 +1709,1043 @@ pub const Parser = struct {
2315 }1709 }
2316 },1710 },
23171711
2318 State.FnProto => |fn_proto| {
2319 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
2320 try stack.append(State { .ParamDecl = fn_proto });
2321 try stack.append(State { .ExpectToken = Token.Id.LParen });
23221712
2323 const next_token = self.getNextToken();1713 State.Payload => |opt_ctx| {
2324 if (next_token.id == Token.Id.Identifier) {1714 const token = self.getNextToken();
2325 fn_proto.name_token = next_token;1715 if (token.id != Token.Id.Pipe) {
1716 if (opt_ctx != OptionalCtx.Optional) {
1717 return self.parseError(token, "expected {}, found {}.",
1718 @tagName(Token.Id.Pipe),
1719 @tagName(token.id));
1720 }
1721
1722 self.putBackToken(token);
2326 continue;1723 continue;
2327 }1724 }
2328 self.putBackToken(next_token);
2329 continue;
2330 },
2331
2332 State.FnProtoAlign => |fn_proto| {
2333 stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable;
23341725
2335 if (self.eatToken(Token.Id.Keyword_align)) |align_token| {1726 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePayload,
2336 try stack.append(State { .ExpectToken = Token.Id.RParen });1727 ast.NodePayload {
2337 try stack.append(State { .Expression = DestPtr { .NullableField = &fn_proto.align_expr } });1728 .base = undefined,
2338 try stack.append(State { .ExpectToken = Token.Id.LParen });1729 .lpipe = token,
2339 }1730 .error_symbol = undefined,
1731 .rpipe = undefined
1732 }
1733 );
23401734
1735 stack.append(State {
1736 .ExpectTokenSave = ExpectTokenSave {
1737 .id = Token.Id.Pipe,
1738 .ptr = &node.rpipe,
1739 }
1740 }) catch unreachable;
1741 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } });
2341 continue;1742 continue;
2342 },1743 },
23431744 State.PointerPayload => |opt_ctx| {
2344 State.FnProtoReturnType => |fn_proto| {
2345 const token = self.getNextToken();1745 const token = self.getNextToken();
2346 switch (token.id) {1746 if (token.id != Token.Id.Pipe) {
2347 Token.Id.Bang => {1747 if (opt_ctx != OptionalCtx.Optional) {
2348 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };1748 return self.parseError(token, "expected {}, found {}.",
2349 stack.append(State {1749 @tagName(Token.Id.Pipe),
2350 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},1750 @tagName(token.id));
2351 }) catch unreachable;1751 }
2352 continue;
2353 },
2354 else => {
2355 // TODO: this is a special case. Remove this when #760 is fixed
2356 if (token.id == Token.Id.Keyword_error) {
2357 if (self.isPeekToken(Token.Id.LBrace)) {
2358 fn_proto.return_type = ast.NodeFnProto.ReturnType {
2359 .Explicit = &(try self.createLiteral(arena, ast.NodeErrorType, token)).base
2360 };
2361 continue;
2362 }
2363 }
2364
2365 self.putBackToken(token);
2366 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
2367 stack.append(State {
2368 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.Explicit},
2369 }) catch unreachable;
2370 continue;
2371 },
2372 }
2373 },
23741752
2375 State.ParamDecl => |fn_proto| {1753 self.putBackToken(token);
2376 if (self.eatToken(Token.Id.RParen)) |_| {
2377 continue;1754 continue;
2378 }1755 }
2379 const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.NodeParamDecl,1756
2380 ast.NodeParamDecl {1757 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerPayload,
1758 ast.NodePointerPayload {
2381 .base = undefined,1759 .base = undefined,
2382 .comptime_token = null,1760 .lpipe = token,
2383 .noalias_token = null,1761 .ptr_token = null,
2384 .name_token = null,1762 .value_symbol = undefined,
2385 .type_node = undefined,1763 .rpipe = undefined
2386 .var_args_token = null,1764 }
2387 },
2388 );1765 );
2389 if (self.eatToken(Token.Id.Keyword_comptime)) |comptime_token| {1766
2390 param_decl.comptime_token = comptime_token;1767 stack.append(State {
2391 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {1768 .ExpectTokenSave = ExpectTokenSave {
2392 param_decl.noalias_token = noalias_token;1769 .id = Token.Id.Pipe,
2393 }1770 .ptr = &node.rpipe,
2394 if (self.eatToken(Token.Id.Identifier)) |identifier| {
2395 if (self.eatToken(Token.Id.Colon)) |_| {
2396 param_decl.name_token = identifier;
2397 } else {
2398 self.putBackToken(identifier);
2399 }1771 }
2400 }1772 }) catch unreachable;
2401 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {1773 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
2402 param_decl.var_args_token = ellipsis3;1774 try stack.append(State {
2403 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;1775 .OptionalTokenSave = OptionalTokenSave {
1776 .id = Token.Id.Asterisk,
1777 .ptr = &node.ptr_token,
1778 }
1779 });
1780 continue;
1781 },
1782 State.PointerIndexPayload => |opt_ctx| {
1783 const token = self.getNextToken();
1784 if (token.id != Token.Id.Pipe) {
1785 if (opt_ctx != OptionalCtx.Optional) {
1786 return self.parseError(token, "expected {}, found {}.",
1787 @tagName(Token.Id.Pipe),
1788 @tagName(token.id));
1789 }
1790
1791 self.putBackToken(token);
2404 continue;1792 continue;
2405 }1793 }
24061794
2407 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;1795 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerIndexPayload,
2408 try stack.append(State.ParamDeclComma);1796 ast.NodePointerIndexPayload {
1797 .base = undefined,
1798 .lpipe = token,
1799 .ptr_token = null,
1800 .value_symbol = undefined,
1801 .index_symbol = null,
1802 .rpipe = undefined
1803 }
1804 );
1805
1806 stack.append(State {
1807 .ExpectTokenSave = ExpectTokenSave {
1808 .id = Token.Id.Pipe,
1809 .ptr = &node.rpipe,
1810 }
1811 }) catch unreachable;
1812 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.index_symbol } });
1813 try stack.append(State { .IfToken = Token.Id.Comma });
1814 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
2409 try stack.append(State {1815 try stack.append(State {
2410 .TypeExprBegin = DestPtr {.Field = &param_decl.type_node}1816 .OptionalTokenSave = OptionalTokenSave {
1817 .id = Token.Id.Asterisk,
1818 .ptr = &node.ptr_token,
1819 }
2411 });1820 });
2412 continue;1821 continue;
2413 },1822 },
24141823
2415 State.ParamDeclComma => {1824
1825 State.Expression => |opt_ctx| {
2416 const token = self.getNextToken();1826 const token = self.getNextToken();
2417 switch (token.id) {1827 switch (token.id) {
2418 Token.Id.RParen => {1828 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
2419 _ = stack.pop(); // pop off the ParamDecl1829 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,
2420 continue;1830 ast.NodeControlFlowExpression {
2421 },1831 .base = undefined,
2422 Token.Id.Comma => continue,1832 .ltoken = token,
2423 else => {1833 .kind = undefined,
2424 try self.parseError(&stack, token, "expected ',' or ')', found {}", @tagName(token.id));1834 .rhs = null,
1835 }
1836 );
1837
1838 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
1839
1840 switch (token.id) {
1841 Token.Id.Keyword_break => {
1842 node.kind = ast.NodeControlFlowExpression.Kind { .Break = null };
1843 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } });
1844 try stack.append(State { .IfToken = Token.Id.Colon });
1845 },
1846 Token.Id.Keyword_continue => {
1847 node.kind = ast.NodeControlFlowExpression.Kind { .Continue = null };
1848 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } });
1849 try stack.append(State { .IfToken = Token.Id.Colon });
1850 },
1851 Token.Id.Keyword_return => {
1852 node.kind = ast.NodeControlFlowExpression.Kind.Return;
1853 },
1854 else => unreachable,
1855 }
2425 continue;1856 continue;
2426 },1857 },
2427 }1858 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
2428 },1859 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
24291860 ast.NodePrefixOp {
2430 State.FnDef => |fn_proto| {
2431 const token = self.getNextToken();
2432 switch(token.id) {
2433 Token.Id.LBrace => {
2434 const block = try self.createNode(arena, ast.NodeBlock,
2435 ast.NodeBlock {
2436 .base = undefined,1861 .base = undefined,
2437 .label = null,1862 .op_token = token,
2438 .lbrace = token,1863 .op = switch (token.id) {
2439 .statements = ArrayList(&ast.Node).init(arena),1864 Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{} },
2440 .rbrace = undefined,1865 Token.Id.Keyword_cancel => ast.NodePrefixOp.PrefixOp { .Cancel = void{} },
1866 Token.Id.Keyword_resume => ast.NodePrefixOp.PrefixOp { .Resume = void{} },
1867 else => unreachable,
1868 },
1869 .rhs = undefined,
2441 }1870 }
2442 );1871 );
2443 fn_proto.body_node = &block.base;1872
2444 stack.append(State { .Block = block }) catch unreachable;1873 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
2445 continue;1874 continue;
2446 },1875 },
2447 Token.Id.Semicolon => continue,
2448 else => {1876 else => {
2449 try self.parseError(&stack, token, "expected ';' or '{{', found {}", @tagName(token.id));1877 if (!try self.parseBlockExpr(&stack, arena, opt_ctx, token)) {
1878 self.putBackToken(token);
1879 stack.append(State { .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
1880 }
1881 continue;
1882 }
1883 }
1884 },
1885 State.RangeExpressionBegin => |opt_ctx| {
1886 stack.append(State { .RangeExpressionEnd = opt_ctx }) catch unreachable;
1887 try stack.append(State { .Expression = opt_ctx });
1888 continue;
1889 },
1890 State.RangeExpressionEnd => |opt_ctx| {
1891 const lhs = opt_ctx.get() ?? continue;
1892
1893 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
1894 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1895 ast.NodeInfixOp {
1896 .base = undefined,
1897 .lhs = lhs,
1898 .op_token = ellipsis3,
1899 .op = ast.NodeInfixOp.InfixOp.Range,
1900 .rhs = undefined,
1901 }
1902 );
1903 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1904 continue;
1905 }
1906 },
1907 State.AssignmentExpressionBegin => |opt_ctx| {
1908 stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable;
1909 try stack.append(State { .Expression = opt_ctx });
1910 continue;
1911 },
1912
1913 State.AssignmentExpressionEnd => |opt_ctx| {
1914 const lhs = opt_ctx.get() ?? continue;
1915
1916 const token = self.getNextToken();
1917 if (tokenIdToAssignment(token.id)) |ass_id| {
1918 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1919 ast.NodeInfixOp {
1920 .base = undefined,
1921 .lhs = lhs,
1922 .op_token = token,
1923 .op = ass_id,
1924 .rhs = undefined,
1925 }
1926 );
1927 stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1928 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1929 continue;
1930 } else {
1931 self.putBackToken(token);
1932 continue;
1933 }
1934 },
1935
1936 State.UnwrapExpressionBegin => |opt_ctx| {
1937 stack.append(State { .UnwrapExpressionEnd = opt_ctx }) catch unreachable;
1938 try stack.append(State { .BoolOrExpressionBegin = opt_ctx });
1939 continue;
1940 },
1941
1942 State.UnwrapExpressionEnd => |opt_ctx| {
1943 const lhs = opt_ctx.get() ?? continue;
1944
1945 const token = self.getNextToken();
1946 if (tokenIdToUnwrapExpr(token.id)) |unwrap_id| {
1947 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1948 ast.NodeInfixOp {
1949 .base = undefined,
1950 .lhs = lhs,
1951 .op_token = token,
1952 .op = unwrap_id,
1953 .rhs = undefined,
1954 }
1955 );
1956
1957 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1958 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1959
1960 if (node.op == ast.NodeInfixOp.InfixOp.Catch) {
1961 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } });
1962 }
1963 continue;
1964 } else {
1965 self.putBackToken(token);
1966 continue;
1967 }
1968 },
1969
1970 State.BoolOrExpressionBegin => |opt_ctx| {
1971 stack.append(State { .BoolOrExpressionEnd = opt_ctx }) catch unreachable;
1972 try stack.append(State { .BoolAndExpressionBegin = opt_ctx });
1973 continue;
1974 },
1975
1976 State.BoolOrExpressionEnd => |opt_ctx| {
1977 const lhs = opt_ctx.get() ?? continue;
1978
1979 if (self.eatToken(Token.Id.Keyword_or)) |or_token| {
1980 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1981 ast.NodeInfixOp {
1982 .base = undefined,
1983 .lhs = lhs,
1984 .op_token = or_token,
1985 .op = ast.NodeInfixOp.InfixOp.BoolOr,
1986 .rhs = undefined,
1987 }
1988 );
1989 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1990 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1991 continue;
1992 }
1993 },
1994
1995 State.BoolAndExpressionBegin => |opt_ctx| {
1996 stack.append(State { .BoolAndExpressionEnd = opt_ctx }) catch unreachable;
1997 try stack.append(State { .ComparisonExpressionBegin = opt_ctx });
1998 continue;
1999 },
2000
2001 State.BoolAndExpressionEnd => |opt_ctx| {
2002 const lhs = opt_ctx.get() ?? continue;
2003
2004 if (self.eatToken(Token.Id.Keyword_and)) |and_token| {
2005 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2006 ast.NodeInfixOp {
2007 .base = undefined,
2008 .lhs = lhs,
2009 .op_token = and_token,
2010 .op = ast.NodeInfixOp.InfixOp.BoolAnd,
2011 .rhs = undefined,
2012 }
2013 );
2014 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2015 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2016 continue;
2017 }
2018 },
2019
2020 State.ComparisonExpressionBegin => |opt_ctx| {
2021 stack.append(State { .ComparisonExpressionEnd = opt_ctx }) catch unreachable;
2022 try stack.append(State { .BinaryOrExpressionBegin = opt_ctx });
2023 continue;
2024 },
2025
2026 State.ComparisonExpressionEnd => |opt_ctx| {
2027 const lhs = opt_ctx.get() ?? continue;
2028
2029 const token = self.getNextToken();
2030 if (tokenIdToComparison(token.id)) |comp_id| {
2031 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2032 ast.NodeInfixOp {
2033 .base = undefined,
2034 .lhs = lhs,
2035 .op_token = token,
2036 .op = comp_id,
2037 .rhs = undefined,
2038 }
2039 );
2040 stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2041 try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2042 continue;
2043 } else {
2044 self.putBackToken(token);
2045 continue;
2046 }
2047 },
2048
2049 State.BinaryOrExpressionBegin => |opt_ctx| {
2050 stack.append(State { .BinaryOrExpressionEnd = opt_ctx }) catch unreachable;
2051 try stack.append(State { .BinaryXorExpressionBegin = opt_ctx });
2052 continue;
2053 },
2054
2055 State.BinaryOrExpressionEnd => |opt_ctx| {
2056 const lhs = opt_ctx.get() ?? continue;
2057
2058 if (self.eatToken(Token.Id.Pipe)) |pipe| {
2059 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2060 ast.NodeInfixOp {
2061 .base = undefined,
2062 .lhs = lhs,
2063 .op_token = pipe,
2064 .op = ast.NodeInfixOp.InfixOp.BitOr,
2065 .rhs = undefined,
2066 }
2067 );
2068 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2069 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2070 continue;
2071 }
2072 },
2073
2074 State.BinaryXorExpressionBegin => |opt_ctx| {
2075 stack.append(State { .BinaryXorExpressionEnd = opt_ctx }) catch unreachable;
2076 try stack.append(State { .BinaryAndExpressionBegin = opt_ctx });
2077 continue;
2078 },
2079
2080 State.BinaryXorExpressionEnd => |opt_ctx| {
2081 const lhs = opt_ctx.get() ?? continue;
2082
2083 if (self.eatToken(Token.Id.Caret)) |caret| {
2084 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2085 ast.NodeInfixOp {
2086 .base = undefined,
2087 .lhs = lhs,
2088 .op_token = caret,
2089 .op = ast.NodeInfixOp.InfixOp.BitXor,
2090 .rhs = undefined,
2091 }
2092 );
2093 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2094 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2095 continue;
2096 }
2097 },
2098
2099 State.BinaryAndExpressionBegin => |opt_ctx| {
2100 stack.append(State { .BinaryAndExpressionEnd = opt_ctx }) catch unreachable;
2101 try stack.append(State { .BitShiftExpressionBegin = opt_ctx });
2102 continue;
2103 },
2104
2105 State.BinaryAndExpressionEnd => |opt_ctx| {
2106 const lhs = opt_ctx.get() ?? continue;
2107
2108 if (self.eatToken(Token.Id.Ampersand)) |ampersand| {
2109 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2110 ast.NodeInfixOp {
2111 .base = undefined,
2112 .lhs = lhs,
2113 .op_token = ampersand,
2114 .op = ast.NodeInfixOp.InfixOp.BitAnd,
2115 .rhs = undefined,
2116 }
2117 );
2118 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2119 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2120 continue;
2121 }
2122 },
2123
2124 State.BitShiftExpressionBegin => |opt_ctx| {
2125 stack.append(State { .BitShiftExpressionEnd = opt_ctx }) catch unreachable;
2126 try stack.append(State { .AdditionExpressionBegin = opt_ctx });
2127 continue;
2128 },
2129
2130 State.BitShiftExpressionEnd => |opt_ctx| {
2131 const lhs = opt_ctx.get() ?? continue;
2132
2133 const token = self.getNextToken();
2134 if (tokenIdToBitShift(token.id)) |bitshift_id| {
2135 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2136 ast.NodeInfixOp {
2137 .base = undefined,
2138 .lhs = lhs,
2139 .op_token = token,
2140 .op = bitshift_id,
2141 .rhs = undefined,
2142 }
2143 );
2144 stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2145 try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2146 continue;
2147 } else {
2148 self.putBackToken(token);
2149 continue;
2150 }
2151 },
2152
2153 State.AdditionExpressionBegin => |opt_ctx| {
2154 stack.append(State { .AdditionExpressionEnd = opt_ctx }) catch unreachable;
2155 try stack.append(State { .MultiplyExpressionBegin = opt_ctx });
2156 continue;
2157 },
2158
2159 State.AdditionExpressionEnd => |opt_ctx| {
2160 const lhs = opt_ctx.get() ?? continue;
2161
2162 const token = self.getNextToken();
2163 if (tokenIdToAddition(token.id)) |add_id| {
2164 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2165 ast.NodeInfixOp {
2166 .base = undefined,
2167 .lhs = lhs,
2168 .op_token = token,
2169 .op = add_id,
2170 .rhs = undefined,
2171 }
2172 );
2173 stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2174 try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2175 continue;
2176 } else {
2177 self.putBackToken(token);
2178 continue;
2179 }
2180 },
2181
2182 State.MultiplyExpressionBegin => |opt_ctx| {
2183 stack.append(State { .MultiplyExpressionEnd = opt_ctx }) catch unreachable;
2184 try stack.append(State { .CurlySuffixExpressionBegin = opt_ctx });
2185 continue;
2186 },
2187
2188 State.MultiplyExpressionEnd => |opt_ctx| {
2189 const lhs = opt_ctx.get() ?? continue;
2190
2191 const token = self.getNextToken();
2192 if (tokenIdToMultiply(token.id)) |mult_id| {
2193 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2194 ast.NodeInfixOp {
2195 .base = undefined,
2196 .lhs = lhs,
2197 .op_token = token,
2198 .op = mult_id,
2199 .rhs = undefined,
2200 }
2201 );
2202 stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2203 try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2204 continue;
2205 } else {
2206 self.putBackToken(token);
2207 continue;
2208 }
2209 },
2210
2211 State.CurlySuffixExpressionBegin => |opt_ctx| {
2212 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable;
2213 try stack.append(State { .IfToken = Token.Id.LBrace });
2214 try stack.append(State { .TypeExprBegin = opt_ctx });
2215 continue;
2216 },
2217
2218 State.CurlySuffixExpressionEnd => |opt_ctx| {
2219 const lhs = opt_ctx.get() ?? continue;
2220
2221 if (self.isPeekToken(Token.Id.Period)) {
2222 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2223 ast.NodeSuffixOp {
2224 .base = undefined,
2225 .lhs = lhs,
2226 .op = ast.NodeSuffixOp.SuffixOp {
2227 .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),
2228 },
2229 .rtoken = undefined,
2230 }
2231 );
2232 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2233 try stack.append(State { .IfToken = Token.Id.LBrace });
2234 try stack.append(State {
2235 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
2236 .list = &node.op.StructInitializer,
2237 .ptr = &node.rtoken,
2238 }
2239 });
2240 continue;
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;
2263 },
2264
2265 State.TypeExprBegin => |opt_ctx| {
2266 stack.append(State { .TypeExprEnd = opt_ctx }) catch unreachable;
2267 try stack.append(State { .PrefixOpExpression = opt_ctx });
2268 continue;
2269 },
2270
2271 State.TypeExprEnd => |opt_ctx| {
2272 const lhs = opt_ctx.get() ?? continue;
2273
2274 if (self.eatToken(Token.Id.Bang)) |bang| {
2275 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2276 ast.NodeInfixOp {
2277 .base = undefined,
2278 .lhs = lhs,
2279 .op_token = bang,
2280 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,
2281 .rhs = undefined,
2282 }
2283 );
2284 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2285 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
2286 continue;
2287 }
2288 },
2289
2290 State.PrefixOpExpression => |opt_ctx| {
2291 const token = self.getNextToken();
2292 if (tokenIdToPrefixOp(token.id)) |prefix_id| {
2293 var node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
2294 ast.NodePrefixOp {
2295 .base = undefined,
2296 .op_token = token,
2297 .op = prefix_id,
2298 .rhs = undefined,
2299 }
2300 );
2301
2302 // Treat '**' token as two derefs
2303 if (token.id == Token.Id.AsteriskAsterisk) {
2304 const child = try self.createNode(arena, ast.NodePrefixOp,
2305 ast.NodePrefixOp {
2306 .base = undefined,
2307 .op_token = token,
2308 .op = prefix_id,
2309 .rhs = undefined,
2310 }
2311 );
2312 node.rhs = &child.base;
2313 node = child;
2314 }
2315
2316 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
2317 if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) {
2318 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });
2319 }
2320 continue;
2321 } else {
2322 self.putBackToken(token);
2323 stack.append(State { .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
2324 continue;
2325 }
2326 },
2327
2328 State.SuffixOpExpressionBegin => |opt_ctx| {
2329 if (self.eatToken(Token.Id.Keyword_async)) |async_token| {
2330 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
2331 ast.NodeAsyncAttribute {
2332 .base = undefined,
2333 .async_token = async_token,
2334 .allocator_type = null,
2335 .rangle_bracket = null,
2336 }
2337 );
2338 stack.append(State {
2339 .AsyncEnd = AsyncEndCtx {
2340 .ctx = opt_ctx,
2341 .attribute = async_node,
2342 }
2343 }) catch unreachable;
2344 try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() });
2345 try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() });
2346 try stack.append(State { .AsyncAllocator = async_node });
2347 continue;
2348 }
2349
2350 stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2351 try stack.append(State { .PrimaryExpression = opt_ctx });
2352 continue;
2353 },
2354
2355 State.SuffixOpExpressionEnd => |opt_ctx| {
2356 const lhs = opt_ctx.get() ?? continue;
2357
2358 const token = self.getNextToken();
2359 switch (token.id) {
2360 Token.Id.LParen => {
2361 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2362 ast.NodeSuffixOp {
2363 .base = undefined,
2364 .lhs = lhs,
2365 .op = ast.NodeSuffixOp.SuffixOp {
2366 .Call = ast.NodeSuffixOp.CallInfo {
2367 .params = ArrayList(&ast.Node).init(arena),
2368 .async_attr = null,
2369 }
2370 },
2371 .rtoken = undefined,
2372 }
2373 );
2374 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2375 try stack.append(State {
2376 .ExprListItemOrEnd = ExprListCtx {
2377 .list = &node.op.Call.params,
2378 .end = Token.Id.RParen,
2379 .ptr = &node.rtoken,
2380 }
2381 });
2382 continue;
2383 },
2384 Token.Id.LBracket => {
2385 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2386 ast.NodeSuffixOp {
2387 .base = undefined,
2388 .lhs = lhs,
2389 .op = ast.NodeSuffixOp.SuffixOp {
2390 .ArrayAccess = undefined,
2391 },
2392 .rtoken = undefined
2393 }
2394 );
2395 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2396 try stack.append(State { .SliceOrArrayAccess = node });
2397 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }});
2398 continue;
2399 },
2400 Token.Id.Period => {
2401 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2402 ast.NodeInfixOp {
2403 .base = undefined,
2404 .lhs = lhs,
2405 .op_token = token,
2406 .op = ast.NodeInfixOp.InfixOp.Period,
2407 .rhs = undefined,
2408 }
2409 );
2410 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2411 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } });
2412 continue;
2413 },
2414 else => {
2415 self.putBackToken(token);
2416 continue;
2417 },
2418 }
2419 },
2420
2421 State.PrimaryExpression => |opt_ctx| {
2422 const token = self.getNextToken();
2423 switch (token.id) {
2424 Token.Id.IntegerLiteral => {
2425 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeStringLiteral, token);
2426 continue;
2427 },
2428 Token.Id.FloatLiteral => {
2429 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeFloatLiteral, token);
2430 continue;
2431 },
2432 Token.Id.CharLiteral => {
2433 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeCharLiteral, token);
2434 continue;
2435 },
2436 Token.Id.Keyword_undefined => {
2437 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUndefinedLiteral, token);
2438 continue;
2439 },
2440 Token.Id.Keyword_true, Token.Id.Keyword_false => {
2441 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeBoolLiteral, token);
2442 continue;
2443 },
2444 Token.Id.Keyword_null => {
2445 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeNullLiteral, token);
2446 continue;
2447 },
2448 Token.Id.Keyword_this => {
2449 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeThisLiteral, token);
2450 continue;
2451 },
2452 Token.Id.Keyword_var => {
2453 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeVarType, token);
2454 continue;
2455 },
2456 Token.Id.Keyword_unreachable => {
2457 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUnreachable, token);
2458 continue;
2459 },
2460 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
2461 opt_ctx.store((try self.parseStringLiteral(arena, token)) ?? unreachable);
2462 continue;
2463 },
2464 Token.Id.LParen => {
2465 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeGroupedExpression,
2466 ast.NodeGroupedExpression {
2467 .base = undefined,
2468 .lparen = token,
2469 .expr = undefined,
2470 .rparen = undefined,
2471 }
2472 );
2473 stack.append(State {
2474 .ExpectTokenSave = ExpectTokenSave {
2475 .id = Token.Id.RParen,
2476 .ptr = &node.rparen,
2477 }
2478 }) catch unreachable;
2479 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2480 continue;
2481 },
2482 Token.Id.Builtin => {
2483 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeBuiltinCall,
2484 ast.NodeBuiltinCall {
2485 .base = undefined,
2486 .builtin_token = token,
2487 .params = ArrayList(&ast.Node).init(arena),
2488 .rparen_token = undefined,
2489 }
2490 );
2491 stack.append(State {
2492 .ExprListItemOrEnd = ExprListCtx {
2493 .list = &node.params,
2494 .end = Token.Id.RParen,
2495 .ptr = &node.rparen_token,
2496 }
2497 }) catch unreachable;
2498 try stack.append(State { .ExpectToken = Token.Id.LParen, });
2499 continue;
2500 },
2501 Token.Id.LBracket => {
2502 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
2503 ast.NodePrefixOp {
2504 .base = undefined,
2505 .op_token = token,
2506 .op = undefined,
2507 .rhs = undefined,
2508 }
2509 );
2510 stack.append(State { .SliceOrArrayType = node }) catch unreachable;
2511 continue;
2512 },
2513 Token.Id.Keyword_error => {
2514 stack.append(State {
2515 .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx {
2516 .error_token = token,
2517 .opt_ctx = opt_ctx
2518 }
2519 }) catch unreachable;
2520 continue;
2521 },
2522 Token.Id.Keyword_packed => {
2523 stack.append(State {
2524 .ContainerKind = ContainerKindCtx {
2525 .opt_ctx = opt_ctx,
2526 .ltoken = token,
2527 .layout = ast.NodeContainerDecl.Layout.Packed,
2528 },
2529 }) catch unreachable;
2530 continue;
2531 },
2532 Token.Id.Keyword_extern => {
2533 stack.append(State {
2534 .ExternType = ExternTypeCtx {
2535 .opt_ctx = opt_ctx,
2536 .extern_token = token,
2537 },
2538 }) catch unreachable;
2539 continue;
2540 },
2541 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
2542 self.putBackToken(token);
2543 stack.append(State {
2544 .ContainerKind = ContainerKindCtx {
2545 .opt_ctx = opt_ctx,
2546 .ltoken = token,
2547 .layout = ast.NodeContainerDecl.Layout.Auto,
2548 },
2549 }) catch unreachable;
2550 continue;
2551 },
2552 Token.Id.Identifier => {
2553 stack.append(State {
2554 .MaybeLabeledExpression = MaybeLabeledExpressionCtx {
2555 .label = token,
2556 .opt_ctx = opt_ctx
2557 }
2558 }) catch unreachable;
2559 continue;
2560 },
2561 Token.Id.Keyword_fn => {
2562 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2563 ast.NodeFnProto {
2564 .base = undefined,
2565 .visib_token = null,
2566 .name_token = null,
2567 .fn_token = token,
2568 .params = ArrayList(&ast.Node).init(arena),
2569 .return_type = undefined,
2570 .var_args_token = null,
2571 .extern_export_inline_token = null,
2572 .cc_token = null,
2573 .async_attr = null,
2574 .body_node = null,
2575 .lib_name = null,
2576 .align_expr = null,
2577 }
2578 );
2579 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2580 continue;
2581 },
2582 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2583 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2584 ast.NodeFnProto {
2585 .base = undefined,
2586 .visib_token = null,
2587 .name_token = null,
2588 .fn_token = undefined,
2589 .params = ArrayList(&ast.Node).init(arena),
2590 .return_type = undefined,
2591 .var_args_token = null,
2592 .extern_export_inline_token = null,
2593 .cc_token = token,
2594 .async_attr = null,
2595 .body_node = null,
2596 .lib_name = null,
2597 .align_expr = null,
2598 }
2599 );
2600 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2601 try stack.append(State {
2602 .ExpectTokenSave = ExpectTokenSave {
2603 .id = Token.Id.Keyword_fn,
2604 .ptr = &fn_proto.fn_token
2605 }
2606 });
2450 continue;2607 continue;
2451 },2608 },
2452 }2609 Token.Id.Keyword_asm => {
2453 },2610 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeAsm,
24542611 ast.NodeAsm {
2455 State.LabeledExpression => |ctx| {
2456 const token = self.getNextToken();
2457 switch (token.id) {
2458 Token.Id.LBrace => {
2459 const block = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeBlock,
2460 ast.NodeBlock {
2461 .base = undefined,2612 .base = undefined,
2462 .label = ctx.label,2613 .asm_token = token,
2463 .lbrace = token,2614 .volatile_token = null,
2464 .statements = ArrayList(&ast.Node).init(arena),2615 .template = undefined,
2465 .rbrace = undefined,2616 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
2617 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
2618 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
2619 .cloppers = ArrayList(&ast.Node).init(arena),
2620 .rparen = undefined,
2466 }2621 }
2467 );2622 );
2468 stack.append(State { .Block = block }) catch unreachable;
2469 continue;
2470 },
2471 Token.Id.Keyword_while => {
2472 stack.append(State {2623 stack.append(State {
2473 .While = LoopCtx {2624 .ExpectTokenSave = ExpectTokenSave {
2474 .label = ctx.label,2625 .id = Token.Id.RParen,
2475 .inline_token = null,2626 .ptr = &node.rparen,
2476 .loop_token = token,
2477 .dest_ptr = ctx.dest_ptr,
2478 }2627 }
2479 }) catch unreachable;2628 }) catch unreachable;
2480 continue;2629 try stack.append(State { .AsmClopperItems = &node.cloppers });
2481 },2630 try stack.append(State { .IfToken = Token.Id.Colon });
2482 Token.Id.Keyword_for => {2631 try stack.append(State { .AsmInputItems = &node.inputs });
2483 stack.append(State {2632 try stack.append(State { .IfToken = Token.Id.Colon });
2484 .For = LoopCtx {2633 try stack.append(State { .AsmOutputItems = &node.outputs });
2485 .label = ctx.label,2634 try stack.append(State { .IfToken = Token.Id.Colon });
2486 .inline_token = null,2635 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.template } });
2487 .loop_token = token,2636 try stack.append(State { .ExpectToken = Token.Id.LParen });
2488 .dest_ptr = ctx.dest_ptr,2637 try stack.append(State {
2638 .OptionalTokenSave = OptionalTokenSave {
2639 .id = Token.Id.Keyword_volatile,
2640 .ptr = &node.volatile_token,
2489 }2641 }
2490 }) catch unreachable;2642 });
2491 continue;
2492 },2643 },
2493 Token.Id.Keyword_inline => {2644 Token.Id.Keyword_inline => {
2494 stack.append(State {2645 stack.append(State {
2495 .Inline = InlineCtx {2646 .Inline = InlineCtx {
2496 .label = ctx.label,2647 .label = null,
2497 .inline_token = token,2648 .inline_token = token,
2498 .dest_ptr = ctx.dest_ptr,2649 .opt_ctx = opt_ctx,
2499 }2650 }
2500 }) catch unreachable;2651 }) catch unreachable;
2501 continue;2652 continue;
2502 },2653 },
2503 else => {2654 else => {
2504 try self.parseError(&stack, token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id));2655 if (!try self.parseBlockExpr(&stack, arena, opt_ctx, token)) {
2656 self.putBackToken(token);
2657 if (opt_ctx != OptionalCtx.Optional) {
2658 return self.parseError(token, "expected primary expression, found {}", @tagName(token.id));
2659 }
2660 }
2505 continue;2661 continue;
2506 },2662 }
2507 }2663 }
2508 },2664 },
25092665
2510 State.Inline => |ctx| {2666
2511 const token = self.getNextToken();2667 State.ErrorTypeOrSetDecl => |ctx| {
2512 switch (token.id) {2668 if (self.eatToken(Token.Id.LBrace) == null) {
2513 Token.Id.Keyword_while => {2669 _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeErrorType, ctx.error_token);
2514 stack.append(State {2670 continue;
2515 .While = LoopCtx {
2516 .inline_token = ctx.inline_token,
2517 .label = ctx.label,
2518 .loop_token = token,
2519 .dest_ptr = ctx.dest_ptr,
2520 }
2521 }) catch unreachable;
2522 continue;
2523 },
2524 Token.Id.Keyword_for => {
2525 stack.append(State {
2526 .For = LoopCtx {
2527 .inline_token = ctx.inline_token,
2528 .label = ctx.label,
2529 .loop_token = token,
2530 .dest_ptr = ctx.dest_ptr,
2531 }
2532 }) catch unreachable;
2533 continue;
2534 },
2535 else => {
2536 try self.parseError(&stack, token, "expected 'while' or 'for', found {}", @tagName(token.id));
2537 continue;
2538 },
2539 }2671 }
2540 },
25412672
2542 State.While => |ctx| {2673 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeErrorSetDecl,
2543 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeWhile,2674 ast.NodeErrorSetDecl {
2544 ast.NodeWhile {
2545 .base = undefined,2675 .base = undefined,
2546 .label = ctx.label,2676 .error_token = ctx.error_token,
2547 .inline_token = ctx.inline_token,2677 .decls = ArrayList(&ast.Node).init(arena),
2548 .while_token = ctx.loop_token,2678 .rbrace_token = undefined,
2549 .condition = undefined,
2550 .payload = null,
2551 .continue_expr = null,
2552 .body = undefined,
2553 .@"else" = null,
2554 }2679 }
2555 );2680 );
2556 stack.append(State { .Else = &node.@"else" }) catch unreachable;
2557 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
2558 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
2559 try stack.append(State { .PointerPayload = &node.payload });
2560 try stack.append(State { .ExpectToken = Token.Id.RParen });
2561 try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
2562 try stack.append(State { .ExpectToken = Token.Id.LParen });
2563 },
25642681
2565 State.For => |ctx| {2682 stack.append(State {
2566 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeFor,2683 .IdentifierListItemOrEnd = ListSave(&ast.Node) {
2567 ast.NodeFor {2684 .list = &node.decls,
2568 .base = undefined,2685 .ptr = &node.rbrace_token,
2569 .label = ctx.label,
2570 .inline_token = ctx.inline_token,
2571 .for_token = ctx.loop_token,
2572 .array_expr = undefined,
2573 .payload = null,
2574 .body = undefined,
2575 .@"else" = null,
2576 }2686 }
2577 );2687 }) catch unreachable;
2578 stack.append(State { .Else = &node.@"else" }) catch unreachable;2688 continue;
2579 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
2580 try stack.append(State { .PointerIndexPayload = &node.payload });
2581 try stack.append(State { .ExpectToken = Token.Id.RParen });
2582 try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } });
2583 try stack.append(State { .ExpectToken = Token.Id.LParen });
2584 },2689 },
25852690 State.StringLiteral => |opt_ctx| {
2586 State.Block => |block| {
2587 const token = self.getNextToken();2691 const token = self.getNextToken();
2588 switch (token.id) {2692 opt_ctx.store(
2589 Token.Id.RBrace => {2693 (try self.parseStringLiteral(arena, token)) ?? {
2590 block.rbrace = token;
2591 continue;
2592 },
2593 else => {
2594 self.putBackToken(token);2694 self.putBackToken(token);
2595 stack.append(State { .Block = block }) catch unreachable;2695 if (opt_ctx != OptionalCtx.Optional) {
2596 try stack.append(State { .Statement = block });2696 return self.parseError(token, "expected primary expression, found {}", @tagName(token.id));
2697 }
2698
2597 continue;2699 continue;
2598 },2700 }
2701 );
2702 },
2703 State.Identifier => |opt_ctx| {
2704 if (self.eatToken(Token.Id.Identifier)) |ident_token| {
2705 _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeIdentifier, ident_token);
2706 continue;
2707 }
2708
2709 if (opt_ctx != OptionalCtx.Optional) {
2710 const token = self.getNextToken();
2711 return self.parseError(token, "expected identifier, found {}", @tagName(token.id));
2599 }2712 }
2600 },2713 },
26012714
2602 State.Statement => |block| {2715
2603 const next = self.getNextToken();2716 State.ExpectToken => |token_id| {
2604 switch (next.id) {2717 _ = try self.expectToken(token_id);
2605 Token.Id.Keyword_comptime => {2718 continue;
2606 const mut_token = self.getNextToken();2719 },
2607 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {2720 State.ExpectTokenSave => |expect_token_save| {
2608 const var_decl = try self.createAttachNode(arena, &block.statements, ast.NodeVarDecl,2721 *expect_token_save.ptr = try self.expectToken(expect_token_save.id);
2609 ast.NodeVarDecl {2722 continue;
2610 .base = undefined,2723 },
2611 .visib_token = null,2724 State.IfToken => |token_id| {
2612 .mut_token = mut_token,2725 if (self.eatToken(token_id)) |_| {
2613 .comptime_token = next,2726 continue;
2614 .extern_export_token = null,
2615 .type_node = null,
2616 .align_node = null,
2617 .init_node = null,
2618 .lib_name = null,
2619 // initialized later
2620 .name_token = undefined,
2621 .eq_token = undefined,
2622 .semicolon_token = undefined,
2623 }
2624 );
2625 stack.append(State { .VarDecl = var_decl }) catch unreachable;
2626 continue;
2627 } else {
2628 self.putBackToken(mut_token);
2629 self.putBackToken(next);
2630 const statememt = try block.statements.addOne();
2631 stack.append(State { .Semicolon = statememt }) catch unreachable;
2632 try stack.append(State { .Expression = DestPtr{.Field = statememt } });
2633 }
2634 },
2635 Token.Id.Keyword_var, Token.Id.Keyword_const => {
2636 const var_decl = try self.createAttachNode(arena, &block.statements, ast.NodeVarDecl,
2637 ast.NodeVarDecl {
2638 .base = undefined,
2639 .visib_token = null,
2640 .mut_token = next,
2641 .comptime_token = null,
2642 .extern_export_token = null,
2643 .type_node = null,
2644 .align_node = null,
2645 .init_node = null,
2646 .lib_name = null,
2647 // initialized later
2648 .name_token = undefined,
2649 .eq_token = undefined,
2650 .semicolon_token = undefined,
2651 }
2652 );
2653 stack.append(State { .VarDecl = var_decl }) catch unreachable;
2654 continue;
2655 },
2656 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
2657 const node = try self.createAttachNode(arena, &block.statements, ast.NodeDefer,
2658 ast.NodeDefer {
2659 .base = undefined,
2660 .defer_token = next,
2661 .kind = switch (next.id) {
2662 Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional,
2663 Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error,
2664 else => unreachable,
2665 },
2666 .expr = undefined,
2667 }
2668 );
2669 stack.append(State { .Semicolon = &node.base }) catch unreachable;
2670 try stack.append(State { .AssignmentExpressionBegin = DestPtr{.Field = &node.expr } });
2671 continue;
2672 },
2673 Token.Id.LBrace => {
2674 const inner_block = try self.createAttachNode(arena, &block.statements, ast.NodeBlock,
2675 ast.NodeBlock {
2676 .base = undefined,
2677 .label = null,
2678 .lbrace = next,
2679 .statements = ArrayList(&ast.Node).init(arena),
2680 .rbrace = undefined,
2681 }
2682 );
2683 stack.append(State { .Block = inner_block }) catch unreachable;
2684 continue;
2685 },
2686 else => {
2687 self.putBackToken(next);
2688 const statememt = try block.statements.addOne();
2689 stack.append(State { .Semicolon = statememt }) catch unreachable;
2690 try stack.append(State { .AssignmentExpressionBegin = DestPtr{.Field = statememt } });
2691 continue;
2692 }
2693 }2727 }
26942728
2729 _ = stack.pop();
2730 continue;
2695 },2731 },
2732 State.IfTokenSave => |if_token_save| {
2733 if (self.eatToken(if_token_save.id)) |token| {
2734 *if_token_save.ptr = token;
2735 continue;
2736 }
26962737
2697 State.Semicolon => |node_ptr| {2738 _ = stack.pop();
2698 const node = *node_ptr;2739 continue;
2699 if (requireSemiColon(node)) {2740 },
2700 _ = (try self.expectToken(&stack, Token.Id.Semicolon)) ?? continue;2741 State.OptionalTokenSave => |optional_token_save| {
2742 if (self.eatToken(optional_token_save.id)) |token| {
2743 *optional_token_save.ptr = token;
2744 continue;
2701 }2745 }
2702 }2746
2747 continue;
2748 },
2703 }2749 }
2704 }2750 }
2705 }2751 }
...@@ -2807,10 +2853,10 @@ pub const Parser = struct {...@@ -2807,10 +2853,10 @@ pub const Parser = struct {
2807 }2853 }
2808 }2854 }
28092855
2810 fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, dest_ptr: &const DestPtr, token: &const Token) !bool {2856 fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token: &const Token) !bool {
2811 switch (token.id) {2857 switch (token.id) {
2812 Token.Id.Keyword_suspend => {2858 Token.Id.Keyword_suspend => {
2813 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuspend,2859 const node = try self.createToCtxNode(arena, ctx, ast.NodeSuspend,
2814 ast.NodeSuspend {2860 ast.NodeSuspend {
2815 .base = undefined,2861 .base = undefined,
2816 .suspend_token = *token,2862 .suspend_token = *token,
...@@ -2820,11 +2866,11 @@ pub const Parser = struct {...@@ -2820,11 +2866,11 @@ pub const Parser = struct {
2820 );2866 );
28212867
2822 stack.append(State { .SuspendBody = node }) catch unreachable;2868 stack.append(State { .SuspendBody = node }) catch unreachable;
2823 try stack.append(State { .Payload = &node.payload });2869 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
2824 return true;2870 return true;
2825 },2871 },
2826 Token.Id.Keyword_if => {2872 Token.Id.Keyword_if => {
2827 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeIf,2873 const node = try self.createToCtxNode(arena, ctx, ast.NodeIf,
2828 ast.NodeIf {2874 ast.NodeIf {
2829 .base = undefined,2875 .base = undefined,
2830 .if_token = *token,2876 .if_token = *token,
...@@ -2836,10 +2882,10 @@ pub const Parser = struct {...@@ -2836,10 +2882,10 @@ pub const Parser = struct {
2836 );2882 );
28372883
2838 stack.append(State { .Else = &node.@"else" }) catch unreachable;2884 stack.append(State { .Else = &node.@"else" }) catch unreachable;
2839 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });2885 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
2840 try stack.append(State { .PointerPayload = &node.payload });2886 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
2841 try stack.append(State { .ExpectToken = Token.Id.RParen });2887 try stack.append(State { .ExpectToken = Token.Id.RParen });
2842 try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });2888 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
2843 try stack.append(State { .ExpectToken = Token.Id.LParen });2889 try stack.append(State { .ExpectToken = Token.Id.LParen });
2844 return true;2890 return true;
2845 },2891 },
...@@ -2849,7 +2895,7 @@ pub const Parser = struct {...@@ -2849,7 +2895,7 @@ pub const Parser = struct {
2849 .label = null,2895 .label = null,
2850 .inline_token = null,2896 .inline_token = null,
2851 .loop_token = *token,2897 .loop_token = *token,
2852 .dest_ptr = *dest_ptr,2898 .opt_ctx = *ctx,
2853 }2899 }
2854 }) catch unreachable;2900 }) catch unreachable;
2855 return true;2901 return true;
...@@ -2860,13 +2906,13 @@ pub const Parser = struct {...@@ -2860,13 +2906,13 @@ pub const Parser = struct {
2860 .label = null,2906 .label = null,
2861 .inline_token = null,2907 .inline_token = null,
2862 .loop_token = *token,2908 .loop_token = *token,
2863 .dest_ptr = *dest_ptr,2909 .opt_ctx = *ctx,
2864 }2910 }
2865 }) catch unreachable;2911 }) catch unreachable;
2866 return true;2912 return true;
2867 },2913 },
2868 Token.Id.Keyword_switch => {2914 Token.Id.Keyword_switch => {
2869 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSwitch,2915 const node = try self.createToCtxNode(arena, ctx, ast.NodeSwitch,
2870 ast.NodeSwitch {2916 ast.NodeSwitch {
2871 .base = undefined,2917 .base = undefined,
2872 .switch_token = *token,2918 .switch_token = *token,
...@@ -2884,23 +2930,23 @@ pub const Parser = struct {...@@ -2884,23 +2930,23 @@ pub const Parser = struct {
2884 }) catch unreachable;2930 }) catch unreachable;
2885 try stack.append(State { .ExpectToken = Token.Id.LBrace });2931 try stack.append(State { .ExpectToken = Token.Id.LBrace });
2886 try stack.append(State { .ExpectToken = Token.Id.RParen });2932 try stack.append(State { .ExpectToken = Token.Id.RParen });
2887 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });2933 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2888 try stack.append(State { .ExpectToken = Token.Id.LParen });2934 try stack.append(State { .ExpectToken = Token.Id.LParen });
2889 return true;2935 return true;
2890 },2936 },
2891 Token.Id.Keyword_comptime => {2937 Token.Id.Keyword_comptime => {
2892 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeComptime,2938 const node = try self.createToCtxNode(arena, ctx, ast.NodeComptime,
2893 ast.NodeComptime {2939 ast.NodeComptime {
2894 .base = undefined,2940 .base = undefined,
2895 .comptime_token = *token,2941 .comptime_token = *token,
2896 .expr = undefined,2942 .expr = undefined,
2897 }2943 }
2898 );2944 );
2899 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });2945 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2900 return true;2946 return true;
2901 },2947 },
2902 Token.Id.LBrace => {2948 Token.Id.LBrace => {
2903 const block = try self.createToDestNode(arena, dest_ptr, ast.NodeBlock,2949 const block = try self.createToCtxNode(arena, ctx, ast.NodeBlock,
2904 ast.NodeBlock {2950 ast.NodeBlock {
2905 .base = undefined,2951 .base = undefined,
2906 .label = null,2952 .label = null,
...@@ -2918,22 +2964,16 @@ pub const Parser = struct {...@@ -2918,22 +2964,16 @@ pub const Parser = struct {
2918 }2964 }
2919 }2965 }
29202966
2921 fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, maybe_ptr: ?&Token, state_after_comma: &const State) !void {2967 fn expectCommaOrEnd(self: &Parser, end: @TagType(Token.Id)) !?Token {
2922 var token = self.getNextToken();2968 var token = self.getNextToken();
2923 switch (token.id) {2969 switch (token.id) {
2924 Token.Id.Comma => {2970 Token.Id.Comma => return null,
2925 stack.append(state_after_comma) catch unreachable;
2926 },
2927 else => {2971 else => {
2928 const IdTag = @TagType(Token.Id);2972 if (end == token.id) {
2929 if (IdTag(*end) == token.id) {2973 return token;
2930 if (maybe_ptr) |ptr| {
2931 *ptr = token;
2932 }
2933 return;
2934 }2974 }
29352975
2936 try self.parseError(stack, token, "expected ',' or {}, found {}", @tagName(*end), @tagName(token.id));2976 return self.parseError(token, "expected ',' or {}, found {}", @tagName(end), @tagName(token.id));
2937 },2977 },
2938 }2978 }
2939 }2979 }
...@@ -2960,8 +3000,16 @@ pub const Parser = struct {...@@ -2960,8 +3000,16 @@ pub const Parser = struct {
2960 };3000 };
2961 }3001 }
29623002
2963 fn tokenIdToComparison(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3003 fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
2964 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) {
2965 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp { .BangEqual = void{} },3013 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp { .BangEqual = void{} },
2966 Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp { .EqualEqual = void{} },3014 Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp { .EqualEqual = void{} },
2967 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp { .LessThan = void{} },3015 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp { .LessThan = void{} },
...@@ -2972,16 +3020,16 @@ pub const Parser = struct {...@@ -2972,16 +3020,16 @@ pub const Parser = struct {
2972 };3020 };
2973 }3021 }
29743022
2975 fn tokenIdToBitShift(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3023 fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
2976 return switch (*id) {3024 return switch (id) {
2977 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp { .BitShiftLeft = void{} },3025 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp { .BitShiftLeft = void{} },
2978 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp { .BitShiftRight = void{} },3026 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp { .BitShiftRight = void{} },
2979 else => null,3027 else => null,
2980 };3028 };
2981 }3029 }
29823030
2983 fn tokenIdToAddition(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3031 fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
2984 return switch (*id) {3032 return switch (id) {
2985 Token.Id.Minus => ast.NodeInfixOp.InfixOp { .Sub = void{} },3033 Token.Id.Minus => ast.NodeInfixOp.InfixOp { .Sub = void{} },
2986 Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp { .SubWrap = void{} },3034 Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp { .SubWrap = void{} },
2987 Token.Id.Plus => ast.NodeInfixOp.InfixOp { .Add = void{} },3035 Token.Id.Plus => ast.NodeInfixOp.InfixOp { .Add = void{} },
...@@ -2991,8 +3039,8 @@ pub const Parser = struct {...@@ -2991,8 +3039,8 @@ pub const Parser = struct {
2991 };3039 };
2992 }3040 }
29933041
2994 fn tokenIdToMultiply(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {3042 fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp {
2995 return switch (*id) {3043 return switch (id) {
2996 Token.Id.Slash => ast.NodeInfixOp.InfixOp { .Div = void{} },3044 Token.Id.Slash => ast.NodeInfixOp.InfixOp { .Div = void{} },
2997 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp { .Mult = void{} },3045 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp { .Mult = void{} },
2998 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp { .ArrayMult = void{} },3046 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp { .ArrayMult = void{} },
...@@ -3003,8 +3051,8 @@ pub const Parser = struct {...@@ -3003,8 +3051,8 @@ pub const Parser = struct {
3003 };3051 };
3004 }3052 }
30053053
3006 fn tokenIdToPrefixOp(id: &const Token.Id) ?ast.NodePrefixOp.PrefixOp {3054 fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.NodePrefixOp.PrefixOp {
3007 return switch (*id) {3055 return switch (id) {
3008 Token.Id.Bang => ast.NodePrefixOp.PrefixOp { .BoolNot = void{} },3056 Token.Id.Bang => ast.NodePrefixOp.PrefixOp { .BoolNot = void{} },
3009 Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} },3057 Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} },
3010 Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} },3058 Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} },
...@@ -3049,9 +3097,9 @@ pub const Parser = struct {...@@ -3049,9 +3097,9 @@ pub const Parser = struct {
3049 return node;3097 return node;
3050 }3098 }
30513099
3052 fn createToDestNode(self: &Parser, arena: &mem.Allocator, dest_ptr: &const DestPtr, comptime T: type, init_to: &const T) !&T {3100 fn createToCtxNode(self: &Parser, arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, init_to: &const T) !&T {
3053 const node = try self.createNode(arena, T, init_to);3101 const node = try self.createNode(arena, T, init_to);
3054 dest_ptr.store(&node.base);3102 opt_ctx.store(&node.base);
30553103
3056 return node;3104 return node;
3057 }3105 }
...@@ -3065,51 +3113,38 @@ pub const Parser = struct {...@@ -3065,51 +3113,38 @@ pub const Parser = struct {
3065 );3113 );
3066 }3114 }
30673115
3068 fn parseError(self: &Parser, stack: &ArrayList(State), token: &const Token, comptime fmt: []const u8, args: ...) !void {3116 fn createToCtxLiteral(self: &Parser, arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, token: &const Token) !&T {
3069 // Before reporting an error. We pop the stack to see if our state was optional3117 const node = try self.createLiteral(arena, T, token);
3070 self.revertIfOptional(stack) catch {3118 opt_ctx.store(&node.base);
3071 const loc = self.tokenizer.getTokenLocation(0, token);3119
3072 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);3120 return node;
3073 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
3074 {
3075 var i: usize = 0;
3076 while (i < loc.column) : (i += 1) {
3077 warn(" ");
3078 }
3079 }
3080 {
3081 const caret_count = token.end - token.start;
3082 var i: usize = 0;
3083 while (i < caret_count) : (i += 1) {
3084 warn("~");
3085 }
3086 }
3087 warn("\n");
3088 return error.ParseError;
3089 };
3090 }3121 }
30913122
3092 fn revertIfOptional(self: &Parser, stack: &ArrayList(State)) !void {3123 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
3093 while (stack.popOrNull()) |state| {3124 const loc = self.tokenizer.getTokenLocation(0, token);
3094 switch (state) {3125 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
3095 State.Optional => |revert| {3126 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
3096 *self = revert.parser;3127 {
3097 *self.tokenizer = revert.tokenizer;3128 var i: usize = 0;
3098 *revert.ptr = null;3129 while (i < loc.column) : (i += 1) {
3099 return;3130 warn(" ");
3100 },
3101 else => { }
3102 }3131 }
3103 }3132 }
31043133 {
3105 return error.NoOptionalStateFound;3134 const caret_count = token.end - token.start;
3135 var i: usize = 0;
3136 while (i < caret_count) : (i += 1) {
3137 warn("~");
3138 }
3139 }
3140 warn("\n");
3141 return error.ParseError;
3106 }3142 }
31073143
3108 fn expectToken(self: &Parser, stack: &ArrayList(State), id: @TagType(Token.Id)) !?Token {3144 fn expectToken(self: &Parser, id: @TagType(Token.Id)) !Token {
3109 const token = self.getNextToken();3145 const token = self.getNextToken();
3110 if (token.id != id) {3146 if (token.id != id) {
3111 try self.parseError(stack, token, "expected {}, found {}", @tagName(id), @tagName(token.id));3147 return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));
3112 return null;
3113 }3148 }
3114 return token;3149 return token;
3115 }3150 }
...@@ -3424,7 +3459,7 @@ pub const Parser = struct {...@@ -3424,7 +3459,7 @@ pub const Parser = struct {
3424 }3459 }
34253460
3426 if (suspend_node.payload) |payload| {3461 if (suspend_node.payload) |payload| {
3427 try stack.append(RenderState { .Expression = &payload.base });3462 try stack.append(RenderState { .Expression = payload });
3428 try stack.append(RenderState { .Text = " " });3463 try stack.append(RenderState { .Text = " " });
3429 }3464 }
3430 },3465 },
...@@ -3435,7 +3470,7 @@ pub const Parser = struct {...@@ -3435,7 +3470,7 @@ pub const Parser = struct {
3435 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {3470 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {
3436 if (prefix_op_node.op.Catch) |payload| {3471 if (prefix_op_node.op.Catch) |payload| {
3437 try stack.append(RenderState { .Text = " " });3472 try stack.append(RenderState { .Text = " " });
3438 try stack.append(RenderState { .Expression = &payload.base });3473 try stack.append(RenderState { .Expression = payload });
3439 }3474 }
3440 try stack.append(RenderState { .Text = " catch " });3475 try stack.append(RenderState { .Text = " catch " });
3441 } else {3476 } else {
...@@ -3624,17 +3659,25 @@ pub const Parser = struct {...@@ -3624,17 +3659,25 @@ pub const Parser = struct {
3624 },3659 },
3625 ast.Node.Id.ControlFlowExpression => {3660 ast.Node.Id.ControlFlowExpression => {
3626 const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base);3661 const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base);
3662
3663 if (flow_expr.rhs) |rhs| {
3664 try stack.append(RenderState { .Expression = rhs });
3665 try stack.append(RenderState { .Text = " " });
3666 }
3667
3627 switch (flow_expr.kind) {3668 switch (flow_expr.kind) {
3628 ast.NodeControlFlowExpression.Kind.Break => |maybe_blk_token| {3669 ast.NodeControlFlowExpression.Kind.Break => |maybe_label| {
3629 try stream.print("break");3670 try stream.print("break");
3630 if (maybe_blk_token) |blk_token| {3671 if (maybe_label) |label| {
3631 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));3672 try stream.print(" :");
3673 try stack.append(RenderState { .Expression = label });
3632 }3674 }
3633 },3675 },
3634 ast.NodeControlFlowExpression.Kind.Continue => |maybe_blk_token| {3676 ast.NodeControlFlowExpression.Kind.Continue => |maybe_label| {
3635 try stream.print("continue");3677 try stream.print("continue");
3636 if (maybe_blk_token) |blk_token| {3678 if (maybe_label) |label| {
3637 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));3679 try stream.print(" :");
3680 try stack.append(RenderState { .Expression = label });
3638 }3681 }
3639 },3682 },
3640 ast.NodeControlFlowExpression.Kind.Return => {3683 ast.NodeControlFlowExpression.Kind.Return => {
...@@ -3642,25 +3685,20 @@ pub const Parser = struct {...@@ -3642,25 +3685,20 @@ pub const Parser = struct {
3642 },3685 },
36433686
3644 }3687 }
3645
3646 if (flow_expr.rhs) |rhs| {
3647 try stream.print(" ");
3648 try stack.append(RenderState { .Expression = rhs });
3649 }
3650 },3688 },
3651 ast.Node.Id.Payload => {3689 ast.Node.Id.Payload => {
3652 const payload = @fieldParentPtr(ast.NodePayload, "base", base);3690 const payload = @fieldParentPtr(ast.NodePayload, "base", base);
3653 try stack.append(RenderState { .Text = "|"});3691 try stack.append(RenderState { .Text = "|"});
3654 try stack.append(RenderState { .Expression = &payload.error_symbol.base });3692 try stack.append(RenderState { .Expression = payload.error_symbol });
3655 try stack.append(RenderState { .Text = "|"});3693 try stack.append(RenderState { .Text = "|"});
3656 },3694 },
3657 ast.Node.Id.PointerPayload => {3695 ast.Node.Id.PointerPayload => {
3658 const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base);3696 const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base);
3659 try stack.append(RenderState { .Text = "|"});3697 try stack.append(RenderState { .Text = "|"});
3660 try stack.append(RenderState { .Expression = &payload.value_symbol.base });3698 try stack.append(RenderState { .Expression = payload.value_symbol });
36613699
3662 if (payload.is_ptr) {3700 if (payload.ptr_token) |ptr_token| {
3663 try stack.append(RenderState { .Text = "*"});3701 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(ptr_token) });
3664 }3702 }
36653703
3666 try stack.append(RenderState { .Text = "|"});3704 try stack.append(RenderState { .Text = "|"});
...@@ -3670,14 +3708,14 @@ pub const Parser = struct {...@@ -3670,14 +3708,14 @@ pub const Parser = struct {
3670 try stack.append(RenderState { .Text = "|"});3708 try stack.append(RenderState { .Text = "|"});
36713709
3672 if (payload.index_symbol) |index_symbol| {3710 if (payload.index_symbol) |index_symbol| {
3673 try stack.append(RenderState { .Expression = &index_symbol.base });3711 try stack.append(RenderState { .Expression = index_symbol });
3674 try stack.append(RenderState { .Text = ", "});3712 try stack.append(RenderState { .Text = ", "});
3675 }3713 }
36763714
3677 try stack.append(RenderState { .Expression = &payload.value_symbol.base });3715 try stack.append(RenderState { .Expression = payload.value_symbol });
36783716
3679 if (payload.is_ptr) {3717 if (payload.ptr_token) |ptr_token| {
3680 try stack.append(RenderState { .Text = "*"});3718 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(ptr_token) });
3681 }3719 }
36823720
3683 try stack.append(RenderState { .Text = "|"});3721 try stack.append(RenderState { .Text = "|"});
...@@ -3809,7 +3847,7 @@ pub const Parser = struct {...@@ -3809,7 +3847,7 @@ pub const Parser = struct {
3809 i -= 1;3847 i -= 1;
3810 const node = decls[i];3848 const node = decls[i];
3811 try stack.append(RenderState { .Text = "," });3849 try stack.append(RenderState { .Text = "," });
3812 try stack.append(RenderState { .Expression = &node.base});3850 try stack.append(RenderState { .Expression = node });
3813 try stack.append(RenderState.PrintIndent);3851 try stack.append(RenderState.PrintIndent);
3814 try stack.append(RenderState {3852 try stack.append(RenderState {
3815 .Text = blk: {3853 .Text = blk: {
...@@ -3961,7 +3999,7 @@ pub const Parser = struct {...@@ -3961,7 +3999,7 @@ pub const Parser = struct {
3961 try stack.append(RenderState { .Expression = switch_case.expr });3999 try stack.append(RenderState { .Expression = switch_case.expr });
3962 if (switch_case.payload) |payload| {4000 if (switch_case.payload) |payload| {
3963 try stack.append(RenderState { .Text = " " });4001 try stack.append(RenderState { .Text = " " });
3964 try stack.append(RenderState { .Expression = &payload.base });4002 try stack.append(RenderState { .Expression = payload });
3965 }4003 }
3966 try stack.append(RenderState { .Text = " => "});4004 try stack.append(RenderState { .Text = " => "});
39674005
...@@ -4003,7 +4041,7 @@ pub const Parser = struct {...@@ -4003,7 +4041,7 @@ pub const Parser = struct {
40034041
4004 if (else_node.payload) |payload| {4042 if (else_node.payload) |payload| {
4005 try stack.append(RenderState { .Text = " " });4043 try stack.append(RenderState { .Text = " " });
4006 try stack.append(RenderState { .Expression = &payload.base });4044 try stack.append(RenderState { .Expression = payload });
4007 }4045 }
4008 },4046 },
4009 ast.Node.Id.While => {4047 ast.Node.Id.While => {
...@@ -4048,7 +4086,7 @@ pub const Parser = struct {...@@ -4048,7 +4086,7 @@ pub const Parser = struct {
4048 }4086 }
40494087
4050 if (while_node.payload) |payload| {4088 if (while_node.payload) |payload| {
4051 try stack.append(RenderState { .Expression = &payload.base });4089 try stack.append(RenderState { .Expression = payload });
4052 try stack.append(RenderState { .Text = " " });4090 try stack.append(RenderState { .Text = " " });
4053 }4091 }
40544092
...@@ -4091,7 +4129,7 @@ pub const Parser = struct {...@@ -4091,7 +4129,7 @@ pub const Parser = struct {
4091 }4129 }
40924130
4093 if (for_node.payload) |payload| {4131 if (for_node.payload) |payload| {
4094 try stack.append(RenderState { .Expression = &payload.base });4132 try stack.append(RenderState { .Expression = payload });
4095 try stack.append(RenderState { .Text = " " });4133 try stack.append(RenderState { .Text = " " });
4096 }4134 }
40974135
...@@ -4124,7 +4162,7 @@ pub const Parser = struct {...@@ -4124,7 +4162,7 @@ pub const Parser = struct {
41244162
4125 if (@"else".payload) |payload| {4163 if (@"else".payload) |payload| {
4126 try stack.append(RenderState { .Text = " " });4164 try stack.append(RenderState { .Text = " " });
4127 try stack.append(RenderState { .Expression = &payload.base });4165 try stack.append(RenderState { .Expression = payload });
4128 }4166 }
41294167
4130 try stack.append(RenderState { .Text = " " });4168 try stack.append(RenderState { .Text = " " });
...@@ -4138,7 +4176,7 @@ pub const Parser = struct {...@@ -4138,7 +4176,7 @@ pub const Parser = struct {
4138 try stack.append(RenderState { .Text = " " });4176 try stack.append(RenderState { .Text = " " });
41394177
4140 if (if_node.payload) |payload| {4178 if (if_node.payload) |payload| {
4141 try stack.append(RenderState { .Expression = &payload.base });4179 try stack.append(RenderState { .Expression = payload });
4142 try stack.append(RenderState { .Text = " " });4180 try stack.append(RenderState { .Text = " " });
4143 }4181 }
41444182
...@@ -4150,8 +4188,8 @@ pub const Parser = struct {...@@ -4150,8 +4188,8 @@ pub const Parser = struct {
4150 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);4188 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);
4151 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));4189 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));
41524190
4153 if (asm_node.is_volatile) {4191 if (asm_node.volatile_token) |volatile_token| {
4154 try stream.write("volatile ");4192 try stream.print("{} ", self.tokenizer.getTokenSlice(volatile_token));
4155 }4193 }
41564194
4157 try stack.append(RenderState { .Indent = indent });4195 try stack.append(RenderState { .Indent = indent });
...@@ -4241,7 +4279,7 @@ pub const Parser = struct {...@@ -4241,7 +4279,7 @@ pub const Parser = struct {
4241 try stack.append(RenderState { .Text = " ("});4279 try stack.append(RenderState { .Text = " ("});
4242 try stack.append(RenderState { .Expression = asm_input.constraint });4280 try stack.append(RenderState { .Expression = asm_input.constraint });
4243 try stack.append(RenderState { .Text = "] "});4281 try stack.append(RenderState { .Text = "] "});
4244 try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});4282 try stack.append(RenderState { .Expression = asm_input.symbolic_name });
4245 try stack.append(RenderState { .Text = "["});4283 try stack.append(RenderState { .Text = "["});
4246 },4284 },
4247 ast.Node.Id.AsmOutput => {4285 ast.Node.Id.AsmOutput => {
...@@ -4260,7 +4298,7 @@ pub const Parser = struct {...@@ -4260,7 +4298,7 @@ pub const Parser = struct {
4260 try stack.append(RenderState { .Text = " ("});4298 try stack.append(RenderState { .Text = " ("});
4261 try stack.append(RenderState { .Expression = asm_output.constraint });4299 try stack.append(RenderState { .Expression = asm_output.constraint });
4262 try stack.append(RenderState { .Text = "] "});4300 try stack.append(RenderState { .Text = "] "});
4263 try stack.append(RenderState { .Expression = &asm_output.symbolic_name.base});4301 try stack.append(RenderState { .Expression = asm_output.symbolic_name });
4264 try stack.append(RenderState { .Text = "["});4302 try stack.append(RenderState { .Text = "["});
4265 },4303 },
42664304