authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-12 16:08:23+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-12 16:08:23+02:00
log206c0b8bdb4838010d6a1e70135134dc3edc6723
tree3969f0899d9db4a103d11a156bb6de705af6db2e
parent0d8646d262ebc3db6631421db8fc79228b6622f8

std.zig.parser: Refactor, round 1:

* Removed the Optional state * We now have an OptionalCtx instead of DestPtr * OptionalCtx simulated return, instead of reverting states * OptionalCtx is a lot less hacky, but is still a small footgun * Trying to avoid consuming more than one token per state * This is required, because of comments * The C++ compiler allows comments between all tokens * We therefor have to consume comment tokens between each state * Reordered states so they are grouped in some logical fasion

2 files changed, 1935 insertions(+), 1868 deletions(-)

std/zig/ast.zig+47-31
...@@ -283,7 +283,7 @@ pub const NodeUse = struct {...@@ -283,7 +283,7 @@ 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 {
...@@ -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,7 +756,7 @@ pub const NodePointerIndexPayload = struct {...@@ -756,7 +756,7 @@ 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 {
...@@ -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 {
...@@ -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,
...@@ -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
...@@ -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
...@@ -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,
...@@ -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,7 +1406,7 @@ pub const NodeControlFlowExpression = struct {...@@ -1390,7 +1406,7 @@ 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 {
...@@ -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+1888-1837
...@@ -59,36 +59,27 @@ pub const Parser = struct {...@@ -59,36 +59,27 @@ pub const Parser = struct {
59 lib_name: ?&ast.Node,59 lib_name: ?&ast.Node,
60 };60 };
6161
62 const TopLevelExternOrFieldCtx = struct {
63 visib_token: Token,
64 container_decl: &ast.NodeContainerDecl,
65 };
66
62 const ContainerExternCtx = struct {67 const ContainerExternCtx = struct {
63 dest_ptr: DestPtr,68 opt_ctx: OptionalCtx,
64 ltoken: Token,69 ltoken: Token,
65 layout: ast.NodeContainerDecl.Layout,70 layout: ast.NodeContainerDecl.Layout,
66 };71 };
6772
68 const DestPtr = union(enum) {
69 Field: &&ast.Node,
70 NullableField: &?&ast.Node,
71
72 pub fn store(self: &const DestPtr, value: &ast.Node) void {
73 switch (*self) {
74 DestPtr.Field => |ptr| *ptr = value,
75 DestPtr.NullableField => |ptr| *ptr = value,
76 }
77 }
78
79 pub fn get(self: &const DestPtr) &ast.Node {
80 switch (*self) {
81 DestPtr.Field => |ptr| return *ptr,
82 DestPtr.NullableField => |ptr| return ??*ptr,
83 }
84 }
85 };
86
87 const ExpectTokenSave = struct {73 const ExpectTokenSave = struct {
88 id: Token.Id,74 id: Token.Id,
89 ptr: &Token,75 ptr: &Token,
90 };76 };
9177
78 const OptionalTokenSave = struct {
79 id: Token.Id,
80 ptr: &?Token,
81 };
82
92 const RevertState = struct {83 const RevertState = struct {
93 parser: Parser,84 parser: Parser,
94 tokenizer: Tokenizer,85 tokenizer: Tokenizer,
...@@ -104,11 +95,6 @@ pub const Parser = struct {...@@ -104,11 +95,6 @@ pub const Parser = struct {
104 ptr: &Token,95 ptr: &Token,
105 };96 };
10697
107 const ElseCtx = struct {
108 payload: ?DestPtr,
109 body: DestPtr,
110 };
111
112 fn ListSave(comptime T: type) type {98 fn ListSave(comptime T: type) type {
113 return struct {99 return struct {
114 list: &ArrayList(T),100 list: &ArrayList(T),
...@@ -118,118 +104,187 @@ pub const Parser = struct {...@@ -118,118 +104,187 @@ pub const Parser = struct {
118104
119 const LabelCtx = struct {105 const LabelCtx = struct {
120 label: ?Token,106 label: ?Token,
121 dest_ptr: DestPtr,107 opt_ctx: OptionalCtx,
122 };108 };
123109
124 const InlineCtx = struct {110 const InlineCtx = struct {
125 label: ?Token,111 label: ?Token,
126 inline_token: ?Token,112 inline_token: ?Token,
127 dest_ptr: DestPtr,113 opt_ctx: OptionalCtx,
128 };114 };
129115
130 const LoopCtx = struct {116 const LoopCtx = struct {
131 label: ?Token,117 label: ?Token,
132 inline_token: ?Token,118 inline_token: ?Token,
133 loop_token: Token,119 loop_token: Token,
134 dest_ptr: DestPtr,120 opt_ctx: OptionalCtx,
135 };121 };
136122
137 const AsyncEndCtx = struct {123 const AsyncEndCtx = struct {
138 dest_ptr: DestPtr,124 ctx: OptionalCtx,
139 attribute: &ast.NodeAsyncAttribute,125 attribute: &ast.NodeAsyncAttribute,
140 };126 };
141127
128 const ErrorTypeOrSetDeclCtx = struct {
129 opt_ctx: OptionalCtx,
130 error_token: Token,
131 };
132
133 const ParamDeclEndCtx = struct {
134 fn_proto: &ast.NodeFnProto,
135 param_decl: &ast.NodeParamDecl,
136 };
137
138 const ComptimeStatementCtx = struct {
139 comptime_token: Token,
140 block: &ast.NodeBlock,
141 };
142
143 const OptionalCtx = union(enum) {
144 Optional: &?&ast.Node,
145 RequiredNull: &?&ast.Node,
146 Required: &&ast.Node,
147
148 pub fn store(self: &const OptionalCtx, value: &ast.Node) void {
149 switch (*self) {
150 OptionalCtx.Optional => |ptr| *ptr = value,
151 OptionalCtx.RequiredNull => |ptr| *ptr = value,
152 OptionalCtx.Required => |ptr| *ptr = value,
153 }
154 }
155
156 pub fn get(self: &const OptionalCtx) ?&ast.Node {
157 switch (*self) {
158 OptionalCtx.Optional => |ptr| return *ptr,
159 OptionalCtx.RequiredNull => |ptr| return ??*ptr,
160 OptionalCtx.Required => |ptr| return *ptr,
161 }
162 }
163
164 pub fn toRequired(self: &const OptionalCtx) OptionalCtx {
165 switch (*self) {
166 OptionalCtx.Optional => |ptr| {
167 return OptionalCtx { .RequiredNull = ptr };
168 },
169 OptionalCtx.RequiredNull => |ptr| return *self,
170 OptionalCtx.Required => |ptr| return *self,
171 }
172 }
173 };
174
142 const State = union(enum) {175 const State = union(enum) {
143 TopLevel,176 TopLevel,
144 TopLevelExtern: TopLevelDeclCtx,177 TopLevelExtern: TopLevelDeclCtx,
145 TopLevelLibname: TopLevelDeclCtx,178 TopLevelLibname: TopLevelDeclCtx,
146 TopLevelDecl: TopLevelDeclCtx,179 TopLevelDecl: TopLevelDeclCtx,
180 TopLevelExternOrField: TopLevelExternOrFieldCtx,
181
147 ContainerExtern: ContainerExternCtx,182 ContainerExtern: ContainerExternCtx,
183 ContainerInitArgStart: &ast.NodeContainerDecl,
184 ContainerInitArg: &ast.NodeContainerDecl,
148 ContainerDecl: &ast.NodeContainerDecl,185 ContainerDecl: &ast.NodeContainerDecl,
149 SliceOrArrayAccess: &ast.NodeSuffixOp,186
150 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
151 VarDecl: &ast.NodeVarDecl,187 VarDecl: &ast.NodeVarDecl,
152 VarDeclAlign: &ast.NodeVarDecl,188 VarDeclAlign: &ast.NodeVarDecl,
153 VarDeclEq: &ast.NodeVarDecl,189 VarDeclEq: &ast.NodeVarDecl,
154 IfToken: @TagType(Token.Id),190
155 IfTokenSave: ExpectTokenSave,191 FnDef: &ast.NodeFnProto,
156 ExpectToken: @TagType(Token.Id),
157 ExpectTokenSave: ExpectTokenSave,
158 FnProto: &ast.NodeFnProto,192 FnProto: &ast.NodeFnProto,
159 FnProtoAlign: &ast.NodeFnProto,193 FnProtoAlign: &ast.NodeFnProto,
160 FnProtoReturnType: &ast.NodeFnProto,194 FnProtoReturnType: &ast.NodeFnProto,
195
161 ParamDecl: &ast.NodeFnProto,196 ParamDecl: &ast.NodeFnProto,
162 ParamDeclComma,197 ParamDeclAliasOrComptime: &ast.NodeParamDecl,
163 FnDef: &ast.NodeFnProto,198 ParamDeclName: &ast.NodeParamDecl,
199 ParamDeclEnd: ParamDeclEndCtx,
200 ParamDeclComma: &ast.NodeFnProto,
201
164 LabeledExpression: LabelCtx,202 LabeledExpression: LabelCtx,
165 Inline: InlineCtx,203 Inline: InlineCtx,
166 While: LoopCtx,204 While: LoopCtx,
205 WhileContinueExpr: &?&ast.Node,
167 For: LoopCtx,206 For: LoopCtx,
168 Block: &ast.NodeBlock,
169 Else: &?&ast.NodeElse,207 Else: &?&ast.NodeElse,
170 WhileContinueExpr: &?&ast.Node,208
209 Block: &ast.NodeBlock,
171 Statement: &ast.NodeBlock,210 Statement: &ast.NodeBlock,
211 ComptimeStatement: ComptimeStatementCtx,
172 Semicolon: &const &const ast.Node,212 Semicolon: &const &const ast.Node,
213
173 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),214 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
215 AsmOutputReturnOrType: &ast.NodeAsmOutput,
174 AsmInputItems: &ArrayList(&ast.NodeAsmInput),216 AsmInputItems: &ArrayList(&ast.NodeAsmInput),
175 AsmClopperItems: &ArrayList(&ast.Node),217 AsmClopperItems: &ArrayList(&ast.Node),
218
176 ExprListItemOrEnd: ExprListCtx,219 ExprListItemOrEnd: ExprListCtx,
177 ExprListCommaOrEnd: ExprListCtx,220 ExprListCommaOrEnd: ExprListCtx,
178 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),221 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
179 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),222 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
180 FieldListCommaOrEnd: &ast.NodeContainerDecl,223 FieldListCommaOrEnd: &ast.NodeContainerDecl,
181 IdentifierListItemOrEnd: ListSave(&ast.NodeIdentifier),224 IdentifierListItemOrEnd: ListSave(&ast.Node),
182 IdentifierListCommaOrEnd: ListSave(&ast.NodeIdentifier),225 IdentifierListCommaOrEnd: ListSave(&ast.Node),
183 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),226 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),227 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
228 SwitchCaseFirstItem: &ArrayList(&ast.Node),
190 SwitchCaseItem: &ArrayList(&ast.Node),229 SwitchCaseItem: &ArrayList(&ast.Node),
191 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),230 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
192231
193 /// A state that can be appended before any other State. If an error occures,232 SuspendBody: &ast.NodeSuspend,
194 /// the parser will first try looking for the closest optional state. If an233 AsyncAllocator: &ast.NodeAsyncAttribute,
195 /// optional state is found, the parser will revert to the state it was in234 AsyncEnd: AsyncEndCtx,
196 /// when the optional was added. This will polute the arena allocator with235
197 /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes.236 SliceOrArrayAccess: &ast.NodeSuffixOp,
198 Optional: RevertState,237 SliceOrArrayType: &ast.NodePrefixOp,
199238 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
200 Expression: DestPtr,239
201 RangeExpressionBegin: DestPtr,240 Payload: OptionalCtx,
202 RangeExpressionEnd: DestPtr,241 PointerPayload: OptionalCtx,
203 AssignmentExpressionBegin: DestPtr,242 PointerIndexPayload: OptionalCtx,
204 AssignmentExpressionEnd: DestPtr,243
205 UnwrapExpressionBegin: DestPtr,244 Expression: OptionalCtx,
206 UnwrapExpressionEnd: DestPtr,245 RangeExpressionBegin: OptionalCtx,
207 BoolOrExpressionBegin: DestPtr,246 RangeExpressionEnd: OptionalCtx,
208 BoolOrExpressionEnd: DestPtr,247 AssignmentExpressionBegin: OptionalCtx,
209 BoolAndExpressionBegin: DestPtr,248 AssignmentExpressionEnd: OptionalCtx,
210 BoolAndExpressionEnd: DestPtr,249 UnwrapExpressionBegin: OptionalCtx,
211 ComparisonExpressionBegin: DestPtr,250 UnwrapExpressionEnd: OptionalCtx,
212 ComparisonExpressionEnd: DestPtr,251 BoolOrExpressionBegin: OptionalCtx,
213 BinaryOrExpressionBegin: DestPtr,252 BoolOrExpressionEnd: OptionalCtx,
214 BinaryOrExpressionEnd: DestPtr,253 BoolAndExpressionBegin: OptionalCtx,
215 BinaryXorExpressionBegin: DestPtr,254 BoolAndExpressionEnd: OptionalCtx,
216 BinaryXorExpressionEnd: DestPtr,255 ComparisonExpressionBegin: OptionalCtx,
217 BinaryAndExpressionBegin: DestPtr,256 ComparisonExpressionEnd: OptionalCtx,
218 BinaryAndExpressionEnd: DestPtr,257 BinaryOrExpressionBegin: OptionalCtx,
219 BitShiftExpressionBegin: DestPtr,258 BinaryOrExpressionEnd: OptionalCtx,
220 BitShiftExpressionEnd: DestPtr,259 BinaryXorExpressionBegin: OptionalCtx,
221 AdditionExpressionBegin: DestPtr,260 BinaryXorExpressionEnd: OptionalCtx,
222 AdditionExpressionEnd: DestPtr,261 BinaryAndExpressionBegin: OptionalCtx,
223 MultiplyExpressionBegin: DestPtr,262 BinaryAndExpressionEnd: OptionalCtx,
224 MultiplyExpressionEnd: DestPtr,263 BitShiftExpressionBegin: OptionalCtx,
225 CurlySuffixExpressionBegin: DestPtr,264 BitShiftExpressionEnd: OptionalCtx,
226 CurlySuffixExpressionEnd: DestPtr,265 AdditionExpressionBegin: OptionalCtx,
227 TypeExprBegin: DestPtr,266 AdditionExpressionEnd: OptionalCtx,
228 TypeExprEnd: DestPtr,267 MultiplyExpressionBegin: OptionalCtx,
229 PrefixOpExpression: DestPtr,268 MultiplyExpressionEnd: OptionalCtx,
230 SuffixOpExpressionBegin: DestPtr,269 CurlySuffixExpressionBegin: OptionalCtx,
231 SuffixOpExpressionEnd: DestPtr,270 CurlySuffixExpressionEnd: OptionalCtx,
232 PrimaryExpression: DestPtr,271 TypeExprBegin: OptionalCtx,
272 TypeExprEnd: OptionalCtx,
273 PrefixOpExpression: OptionalCtx,
274 SuffixOpExpressionBegin: OptionalCtx,
275 SuffixOpExpressionEnd: OptionalCtx,
276 PrimaryExpression: OptionalCtx,
277
278 ErrorTypeOrSetDecl: ErrorTypeOrSetDeclCtx,
279 StringLiteral: OptionalCtx,
280 Identifier: OptionalCtx,
281
282
283 IfToken: @TagType(Token.Id),
284 IfTokenSave: ExpectTokenSave,
285 ExpectToken: @TagType(Token.Id),
286 ExpectTokenSave: ExpectTokenSave,
287 OptionalTokenSave: OptionalTokenSave,
233 };288 };
234289
235 /// Returns an AST tree, allocated with the parser's allocator.290 /// Returns an AST tree, allocated with the parser's allocator.
...@@ -302,31 +357,31 @@ pub const Parser = struct {...@@ -302,31 +357,31 @@ pub const Parser = struct {
302 Token.Id.Keyword_test => {357 Token.Id.Keyword_test => {
303 stack.append(State.TopLevel) catch unreachable;358 stack.append(State.TopLevel) catch unreachable;
304359
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,360 const block = try self.createNode(arena, ast.NodeBlock,
313 ast.NodeBlock {361 ast.NodeBlock {
314 .base = undefined,362 .base = undefined,
315 .label = null,363 .label = null,
316 .lbrace = lbrace,364 .lbrace = undefined,
317 .statements = ArrayList(&ast.Node).init(arena),365 .statements = ArrayList(&ast.Node).init(arena),
318 .rbrace = undefined,366 .rbrace = undefined,
319 }367 }
320 );368 );
321 _ = try self.createAttachNode(arena, &root_node.decls, ast.NodeTestDecl,369 const test_node = try self.createAttachNode(arena, &root_node.decls, ast.NodeTestDecl,
322 ast.NodeTestDecl {370 ast.NodeTestDecl {
323 .base = undefined,371 .base = undefined,
324 .test_token = token,372 .test_token = token,
325 .name = name,373 .name = undefined,
326 .body_node = &block.base,374 .body_node = &block.base,
327 }375 }
328 );376 );
329 stack.append(State { .Block = block }) catch unreachable;377 stack.append(State { .Block = block }) catch unreachable;
378 try stack.append(State {
379 .ExpectTokenSave = ExpectTokenSave {
380 .id = Token.Id.LBrace,
381 .ptr = &block.rbrace,
382 }
383 });
384 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &test_node.name } });
330 continue;385 continue;
331 },386 },
332 Token.Id.Eof => {387 Token.Id.Eof => {
...@@ -346,15 +401,30 @@ pub const Parser = struct {...@@ -346,15 +401,30 @@ pub const Parser = struct {
346 continue;401 continue;
347 },402 },
348 Token.Id.Keyword_comptime => {403 Token.Id.Keyword_comptime => {
404 const block = try self.createNode(arena, ast.NodeBlock,
405 ast.NodeBlock {
406 .base = undefined,
407 .label = null,
408 .lbrace = undefined,
409 .statements = ArrayList(&ast.Node).init(arena),
410 .rbrace = undefined,
411 }
412 );
349 const node = try self.createAttachNode(arena, &root_node.decls, ast.NodeComptime,413 const node = try self.createAttachNode(arena, &root_node.decls, ast.NodeComptime,
350 ast.NodeComptime {414 ast.NodeComptime {
351 .base = undefined,415 .base = undefined,
352 .comptime_token = token,416 .comptime_token = token,
353 .expr = undefined,417 .expr = &block.base,
354 }418 }
355 );419 );
356 stack.append(State.TopLevel) catch unreachable;420 stack.append(State.TopLevel) catch unreachable;
357 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });421 try stack.append(State { .Block = block });
422 try stack.append(State {
423 .ExpectTokenSave = ExpectTokenSave {
424 .id = Token.Id.LBrace,
425 .ptr = &block.rbrace,
426 }
427 });
358 continue;428 continue;
359 },429 },
360 else => {430 else => {
...@@ -404,7 +474,6 @@ pub const Parser = struct {...@@ -404,7 +474,6 @@ pub const Parser = struct {
404 }474 }
405 }475 }
406 },476 },
407
408 State.TopLevelLibname => |ctx| {477 State.TopLevelLibname => |ctx| {
409 const lib_name = blk: {478 const lib_name = blk: {
410 const lib_name_token = self.getNextToken();479 const lib_name_token = self.getNextToken();
...@@ -423,14 +492,12 @@ pub const Parser = struct {...@@ -423,14 +492,12 @@ pub const Parser = struct {
423 },492 },
424 }) catch unreachable;493 }) catch unreachable;
425 },494 },
426
427 State.TopLevelDecl => |ctx| {495 State.TopLevelDecl => |ctx| {
428 const token = self.getNextToken();496 const token = self.getNextToken();
429 switch (token.id) {497 switch (token.id) {
430 Token.Id.Keyword_use => {498 Token.Id.Keyword_use => {
431 if (ctx.extern_export_inline_token != null) {499 if (ctx.extern_export_inline_token != null) {
432 try self.parseError(&stack, token, "Invalid token {}", @tagName((??ctx.extern_export_inline_token).id));500 return self.parseError(token, "Invalid token {}", @tagName((??ctx.extern_export_inline_token).id));
433 continue;
434 }501 }
435502
436 const node = try self.createAttachNode(arena, ctx.decls, ast.NodeUse,503 const node = try self.createAttachNode(arena, ctx.decls, ast.NodeUse,
...@@ -447,14 +514,13 @@ pub const Parser = struct {...@@ -447,14 +514,13 @@ pub const Parser = struct {
447 .ptr = &node.semicolon_token,514 .ptr = &node.semicolon_token,
448 }515 }
449 }) catch unreachable;516 }) catch unreachable;
450 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });517 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
451 continue;518 continue;
452 },519 },
453 Token.Id.Keyword_var, Token.Id.Keyword_const => {520 Token.Id.Keyword_var, Token.Id.Keyword_const => {
454 if (ctx.extern_export_inline_token) |extern_export_inline_token| {521 if (ctx.extern_export_inline_token) |extern_export_inline_token| {
455 if (extern_export_inline_token.id == Token.Id.Keyword_inline) {522 if (extern_export_inline_token.id == Token.Id.Keyword_inline) {
456 try self.parseError(&stack, token, "Invalid token {}", @tagName(extern_export_inline_token.id));523 return self.parseError(token, "Invalid token {}", @tagName(extern_export_inline_token.id));
457 continue;
458 }524 }
459 }525 }
460526
...@@ -564,82 +630,48 @@ pub const Parser = struct {...@@ -564,82 +630,48 @@ pub const Parser = struct {
564 }630 }
565 });631 });
566632
567 const langle_bracket = self.getNextToken();633 try stack.append(State { .AsyncAllocator = async_node });
568 if (langle_bracket.id != Token.Id.AngleBracketLeft) {
569 self.putBackToken(langle_bracket);
570 continue;
571 }
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;634 continue;
582 },635 },
583 else => {636 else => {
584 try self.parseError(&stack, token, "expected variable declaration or function, found {}", @tagName(token.id));637 return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id));
585 continue;
586 },638 },
587 }639 }
588 },640 },
589 State.VarDecl => |var_decl| {641 State.TopLevelExternOrField => |ctx| {
590 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;642 if (self.eatToken(Token.Id.Identifier)) |identifier| {
591 try stack.append(State { .TypeExprBegin = DestPtr {.NullableField = &var_decl.type_node} });643 std.debug.assert(ctx.container_decl.kind == ast.NodeContainerDecl.Kind.Struct);
592 try stack.append(State { .IfToken = Token.Id.Colon });644 const node = try self.createAttachNode(arena, &ctx.container_decl.fields_and_decls, ast.NodeStructField,
593 try stack.append(State {645 ast.NodeStructField {
594 .ExpectTokenSave = ExpectTokenSave {646 .base = undefined,
595 .id = Token.Id.Identifier,647 .visib_token = ctx.visib_token,
596 .ptr = &var_decl.name_token,648 .name_token = identifier,
597 }649 .type_expr = undefined,
598 });650 }
599 continue;651 );
600 },
601 State.VarDeclAlign => |var_decl| {
602 stack.append(State { .VarDeclEq = var_decl }) catch unreachable;
603652
604 const next_token = self.getNextToken();653 stack.append(State { .FieldListCommaOrEnd = ctx.container_decl }) catch unreachable;
605 if (next_token.id == Token.Id.Keyword_align) {654 try stack.append(State { .Expression = OptionalCtx { .Required = &node.type_expr } });
606 try stack.append(State { .ExpectToken = Token.Id.RParen });655 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;656 continue;
610 }657 }
611658
612 self.putBackToken(next_token);659 stack.append(State{ .ContainerDecl = ctx.container_decl }) catch unreachable;
613 continue;660 try stack.append(State {
614 },661 .TopLevelExtern = TopLevelDeclCtx {
615 State.VarDeclEq => |var_decl| {662 .decls = &ctx.container_decl.fields_and_decls,
616 const token = self.getNextToken();663 .visib_token = ctx.visib_token,
617 switch (token.id) {664 .extern_export_inline_token = null,
618 Token.Id.Equal => {665 .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 }666 }
637 }667 });
668 continue;
638 },669 },
639670
671
640 State.ContainerExtern => |ctx| {672 State.ContainerExtern => |ctx| {
641 const token = self.getNextToken();673 const token = self.getNextToken();
642 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeContainerDecl,674 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeContainerDecl,
643 ast.NodeContainerDecl {675 ast.NodeContainerDecl {
644 .base = undefined,676 .base = undefined,
645 .ltoken = ctx.ltoken,677 .ltoken = ctx.ltoken,
...@@ -649,15 +681,14 @@ pub const Parser = struct {...@@ -649,15 +681,14 @@ pub const Parser = struct {
649 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,681 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,
650 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,682 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,
651 else => {683 else => {
652 try self.parseError(&stack, token, "expected {}, {} or {}, found {}",684 return self.parseError(token, "expected {}, {} or {}, found {}",
653 @tagName(Token.Id.Keyword_struct),685 @tagName(Token.Id.Keyword_struct),
654 @tagName(Token.Id.Keyword_union),686 @tagName(Token.Id.Keyword_union),
655 @tagName(Token.Id.Keyword_enum),687 @tagName(Token.Id.Keyword_enum),
656 @tagName(token.id));688 @tagName(token.id));
657 continue;
658 },689 },
659 },690 },
660 .init_arg_expr = undefined,691 .init_arg_expr = ast.NodeContainerDecl.InitArg.None,
661 .fields_and_decls = ArrayList(&ast.Node).init(arena),692 .fields_and_decls = ArrayList(&ast.Node).init(arena),
662 .rbrace_token = undefined,693 .rbrace_token = undefined,
663 }694 }
...@@ -665,37 +696,34 @@ pub const Parser = struct {...@@ -665,37 +696,34 @@ pub const Parser = struct {
665696
666 stack.append(State { .ContainerDecl = node }) catch unreachable;697 stack.append(State { .ContainerDecl = node }) catch unreachable;
667 try stack.append(State { .ExpectToken = Token.Id.LBrace });698 try stack.append(State { .ExpectToken = Token.Id.LBrace });
699 try stack.append(State { .ContainerInitArgStart = node });
700 },
668701
669 const lparen = self.getNextToken();702 State.ContainerInitArgStart => |container_decl| {
670 if (lparen.id != Token.Id.LParen) {703 if (self.eatToken(Token.Id.LParen) == null) {
671 self.putBackToken(lparen);
672 node.init_arg_expr = ast.NodeContainerDecl.InitArg.None;
673 continue;704 continue;
674 }705 }
675706
676 try stack.append(State { .ExpectToken = Token.Id.RParen });707 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
708 try stack.append(State { .ContainerInitArg = container_decl });
709 },
677710
711 State.ContainerInitArg => |container_decl| {
678 const init_arg_token = self.getNextToken();712 const init_arg_token = self.getNextToken();
679 switch (init_arg_token.id) {713 switch (init_arg_token.id) {
680 Token.Id.Keyword_enum => {714 Token.Id.Keyword_enum => {
681 node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;715 container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;
682 },716 },
683 else => {717 else => {
684 self.putBackToken(init_arg_token);718 self.putBackToken(init_arg_token);
685 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };719 container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };
686 try stack.append(State {720 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 },721 },
692 }722 }
693 continue;723 continue;
694 },724 },
695
696 State.ContainerDecl => |container_decl| {725 State.ContainerDecl => |container_decl| {
697 const token = self.getNextToken();726 const token = self.getNextToken();
698
699 switch (token.id) {727 switch (token.id) {
700 Token.Id.Identifier => {728 Token.Id.Identifier => {
701 switch (container_decl.kind) {729 switch (container_decl.kind) {
...@@ -710,7 +738,7 @@ pub const Parser = struct {...@@ -710,7 +738,7 @@ pub const Parser = struct {
710 );738 );
711739
712 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;740 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
713 try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } });741 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.type_expr } });
714 try stack.append(State { .ExpectToken = Token.Id.Colon });742 try stack.append(State { .ExpectToken = Token.Id.Colon });
715 continue;743 continue;
716 },744 },
...@@ -724,14 +752,8 @@ pub const Parser = struct {...@@ -724,14 +752,8 @@ pub const Parser = struct {
724 );752 );
725753
726 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;754 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
727755 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &node.type_expr } });
728 const next = self.getNextToken();756 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;757 continue;
736 },758 },
737 ast.NodeContainerDecl.Kind.Enum => {759 ast.NodeContainerDecl.Kind.Enum => {
...@@ -744,52 +766,34 @@ pub const Parser = struct {...@@ -744,52 +766,34 @@ pub const Parser = struct {
744 );766 );
745767
746 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;768 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
747769 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &node.value } });
748 const next = self.getNextToken();770 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;771 continue;
756 },772 },
757 }773 }
758 },774 },
759 Token.Id.Keyword_pub => {775 Token.Id.Keyword_pub => {
760 if (self.eatToken(Token.Id.Identifier)) |identifier| {776 switch (container_decl.kind) {
761 switch (container_decl.kind) {777 ast.NodeContainerDecl.Kind.Struct => {
762 ast.NodeContainerDecl.Kind.Struct => {778 try stack.append(State {
763 const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeStructField,779 .TopLevelExternOrField = TopLevelExternOrFieldCtx {
764 ast.NodeStructField {780 .visib_token = token,
765 .base = undefined,781 .container_decl = container_decl,
766 .visib_token = token,782 }
767 .name_token = identifier,783 });
768 .type_expr = undefined,784 },
769 }785 else => {
770 );786 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
771787 try stack.append(State {
772 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;788 .TopLevelExtern = TopLevelDeclCtx {
773 try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } });789 .decls = &container_decl.fields_and_decls,
774 try stack.append(State { .ExpectToken = Token.Id.Colon });790 .visib_token = token,
775 continue;791 .extern_export_inline_token = null,
776 },792 .lib_name = null,
777 else => {793 }
778 self.putBackToken(identifier);794 });
779 }
780 }795 }
781 }796 }
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 },797 },
794 Token.Id.Keyword_export => {798 Token.Id.Keyword_export => {
795 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;799 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
...@@ -823,1883 +827,1947 @@ pub const Parser = struct {...@@ -823,1883 +827,1947 @@ pub const Parser = struct {
823 }827 }
824 },828 },
825829
826 State.ExpectToken => |token_id| {
827 _ = (try self.expectToken(&stack, token_id)) ?? continue;
828 continue;
829 },
830
831 State.ExpectTokenSave => |expect_token_save| {
832 *expect_token_save.ptr = (try self.expectToken(&stack, expect_token_save.id)) ?? continue;
833 continue;
834 },
835830
836 State.IfToken => |token_id| {831 State.VarDecl => |var_decl| {
837 const token = self.getNextToken();832 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
838 if (@TagType(Token.Id)(token.id) != token_id) {833 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &var_decl.type_node} });
839 self.putBackToken(token);834 try stack.append(State { .IfToken = Token.Id.Colon });
840 _ = stack.pop();835 try stack.append(State {
841 continue;836 .ExpectTokenSave = ExpectTokenSave {
842 }837 .id = Token.Id.Identifier,
838 .ptr = &var_decl.name_token,
839 }
840 });
843 continue;841 continue;
844 },842 },
843 State.VarDeclAlign => |var_decl| {
844 stack.append(State { .VarDeclEq = var_decl }) catch unreachable;
845845
846 State.IfTokenSave => |if_token_save| {846 const next_token = self.getNextToken();
847 const token = self.getNextToken();847 if (next_token.id == Token.Id.Keyword_align) {
848 if (@TagType(Token.Id)(token.id) != if_token_save.id) {848 try stack.append(State { .ExpectToken = Token.Id.RParen });
849 self.putBackToken(token);849 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.align_node} });
850 _ = stack.pop();850 try stack.append(State { .ExpectToken = Token.Id.LParen });
851 continue;851 continue;
852 }852 }
853853
854 *if_token_save.ptr = token;854 self.putBackToken(next_token);
855 continue;855 continue;
856 },856 },
857857 State.VarDeclEq => |var_decl| {
858 State.Optional => { },
859
860 State.Expression => |dest_ptr| {
861 const token = self.getNextToken();858 const token = self.getNextToken();
862 switch (token.id) {859 switch (token.id) {
863 Token.Id.Keyword_return => {860 Token.Id.Equal => {
864 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeControlFlowExpression,861 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 {862 stack.append(State {
875 .Optional = RevertState {863 .ExpectTokenSave = ExpectTokenSave {
876 .parser = *self,864 .id = Token.Id.Semicolon,
877 .tokenizer = *self.tokenizer,865 .ptr = &var_decl.semicolon_token,
878 .ptr = &node.rhs,866 },
879 }
880 }) catch unreachable;867 }) catch unreachable;
881 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });868 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } });
882 continue;869 continue;
883 },870 },
884 Token.Id.Keyword_break, Token.Id.Keyword_continue => {871 Token.Id.Semicolon => {
885 const label = blk: {872 var_decl.semicolon_token = token;
886 const colon = self.getNextToken();873 continue;
887 if (colon.id != Token.Id.Colon) {874 },
888 self.putBackToken(colon);875 else => {
889 break :blk null;876 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));
890 }877 }
878 }
879 },
891880
892 break :blk (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;
893 };
894881
895 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeControlFlowExpression,882 State.FnDef => |fn_proto| {
896 ast.NodeControlFlowExpression {883 const token = self.getNextToken();
897 .base = undefined,884 switch(token.id) {
898 .ltoken = token,885 Token.Id.LBrace => {
899 .kind = switch (token.id) {886 const block = try self.createNode(arena, ast.NodeBlock,
900 Token.Id.Keyword_break => ast.NodeControlFlowExpression.Kind { .Break = label },887 ast.NodeBlock {
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 {
910 .Optional = RevertState {
911 .parser = *self,
912 .tokenizer = *self.tokenizer,
913 .ptr = &node.rhs,
914 }
915 }) catch unreachable;
916 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });
917 continue;
918 },
919 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
920 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,
921 ast.NodePrefixOp {
922 .base = undefined,888 .base = undefined,
923 .op_token = token,889 .label = null,
924 .op = switch (token.id) {890 .lbrace = token,
925 Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{} },891 .statements = ArrayList(&ast.Node).init(arena),
926 Token.Id.Keyword_cancel => ast.NodePrefixOp.PrefixOp { .Cancel = void{} },892 .rbrace = undefined,
927 Token.Id.Keyword_resume => ast.NodePrefixOp.PrefixOp { .Resume = void{} },
928 else => unreachable,
929 },
930 .rhs = undefined,
931 }893 }
932 );894 );
933895 fn_proto.body_node = &block.base;
934 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;896 stack.append(State { .Block = block }) catch unreachable;
935 continue;897 continue;
936 },898 },
899 Token.Id.Semicolon => continue,
937 else => {900 else => {
938 if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) {901 return self.parseError(token, "expected ';' or '{{', found {}", @tagName(token.id));
939 self.putBackToken(token);902 },
940 stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable;
941 }
942 continue;
943 }
944 }903 }
945 },904 },
905 State.FnProto => |fn_proto| {
906 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
907 try stack.append(State { .ParamDecl = fn_proto });
908 try stack.append(State { .ExpectToken = Token.Id.LParen });
946909
947 State.RangeExpressionBegin => |dest_ptr| {910 const next_token = self.getNextToken();
948 stack.append(State { .RangeExpressionEnd = dest_ptr }) catch unreachable;911 if (next_token.id == Token.Id.Identifier) {
949 try stack.append(State { .Expression = dest_ptr });912 fn_proto.name_token = next_token;
950 continue;913 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 }914 }
966915 self.putBackToken(next_token);
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;916 continue;
974 },917 },
918 State.FnProtoAlign => |fn_proto| {
919 stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable;
975920
976 State.AssignmentExpressionEnd => |dest_ptr| {921 if (self.eatToken(Token.Id.Keyword_align)) |align_token| {
977 const token = self.getNextToken();922 try stack.append(State { .ExpectToken = Token.Id.RParen });
978 if (tokenIdToAssignment(token.id)) |ass_id| {923 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &fn_proto.align_expr } });
979 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,924 try stack.append(State { .ExpectToken = Token.Id.LParen });
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 }925 }
995 },
996926
997 State.UnwrapExpressionBegin => |dest_ptr| {
998 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
999 try stack.append(State { .BoolOrExpressionBegin = dest_ptr });
1000 continue;927 continue;
1001 },928 },
1002929 State.FnProtoReturnType => |fn_proto| {
1003 State.UnwrapExpressionEnd => |dest_ptr| {
1004 const token = self.getNextToken();930 const token = self.getNextToken();
1005 switch (token.id) {931 switch (token.id) {
1006 Token.Id.Keyword_catch, Token.Id.QuestionMarkQuestionMark => {932 Token.Id.Bang => {
1007 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,933 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };
1008 ast.NodeInfixOp {934 stack.append(State {
1009 .base = undefined,935 .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet },
1010 .lhs = dest_ptr.get(),936 }) catch unreachable;
1011 .op_token = token,
1012 .op = switch (token.id) {
1013 Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null },
1014 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} },
1015 else => unreachable,
1016 },
1017 .rhs = undefined,
1018 }
1019 );
1020
1021 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) 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;937 continue;
1028 },938 },
1029 else => {939 else => {
940 // TODO: this is a special case. Remove this when #760 is fixed
941 if (token.id == Token.Id.Keyword_error) {
942 if (self.isPeekToken(Token.Id.LBrace)) {
943 fn_proto.return_type = ast.NodeFnProto.ReturnType {
944 .Explicit = &(try self.createLiteral(arena, ast.NodeErrorType, token)).base
945 };
946 continue;
947 }
948 }
949
1030 self.putBackToken(token);950 self.putBackToken(token);
951 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
952 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable;
1031 continue;953 continue;
1032 },954 },
1033 }955 }
1034 },956 },
1035957
1036 State.BoolOrExpressionBegin => |dest_ptr| {
1037 stack.append(State { .BoolOrExpressionEnd = dest_ptr }) catch unreachable;
1038 try stack.append(State { .BoolAndExpressionBegin = dest_ptr });
1039 continue;
1040 },
1041958
1042 State.BoolOrExpressionEnd => |dest_ptr| {959 State.ParamDecl => |fn_proto| {
1043 const token = self.getNextToken();960 if (self.eatToken(Token.Id.RParen)) |_| {
1044 switch (token.id) {961 continue;
1045 Token.Id.Keyword_or => {
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 }962 }
1064 },963 const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.NodeParamDecl,
964 ast.NodeParamDecl {
965 .base = undefined,
966 .comptime_token = null,
967 .noalias_token = null,
968 .name_token = null,
969 .type_node = undefined,
970 .var_args_token = null,
971 },
972 );
1065973
1066 State.BoolAndExpressionBegin => |dest_ptr| {974 stack.append(State {
1067 stack.append(State { .BoolAndExpressionEnd = dest_ptr }) catch unreachable;975 .ParamDeclEnd = ParamDeclEndCtx {
1068 try stack.append(State { .ComparisonExpressionBegin = dest_ptr });976 .param_decl = param_decl,
977 .fn_proto = fn_proto,
978 }
979 }) catch unreachable;
980 try stack.append(State { .ParamDeclName = param_decl });
981 try stack.append(State { .ParamDeclAliasOrComptime = param_decl });
1069 continue;982 continue;
1070 },983 },
1071984 State.ParamDeclAliasOrComptime => |param_decl| {
1072 State.BoolAndExpressionEnd => |dest_ptr| {985 if (self.eatToken(Token.Id.Keyword_comptime)) |comptime_token| {
1073 const token = self.getNextToken();986 param_decl.comptime_token = comptime_token;
1074 switch (token.id) {987 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {
1075 Token.Id.Keyword_and => {988 param_decl.noalias_token = noalias_token;
1076 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1077 ast.NodeInfixOp {
1078 .base = undefined,
1079 .lhs = dest_ptr.get(),
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;
1088 },
1089 else => {
1090 self.putBackToken(token);
1091 continue;
1092 },
1093 }989 }
1094 },990 },
1095991 State.ParamDeclName => |param_decl| {
1096 State.ComparisonExpressionBegin => |dest_ptr| {992 // TODO: Here, we eat two tokens in one state. This means that we can't have
1097 stack.append(State { .ComparisonExpressionEnd = dest_ptr }) catch unreachable;993 // comments between these two tokens.
1098 try stack.append(State { .BinaryOrExpressionBegin = dest_ptr });994 if (self.eatToken(Token.Id.Identifier)) |ident_token| {
1099 continue;995 if (self.eatToken(Token.Id.Colon)) |_| {
996 param_decl.name_token = ident_token;
997 } else {
998 self.putBackToken(ident_token);
999 }
1000 }
1100 },1001 },
11011002 State.ParamDeclEnd => |ctx| {
1102 State.ComparisonExpressionEnd => |dest_ptr| {1003 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
1103 const token = self.getNextToken();1004 ctx.param_decl.var_args_token = ellipsis3;
1104 if (tokenIdToComparison(token.id)) |comp_id| {1005 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
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;1006 continue;
1120 }1007 }
1121 },
11221008
1123 State.BinaryOrExpressionBegin => |dest_ptr| {1009 try stack.append(State { .ParamDeclComma = ctx.fn_proto });
1124 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;1010 try stack.append(State {
1125 try stack.append(State { .BinaryXorExpressionBegin = dest_ptr });1011 .TypeExprBegin = OptionalCtx { .Required = &ctx.param_decl.type_node }
1012 });
1013 },
1014 State.ParamDeclComma => |fn_proto| {
1015 var discard_end: Token = undefined;
1016 try self.commaOrEnd(&stack, Token.Id.RParen, &discard_end, State { .ParamDecl = fn_proto });
1126 continue;1017 continue;
1127 },1018 },
11281019
1129 State.BinaryOrExpressionEnd => |dest_ptr| {1020
1021 State.LabeledExpression => |ctx| {
1130 const token = self.getNextToken();1022 const token = self.getNextToken();
1131 switch (token.id) {1023 switch (token.id) {
1132 Token.Id.Pipe => {1024 Token.Id.LBrace => {
1133 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1025 const block = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeBlock,
1134 ast.NodeInfixOp {1026 ast.NodeBlock {
1135 .base = undefined,1027 .base = undefined,
1136 .lhs = dest_ptr.get(),1028 .label = ctx.label,
1137 .op_token = token,1029 .lbrace = token,
1138 .op = ast.NodeInfixOp.InfixOp.BitOr,1030 .statements = ArrayList(&ast.Node).init(arena),
1139 .rhs = undefined,1031 .rbrace = undefined,
1140 }1032 }
1141 );1033 );
1142 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;1034 stack.append(State { .Block = block }) catch unreachable;
1143 try stack.append(State { .BinaryXorExpressionBegin = DestPtr { .Field = &node.rhs } });
1144 continue;1035 continue;
1145 },1036 },
1146 else => {1037 Token.Id.Keyword_while => {
1147 self.putBackToken(token);1038 stack.append(State {
1039 .While = LoopCtx {
1040 .label = ctx.label,
1041 .inline_token = null,
1042 .loop_token = token,
1043 .opt_ctx = ctx.opt_ctx.toRequired(),
1044 }
1045 }) catch unreachable;
1148 continue;1046 continue;
1149 },1047 },
1150 }1048 Token.Id.Keyword_for => {
1151 },1049 stack.append(State {
11521050 .For = LoopCtx {
1153 State.BinaryXorExpressionBegin => |dest_ptr| {1051 .label = ctx.label,
1154 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;1052 .inline_token = null,
1155 try stack.append(State { .BinaryAndExpressionBegin = dest_ptr });1053 .loop_token = token,
1156 continue;1054 .opt_ctx = ctx.opt_ctx.toRequired(),
1157 },
1158
1159 State.BinaryXorExpressionEnd => |dest_ptr| {
1160 const token = self.getNextToken();
1161 switch (token.id) {
1162 Token.Id.Caret => {
1163 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1164 ast.NodeInfixOp {
1165 .base = undefined,
1166 .lhs = dest_ptr.get(),
1167 .op_token = token,
1168 .op = ast.NodeInfixOp.InfixOp.BitXor,
1169 .rhs = undefined,
1170 }1055 }
1171 );1056 }) catch unreachable;
1172 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;1057 continue;
1173 try stack.append(State { .BinaryAndExpressionBegin = DestPtr { .Field = &node.rhs } });1058 },
1059 Token.Id.Keyword_inline => {
1060 stack.append(State {
1061 .Inline = InlineCtx {
1062 .label = ctx.label,
1063 .inline_token = token,
1064 .opt_ctx = ctx.opt_ctx.toRequired(),
1065 }
1066 }) catch unreachable;
1174 continue;1067 continue;
1175 },1068 },
1176 else => {1069 else => {
1070 if (ctx.opt_ctx != OptionalCtx.Optional) {
1071 return self.parseError(token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id));
1072 }
1073
1177 self.putBackToken(token);1074 self.putBackToken(token);
1178 continue;1075 continue;
1179 },1076 },
1180 }1077 }
1181 },1078 },
11821079 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();1080 const token = self.getNextToken();
1191 switch (token.id) {1081 switch (token.id) {
1192 Token.Id.Ampersand => {1082 Token.Id.Keyword_while => {
1193 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1083 stack.append(State {
1194 ast.NodeInfixOp {1084 .While = LoopCtx {
1195 .base = undefined,1085 .inline_token = ctx.inline_token,
1196 .lhs = dest_ptr.get(),1086 .label = ctx.label,
1197 .op_token = token,1087 .loop_token = token,
1198 .op = ast.NodeInfixOp.InfixOp.BitAnd,1088 .opt_ctx = ctx.opt_ctx.toRequired(),
1199 .rhs = undefined,
1200 }1089 }
1201 );1090 }) catch unreachable;
1202 stack.append(State { .BinaryAndExpressionEnd = dest_ptr }) catch unreachable;1091 continue;
1203 try stack.append(State { .BitShiftExpressionBegin = DestPtr { .Field = &node.rhs } });1092 },
1093 Token.Id.Keyword_for => {
1094 stack.append(State {
1095 .For = LoopCtx {
1096 .inline_token = ctx.inline_token,
1097 .label = ctx.label,
1098 .loop_token = token,
1099 .opt_ctx = ctx.opt_ctx.toRequired(),
1100 }
1101 }) catch unreachable;
1204 continue;1102 continue;
1205 },1103 },
1206 else => {1104 else => {
1105 if (ctx.opt_ctx != OptionalCtx.Optional) {
1106 return self.parseError(token, "expected 'while' or 'for', found {}", @tagName(token.id));
1107 }
1108
1207 self.putBackToken(token);1109 self.putBackToken(token);
1208 continue;1110 continue;
1209 },1111 },
1210 }1112 }
1211 },1113 },
12121114 State.While => |ctx| {
1213 State.BitShiftExpressionBegin => |dest_ptr| {1115 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeWhile,
1214 stack.append(State { .BitShiftExpressionEnd = dest_ptr }) catch unreachable;1116 ast.NodeWhile {
1215 try stack.append(State { .AdditionExpressionBegin = dest_ptr });1117 .base = undefined,
1216 continue;1118 .label = ctx.label,
1119 .inline_token = ctx.inline_token,
1120 .while_token = ctx.loop_token,
1121 .condition = undefined,
1122 .payload = null,
1123 .continue_expr = null,
1124 .body = undefined,
1125 .@"else" = null,
1126 }
1127 );
1128 stack.append(State { .Else = &node.@"else" }) catch unreachable;
1129 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
1130 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
1131 try stack.append(State { .IfToken = Token.Id.Colon });
1132 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
1133 try stack.append(State { .ExpectToken = Token.Id.RParen });
1134 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
1135 try stack.append(State { .ExpectToken = Token.Id.LParen });
1217 },1136 },
12181137 State.WhileContinueExpr => |dest| {
1219 State.BitShiftExpressionEnd => |dest_ptr| {1138 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
1220 const token = self.getNextToken();1139 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = dest } });
1221 if (tokenIdToBitShift(token.id)) |bitshift_id| {1140 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 },1141 },
12391142 State.For => |ctx| {
1240 State.AdditionExpressionBegin => |dest_ptr| {1143 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFor,
1241 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;1144 ast.NodeFor {
1242 try stack.append(State { .MultiplyExpressionBegin = dest_ptr });1145 .base = undefined,
1243 continue;1146 .label = ctx.label,
1147 .inline_token = ctx.inline_token,
1148 .for_token = ctx.loop_token,
1149 .array_expr = undefined,
1150 .payload = null,
1151 .body = undefined,
1152 .@"else" = null,
1153 }
1154 );
1155 stack.append(State { .Else = &node.@"else" }) catch unreachable;
1156 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
1157 try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } });
1158 try stack.append(State { .ExpectToken = Token.Id.RParen });
1159 try stack.append(State { .Expression = OptionalCtx { .Required = &node.array_expr } });
1160 try stack.append(State { .ExpectToken = Token.Id.LParen });
1244 },1161 },
12451162 State.Else => |dest| {
1246 State.AdditionExpressionEnd => |dest_ptr| {1163 const else_token = self.getNextToken();
1247 const token = self.getNextToken();1164 if (else_token.id != Token.Id.Keyword_else) {
1248 if (tokenIdToAddition(token.id)) |add_id| {1165 self.putBackToken(else_token);
1249 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1250 ast.NodeInfixOp {
1251 .base = undefined,
1252 .lhs = dest_ptr.get(),
1253 .op_token = token,
1254 .op = add_id,
1255 .rhs = undefined,
1256 }
1257 );
1258 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;
1259 try stack.append(State { .MultiplyExpressionBegin = DestPtr { .Field = &node.rhs } });
1260 continue;
1261 } else {
1262 self.putBackToken(token);
1263 continue;1166 continue;
1264 }1167 }
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;
1271 },
12721168
1273 State.MultiplyExpressionEnd => |dest_ptr| {1169 const node = try self.createNode(arena, ast.NodeElse,
1274 const token = self.getNextToken();1170 ast.NodeElse {
1275 if (tokenIdToMultiply(token.id)) |mult_id| {1171 .base = undefined,
1276 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1172 .else_token = else_token,
1277 ast.NodeInfixOp {1173 .payload = null,
1278 .base = undefined,1174 .body = undefined,
1279 .lhs = dest_ptr.get(),1175 }
1280 .op_token = token,1176 );
1281 .op = mult_id,1177 *dest = node;
1282 .rhs = undefined,
1283 }
1284 );
1285 stack.append(State { .MultiplyExpressionEnd = dest_ptr }) catch unreachable;
1286 try stack.append(State { .CurlySuffixExpressionBegin = DestPtr { .Field = &node.rhs } });
1287 continue;
1288 } else {
1289 self.putBackToken(token);
1290 continue;
1291 }
1292 },
12931178
1294 State.CurlySuffixExpressionBegin => |dest_ptr| {1179 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
1295 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;1180 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
1296 try stack.append(State { .TypeExprBegin = dest_ptr });
1297 continue;
1298 },1181 },
12991182
1300 State.CurlySuffixExpressionEnd => |dest_ptr| {
1301 if (self.eatToken(Token.Id.LBrace) == null) {
1302 continue;
1303 }
13041183
1305 if (self.isPeekToken(Token.Id.Period)) {1184 State.Block => |block| {
1306 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,1185 const token = self.getNextToken();
1307 ast.NodeSuffixOp {1186 switch (token.id) {
1308 .base = undefined,1187 Token.Id.RBrace => {
1309 .lhs = dest_ptr.get(),1188 block.rbrace = token;
1310 .op = ast.NodeSuffixOp.SuffixOp {1189 continue;
1311 .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),1190 },
1312 },1191 else => {
1313 .rtoken = undefined,1192 self.putBackToken(token);
1314 }1193 stack.append(State { .Block = block }) catch unreachable;
1315 );1194 try stack.append(State { .Statement = block });
1316 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;1195 continue;
1317 try stack.append(State {1196 },
1318 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
1319 .list = &node.op.StructInitializer,
1320 .ptr = &node.rtoken,
1321 }
1322 });
1323 continue;
1324 } 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;
1344 }1197 }
1345 },1198 },
13461199 State.Statement => |block| {
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 },
1352
1353 State.TypeExprEnd => |dest_ptr| {
1354 const token = self.getNextToken();1200 const token = self.getNextToken();
1355 switch (token.id) {1201 switch (token.id) {
1356 Token.Id.Bang => {1202 Token.Id.Keyword_comptime => {
1357 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,1203 stack.append(State {
1358 ast.NodeInfixOp {1204 .ComptimeStatement = ComptimeStatementCtx {
1205 .comptime_token = token,
1206 .block = block,
1207 }
1208 }) catch unreachable;
1209 },
1210 Token.Id.Keyword_var, Token.Id.Keyword_const => {
1211 const var_decl = try self.createAttachNode(arena, &block.statements, ast.NodeVarDecl,
1212 ast.NodeVarDecl {
1359 .base = undefined,1213 .base = undefined,
1360 .lhs = dest_ptr.get(),1214 .visib_token = null,
1361 .op_token = token,1215 .mut_token = token,
1362 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,1216 .comptime_token = null,
1363 .rhs = undefined,1217 .extern_export_token = null,
1218 .type_node = null,
1219 .align_node = null,
1220 .init_node = null,
1221 .lib_name = null,
1222 // initialized later
1223 .name_token = undefined,
1224 .eq_token = undefined,
1225 .semicolon_token = undefined,
1226 }
1227 );
1228 stack.append(State { .VarDecl = var_decl }) catch unreachable;
1229 continue;
1230 },
1231 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1232 const node = try self.createAttachNode(arena, &block.statements, ast.NodeDefer,
1233 ast.NodeDefer {
1234 .base = undefined,
1235 .defer_token = token,
1236 .kind = switch (token.id) {
1237 Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional,
1238 Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error,
1239 else => unreachable,
1240 },
1241 .expr = undefined,
1242 }
1243 );
1244 stack.append(State { .Semicolon = &node.base }) catch unreachable;
1245 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
1246 continue;
1247 },
1248 Token.Id.LBrace => {
1249 const inner_block = try self.createAttachNode(arena, &block.statements, ast.NodeBlock,
1250 ast.NodeBlock {
1251 .base = undefined,
1252 .label = null,
1253 .lbrace = token,
1254 .statements = ArrayList(&ast.Node).init(arena),
1255 .rbrace = undefined,
1364 }1256 }
1365 );1257 );
1366 stack.append(State { .TypeExprEnd = dest_ptr }) catch unreachable;1258 stack.append(State { .Block = inner_block }) catch unreachable;
1367 try stack.append(State { .PrefixOpExpression = DestPtr { .Field = &node.rhs } });
1368 continue;1259 continue;
1369 },1260 },
1370 else => {1261 else => {
1371 self.putBackToken(token);1262 self.putBackToken(token);
1263 const statememt = try block.statements.addOne();
1264 stack.append(State { .Semicolon = statememt }) catch unreachable;
1265 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx{ .Required = statememt } });
1372 continue;1266 continue;
1373 },1267 }
1374 }1268 }
1375 },1269 },
13761270 State.ComptimeStatement => |ctx| {
1377 State.PrefixOpExpression => |dest_ptr| {
1378 const token = self.getNextToken();1271 const token = self.getNextToken();
1379 if (tokenIdToPrefixOp(token.id)) |prefix_id| {1272 if (token.id == Token.Id.Keyword_var or token.id == Token.Id.Keyword_const) {
1380 var node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,1273 const var_decl = try self.createAttachNode(arena, &ctx.block.statements, ast.NodeVarDecl,
1381 ast.NodePrefixOp {1274 ast.NodeVarDecl {
1382 .base = undefined,1275 .base = undefined,
1383 .op_token = token,1276 .visib_token = null,
1384 .op = prefix_id,1277 .mut_token = token,
1385 .rhs = undefined,1278 .comptime_token = ctx.comptime_token,
1279 .extern_export_token = null,
1280 .type_node = null,
1281 .align_node = null,
1282 .init_node = null,
1283 .lib_name = null,
1284 // initialized later
1285 .name_token = undefined,
1286 .eq_token = undefined,
1287 .semicolon_token = undefined,
1386 }1288 }
1387 );1289 );
13881290 stack.append(State { .VarDecl = var_decl }) catch unreachable;
1389 if (token.id == Token.Id.AsteriskAsterisk) {1291 continue;
1390 const child = try self.createNode(arena, ast.NodePrefixOp,1292 } else {
1391 ast.NodePrefixOp {1293 self.putBackToken(token);
1392 .base = undefined,1294 self.putBackToken(ctx.comptime_token);
1393 .op_token = token,1295 const statememt = try ctx.block.statements.addOne();
1394 .op = prefix_id,1296 stack.append(State { .Semicolon = statememt }) catch unreachable;
1395 .rhs = undefined,1297 try stack.append(State { .Expression = OptionalCtx { .Required = statememt } });
1396 }1298 continue;
1397 );1299 }
1398 node.rhs = &child.base;1300 },
1399 node = child;1301 State.Semicolon => |node_ptr| {
1302 const node = *node_ptr;
1303 if (requireSemiColon(node)) {
1304 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
1305 }
1306 },
1307
1308
1309 State.AsmOutputItems => |items| {
1310 const lbracket = self.getNextToken();
1311 if (lbracket.id != Token.Id.LBracket) {
1312 self.putBackToken(lbracket);
1313 continue;
1314 }
1315
1316 const node = try self.createNode(arena, ast.NodeAsmOutput,
1317 ast.NodeAsmOutput {
1318 .base = undefined,
1319 .symbolic_name = undefined,
1320 .constraint = undefined,
1321 .kind = undefined,
1400 }1322 }
1323 );
1324 try items.append(node);
14011325
1402 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;1326 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1403 if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) {1327 try stack.append(State { .IfToken = Token.Id.Comma });
1404 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });1328 try stack.append(State { .ExpectToken = Token.Id.RParen });
1329 try stack.append(State { .AsmOutputReturnOrType = node });
1330 try stack.append(State { .ExpectToken = Token.Id.LParen });
1331 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1332 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1333 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1334 },
1335 State.AsmOutputReturnOrType => |node| {
1336 const token = self.getNextToken();
1337 switch (token.id) {
1338 Token.Id.Identifier => {
1339 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.NodeIdentifier, token) };
1340 continue;
1341 },
1342 Token.Id.Arrow => {
1343 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
1344 try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } });
1345 continue;
1346 },
1347 else => {
1348 return self.parseError(token, "expected '->' or {}, found {}",
1349 @tagName(Token.Id.Identifier),
1350 @tagName(token.id));
1351 },
1352 }
1353 },
1354 State.AsmInputItems => |items| {
1355 const lbracket = self.getNextToken();
1356 if (lbracket.id != Token.Id.LBracket) {
1357 self.putBackToken(lbracket);
1358 continue;
1359 }
1360
1361 const node = try self.createNode(arena, ast.NodeAsmInput,
1362 ast.NodeAsmInput {
1363 .base = undefined,
1364 .symbolic_name = undefined,
1365 .constraint = undefined,
1366 .expr = undefined,
1367 }
1368 );
1369 try items.append(node);
1370
1371 stack.append(State { .AsmInputItems = items }) catch unreachable;
1372 try stack.append(State { .IfToken = Token.Id.Comma });
1373 try stack.append(State { .ExpectToken = Token.Id.RParen });
1374 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
1375 try stack.append(State { .ExpectToken = Token.Id.LParen });
1376 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.constraint } });
1377 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1378 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.symbolic_name } });
1379 },
1380 State.AsmClopperItems => |items| {
1381 stack.append(State { .AsmClopperItems = items }) catch unreachable;
1382 try stack.append(State { .IfToken = Token.Id.Comma });
1383 try stack.append(State { .StringLiteral = OptionalCtx { .Required = try items.addOne() } });
1384 },
1385
1386
1387 State.ExprListItemOrEnd => |list_state| {
1388 if (self.eatToken(list_state.end)) |token| {
1389 *list_state.ptr = token;
1390 continue;
1391 }
1392
1393 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1394 try stack.append(State { .Expression = OptionalCtx { .Required = try list_state.list.addOne() } });
1395 },
1396 State.ExprListCommaOrEnd => |list_state| {
1397 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
1398 continue;
1399 },
1400 State.FieldInitListItemOrEnd => |list_state| {
1401 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
1402 *list_state.ptr = rbrace;
1403 continue;
1404 }
1405
1406 const node = try self.createNode(arena, ast.NodeFieldInitializer,
1407 ast.NodeFieldInitializer {
1408 .base = undefined,
1409 .period_token = undefined,
1410 .name_token = undefined,
1411 .expr = undefined,
1412 }
1413 );
1414 try list_state.list.append(node);
1415
1416 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
1417 try stack.append(State { .Expression = OptionalCtx{ .Required = &node.expr } });
1418 try stack.append(State { .ExpectToken = Token.Id.Equal });
1419 try stack.append(State {
1420 .ExpectTokenSave = ExpectTokenSave {
1421 .id = Token.Id.Identifier,
1422 .ptr = &node.name_token,
1423 }
1424 });
1425 try stack.append(State {
1426 .ExpectTokenSave = ExpectTokenSave {
1427 .id = Token.Id.Period,
1428 .ptr = &node.period_token,
1429 }
1430 });
1431 },
1432 State.FieldInitListCommaOrEnd => |list_state| {
1433 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
1434 continue;
1435 },
1436 State.FieldListCommaOrEnd => |container_decl| {
1437 try self.commaOrEnd(&stack, Token.Id.RBrace, &container_decl.rbrace_token,
1438 State { .ContainerDecl = container_decl });
1439 continue;
1440 },
1441 State.IdentifierListItemOrEnd => |list_state| {
1442 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
1443 *list_state.ptr = rbrace;
1444 continue;
1445 }
1446
1447 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;
1448 try stack.append(State { .Identifier = OptionalCtx { .Required = try list_state.list.addOne() } });
1449 },
1450 State.IdentifierListCommaOrEnd => |list_state| {
1451 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .IdentifierListItemOrEnd = list_state });
1452 continue;
1453 },
1454 State.SwitchCaseOrEnd => |list_state| {
1455 if (self.eatToken(Token.Id.RBrace)) |rbrace| {
1456 *list_state.ptr = rbrace;
1457 continue;
1458 }
1459
1460 const node = try self.createNode(arena, ast.NodeSwitchCase,
1461 ast.NodeSwitchCase {
1462 .base = undefined,
1463 .items = ArrayList(&ast.Node).init(arena),
1464 .payload = null,
1465 .expr = undefined,
1405 }1466 }
1467 );
1468 try list_state.list.append(node);
1469 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
1470 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .Required = &node.expr } });
1471 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
1472 try stack.append(State { .SwitchCaseFirstItem = &node.items });
1473
1474 },
1475 State.SwitchCaseCommaOrEnd => |list_state| {
1476 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });
1477 continue;
1478 },
1479 State.SwitchCaseFirstItem => |case_items| {
1480 const token = self.getNextToken();
1481 if (token.id == Token.Id.Keyword_else) {
1482 const else_node = try self.createAttachNode(arena, case_items, ast.NodeSwitchElse,
1483 ast.NodeSwitchElse {
1484 .base = undefined,
1485 .token = token,
1486 }
1487 );
1488 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
1406 continue;1489 continue;
1407 } else {1490 } else {
1408 self.putBackToken(token);1491 self.putBackToken(token);
1409 stack.append(State { .SuffixOpExpressionBegin = dest_ptr }) catch unreachable;1492 try stack.append(State { .SwitchCaseItem = case_items });
1410 continue;1493 continue;
1411 }1494 }
1412 },1495 },
1496 State.SwitchCaseItem => |case_items| {
1497 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
1498 try stack.append(State { .RangeExpressionBegin = OptionalCtx { .Required = try case_items.addOne() } });
1499 },
1500 State.SwitchCaseItemCommaOrEnd => |case_items| {
1501 try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });
1502 continue;
1503 },
14131504
1414 State.SuffixOpExpressionBegin => |dest_ptr| {
1415 const token = self.getNextToken();
1416 switch (token.id) {
1417 Token.Id.Keyword_async => {
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 {
1427 .AsyncEnd = AsyncEndCtx {
1428 .dest_ptr = dest_ptr,
1429 .attribute = async_node,
1430 }
1431 }) catch unreachable;
1432 try stack.append(State { .SuffixOpExpressionEnd = dest_ptr });
1433 try stack.append(State { .PrimaryExpression = dest_ptr });
14341505
1435 const langle_bracket = self.getNextToken();1506 State.SuspendBody => |suspend_node| {
1436 if (langle_bracket.id != Token.Id.AngleBracketLeft) {1507 if (suspend_node.payload != null) {
1437 self.putBackToken(langle_bracket);1508 try stack.append(State { .AssignmentExpressionBegin = OptionalCtx { .RequiredNull = &suspend_node.body } });
1509 }
1510 continue;
1511 },
1512 State.AsyncAllocator => |async_node| {
1513 if (self.eatToken(Token.Id.AngleBracketLeft) == null) {
1514 continue;
1515 }
1516
1517 async_node.rangle_bracket = Token(undefined);
1518 try stack.append(State {
1519 .ExpectTokenSave = ExpectTokenSave {
1520 .id = Token.Id.AngleBracketRight,
1521 .ptr = &??async_node.rangle_bracket,
1522 }
1523 });
1524 try stack.append(State { .TypeExprBegin = OptionalCtx { .RequiredNull = &async_node.allocator_type } });
1525 },
1526 State.AsyncEnd => |ctx| {
1527 const node = ctx.ctx.get() ?? continue;
1528
1529 switch (node.id) {
1530 ast.Node.Id.FnProto => {
1531 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);
1532 fn_proto.async_attr = ctx.attribute;
1533 },
1534 ast.Node.Id.SuffixOp => {
1535 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);
1536 if (suffix_op.op == ast.NodeSuffixOp.SuffixOp.Call) {
1537 suffix_op.op.Call.async_attr = ctx.attribute;
1438 continue;1538 continue;
1439 }1539 }
14401540
1441 async_node.rangle_bracket = Token(undefined);1541 return self.parseError(node.firstToken(), "expected {}, found {}.",
1442 try stack.append(State {1542 @tagName(ast.NodeSuffixOp.SuffixOp.Call),
1443 .ExpectTokenSave = ExpectTokenSave {1543 @tagName(suffix_op.op));
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;
1450 },1544 },
1451 else => {1545 else => {
1452 self.putBackToken(token);1546 return self.parseError(node.firstToken(), "expected {} or {}, found {}.",
1453 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1547 @tagName(ast.NodeSuffixOp.SuffixOp.Call),
1454 try stack.append(State { .PrimaryExpression = dest_ptr });1548 @tagName(ast.Node.Id.FnProto),
1455 continue;1549 @tagName(node.id));
1456 }1550 }
1457 }1551 }
1458 },1552 },
14591553
1460 State.SuffixOpExpressionEnd => |dest_ptr| {1554
1461 const token = self.getNextToken();1555 State.SliceOrArrayAccess => |node| {
1556 var token = self.getNextToken();
1462 switch (token.id) {1557 switch (token.id) {
1463 Token.Id.LParen => {1558 Token.Id.Ellipsis2 => {
1464 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,1559 const start = node.op.ArrayAccess;
1465 ast.NodeSuffixOp {1560 node.op = ast.NodeSuffixOp.SuffixOp {
1466 .base = undefined,1561 .Slice = ast.NodeSuffixOp.SliceRange {
1467 .lhs = dest_ptr.get(),1562 .start = start,
1468 .op = ast.NodeSuffixOp.SuffixOp {1563 .end = null,
1469 .Call = ast.NodeSuffixOp.CallInfo {
1470 .params = ArrayList(&ast.Node).init(arena),
1471 .async_attr = null,
1472 }
1473 },
1474 .rtoken = undefined,
1475 }1564 }
1476 );1565 };
1477 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;1566
1478 try stack.append(State {1567 stack.append(State {
1479 .ExprListItemOrEnd = ExprListCtx {1568 .ExpectTokenSave = ExpectTokenSave {
1480 .list = &node.op.Call.params,1569 .id = Token.Id.RBracket,
1481 .end = Token.Id.RParen,
1482 .ptr = &node.rtoken,1570 .ptr = &node.rtoken,
1483 }1571 }
1484 });1572 }) catch unreachable;
1485 continue;1573 try stack.append(State { .Expression = OptionalCtx { .Optional = &node.op.Slice.end } });
1486 },
1487 Token.Id.LBracket => {
1488 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuffixOp,
1489 ast.NodeSuffixOp {
1490 .base = undefined,
1491 .lhs = dest_ptr.get(),
1492 .op = ast.NodeSuffixOp.SuffixOp {
1493 .ArrayAccess = undefined,
1494 },
1495 .rtoken = undefined
1496 }
1497 );
1498 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1499 try stack.append(State { .SliceOrArrayAccess = node });
1500 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }});
1501 continue;1574 continue;
1502 },1575 },
1503 Token.Id.Period => {1576 Token.Id.RBracket => {
1504 const identifier = try self.createLiteral(arena, ast.NodeIdentifier, Token(undefined));1577 node.rtoken = token;
1505 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeInfixOp,
1506 ast.NodeInfixOp {
1507 .base = undefined,
1508 .lhs = dest_ptr.get(),
1509 .op_token = token,
1510 .op = ast.NodeInfixOp.InfixOp.Period,
1511 .rhs = &identifier.base,
1512 }
1513 );
1514 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1515 try stack.append(State {
1516 .ExpectTokenSave = ExpectTokenSave {
1517 .id = Token.Id.Identifier,
1518 .ptr = &identifier.token
1519 }
1520 });
1521 continue;1578 continue;
1522 },1579 },
1523 else => {1580 else => {
1524 self.putBackToken(token);1581 return self.parseError(token, "expected ']' or '..', found {}", @tagName(token.id));
1525 continue;1582 }
1526 },
1527 }1583 }
1528 },1584 },
1585 State.SliceOrArrayType => |node| {
1586 if (self.eatToken(Token.Id.RBracket)) |_| {
1587 node.op = ast.NodePrefixOp.PrefixOp {
1588 .SliceType = ast.NodePrefixOp.AddrOfInfo {
1589 .align_expr = null,
1590 .bit_offset_start_token = null,
1591 .bit_offset_end_token = null,
1592 .const_token = null,
1593 .volatile_token = null,
1594 }
1595 };
1596 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1597 try stack.append(State { .AddrOfModifiers = &node.op.SliceType });
1598 continue;
1599 }
15291600
1530 State.PrimaryExpression => |dest_ptr| {1601 node.op = ast.NodePrefixOp.PrefixOp { .ArrayType = undefined };
1531 const token = self.getNextToken();1602 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1603 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1604 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } });
1605 continue;
1606 },
1607 State.AddrOfModifiers => |addr_of_info| {
1608 var token = self.getNextToken();
1532 switch (token.id) {1609 switch (token.id) {
1533 Token.Id.IntegerLiteral => {1610 Token.Id.Keyword_align => {
1534 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeStringLiteral, token)).base);1611 stack.append(state) catch unreachable;
1535 continue;1612 if (addr_of_info.align_expr != null) {
1536 },1613 return self.parseError(token, "multiple align qualifiers");
1537 Token.Id.FloatLiteral => {1614 }
1538 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeFloatLiteral, token)).base);1615 try stack.append(State { .ExpectToken = Token.Id.RParen });
1539 continue;1616 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &addr_of_info.align_expr} });
1540 },1617 try stack.append(State { .ExpectToken = Token.Id.LParen });
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;1618 continue;
1556 },1619 },
1557 Token.Id.Keyword_this => {1620 Token.Id.Keyword_const => {
1558 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeThisLiteral, token)).base);1621 stack.append(state) catch unreachable;
1622 if (addr_of_info.const_token != null) {
1623 return self.parseError(token, "duplicate qualifier: const");
1624 }
1625 addr_of_info.const_token = token;
1559 continue;1626 continue;
1560 },1627 },
1561 Token.Id.Keyword_var => {1628 Token.Id.Keyword_volatile => {
1562 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeVarType, token)).base);1629 stack.append(state) catch unreachable;
1630 if (addr_of_info.volatile_token != null) {
1631 return self.parseError(token, "duplicate qualifier: volatile");
1632 }
1633 addr_of_info.volatile_token = token;
1563 continue;1634 continue;
1564 },1635 },
1565 Token.Id.Keyword_unreachable => {1636 else => {
1566 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeUnreachable, token)).base);1637 self.putBackToken(token);
1567 continue;1638 continue;
1568 },1639 },
1569 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {1640 }
1570 dest_ptr.store((try self.parseStringLiteral(arena, token)) ?? unreachable);1641 },
1571 },1642
1572 Token.Id.LParen => {1643
1573 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeGroupedExpression,1644 State.Payload => |opt_ctx| {
1574 ast.NodeGroupedExpression {1645 const token = self.getNextToken();
1646 if (token.id != Token.Id.Pipe) {
1647 if (opt_ctx != OptionalCtx.Optional) {
1648 return self.parseError(token, "expected {}, found {}.",
1649 @tagName(Token.Id.Pipe),
1650 @tagName(token.id));
1651 }
1652
1653 self.putBackToken(token);
1654 continue;
1655 }
1656
1657 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePayload,
1658 ast.NodePayload {
1659 .base = undefined,
1660 .lpipe = token,
1661 .error_symbol = undefined,
1662 .rpipe = undefined
1663 }
1664 );
1665
1666 stack.append(State {
1667 .ExpectTokenSave = ExpectTokenSave {
1668 .id = Token.Id.Pipe,
1669 .ptr = &node.rpipe,
1670 }
1671 }) catch unreachable;
1672 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.error_symbol } });
1673 },
1674 State.PointerPayload => |opt_ctx| {
1675 const token = self.getNextToken();
1676 if (token.id != Token.Id.Pipe) {
1677 if (opt_ctx != OptionalCtx.Optional) {
1678 return self.parseError(token, "expected {}, found {}.",
1679 @tagName(Token.Id.Pipe),
1680 @tagName(token.id));
1681 }
1682
1683 self.putBackToken(token);
1684 continue;
1685 }
1686
1687 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerPayload,
1688 ast.NodePointerPayload {
1689 .base = undefined,
1690 .lpipe = token,
1691 .ptr_token = null,
1692 .value_symbol = undefined,
1693 .rpipe = undefined
1694 }
1695 );
1696
1697 stack.append(State {
1698 .ExpectTokenSave = ExpectTokenSave {
1699 .id = Token.Id.Pipe,
1700 .ptr = &node.rpipe,
1701 }
1702 }) catch unreachable;
1703 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
1704 try stack.append(State {
1705 .OptionalTokenSave = OptionalTokenSave {
1706 .id = Token.Id.Asterisk,
1707 .ptr = &node.ptr_token,
1708 }
1709 });
1710 },
1711 State.PointerIndexPayload => |opt_ctx| {
1712 const token = self.getNextToken();
1713 if (token.id != Token.Id.Pipe) {
1714 if (opt_ctx != OptionalCtx.Optional) {
1715 return self.parseError(token, "expected {}, found {}.",
1716 @tagName(Token.Id.Pipe),
1717 @tagName(token.id));
1718 }
1719
1720 self.putBackToken(token);
1721 continue;
1722 }
1723
1724 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerIndexPayload,
1725 ast.NodePointerIndexPayload {
1726 .base = undefined,
1727 .lpipe = token,
1728 .ptr_token = null,
1729 .value_symbol = undefined,
1730 .index_symbol = null,
1731 .rpipe = undefined
1732 }
1733 );
1734
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 { .RequiredNull = &node.index_symbol } });
1742 try stack.append(State { .IfToken = Token.Id.Comma });
1743 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.value_symbol } });
1744 try stack.append(State {
1745 .OptionalTokenSave = OptionalTokenSave {
1746 .id = Token.Id.Asterisk,
1747 .ptr = &node.ptr_token,
1748 }
1749 });
1750 },
1751
1752
1753 State.Expression => |opt_ctx| {
1754 const token = self.getNextToken();
1755 switch (token.id) {
1756 Token.Id.Keyword_return => {
1757 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,
1758 ast.NodeControlFlowExpression {
1575 .base = undefined,1759 .base = undefined,
1576 .lparen = token,1760 .ltoken = token,
1577 .expr = undefined,1761 .kind = ast.NodeControlFlowExpression.Kind.Return,
1578 .rparen = undefined,1762 .rhs = null,
1579 }1763 }
1580 );1764 );
1581 stack.append(State {1765
1582 .ExpectTokenSave = ExpectTokenSave {1766 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
1583 .id = Token.Id.RParen,
1584 .ptr = &node.rparen,
1585 }
1586 }) catch unreachable;
1587 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1588 continue;1767 continue;
1589 },1768 },
1590 Token.Id.Builtin => {1769 Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1591 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeBuiltinCall,1770 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression,
1592 ast.NodeBuiltinCall {1771 ast.NodeControlFlowExpression {
1593 .base = undefined,1772 .base = undefined,
1594 .builtin_token = token,1773 .ltoken = token,
1595 .params = ArrayList(&ast.Node).init(arena),1774 .kind = undefined,
1596 .rparen_token = undefined,1775 .rhs = null,
1597 }1776 }
1598 );1777 );
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;
1608 },
1609 Token.Id.LBracket => {
1610 const rbracket_token = self.getNextToken();
1611 if (rbracket_token.id == Token.Id.RBracket) {
1612 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,
1613 ast.NodePrefixOp {
1614 .base = undefined,
1615 .op_token = token,
1616 .op = ast.NodePrefixOp.PrefixOp{
1617 .SliceType = ast.NodePrefixOp.AddrOfInfo {
1618 .align_expr = null,
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 }
16331778
1634 self.putBackToken(rbracket_token);1779 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
16351780
1636 const node = try self.createToDestNode(arena, dest_ptr, ast.NodePrefixOp,1781 switch (token.id) {
1782 Token.Id.Keyword_break => {
1783 node.kind = ast.NodeControlFlowExpression.Kind { .Break = null };
1784 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } });
1785 try stack.append(State { .IfToken = Token.Id.Colon });
1786 },
1787 Token.Id.Keyword_continue => {
1788 node.kind = ast.NodeControlFlowExpression.Kind { .Continue = null };
1789 try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } });
1790 try stack.append(State { .IfToken = Token.Id.Colon });
1791 },
1792 else => unreachable,
1793 }
1794 continue;
1795 },
1796 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
1797 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
1637 ast.NodePrefixOp {1798 ast.NodePrefixOp {
1638 .base = undefined,1799 .base = undefined,
1639 .op_token = token,1800 .op_token = token,
1640 .op = ast.NodePrefixOp.PrefixOp{1801 .op = switch (token.id) {
1641 .ArrayType = undefined,1802 Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{} },
1803 Token.Id.Keyword_cancel => ast.NodePrefixOp.PrefixOp { .Cancel = void{} },
1804 Token.Id.Keyword_resume => ast.NodePrefixOp.PrefixOp { .Resume = void{} },
1805 else => unreachable,
1642 },1806 },
1643 .rhs = undefined,1807 .rhs = undefined,
1644 }1808 }
1645 );1809 );
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 } });
16491810
1811 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1812 continue;
1650 },1813 },
1651 Token.Id.Keyword_error => {1814 else => {
1652 if (self.eatToken(Token.Id.LBrace) == null) {1815 if (!try self.parseBlockExpr(&stack, arena, opt_ctx, token)) {
1653 dest_ptr.store(&(try self.createLiteral(arena, ast.NodeErrorType, token)).base);1816 self.putBackToken(token);
1654 continue;1817 stack.append(State { .UnwrapExpressionBegin = opt_ctx }) catch unreachable;
1655 }1818 }
1656
1657 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeErrorSetDecl,
1658 ast.NodeErrorSetDecl {
1659 .base = undefined,
1660 .error_token = token,
1661 .decls = ArrayList(&ast.NodeIdentifier).init(arena),
1662 .rbrace_token = undefined,
1663 }
1664 );
1665
1666 stack.append(State {
1667 .IdentifierListItemOrEnd = ListSave(&ast.NodeIdentifier) {
1668 .list = &node.decls,
1669 .ptr = &node.rbrace_token,
1670 }
1671 }) catch unreachable;
1672 continue;1819 continue;
1673 },1820 }
1674 Token.Id.Keyword_packed => {1821 }
1675 stack.append(State {1822 },
1676 .ContainerExtern = ContainerExternCtx {1823 State.RangeExpressionBegin => |opt_ctx| {
1677 .dest_ptr = dest_ptr,1824 stack.append(State { .RangeExpressionEnd = opt_ctx }) catch unreachable;
1678 .ltoken = token,1825 try stack.append(State { .Expression = opt_ctx });
1679 .layout = ast.NodeContainerDecl.Layout.Packed,1826 continue;
1680 },1827 },
1681 }) catch unreachable;1828 State.RangeExpressionEnd => |opt_ctx| {
1682 },1829 const lhs = opt_ctx.get() ?? continue;
1683 Token.Id.Keyword_extern => {1830
1684 const next = self.getNextToken();1831 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {
1685 if (next.id == Token.Id.Keyword_fn) {1832 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1686 const fn_proto = try self.createToDestNode(arena, dest_ptr, ast.NodeFnProto,1833 ast.NodeInfixOp {
1687 ast.NodeFnProto {1834 .base = undefined,
1688 .base = undefined,1835 .lhs = lhs,
1689 .visib_token = null,1836 .op_token = ellipsis3,
1690 .name_token = null,1837 .op = ast.NodeInfixOp.InfixOp.Range,
1691 .fn_token = next,1838 .rhs = undefined,
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 }1839 }
1840 );
1841 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
1842 }
17061843
1707 self.putBackToken(next);1844 continue;
1708 stack.append(State {1845 },
1709 .ContainerExtern = ContainerExternCtx {1846 State.AssignmentExpressionBegin => |opt_ctx| {
1710 .dest_ptr = dest_ptr,1847 stack.append(State { .AssignmentExpressionEnd = opt_ctx }) catch unreachable;
1711 .ltoken = token,1848 try stack.append(State { .Expression = opt_ctx });
1712 .layout = ast.NodeContainerDecl.Layout.Extern,1849 continue;
1713 },1850 },
1714 }) catch unreachable;1851
1715 },1852 State.AssignmentExpressionEnd => |opt_ctx| {
1716 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {1853 const lhs = opt_ctx.get() ?? continue;
1717 self.putBackToken(token);1854
1718 stack.append(State {1855 const token = self.getNextToken();
1719 .ContainerExtern = ContainerExternCtx {1856 if (tokenIdToAssignment(token.id)) |ass_id| {
1720 .dest_ptr = dest_ptr,1857 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1721 .ltoken = token,1858 ast.NodeInfixOp {
1722 .layout = ast.NodeContainerDecl.Layout.Auto,1859 .base = undefined,
1723 },1860 .lhs = lhs,
1724 }) catch unreachable;1861 .op_token = token,
1725 },1862 .op = ass_id,
1726 Token.Id.Identifier => {1863 .rhs = undefined,
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 }1864 }
1865 );
1866 stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1867 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1868 continue;
1869 } else {
1870 self.putBackToken(token);
1871 continue;
1872 }
1873 },
17331874
1734 stack.append(State {1875 State.UnwrapExpressionBegin => |opt_ctx| {
1735 .LabeledExpression = LabelCtx {1876 stack.append(State { .UnwrapExpressionEnd = opt_ctx }) catch unreachable;
1736 .label = token,1877 try stack.append(State { .BoolOrExpressionBegin = opt_ctx });
1737 .dest_ptr = dest_ptr1878 continue;
1738 }1879 },
1739 }) catch unreachable;1880
1740 continue;1881 State.UnwrapExpressionEnd => |opt_ctx| {
1741 },1882 const lhs = opt_ctx.get() ?? continue;
1742 Token.Id.Keyword_fn => {1883
1743 const fn_proto = try self.createToDestNode(arena, dest_ptr, ast.NodeFnProto,1884 const token = self.getNextToken();
1744 ast.NodeFnProto {1885 switch (token.id) {
1886 Token.Id.Keyword_catch, Token.Id.QuestionMarkQuestionMark => {
1887 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1888 ast.NodeInfixOp {
1745 .base = undefined,1889 .base = undefined,
1746 .visib_token = null,1890 .lhs = lhs,
1747 .name_token = null,1891 .op_token = token,
1748 .fn_token = token,1892 .op = switch (token.id) {
1749 .params = ArrayList(&ast.Node).init(arena),1893 Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null },
1750 .return_type = undefined,1894 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} },
1751 .var_args_token = null,1895 else => unreachable,
1752 .extern_export_inline_token = null,1896 },
1753 .cc_token = null,1897 .rhs = undefined,
1754 .async_attr = null,
1755 .body_node = null,
1756 .lib_name = null,
1757 .align_expr = null,
1758 }1898 }
1759 );1899 );
1760 stack.append(State { .FnProto = fn_proto }) catch unreachable;1900
1901 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1902 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
1903
1904 if (node.op == ast.NodeInfixOp.InfixOp.Catch) {
1905 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } });
1906 }
1761 continue;1907 continue;
1762 },1908 },
1763 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {1909 else => {
1764 const fn_token = (try self.expectToken(&stack, Token.Id.Keyword_fn)) ?? continue;1910 self.putBackToken(token);
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;1911 continue;
1784 },1912 },
1785 Token.Id.Keyword_asm => {1913 }
1786 const is_volatile = blk: {1914 },
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;
17951915
1796 const template_token = self.getNextToken();1916 State.BoolOrExpressionBegin => |opt_ctx| {
1797 const template = (try self.parseStringLiteral(arena, template_token)) ?? {1917 stack.append(State { .BoolOrExpressionEnd = opt_ctx }) catch unreachable;
1798 try self.parseError(&stack, template_token, "expected string literal, found {}", @tagName(template_token.id));1918 try stack.append(State { .BoolAndExpressionBegin = opt_ctx });
1799 continue;1919 continue;
1800 };1920 },
1801 // TODO parse template
18021921
1803 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeAsm,1922 State.BoolOrExpressionEnd => |opt_ctx| {
1804 ast.NodeAsm {1923 const lhs = opt_ctx.get() ?? continue;
1924
1925 const token = self.getNextToken();
1926 switch (token.id) {
1927 Token.Id.Keyword_or => {
1928 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1929 ast.NodeInfixOp {
1805 .base = undefined,1930 .base = undefined,
1806 .asm_token = token,1931 .lhs = lhs,
1807 .is_volatile = is_volatile,1932 .op_token = token,
1808 .template = template,1933 .op = ast.NodeInfixOp.InfixOp.BoolOr,
1809 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),1934 .rhs = undefined,
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 }1935 }
1815 );1936 );
1816 stack.append(State {1937 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1817 .ExpectTokenSave = ExpectTokenSave {1938 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
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;1939 continue;
1838 },1940 },
1839 else => {1941 else => {
1840 if (!try self.parseBlockExpr(&stack, arena, dest_ptr, token)) {1942 self.putBackToken(token);
1841 try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
1842 }
1843 continue;1943 continue;
1844 }1944 },
1845 }1945 }
1846 },1946 },
18471947
1848 State.SliceOrArrayAccess => |node| {1948 State.BoolAndExpressionBegin => |opt_ctx| {
1849 var token = self.getNextToken();1949 stack.append(State { .BoolAndExpressionEnd = opt_ctx }) catch unreachable;
1950 try stack.append(State { .ComparisonExpressionBegin = opt_ctx });
1951 continue;
1952 },
1953
1954 State.BoolAndExpressionEnd => |opt_ctx| {
1955 const lhs = opt_ctx.get() ?? continue;
18501956
1957 const token = self.getNextToken();
1851 switch (token.id) {1958 switch (token.id) {
1852 Token.Id.Ellipsis2 => {1959 Token.Id.Keyword_and => {
1853 const start = node.op.ArrayAccess;1960 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1854 node.op = ast.NodeSuffixOp.SuffixOp {1961 ast.NodeInfixOp {
1855 .Slice = ast.NodeSuffixOp.SliceRange {1962 .base = undefined,
1856 .start = start,1963 .lhs = lhs,
1857 .end = undefined,1964 .op_token = token,
1965 .op = ast.NodeInfixOp.InfixOp.BoolAnd,
1966 .rhs = undefined,
1858 }1967 }
1859 };1968 );
18601969 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1861 const rbracket_token = self.getNextToken();1970 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
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;1971 continue;
1879 },1972 },
1880 else => {1973 else => {
1881 try self.parseError(&stack, token, "expected ']' or '..', found {}", @tagName(token.id));1974 self.putBackToken(token);
1882 continue;1975 continue;
1883 }1976 },
1884 }1977 }
1885 },1978 },
18861979
1980 State.ComparisonExpressionBegin => |opt_ctx| {
1981 stack.append(State { .ComparisonExpressionEnd = opt_ctx }) catch unreachable;
1982 try stack.append(State { .BinaryOrExpressionBegin = opt_ctx });
1983 continue;
1984 },
18871985
1888 State.AsmOutputItems => |items| {1986 State.ComparisonExpressionEnd => |opt_ctx| {
1889 const lbracket = self.getNextToken();1987 const lhs = opt_ctx.get() ?? continue;
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;
19001988
1901 const constraint_token = self.getNextToken();1989 const token = self.getNextToken();
1902 const constraint = (try self.parseStringLiteral(arena, constraint_token)) ?? {1990 if (tokenIdToComparison(token.id)) |comp_id| {
1903 try self.parseError(&stack, constraint_token, "expected string literal, found {}", @tagName(constraint_token.id));1991 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1992 ast.NodeInfixOp {
1993 .base = undefined,
1994 .lhs = lhs,
1995 .op_token = token,
1996 .op = comp_id,
1997 .rhs = undefined,
1998 }
1999 );
2000 stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2001 try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } });
1904 continue;2002 continue;
1905 };2003 } else {
2004 self.putBackToken(token);
2005 continue;
2006 }
2007 },
19062008
1907 _ = (try self.expectToken(&stack, Token.Id.LParen)) ?? continue;2009 State.BinaryOrExpressionBegin => |opt_ctx| {
1908 try stack.append(State { .ExpectToken = Token.Id.RParen });2010 stack.append(State { .BinaryOrExpressionEnd = opt_ctx }) catch unreachable;
2011 try stack.append(State { .BinaryXorExpressionBegin = opt_ctx });
2012 continue;
2013 },
19092014
1910 const node = try self.createNode(arena, ast.NodeAsmOutput,2015 State.BinaryOrExpressionEnd => |opt_ctx| {
1911 ast.NodeAsmOutput {2016 const lhs = opt_ctx.get() ?? continue;
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);
19192017
1920 const symbol_or_arrow = self.getNextToken();2018 const token = self.getNextToken();
1921 switch (symbol_or_arrow.id) {2019 switch (token.id) {
1922 Token.Id.Identifier => {2020 Token.Id.Pipe => {
1923 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.NodeIdentifier, symbol_or_arrow) };2021 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
1924 },2022 ast.NodeInfixOp {
1925 Token.Id.Arrow => {2023 .base = undefined,
1926 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };2024 .lhs = lhs,
1927 try stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.kind.Return } });2025 .op_token = token,
2026 .op = ast.NodeInfixOp.InfixOp.BitOr,
2027 .rhs = undefined,
2028 }
2029 );
2030 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2031 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2032 continue;
1928 },2033 },
1929 else => {2034 else => {
1930 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",2035 self.putBackToken(token);
1931 @tagName(Token.Id.Identifier),
1932 @tagName(symbol_or_arrow.id));
1933 continue;2036 continue;
1934 },2037 },
1935 }2038 }
1936 },2039 },
19372040
1938 State.AsmInputItems => |items| {2041 State.BinaryXorExpressionBegin => |opt_ctx| {
1939 const lbracket = self.getNextToken();2042 stack.append(State { .BinaryXorExpressionEnd = opt_ctx }) catch unreachable;
1940 if (lbracket.id != Token.Id.LBracket) {2043 try stack.append(State { .BinaryAndExpressionBegin = opt_ctx });
1941 self.putBackToken(lbracket);2044 continue;
1942 continue;
1943 }
1944
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,
1961 ast.NodeAsmInput {
1962 .base = undefined,
1963 .symbolic_name = try self.createLiteral(arena, ast.NodeIdentifier, symbolic_name),
1964 .constraint = constraint,
1965 .expr = undefined,
1966 }
1967 );
1968 try items.append(node);
1969 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1970 },
1971
1972 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;
1981 try stack.append(State { .IfToken = Token.Id.Comma });
1982 },2045 },
19832046
1984 State.ExprListItemOrEnd => |list_state| {2047 State.BinaryXorExpressionEnd => |opt_ctx| {
1985 var token = self.getNextToken();2048 const lhs = opt_ctx.get() ?? continue;
19862049
1987 const IdTag = @TagType(Token.Id);2050 const token = self.getNextToken();
1988 if (IdTag(list_state.end) == token.id) {2051 switch (token.id) {
1989 *list_state.ptr = token;2052 Token.Id.Caret => {
1990 continue;2053 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2054 ast.NodeInfixOp {
2055 .base = undefined,
2056 .lhs = lhs,
2057 .op_token = token,
2058 .op = ast.NodeInfixOp.InfixOp.BitXor,
2059 .rhs = undefined,
2060 }
2061 );
2062 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2063 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2064 continue;
2065 },
2066 else => {
2067 self.putBackToken(token);
2068 continue;
2069 },
1991 }2070 }
1992
1993 self.putBackToken(token);
1994 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1995 try stack.append(State { .Expression = DestPtr{ .Field = try list_state.list.addOne() } });
1996 },2071 },
19972072
1998 State.FieldInitListItemOrEnd => |list_state| {2073 State.BinaryAndExpressionBegin => |opt_ctx| {
1999 if (self.eatToken(Token.Id.RBrace)) |rbrace| {2074 stack.append(State { .BinaryAndExpressionEnd = opt_ctx }) catch unreachable;
2000 *list_state.ptr = rbrace;2075 try stack.append(State { .BitShiftExpressionBegin = opt_ctx });
2001 continue;2076 continue;
2002 }
2003
2004 const node = try self.createNode(arena, ast.NodeFieldInitializer,
2005 ast.NodeFieldInitializer {
2006 .base = undefined,
2007 .period_token = undefined,
2008 .name_token = undefined,
2009 .expr = undefined,
2010 }
2011 );
2012 try list_state.list.append(node);
2013
2014 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
2015 try stack.append(State { .Expression = DestPtr{.Field = &node.expr} });
2016 try stack.append(State { .ExpectToken = Token.Id.Equal });
2017 try stack.append(State {
2018 .ExpectTokenSave = ExpectTokenSave {
2019 .id = Token.Id.Identifier,
2020 .ptr = &node.name_token,
2021 }
2022 });
2023 try stack.append(State {
2024 .ExpectTokenSave = ExpectTokenSave {
2025 .id = Token.Id.Period,
2026 .ptr = &node.period_token,
2027 }
2028 });
2029 },2077 },
20302078
2031 State.IdentifierListItemOrEnd => |list_state| {2079 State.BinaryAndExpressionEnd => |opt_ctx| {
2032 if (self.eatToken(Token.Id.RBrace)) |rbrace| {2080 const lhs = opt_ctx.get() ?? continue;
2033 *list_state.ptr = rbrace;
2034 continue;
2035 }
2036
2037 const node = try self.createLiteral(arena, ast.NodeIdentifier, Token(undefined));
2038 try list_state.list.append(node);
20392081
2040 stack.append(State { .IdentifierListCommaOrEnd = list_state }) catch unreachable;2082 const token = self.getNextToken();
2041 try stack.append(State {2083 switch (token.id) {
2042 .ExpectTokenSave = ExpectTokenSave {2084 Token.Id.Ampersand => {
2043 .id = Token.Id.Identifier,2085 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2044 .ptr = &node.token,2086 ast.NodeInfixOp {
2045 }2087 .base = undefined,
2046 });2088 .lhs = lhs,
2089 .op_token = token,
2090 .op = ast.NodeInfixOp.InfixOp.BitAnd,
2091 .rhs = undefined,
2092 }
2093 );
2094 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2095 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2096 continue;
2097 },
2098 else => {
2099 self.putBackToken(token);
2100 continue;
2101 },
2102 }
2047 },2103 },
20482104
2049 State.SwitchCaseOrEnd => |list_state| {2105 State.BitShiftExpressionBegin => |opt_ctx| {
2050 if (self.eatToken(Token.Id.RBrace)) |rbrace| {2106 stack.append(State { .BitShiftExpressionEnd = opt_ctx }) catch unreachable;
2051 *list_state.ptr = rbrace;2107 try stack.append(State { .AdditionExpressionBegin = opt_ctx });
2052 continue;2108 continue;
2053 }2109 },
20542110
2055 const node = try self.createNode(arena, ast.NodeSwitchCase,2111 State.BitShiftExpressionEnd => |opt_ctx| {
2056 ast.NodeSwitchCase {2112 const lhs = opt_ctx.get() ?? continue;
2057 .base = undefined,
2058 .items = ArrayList(&ast.Node).init(arena),
2059 .payload = null,
2060 .expr = undefined,
2061 }
2062 );
2063 try list_state.list.append(node);
2064 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
2065 try stack.append(State { .AssignmentExpressionBegin = DestPtr{ .Field = &node.expr } });
2066 try stack.append(State { .PointerPayload = &node.payload });
20672113
2068 const maybe_else = self.getNextToken();2114 const token = self.getNextToken();
2069 if (maybe_else.id == Token.Id.Keyword_else) {2115 if (tokenIdToBitShift(token.id)) |bitshift_id| {
2070 const else_node = try self.createAttachNode(arena, &node.items, ast.NodeSwitchElse,2116 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2071 ast.NodeSwitchElse {2117 ast.NodeInfixOp {
2072 .base = undefined,2118 .base = undefined,
2073 .token = maybe_else,2119 .lhs = lhs,
2120 .op_token = token,
2121 .op = bitshift_id,
2122 .rhs = undefined,
2074 }2123 }
2075 );2124 );
2076 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });2125 stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2126 try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2077 continue;2127 continue;
2078 } else {2128 } else {
2079 self.putBackToken(maybe_else);2129 self.putBackToken(token);
2080 try stack.append(State { .SwitchCaseItem = &node.items });
2081 continue;2130 continue;
2082 }2131 }
2083 },2132 },
20842133
2085 State.SwitchCaseItem => |case_items| {2134 State.AdditionExpressionBegin => |opt_ctx| {
2086 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;2135 stack.append(State { .AdditionExpressionEnd = opt_ctx }) catch unreachable;
2087 try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });2136 try stack.append(State { .MultiplyExpressionBegin = opt_ctx });
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;2137 continue;
2098 },2138 },
20992139
2100 State.FieldListCommaOrEnd => |container_decl| {2140 State.AdditionExpressionEnd => |opt_ctx| {
2101 try self.commaOrEnd(&stack, Token.Id.RBrace, &container_decl.rbrace_token,2141 const lhs = opt_ctx.get() ?? continue;
2102 State { .ContainerDecl = container_decl });
2103 continue;
2104 },
21052142
2106 State.IdentifierListCommaOrEnd => |list_state| {2143 const token = self.getNextToken();
2107 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .IdentifierListItemOrEnd = list_state });2144 if (tokenIdToAddition(token.id)) |add_id| {
2108 continue;2145 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2146 ast.NodeInfixOp {
2147 .base = undefined,
2148 .lhs = lhs,
2149 .op_token = token,
2150 .op = add_id,
2151 .rhs = undefined,
2152 }
2153 );
2154 stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2155 try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2156 continue;
2157 } else {
2158 self.putBackToken(token);
2159 continue;
2160 }
2109 },2161 },
21102162
2111 State.SwitchCaseCommaOrEnd => |list_state| {2163 State.MultiplyExpressionBegin => |opt_ctx| {
2112 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });2164 stack.append(State { .MultiplyExpressionEnd = opt_ctx }) catch unreachable;
2165 try stack.append(State { .CurlySuffixExpressionBegin = opt_ctx });
2113 continue;2166 continue;
2114 },2167 },
21152168
2116 State.SwitchCaseItemCommaOrEnd => |case_items| {2169 State.MultiplyExpressionEnd => |opt_ctx| {
2117 try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });2170 const lhs = opt_ctx.get() ?? continue;
2118 continue;
2119 },
21202171
2121 State.Else => |dest| {2172 const token = self.getNextToken();
2122 const else_token = self.getNextToken();2173 if (tokenIdToMultiply(token.id)) |mult_id| {
2123 if (else_token.id != Token.Id.Keyword_else) {2174 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2124 self.putBackToken(else_token);2175 ast.NodeInfixOp {
2176 .base = undefined,
2177 .lhs = lhs,
2178 .op_token = token,
2179 .op = mult_id,
2180 .rhs = undefined,
2181 }
2182 );
2183 stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2184 try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } });
2185 continue;
2186 } else {
2187 self.putBackToken(token);
2125 continue;2188 continue;
2126 }2189 }
2190 },
21272191
2128 const node = try self.createNode(arena, ast.NodeElse,2192 State.CurlySuffixExpressionBegin => |opt_ctx| {
2129 ast.NodeElse {2193 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx }) catch unreachable;
2130 .base = undefined,2194 try stack.append(State { .IfToken = Token.Id.LBrace });
2131 .else_token = else_token,2195 try stack.append(State { .TypeExprBegin = opt_ctx });
2132 .payload = null,2196 continue;
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 },2197 },
21412198
2142 State.WhileContinueExpr => |dest| {2199 State.CurlySuffixExpressionEnd => |opt_ctx| {
2143 const colon = self.getNextToken();2200 const lhs = opt_ctx.get() ?? continue;
2144 if (colon.id != Token.Id.Colon) {2201
2145 self.putBackToken(colon);2202 if (self.isPeekToken(Token.Id.Period)) {
2203 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2204 ast.NodeSuffixOp {
2205 .base = undefined,
2206 .lhs = lhs,
2207 .op = ast.NodeSuffixOp.SuffixOp {
2208 .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),
2209 },
2210 .rtoken = undefined,
2211 }
2212 );
2213 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2214 try stack.append(State { .IfToken = Token.Id.LBrace });
2215 try stack.append(State {
2216 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
2217 .list = &node.op.StructInitializer,
2218 .ptr = &node.rtoken,
2219 }
2220 });
2221 continue;
2222 } else {
2223 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2224 ast.NodeSuffixOp {
2225 .base = undefined,
2226 .lhs = lhs,
2227 .op = ast.NodeSuffixOp.SuffixOp {
2228 .ArrayInitializer = ArrayList(&ast.Node).init(arena),
2229 },
2230 .rtoken = undefined,
2231 }
2232 );
2233 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2234 try stack.append(State { .IfToken = Token.Id.LBrace });
2235 try stack.append(State {
2236 .ExprListItemOrEnd = ExprListCtx {
2237 .list = &node.op.ArrayInitializer,
2238 .end = Token.Id.RBrace,
2239 .ptr = &node.rtoken,
2240 }
2241 });
2146 continue;2242 continue;
2147 }2243 }
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 },2244 },
21532245
2154 State.SuspendBody => |suspend_node| {2246 State.TypeExprBegin => |opt_ctx| {
2155 if (suspend_node.payload != null) {2247 stack.append(State { .TypeExprEnd = opt_ctx }) catch unreachable;
2156 try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = &suspend_node.body } });2248 try stack.append(State { .PrefixOpExpression = opt_ctx });
2157 }
2158 continue;2249 continue;
2159 },2250 },
21602251
2161 State.AsyncEnd => |ctx| {2252 State.TypeExprEnd => |opt_ctx| {
2162 const node = ctx.dest_ptr.get();2253 const lhs = opt_ctx.get() ?? continue;
2163
2164 switch (node.id) {
2165 ast.Node.Id.FnProto => {
2166 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);
2167 fn_proto.async_attr = ctx.attribute;
2168 },
2169 ast.Node.Id.SuffixOp => {
2170 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);
2171 if (suffix_op.op == ast.NodeSuffixOp.SuffixOp.Call) {
2172 suffix_op.op.Call.async_attr = ctx.attribute;
2173 continue;
2174 }
21752254
2176 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",2255 const token = self.getNextToken();
2177 @tagName(suffix_op.op));2256 switch (token.id) {
2257 Token.Id.Bang => {
2258 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2259 ast.NodeInfixOp {
2260 .base = undefined,
2261 .lhs = lhs,
2262 .op_token = token,
2263 .op = ast.NodeInfixOp.InfixOp.ErrorUnion,
2264 .rhs = undefined,
2265 }
2266 );
2267 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2268 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
2178 continue;2269 continue;
2179 },2270 },
2180 else => {2271 else => {
2181 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",2272 self.putBackToken(token);
2182 @tagName(node.id));
2183 continue;2273 continue;
2184 }2274 },
2185 }
2186 },
2187
2188 State.Payload => |dest| {
2189 const lpipe = self.getNextToken();
2190 if (lpipe.id != Token.Id.Pipe) {
2191 self.putBackToken(lpipe);
2192 continue;
2193 }2275 }
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 },2276 },
22062277
2207 State.PointerPayload => |dest| {2278 State.PrefixOpExpression => |opt_ctx| {
2208 const lpipe = self.getNextToken();2279 const token = self.getNextToken();
2209 if (lpipe.id != Token.Id.Pipe) {2280 if (tokenIdToPrefixOp(token.id)) |prefix_id| {
2210 self.putBackToken(lpipe);2281 var node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
2211 continue;2282 ast.NodePrefixOp {
2212 }2283 .base = undefined,
2284 .op_token = token,
2285 .op = prefix_id,
2286 .rhs = undefined,
2287 }
2288 );
22132289
2214 const is_ptr = blk: {2290 if (token.id == Token.Id.AsteriskAsterisk) {
2215 const asterik = self.getNextToken();2291 const child = try self.createNode(arena, ast.NodePrefixOp,
2216 if (asterik.id == Token.Id.Asterisk) {2292 ast.NodePrefixOp {
2217 break :blk true;2293 .base = undefined,
2218 } else {2294 .op_token = token,
2219 self.putBackToken(asterik);2295 .op = prefix_id,
2220 break :blk false;2296 .rhs = undefined,
2297 }
2298 );
2299 node.rhs = &child.base;
2300 node = child;
2221 }2301 }
2222 };
22232302
2224 const value_symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;2303 stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
2225 const rpipe = (try self.expectToken(&stack, Token.Id.Pipe)) ?? continue;2304 if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) {
2226 *dest = try self.createNode(arena, ast.NodePointerPayload,2305 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });
2227 ast.NodePointerPayload {
2228 .base = undefined,
2229 .lpipe = lpipe,
2230 .is_ptr = is_ptr,
2231 .value_symbol = try self.createLiteral(arena, ast.NodeIdentifier, value_symbol),
2232 .rpipe = rpipe
2233 }2306 }
2234 );2307 continue;
2235 },2308 } else {
22362309 self.putBackToken(token);
2237 State.PointerIndexPayload => |dest| {2310 stack.append(State { .SuffixOpExpressionBegin = opt_ctx }) catch unreachable;
2238 const lpipe = self.getNextToken();
2239 if (lpipe.id != Token.Id.Pipe) {
2240 self.putBackToken(lpipe);
2241 continue;2311 continue;
2242 }2312 }
2313 },
22432314
2244 const is_ptr = blk: {2315 State.SuffixOpExpressionBegin => |opt_ctx| {
2245 const asterik = self.getNextToken();2316 const token = self.getNextToken();
2246 if (asterik.id == Token.Id.Asterisk) {2317 switch (token.id) {
2247 break :blk true;2318 Token.Id.Keyword_async => {
2248 } else {2319 const async_node = try self.createNode(arena, ast.NodeAsyncAttribute,
2249 self.putBackToken(asterik);2320 ast.NodeAsyncAttribute {
2250 break :blk false;2321 .base = undefined,
2251 }2322 .async_token = token,
2252 };2323 .allocator_type = null,
22532324 .rangle_bracket = null,
2254 const value_symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;2325 }
2255 const index_symbol = blk: {2326 );
2256 const comma = self.getNextToken();2327 stack.append(State {
2257 if (comma.id != Token.Id.Comma) {2328 .AsyncEnd = AsyncEndCtx {
2258 self.putBackToken(comma);2329 .ctx = opt_ctx,
2259 break :blk null;2330 .attribute = async_node,
2331 }
2332 }) catch unreachable;
2333 try stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() });
2334 try stack.append(State { .PrimaryExpression = opt_ctx.toRequired() });
2335 try stack.append(State { .AsyncAllocator = async_node });
2336 continue;
2337 },
2338 else => {
2339 self.putBackToken(token);
2340 stack.append(State { .SuffixOpExpressionEnd = opt_ctx }) catch unreachable;
2341 try stack.append(State { .PrimaryExpression = opt_ctx });
2342 continue;
2260 }2343 }
2344 }
2345 },
22612346
2262 const symbol = (try self.expectToken(&stack, Token.Id.Identifier)) ?? continue;2347 State.SuffixOpExpressionEnd => |opt_ctx| {
2263 break :blk try self.createLiteral(arena, ast.NodeIdentifier, symbol);2348 const lhs = opt_ctx.get() ?? continue;
2264 };
22652349
2266 const rpipe = (try self.expectToken(&stack, Token.Id.Pipe)) ?? continue;2350 const token = self.getNextToken();
2267 *dest = try self.createNode(arena, ast.NodePointerIndexPayload,2351 switch (token.id) {
2268 ast.NodePointerIndexPayload {2352 Token.Id.LParen => {
2269 .base = undefined,2353 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2270 .lpipe = lpipe,2354 ast.NodeSuffixOp {
2271 .is_ptr = is_ptr,2355 .base = undefined,
2272 .value_symbol = try self.createLiteral(arena, ast.NodeIdentifier, value_symbol),2356 .lhs = lhs,
2273 .index_symbol = index_symbol,2357 .op = ast.NodeSuffixOp.SuffixOp {
2274 .rpipe = rpipe2358 .Call = ast.NodeSuffixOp.CallInfo {
2275 }2359 .params = ArrayList(&ast.Node).init(arena),
2276 );2360 .async_attr = null,
2361 }
2362 },
2363 .rtoken = undefined,
2364 }
2365 );
2366 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2367 try stack.append(State {
2368 .ExprListItemOrEnd = ExprListCtx {
2369 .list = &node.op.Call.params,
2370 .end = Token.Id.RParen,
2371 .ptr = &node.rtoken,
2372 }
2373 });
2374 continue;
2375 },
2376 Token.Id.LBracket => {
2377 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp,
2378 ast.NodeSuffixOp {
2379 .base = undefined,
2380 .lhs = lhs,
2381 .op = ast.NodeSuffixOp.SuffixOp {
2382 .ArrayAccess = undefined,
2383 },
2384 .rtoken = undefined
2385 }
2386 );
2387 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2388 try stack.append(State { .SliceOrArrayAccess = node });
2389 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }});
2390 continue;
2391 },
2392 Token.Id.Period => {
2393 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp,
2394 ast.NodeInfixOp {
2395 .base = undefined,
2396 .lhs = lhs,
2397 .op_token = token,
2398 .op = ast.NodeInfixOp.InfixOp.Period,
2399 .rhs = undefined,
2400 }
2401 );
2402 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2403 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } });
2404 continue;
2405 },
2406 else => {
2407 self.putBackToken(token);
2408 continue;
2409 },
2410 }
2277 },2411 },
22782412
2279 State.AddrOfModifiers => |addr_of_info| {2413 State.PrimaryExpression => |opt_ctx| {
2280 var token = self.getNextToken();2414 const token = self.getNextToken();
2281 switch (token.id) {2415 switch (token.id) {
2282 Token.Id.Keyword_align => {2416 Token.Id.IntegerLiteral => {
2283 stack.append(state) catch unreachable;2417 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeStringLiteral, token)).base);
2284 if (addr_of_info.align_expr != null) {2418 continue;
2285 try self.parseError(&stack, token, "multiple align qualifiers");2419 },
2286 continue;2420 Token.Id.FloatLiteral => {
2287 }2421 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeFloatLiteral, token)).base);
2288 try stack.append(State { .ExpectToken = Token.Id.RParen });2422 continue;
2289 try stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });2423 },
2290 try stack.append(State { .ExpectToken = Token.Id.LParen });2424 Token.Id.CharLiteral => {
2425 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeCharLiteral, token)).base);
2426 continue;
2427 },
2428 Token.Id.Keyword_undefined => {
2429 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeUndefinedLiteral, token)).base);
2430 continue;
2431 },
2432 Token.Id.Keyword_true, Token.Id.Keyword_false => {
2433 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeBoolLiteral, token)).base);
2291 continue;2434 continue;
2292 },2435 },
2293 Token.Id.Keyword_const => {2436 Token.Id.Keyword_null => {
2294 stack.append(state) catch unreachable;2437 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeNullLiteral, token)).base);
2295 if (addr_of_info.const_token != null) {
2296 try self.parseError(&stack, token, "duplicate qualifier: const");
2297 continue;
2298 }
2299 addr_of_info.const_token = token;
2300 continue;2438 continue;
2301 },2439 },
2302 Token.Id.Keyword_volatile => {2440 Token.Id.Keyword_this => {
2303 stack.append(state) catch unreachable;2441 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeThisLiteral, token)).base);
2304 if (addr_of_info.volatile_token != null) {
2305 try self.parseError(&stack, token, "duplicate qualifier: volatile");
2306 continue;
2307 }
2308 addr_of_info.volatile_token = token;
2309 continue;2442 continue;
2310 },2443 },
2311 else => {2444 Token.Id.Keyword_var => {
2312 self.putBackToken(token);2445 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeVarType, token)).base);
2313 continue;2446 continue;
2314 },2447 },
2315 }2448 Token.Id.Keyword_unreachable => {
2316 },2449 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeUnreachable, token)).base);
23172450 continue;
2318 State.FnProto => |fn_proto| {2451 },
2319 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;2452 Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => {
2320 try stack.append(State { .ParamDecl = fn_proto });2453 opt_ctx.store((try self.parseStringLiteral(arena, token)) ?? unreachable);
2321 try stack.append(State { .ExpectToken = Token.Id.LParen });2454 },
23222455 Token.Id.LParen => {
2323 const next_token = self.getNextToken();2456 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeGroupedExpression,
2324 if (next_token.id == Token.Id.Identifier) {2457 ast.NodeGroupedExpression {
2325 fn_proto.name_token = next_token;2458 .base = undefined,
2326 continue;2459 .lparen = token,
2327 }2460 .expr = undefined,
2328 self.putBackToken(next_token);2461 .rparen = undefined,
2329 continue;2462 }
2330 },2463 );
2331
2332 State.FnProtoAlign => |fn_proto| {
2333 stack.append(State { .FnProtoReturnType = fn_proto }) catch unreachable;
2334
2335 if (self.eatToken(Token.Id.Keyword_align)) |align_token| {
2336 try stack.append(State { .ExpectToken = Token.Id.RParen });
2337 try stack.append(State { .Expression = DestPtr { .NullableField = &fn_proto.align_expr } });
2338 try stack.append(State { .ExpectToken = Token.Id.LParen });
2339 }
2340
2341 continue;
2342 },
2343
2344 State.FnProtoReturnType => |fn_proto| {
2345 const token = self.getNextToken();
2346 switch (token.id) {
2347 Token.Id.Bang => {
2348 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };
2349 stack.append(State {2464 stack.append(State {
2350 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},2465 .ExpectTokenSave = ExpectTokenSave {
2466 .id = Token.Id.RParen,
2467 .ptr = &node.rparen,
2468 }
2351 }) catch unreachable;2469 }) catch unreachable;
2470 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2352 continue;2471 continue;
2353 },2472 },
2354 else => {2473 Token.Id.Builtin => {
2355 // TODO: this is a special case. Remove this when #760 is fixed2474 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeBuiltinCall,
2356 if (token.id == Token.Id.Keyword_error) {2475 ast.NodeBuiltinCall {
2357 if (self.isPeekToken(Token.Id.LBrace)) {2476 .base = undefined,
2358 fn_proto.return_type = ast.NodeFnProto.ReturnType {2477 .builtin_token = token,
2359 .Explicit = &(try self.createLiteral(arena, ast.NodeErrorType, token)).base2478 .params = ArrayList(&ast.Node).init(arena),
2360 };2479 .rparen_token = undefined,
2361 continue;
2362 }2480 }
2363 }2481 );
2364
2365 self.putBackToken(token);
2366 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
2367 stack.append(State {2482 stack.append(State {
2368 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.Explicit},2483 .ExprListItemOrEnd = ExprListCtx {
2484 .list = &node.params,
2485 .end = Token.Id.RParen,
2486 .ptr = &node.rparen_token,
2487 }
2369 }) catch unreachable;2488 }) catch unreachable;
2489 try stack.append(State { .ExpectToken = Token.Id.LParen, });
2370 continue;2490 continue;
2371 },2491 },
2372 }2492 Token.Id.LBracket => {
2373 },2493 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp,
23742494 ast.NodePrefixOp {
2375 State.ParamDecl => |fn_proto| {2495 .base = undefined,
2376 if (self.eatToken(Token.Id.RParen)) |_| {2496 .op_token = token,
2377 continue;2497 .op = undefined,
2378 }2498 .rhs = undefined,
2379 const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.NodeParamDecl,2499 }
2380 ast.NodeParamDecl {2500 );
2381 .base = undefined,2501 stack.append(State { .SliceOrArrayType = node }) catch unreachable;
2382 .comptime_token = null,
2383 .noalias_token = null,
2384 .name_token = null,
2385 .type_node = undefined,
2386 .var_args_token = null,
2387 },2502 },
2388 );2503 Token.Id.Keyword_error => {
2389 if (self.eatToken(Token.Id.Keyword_comptime)) |comptime_token| {2504 stack.append(State {
2390 param_decl.comptime_token = comptime_token;2505 .ErrorTypeOrSetDecl = ErrorTypeOrSetDeclCtx {
2391 } else if (self.eatToken(Token.Id.Keyword_noalias)) |noalias_token| {2506 .error_token = token,
2392 param_decl.noalias_token = noalias_token;2507 .opt_ctx = opt_ctx
2393 }2508 }
2394 if (self.eatToken(Token.Id.Identifier)) |identifier| {2509 }) catch unreachable;
2395 if (self.eatToken(Token.Id.Colon)) |_| {2510 },
2396 param_decl.name_token = identifier;2511 Token.Id.Keyword_packed => {
2397 } else {2512 stack.append(State {
2398 self.putBackToken(identifier);2513 .ContainerExtern = ContainerExternCtx {
2399 }2514 .opt_ctx = opt_ctx,
2400 }2515 .ltoken = token,
2401 if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| {2516 .layout = ast.NodeContainerDecl.Layout.Packed,
2402 param_decl.var_args_token = ellipsis3;2517 },
2403 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;2518 }) catch unreachable;
2404 continue;2519 },
2405 }2520 Token.Id.Keyword_extern => {
24062521 // TODO: Here, we eat two tokens in the same state. This prevents comments
2407 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;2522 // from being between these two tokens.
2408 try stack.append(State.ParamDeclComma);2523 const next = self.getNextToken();
2409 try stack.append(State {2524 if (next.id == Token.Id.Keyword_fn) {
2410 .TypeExprBegin = DestPtr {.Field = &param_decl.type_node}2525 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2411 });2526 ast.NodeFnProto {
2412 continue;2527 .base = undefined,
2413 },2528 .visib_token = null,
2529 .name_token = null,
2530 .fn_token = next,
2531 .params = ArrayList(&ast.Node).init(arena),
2532 .return_type = undefined,
2533 .var_args_token = null,
2534 .extern_export_inline_token = token,
2535 .cc_token = null,
2536 .async_attr = null,
2537 .body_node = null,
2538 .lib_name = null,
2539 .align_expr = null,
2540 }
2541 );
2542 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2543 continue;
2544 }
24142545
2415 State.ParamDeclComma => {2546 self.putBackToken(next);
2416 const token = self.getNextToken();2547 stack.append(State {
2417 switch (token.id) {2548 .ContainerExtern = ContainerExternCtx {
2418 Token.Id.RParen => {2549 .opt_ctx = opt_ctx,
2419 _ = stack.pop(); // pop off the ParamDecl2550 .ltoken = token,
2420 continue;2551 .layout = ast.NodeContainerDecl.Layout.Extern,
2552 },
2553 }) catch unreachable;
2421 },2554 },
2422 Token.Id.Comma => continue,2555 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
2423 else => {2556 self.putBackToken(token);
2424 try self.parseError(&stack, token, "expected ',' or ')', found {}", @tagName(token.id));2557 stack.append(State {
2425 continue;2558 .ContainerExtern = ContainerExternCtx {
2559 .opt_ctx = opt_ctx,
2560 .ltoken = token,
2561 .layout = ast.NodeContainerDecl.Layout.Auto,
2562 },
2563 }) catch unreachable;
2426 },2564 },
2427 }2565 Token.Id.Identifier => {
2428 },2566 // TODO: Here, we eat two tokens in the same state. This prevents comments
2567 // from being between these two tokens.
2568 const next = self.getNextToken();
2569 if (next.id != Token.Id.Colon) {
2570 self.putBackToken(next);
2571 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeIdentifier, token)).base);
2572 continue;
2573 }
24292574
2430 State.FnDef => |fn_proto| {2575 stack.append(State {
2431 const token = self.getNextToken();2576 .LabeledExpression = LabelCtx {
2432 switch(token.id) {2577 .label = token,
2433 Token.Id.LBrace => {2578 .opt_ctx = opt_ctx
2434 const block = try self.createNode(arena, ast.NodeBlock,2579 }
2435 ast.NodeBlock {2580 }) catch unreachable;
2581 continue;
2582 },
2583 Token.Id.Keyword_fn => {
2584 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2585 ast.NodeFnProto {
2436 .base = undefined,2586 .base = undefined,
2437 .label = null,2587 .visib_token = null,
2438 .lbrace = token,2588 .name_token = null,
2439 .statements = ArrayList(&ast.Node).init(arena),2589 .fn_token = token,
2440 .rbrace = undefined,2590 .params = ArrayList(&ast.Node).init(arena),
2591 .return_type = undefined,
2592 .var_args_token = null,
2593 .extern_export_inline_token = null,
2594 .cc_token = null,
2595 .async_attr = null,
2596 .body_node = null,
2597 .lib_name = null,
2598 .align_expr = null,
2441 }2599 }
2442 );2600 );
2443 fn_proto.body_node = &block.base;2601 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2444 stack.append(State { .Block = block }) catch unreachable;
2445 continue;2602 continue;
2446 },2603 },
2447 Token.Id.Semicolon => continue,2604 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2448 else => {2605 const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto,
2449 try self.parseError(&stack, token, "expected ';' or '{{', found {}", @tagName(token.id));2606 ast.NodeFnProto {
2607 .base = undefined,
2608 .visib_token = null,
2609 .name_token = null,
2610 .fn_token = undefined,
2611 .params = ArrayList(&ast.Node).init(arena),
2612 .return_type = undefined,
2613 .var_args_token = null,
2614 .extern_export_inline_token = null,
2615 .cc_token = token,
2616 .async_attr = null,
2617 .body_node = null,
2618 .lib_name = null,
2619 .align_expr = null,
2620 }
2621 );
2622 stack.append(State { .FnProto = fn_proto }) catch unreachable;
2623 try stack.append(State {
2624 .ExpectTokenSave = ExpectTokenSave {
2625 .id = Token.Id.Keyword_fn,
2626 .ptr = &fn_proto.fn_token
2627 }
2628 });
2450 continue;2629 continue;
2451 },2630 },
2452 }2631 Token.Id.Keyword_asm => {
2453 },2632 const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeAsm,
24542633 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,2634 .base = undefined,
2462 .label = ctx.label,2635 .asm_token = token,
2463 .lbrace = token,2636 .volatile_token = null,
2464 .statements = ArrayList(&ast.Node).init(arena),2637 .template = undefined,
2465 .rbrace = undefined,2638 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
2639 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
2640 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
2641 .cloppers = ArrayList(&ast.Node).init(arena),
2642 .rparen = undefined,
2466 }2643 }
2467 );2644 );
2468 stack.append(State { .Block = block }) catch unreachable;
2469 continue;
2470 },
2471 Token.Id.Keyword_while => {
2472 stack.append(State {2645 stack.append(State {
2473 .While = LoopCtx {2646 .ExpectTokenSave = ExpectTokenSave {
2474 .label = ctx.label,2647 .id = Token.Id.RParen,
2475 .inline_token = null,2648 .ptr = &node.rparen,
2476 .loop_token = token,
2477 .dest_ptr = ctx.dest_ptr,
2478 }2649 }
2479 }) catch unreachable;2650 }) catch unreachable;
2480 continue;2651 try stack.append(State { .AsmClopperItems = &node.cloppers });
2481 },2652 try stack.append(State { .IfToken = Token.Id.Colon });
2482 Token.Id.Keyword_for => {2653 try stack.append(State { .AsmInputItems = &node.inputs });
2483 stack.append(State {2654 try stack.append(State { .IfToken = Token.Id.Colon });
2484 .For = LoopCtx {2655 try stack.append(State { .AsmOutputItems = &node.outputs });
2485 .label = ctx.label,2656 try stack.append(State { .IfToken = Token.Id.Colon });
2486 .inline_token = null,2657 try stack.append(State { .StringLiteral = OptionalCtx { .Required = &node.template } });
2487 .loop_token = token,2658 try stack.append(State { .ExpectToken = Token.Id.LParen });
2488 .dest_ptr = ctx.dest_ptr,2659 try stack.append(State {
2660 .OptionalTokenSave = OptionalTokenSave {
2661 .id = Token.Id.Keyword_volatile,
2662 .ptr = &node.volatile_token,
2489 }2663 }
2490 }) catch unreachable;2664 });
2491 continue;
2492 },2665 },
2493 Token.Id.Keyword_inline => {2666 Token.Id.Keyword_inline => {
2494 stack.append(State {2667 stack.append(State {
2495 .Inline = InlineCtx {2668 .Inline = InlineCtx {
2496 .label = ctx.label,2669 .label = null,
2497 .inline_token = token,2670 .inline_token = token,
2498 .dest_ptr = ctx.dest_ptr,2671 .opt_ctx = opt_ctx,
2499 }2672 }
2500 }) catch unreachable;2673 }) catch unreachable;
2501 continue;2674 continue;
2502 },2675 },
2503 else => {2676 else => {
2504 try self.parseError(&stack, token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id));2677 if (!try self.parseBlockExpr(&stack, arena, opt_ctx, token)) {
2678 self.putBackToken(token);
2679 if (opt_ctx != OptionalCtx.Optional) {
2680 return self.parseError(token, "expected primary expression, found {}", @tagName(token.id));
2681 }
2682 }
2505 continue;2683 continue;
2506 },2684 }
2507 }2685 }
2508 },2686 },
25092687
2510 State.Inline => |ctx| {2688
2511 const token = self.getNextToken();2689 State.ErrorTypeOrSetDecl => |ctx| {
2512 switch (token.id) {2690 if (self.eatToken(Token.Id.LBrace) == null) {
2513 Token.Id.Keyword_while => {2691 ctx.opt_ctx.store(&(try self.createLiteral(arena, ast.NodeErrorType, ctx.error_token)).base);
2514 stack.append(State {2692 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 }2693 }
2540 },
25412694
2542 State.While => |ctx| {2695 const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeErrorSetDecl,
2543 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeWhile,2696 ast.NodeErrorSetDecl {
2544 ast.NodeWhile {
2545 .base = undefined,2697 .base = undefined,
2546 .label = ctx.label,2698 .error_token = ctx.error_token,
2547 .inline_token = ctx.inline_token,2699 .decls = ArrayList(&ast.Node).init(arena),
2548 .while_token = ctx.loop_token,2700 .rbrace_token = undefined,
2549 .condition = undefined,
2550 .payload = null,
2551 .continue_expr = null,
2552 .body = undefined,
2553 .@"else" = null,
2554 }2701 }
2555 );2702 );
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 },
25642703
2565 State.For => |ctx| {2704 stack.append(State {
2566 const node = try self.createToDestNode(arena, ctx.dest_ptr, ast.NodeFor,2705 .IdentifierListItemOrEnd = ListSave(&ast.Node) {
2567 ast.NodeFor {2706 .list = &node.decls,
2568 .base = undefined,2707 .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 }2708 }
2577 );2709 }) catch unreachable;
2578 stack.append(State { .Else = &node.@"else" }) catch unreachable;2710 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 },2711 },
25852712 State.StringLiteral => |opt_ctx| {
2586 State.Block => |block| {
2587 const token = self.getNextToken();2713 const token = self.getNextToken();
2588 switch (token.id) {2714 opt_ctx.store(
2589 Token.Id.RBrace => {2715 (try self.parseStringLiteral(arena, token)) ?? {
2590 block.rbrace = token;
2591 continue;
2592 },
2593 else => {
2594 self.putBackToken(token);2716 self.putBackToken(token);
2595 stack.append(State { .Block = block }) catch unreachable;2717 if (opt_ctx != OptionalCtx.Optional) {
2596 try stack.append(State { .Statement = block });2718 return self.parseError(token, "expected primary expression, found {}", @tagName(token.id));
2719 }
2720
2597 continue;2721 continue;
2598 },2722 }
2723 );
2724 },
2725 State.Identifier => |opt_ctx| {
2726 if (self.eatToken(Token.Id.Identifier)) |ident_token| {
2727 opt_ctx.store(&(try self.createLiteral(arena, ast.NodeIdentifier, ident_token)).base);
2728 continue;
2729 }
2730
2731 if (opt_ctx != OptionalCtx.Optional) {
2732 const token = self.getNextToken();
2733 return self.parseError(token, "expected identifier, found {}", @tagName(token.id));
2599 }2734 }
2600 },2735 },
26012736
2602 State.Statement => |block| {2737
2603 const next = self.getNextToken();2738 State.ExpectToken => |token_id| {
2604 switch (next.id) {2739 _ = try self.expectToken(token_id);
2605 Token.Id.Keyword_comptime => {2740 continue;
2606 const mut_token = self.getNextToken();2741 },
2607 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {2742 State.ExpectTokenSave => |expect_token_save| {
2608 const var_decl = try self.createAttachNode(arena, &block.statements, ast.NodeVarDecl,2743 *expect_token_save.ptr = try self.expectToken(expect_token_save.id);
2609 ast.NodeVarDecl {2744 continue;
2610 .base = undefined,2745 },
2611 .visib_token = null,2746 State.IfToken => |token_id| {
2612 .mut_token = mut_token,2747 if (self.eatToken(token_id)) |_| {
2613 .comptime_token = next,2748 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 }2749 }
26942750
2751 _ = stack.pop();
2752 continue;
2695 },2753 },
2754 State.IfTokenSave => |if_token_save| {
2755 if (self.eatToken(if_token_save.id)) |token| {
2756 *if_token_save.ptr = token;
2757 continue;
2758 }
26962759
2697 State.Semicolon => |node_ptr| {2760 _ = stack.pop();
2698 const node = *node_ptr;2761 continue;
2699 if (requireSemiColon(node)) {2762 },
2700 _ = (try self.expectToken(&stack, Token.Id.Semicolon)) ?? continue;2763 State.OptionalTokenSave => |optional_token_save| {
2764 if (self.eatToken(optional_token_save.id)) |token| {
2765 *optional_token_save.ptr = token;
2766 continue;
2701 }2767 }
2702 }2768
2769 continue;
2770 },
2703 }2771 }
2704 }2772 }
2705 }2773 }
...@@ -2807,10 +2875,10 @@ pub const Parser = struct {...@@ -2807,10 +2875,10 @@ pub const Parser = struct {
2807 }2875 }
2808 }2876 }
28092877
2810 fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, dest_ptr: &const DestPtr, token: &const Token) !bool {2878 fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token: &const Token) !bool {
2811 switch (token.id) {2879 switch (token.id) {
2812 Token.Id.Keyword_suspend => {2880 Token.Id.Keyword_suspend => {
2813 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSuspend,2881 const node = try self.createToCtxNode(arena, ctx, ast.NodeSuspend,
2814 ast.NodeSuspend {2882 ast.NodeSuspend {
2815 .base = undefined,2883 .base = undefined,
2816 .suspend_token = *token,2884 .suspend_token = *token,
...@@ -2820,11 +2888,11 @@ pub const Parser = struct {...@@ -2820,11 +2888,11 @@ pub const Parser = struct {
2820 );2888 );
28212889
2822 stack.append(State { .SuspendBody = node }) catch unreachable;2890 stack.append(State { .SuspendBody = node }) catch unreachable;
2823 try stack.append(State { .Payload = &node.payload });2891 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
2824 return true;2892 return true;
2825 },2893 },
2826 Token.Id.Keyword_if => {2894 Token.Id.Keyword_if => {
2827 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeIf,2895 const node = try self.createToCtxNode(arena, ctx, ast.NodeIf,
2828 ast.NodeIf {2896 ast.NodeIf {
2829 .base = undefined,2897 .base = undefined,
2830 .if_token = *token,2898 .if_token = *token,
...@@ -2836,10 +2904,10 @@ pub const Parser = struct {...@@ -2836,10 +2904,10 @@ pub const Parser = struct {
2836 );2904 );
28372905
2838 stack.append(State { .Else = &node.@"else" }) catch unreachable;2906 stack.append(State { .Else = &node.@"else" }) catch unreachable;
2839 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });2907 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
2840 try stack.append(State { .PointerPayload = &node.payload });2908 try stack.append(State { .PointerPayload = OptionalCtx { .Optional = &node.payload } });
2841 try stack.append(State { .ExpectToken = Token.Id.RParen });2909 try stack.append(State { .ExpectToken = Token.Id.RParen });
2842 try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });2910 try stack.append(State { .Expression = OptionalCtx { .Required = &node.condition } });
2843 try stack.append(State { .ExpectToken = Token.Id.LParen });2911 try stack.append(State { .ExpectToken = Token.Id.LParen });
2844 return true;2912 return true;
2845 },2913 },
...@@ -2849,7 +2917,7 @@ pub const Parser = struct {...@@ -2849,7 +2917,7 @@ pub const Parser = struct {
2849 .label = null,2917 .label = null,
2850 .inline_token = null,2918 .inline_token = null,
2851 .loop_token = *token,2919 .loop_token = *token,
2852 .dest_ptr = *dest_ptr,2920 .opt_ctx = *ctx,
2853 }2921 }
2854 }) catch unreachable;2922 }) catch unreachable;
2855 return true;2923 return true;
...@@ -2860,13 +2928,13 @@ pub const Parser = struct {...@@ -2860,13 +2928,13 @@ pub const Parser = struct {
2860 .label = null,2928 .label = null,
2861 .inline_token = null,2929 .inline_token = null,
2862 .loop_token = *token,2930 .loop_token = *token,
2863 .dest_ptr = *dest_ptr,2931 .opt_ctx = *ctx,
2864 }2932 }
2865 }) catch unreachable;2933 }) catch unreachable;
2866 return true;2934 return true;
2867 },2935 },
2868 Token.Id.Keyword_switch => {2936 Token.Id.Keyword_switch => {
2869 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeSwitch,2937 const node = try self.createToCtxNode(arena, ctx, ast.NodeSwitch,
2870 ast.NodeSwitch {2938 ast.NodeSwitch {
2871 .base = undefined,2939 .base = undefined,
2872 .switch_token = *token,2940 .switch_token = *token,
...@@ -2884,23 +2952,23 @@ pub const Parser = struct {...@@ -2884,23 +2952,23 @@ pub const Parser = struct {
2884 }) catch unreachable;2952 }) catch unreachable;
2885 try stack.append(State { .ExpectToken = Token.Id.LBrace });2953 try stack.append(State { .ExpectToken = Token.Id.LBrace });
2886 try stack.append(State { .ExpectToken = Token.Id.RParen });2954 try stack.append(State { .ExpectToken = Token.Id.RParen });
2887 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });2955 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2888 try stack.append(State { .ExpectToken = Token.Id.LParen });2956 try stack.append(State { .ExpectToken = Token.Id.LParen });
2889 return true;2957 return true;
2890 },2958 },
2891 Token.Id.Keyword_comptime => {2959 Token.Id.Keyword_comptime => {
2892 const node = try self.createToDestNode(arena, dest_ptr, ast.NodeComptime,2960 const node = try self.createToCtxNode(arena, ctx, ast.NodeComptime,
2893 ast.NodeComptime {2961 ast.NodeComptime {
2894 .base = undefined,2962 .base = undefined,
2895 .comptime_token = *token,2963 .comptime_token = *token,
2896 .expr = undefined,2964 .expr = undefined,
2897 }2965 }
2898 );2966 );
2899 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });2967 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
2900 return true;2968 return true;
2901 },2969 },
2902 Token.Id.LBrace => {2970 Token.Id.LBrace => {
2903 const block = try self.createToDestNode(arena, dest_ptr, ast.NodeBlock,2971 const block = try self.createToCtxNode(arena, ctx, ast.NodeBlock,
2904 ast.NodeBlock {2972 ast.NodeBlock {
2905 .base = undefined,2973 .base = undefined,
2906 .label = null,2974 .label = null,
...@@ -2933,7 +3001,7 @@ pub const Parser = struct {...@@ -2933,7 +3001,7 @@ pub const Parser = struct {
2933 return;3001 return;
2934 }3002 }
29353003
2936 try self.parseError(stack, token, "expected ',' or {}, found {}", @tagName(*end), @tagName(token.id));3004 return self.parseError(token, "expected ',' or {}, found {}", @tagName(*end), @tagName(token.id));
2937 },3005 },
2938 }3006 }
2939 }3007 }
...@@ -3049,9 +3117,9 @@ pub const Parser = struct {...@@ -3049,9 +3117,9 @@ pub const Parser = struct {
3049 return node;3117 return node;
3050 }3118 }
30513119
3052 fn createToDestNode(self: &Parser, arena: &mem.Allocator, dest_ptr: &const DestPtr, comptime T: type, init_to: &const T) !&T {3120 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);3121 const node = try self.createNode(arena, T, init_to);
3054 dest_ptr.store(&node.base);3122 opt_ctx.store(&node.base);
30553123
3056 return node;3124 return node;
3057 }3125 }
...@@ -3065,51 +3133,31 @@ pub const Parser = struct {...@@ -3065,51 +3133,31 @@ pub const Parser = struct {
3065 );3133 );
3066 }3134 }
30673135
3068 fn parseError(self: &Parser, stack: &ArrayList(State), token: &const Token, comptime fmt: []const u8, args: ...) !void {3136 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
3069 // Before reporting an error. We pop the stack to see if our state was optional3137 const loc = self.tokenizer.getTokenLocation(0, token);
3070 self.revertIfOptional(stack) catch {3138 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
3071 const loc = self.tokenizer.getTokenLocation(0, token);3139 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
3072 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);3140 {
3073 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);3141 var i: usize = 0;
3074 {3142 while (i < loc.column) : (i += 1) {
3075 var i: usize = 0;3143 warn(" ");
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 }3144 }
3087 warn("\n");3145 }
3088 return error.ParseError;3146 {
3089 };3147 const caret_count = token.end - token.start;
3090 }3148 var i: usize = 0;
30913149 while (i < caret_count) : (i += 1) {
3092 fn revertIfOptional(self: &Parser, stack: &ArrayList(State)) !void {3150 warn("~");
3093 while (stack.popOrNull()) |state| {
3094 switch (state) {
3095 State.Optional => |revert| {
3096 *self = revert.parser;
3097 *self.tokenizer = revert.tokenizer;
3098 *revert.ptr = null;
3099 return;
3100 },
3101 else => { }
3102 }3151 }
3103 }3152 }
31043153 warn("\n");
3105 return error.NoOptionalStateFound;3154 return error.ParseError;
3106 }3155 }
31073156
3108 fn expectToken(self: &Parser, stack: &ArrayList(State), id: @TagType(Token.Id)) !?Token {3157 fn expectToken(self: &Parser, id: @TagType(Token.Id)) !Token {
3109 const token = self.getNextToken();3158 const token = self.getNextToken();
3110 if (token.id != id) {3159 if (token.id != id) {
3111 try self.parseError(stack, token, "expected {}, found {}", @tagName(id), @tagName(token.id));3160 return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));
3112 return null;
3113 }3161 }
3114 return token;3162 return token;
3115 }3163 }
...@@ -3424,7 +3472,7 @@ pub const Parser = struct {...@@ -3424,7 +3472,7 @@ pub const Parser = struct {
3424 }3472 }
34253473
3426 if (suspend_node.payload) |payload| {3474 if (suspend_node.payload) |payload| {
3427 try stack.append(RenderState { .Expression = &payload.base });3475 try stack.append(RenderState { .Expression = payload });
3428 try stack.append(RenderState { .Text = " " });3476 try stack.append(RenderState { .Text = " " });
3429 }3477 }
3430 },3478 },
...@@ -3435,7 +3483,7 @@ pub const Parser = struct {...@@ -3435,7 +3483,7 @@ pub const Parser = struct {
3435 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {3483 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {
3436 if (prefix_op_node.op.Catch) |payload| {3484 if (prefix_op_node.op.Catch) |payload| {
3437 try stack.append(RenderState { .Text = " " });3485 try stack.append(RenderState { .Text = " " });
3438 try stack.append(RenderState { .Expression = &payload.base });3486 try stack.append(RenderState { .Expression = payload });
3439 }3487 }
3440 try stack.append(RenderState { .Text = " catch " });3488 try stack.append(RenderState { .Text = " catch " });
3441 } else {3489 } else {
...@@ -3612,17 +3660,25 @@ pub const Parser = struct {...@@ -3612,17 +3660,25 @@ pub const Parser = struct {
3612 },3660 },
3613 ast.Node.Id.ControlFlowExpression => {3661 ast.Node.Id.ControlFlowExpression => {
3614 const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base);3662 const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base);
3663
3664 if (flow_expr.rhs) |rhs| {
3665 try stack.append(RenderState { .Expression = rhs });
3666 try stack.append(RenderState { .Text = " " });
3667 }
3668
3615 switch (flow_expr.kind) {3669 switch (flow_expr.kind) {
3616 ast.NodeControlFlowExpression.Kind.Break => |maybe_blk_token| {3670 ast.NodeControlFlowExpression.Kind.Break => |maybe_label| {
3617 try stream.print("break");3671 try stream.print("break");
3618 if (maybe_blk_token) |blk_token| {3672 if (maybe_label) |label| {
3619 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));3673 try stream.print(" :");
3674 try stack.append(RenderState { .Expression = label });
3620 }3675 }
3621 },3676 },
3622 ast.NodeControlFlowExpression.Kind.Continue => |maybe_blk_token| {3677 ast.NodeControlFlowExpression.Kind.Continue => |maybe_label| {
3623 try stream.print("continue");3678 try stream.print("continue");
3624 if (maybe_blk_token) |blk_token| {3679 if (maybe_label) |label| {
3625 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));3680 try stream.print(" :");
3681 try stack.append(RenderState { .Expression = label });
3626 }3682 }
3627 },3683 },
3628 ast.NodeControlFlowExpression.Kind.Return => {3684 ast.NodeControlFlowExpression.Kind.Return => {
...@@ -3630,25 +3686,20 @@ pub const Parser = struct {...@@ -3630,25 +3686,20 @@ pub const Parser = struct {
3630 },3686 },
36313687
3632 }3688 }
3633
3634 if (flow_expr.rhs) |rhs| {
3635 try stream.print(" ");
3636 try stack.append(RenderState { .Expression = rhs });
3637 }
3638 },3689 },
3639 ast.Node.Id.Payload => {3690 ast.Node.Id.Payload => {
3640 const payload = @fieldParentPtr(ast.NodePayload, "base", base);3691 const payload = @fieldParentPtr(ast.NodePayload, "base", base);
3641 try stack.append(RenderState { .Text = "|"});3692 try stack.append(RenderState { .Text = "|"});
3642 try stack.append(RenderState { .Expression = &payload.error_symbol.base });3693 try stack.append(RenderState { .Expression = payload.error_symbol });
3643 try stack.append(RenderState { .Text = "|"});3694 try stack.append(RenderState { .Text = "|"});
3644 },3695 },
3645 ast.Node.Id.PointerPayload => {3696 ast.Node.Id.PointerPayload => {
3646 const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base);3697 const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base);
3647 try stack.append(RenderState { .Text = "|"});3698 try stack.append(RenderState { .Text = "|"});
3648 try stack.append(RenderState { .Expression = &payload.value_symbol.base });3699 try stack.append(RenderState { .Expression = payload.value_symbol });
36493700
3650 if (payload.is_ptr) {3701 if (payload.ptr_token) |ptr_token| {
3651 try stack.append(RenderState { .Text = "*"});3702 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(ptr_token) });
3652 }3703 }
36533704
3654 try stack.append(RenderState { .Text = "|"});3705 try stack.append(RenderState { .Text = "|"});
...@@ -3658,14 +3709,14 @@ pub const Parser = struct {...@@ -3658,14 +3709,14 @@ pub const Parser = struct {
3658 try stack.append(RenderState { .Text = "|"});3709 try stack.append(RenderState { .Text = "|"});
36593710
3660 if (payload.index_symbol) |index_symbol| {3711 if (payload.index_symbol) |index_symbol| {
3661 try stack.append(RenderState { .Expression = &index_symbol.base });3712 try stack.append(RenderState { .Expression = index_symbol });
3662 try stack.append(RenderState { .Text = ", "});3713 try stack.append(RenderState { .Text = ", "});
3663 }3714 }
36643715
3665 try stack.append(RenderState { .Expression = &payload.value_symbol.base });3716 try stack.append(RenderState { .Expression = payload.value_symbol });
36663717
3667 if (payload.is_ptr) {3718 if (payload.ptr_token) |ptr_token| {
3668 try stack.append(RenderState { .Text = "*"});3719 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(ptr_token) });
3669 }3720 }
36703721
3671 try stack.append(RenderState { .Text = "|"});3722 try stack.append(RenderState { .Text = "|"});
...@@ -3800,7 +3851,7 @@ pub const Parser = struct {...@@ -3800,7 +3851,7 @@ pub const Parser = struct {
3800 while (i != 0) {3851 while (i != 0) {
3801 i -= 1;3852 i -= 1;
3802 const node = decls[i];3853 const node = decls[i];
3803 try stack.append(RenderState { .Expression = &node.base});3854 try stack.append(RenderState { .Expression = node });
3804 try stack.append(RenderState.PrintIndent);3855 try stack.append(RenderState.PrintIndent);
3805 try stack.append(RenderState {3856 try stack.append(RenderState {
3806 .Text = blk: {3857 .Text = blk: {
...@@ -3959,7 +4010,7 @@ pub const Parser = struct {...@@ -3959,7 +4010,7 @@ pub const Parser = struct {
3959 try stack.append(RenderState { .Expression = switch_case.expr });4010 try stack.append(RenderState { .Expression = switch_case.expr });
3960 if (switch_case.payload) |payload| {4011 if (switch_case.payload) |payload| {
3961 try stack.append(RenderState { .Text = " " });4012 try stack.append(RenderState { .Text = " " });
3962 try stack.append(RenderState { .Expression = &payload.base });4013 try stack.append(RenderState { .Expression = payload });
3963 }4014 }
3964 try stack.append(RenderState { .Text = " => "});4015 try stack.append(RenderState { .Text = " => "});
39654016
...@@ -4000,7 +4051,7 @@ pub const Parser = struct {...@@ -4000,7 +4051,7 @@ pub const Parser = struct {
40004051
4001 if (else_node.payload) |payload| {4052 if (else_node.payload) |payload| {
4002 try stack.append(RenderState { .Text = " " });4053 try stack.append(RenderState { .Text = " " });
4003 try stack.append(RenderState { .Expression = &payload.base });4054 try stack.append(RenderState { .Expression = payload });
4004 }4055 }
4005 },4056 },
4006 ast.Node.Id.While => {4057 ast.Node.Id.While => {
...@@ -4045,7 +4096,7 @@ pub const Parser = struct {...@@ -4045,7 +4096,7 @@ pub const Parser = struct {
4045 }4096 }
40464097
4047 if (while_node.payload) |payload| {4098 if (while_node.payload) |payload| {
4048 try stack.append(RenderState { .Expression = &payload.base });4099 try stack.append(RenderState { .Expression = payload });
4049 try stack.append(RenderState { .Text = " " });4100 try stack.append(RenderState { .Text = " " });
4050 }4101 }
40514102
...@@ -4088,7 +4139,7 @@ pub const Parser = struct {...@@ -4088,7 +4139,7 @@ pub const Parser = struct {
4088 }4139 }
40894140
4090 if (for_node.payload) |payload| {4141 if (for_node.payload) |payload| {
4091 try stack.append(RenderState { .Expression = &payload.base });4142 try stack.append(RenderState { .Expression = payload });
4092 try stack.append(RenderState { .Text = " " });4143 try stack.append(RenderState { .Text = " " });
4093 }4144 }
40944145
...@@ -4121,7 +4172,7 @@ pub const Parser = struct {...@@ -4121,7 +4172,7 @@ pub const Parser = struct {
41214172
4122 if (@"else".payload) |payload| {4173 if (@"else".payload) |payload| {
4123 try stack.append(RenderState { .Text = " " });4174 try stack.append(RenderState { .Text = " " });
4124 try stack.append(RenderState { .Expression = &payload.base });4175 try stack.append(RenderState { .Expression = payload });
4125 }4176 }
41264177
4127 try stack.append(RenderState { .Text = " " });4178 try stack.append(RenderState { .Text = " " });
...@@ -4135,7 +4186,7 @@ pub const Parser = struct {...@@ -4135,7 +4186,7 @@ pub const Parser = struct {
4135 try stack.append(RenderState { .Text = " " });4186 try stack.append(RenderState { .Text = " " });
41364187
4137 if (if_node.payload) |payload| {4188 if (if_node.payload) |payload| {
4138 try stack.append(RenderState { .Expression = &payload.base });4189 try stack.append(RenderState { .Expression = payload });
4139 try stack.append(RenderState { .Text = " " });4190 try stack.append(RenderState { .Text = " " });
4140 }4191 }
41414192
...@@ -4147,8 +4198,8 @@ pub const Parser = struct {...@@ -4147,8 +4198,8 @@ pub const Parser = struct {
4147 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);4198 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);
4148 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));4199 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));
41494200
4150 if (asm_node.is_volatile) {4201 if (asm_node.volatile_token) |volatile_token| {
4151 try stream.write("volatile ");4202 try stream.print("{} ", self.tokenizer.getTokenSlice(volatile_token));
4152 }4203 }
41534204
4154 try stack.append(RenderState { .Indent = indent });4205 try stack.append(RenderState { .Indent = indent });
...@@ -4238,7 +4289,7 @@ pub const Parser = struct {...@@ -4238,7 +4289,7 @@ pub const Parser = struct {
4238 try stack.append(RenderState { .Text = " ("});4289 try stack.append(RenderState { .Text = " ("});
4239 try stack.append(RenderState { .Expression = asm_input.constraint });4290 try stack.append(RenderState { .Expression = asm_input.constraint });
4240 try stack.append(RenderState { .Text = "] "});4291 try stack.append(RenderState { .Text = "] "});
4241 try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});4292 try stack.append(RenderState { .Expression = asm_input.symbolic_name });
4242 try stack.append(RenderState { .Text = "["});4293 try stack.append(RenderState { .Text = "["});
4243 },4294 },
4244 ast.Node.Id.AsmOutput => {4295 ast.Node.Id.AsmOutput => {
...@@ -4257,7 +4308,7 @@ pub const Parser = struct {...@@ -4257,7 +4308,7 @@ pub const Parser = struct {
4257 try stack.append(RenderState { .Text = " ("});4308 try stack.append(RenderState { .Text = " ("});
4258 try stack.append(RenderState { .Expression = asm_output.constraint });4309 try stack.append(RenderState { .Expression = asm_output.constraint });
4259 try stack.append(RenderState { .Text = "] "});4310 try stack.append(RenderState { .Text = "] "});
4260 try stack.append(RenderState { .Expression = &asm_output.symbolic_name.base});4311 try stack.append(RenderState { .Expression = asm_output.symbolic_name });
4261 try stack.append(RenderState { .Text = "["});4312 try stack.append(RenderState { .Text = "["});
4262 },4313 },
42634314