authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-04-10 22:47:18-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-04-10 22:47:18-04:00
log64d96ad70360a82ec1a441fc28ddbb3f513995be
treeb19f1ae0ecc6e835f8665390b1d83b99e67f6d44
parentee3e2790aa85c624fc952bc8326b82d72843bb17
parent405a2390f09c78fb5db435e97d8ff23c0b44753b
signature Signed by PGP key 4AEE18F83AFDEB23

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

Self hosted parser completion

4 files changed, 5291 insertions(+), 644 deletions(-)

std/special/builtin.zig+25-8
...@@ -14,26 +14,43 @@ pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn...@@ -14,26 +14,43 @@ pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn
14 }14 }
15}15}
1616
17// Note that memset does not return `dest`, like the libc API.17export fn memset(dest: ?&u8, c: u8, n: usize) ?&u8 {
18// The semantics of memset is dictated by the corresponding
19// LLVM intrinsics, not by the libc API.
20export fn memset(dest: ?&u8, c: u8, n: usize) void {
21 @setRuntimeSafety(false);18 @setRuntimeSafety(false);
2219
23 var index: usize = 0;20 var index: usize = 0;
24 while (index != n) : (index += 1)21 while (index != n) : (index += 1)
25 (??dest)[index] = c;22 (??dest)[index] = c;
23
24 return dest;
26}25}
2726
28// Note that memcpy does not return `dest`, like the libc API.27export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) ?&u8 {
29// The semantics of memcpy is dictated by the corresponding
30// LLVM intrinsics, not by the libc API.
31export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) void {
32 @setRuntimeSafety(false);28 @setRuntimeSafety(false);
3329
34 var index: usize = 0;30 var index: usize = 0;
35 while (index != n) : (index += 1)31 while (index != n) : (index += 1)
36 (??dest)[index] = (??src)[index];32 (??dest)[index] = (??src)[index];
33
34 return dest;
35}
36
37export fn memmove(dest: ?&u8, src: ?&const u8, n: usize) ?&u8 {
38 @setRuntimeSafety(false);
39
40 if (@ptrToInt(dest) < @ptrToInt(src)) {
41 var index: usize = 0;
42 while (index != n) : (index += 1) {
43 (??dest)[index] = (??src)[index];
44 }
45 } else {
46 var index = n;
47 while (index != 0) {
48 index -= 1;
49 (??dest)[index] = (??src)[index];
50 }
51 }
52
53 return dest;
37}54}
3855
39comptime {56comptime {
std/zig/ast.zig+1278-77
...@@ -11,18 +11,52 @@ pub const Node = struct {...@@ -11,18 +11,52 @@ pub const Node = struct {
11 pub const Id = enum {11 pub const Id = enum {
12 Root,12 Root,
13 VarDecl,13 VarDecl,
14 Use,
15 ErrorSetDecl,
16 ContainerDecl,
17 StructField,
18 UnionTag,
19 EnumTag,
14 Identifier,20 Identifier,
21 AsyncAttribute,
15 FnProto,22 FnProto,
16 ParamDecl,23 ParamDecl,
17 Block,24 Block,
25 Defer,
26 Comptime,
27 Payload,
28 PointerPayload,
29 PointerIndexPayload,
30 Else,
31 Switch,
32 SwitchCase,
33 SwitchElse,
34 While,
35 For,
36 If,
18 InfixOp,37 InfixOp,
19 PrefixOp,38 PrefixOp,
39 SuffixOp,
40 GroupedExpression,
41 ControlFlowExpression,
42 Suspend,
43 FieldInitializer,
20 IntegerLiteral,44 IntegerLiteral,
21 FloatLiteral,45 FloatLiteral,
22 StringLiteral,46 StringLiteral,
47 MultilineStringLiteral,
48 CharLiteral,
49 BoolLiteral,
50 NullLiteral,
23 UndefinedLiteral,51 UndefinedLiteral,
52 ThisLiteral,
53 Asm,
54 AsmInput,
55 AsmOutput,
56 Unreachable,
57 ErrorType,
58 VarType,
24 BuiltinCall,59 BuiltinCall,
25 Call,
26 LineComment,60 LineComment,
27 TestDecl,61 TestDecl,
28 };62 };
...@@ -31,18 +65,52 @@ pub const Node = struct {...@@ -31,18 +65,52 @@ pub const Node = struct {
31 return switch (base.id) {65 return switch (base.id) {
32 Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),66 Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),
33 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index),67 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index),
68 Id.Use => @fieldParentPtr(NodeUse, "base", base).iterate(index),
69 Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).iterate(index),
70 Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).iterate(index),
71 Id.StructField => @fieldParentPtr(NodeStructField, "base", base).iterate(index),
72 Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).iterate(index),
73 Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).iterate(index),
34 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index),74 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index),
75 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).iterate(index),
35 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),76 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
36 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),77 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
37 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),78 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
79 Id.Defer => @fieldParentPtr(NodeDefer, "base", base).iterate(index),
80 Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).iterate(index),
81 Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index),
82 Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).iterate(index),
83 Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).iterate(index),
84 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
85 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index),
86 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index),
87 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).iterate(index),
88 Id.While => @fieldParentPtr(NodeWhile, "base", base).iterate(index),
89 Id.For => @fieldParentPtr(NodeFor, "base", base).iterate(index),
90 Id.If => @fieldParentPtr(NodeIf, "base", base).iterate(index),
38 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),91 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
39 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),92 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
93 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index),
94 Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).iterate(index),
95 Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).iterate(index),
96 Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).iterate(index),
97 Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).iterate(index),
40 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),98 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
41 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),99 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
42 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),100 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).iterate(index),
101 Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).iterate(index),
102 Id.CharLiteral => @fieldParentPtr(NodeCharLiteral, "base", base).iterate(index),
103 Id.BoolLiteral => @fieldParentPtr(NodeBoolLiteral, "base", base).iterate(index),
104 Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).iterate(index),
43 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),105 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).iterate(index),
106 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).iterate(index),
107 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).iterate(index),
108 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).iterate(index),
109 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).iterate(index),
110 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).iterate(index),
111 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).iterate(index),
112 Id.VarType => @fieldParentPtr(NodeVarType, "base", base).iterate(index),
44 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),113 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
45 Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index),
46 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),114 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
47 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),115 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),
48 };116 };
...@@ -52,18 +120,52 @@ pub const Node = struct {...@@ -52,18 +120,52 @@ pub const Node = struct {
52 return switch (base.id) {120 return switch (base.id) {
53 Id.Root => @fieldParentPtr(NodeRoot, "base", base).firstToken(),121 Id.Root => @fieldParentPtr(NodeRoot, "base", base).firstToken(),
54 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).firstToken(),122 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).firstToken(),
123 Id.Use => @fieldParentPtr(NodeUse, "base", base).firstToken(),
124 Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).firstToken(),
125 Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).firstToken(),
126 Id.StructField => @fieldParentPtr(NodeStructField, "base", base).firstToken(),
127 Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).firstToken(),
128 Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).firstToken(),
55 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).firstToken(),129 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).firstToken(),
130 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).firstToken(),
56 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),131 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
57 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),132 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
58 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),133 Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(),
134 Id.Defer => @fieldParentPtr(NodeDefer, "base", base).firstToken(),
135 Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).firstToken(),
136 Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(),
137 Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).firstToken(),
138 Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).firstToken(),
139 Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
140 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(),
141 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(),
142 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).firstToken(),
143 Id.While => @fieldParentPtr(NodeWhile, "base", base).firstToken(),
144 Id.For => @fieldParentPtr(NodeFor, "base", base).firstToken(),
145 Id.If => @fieldParentPtr(NodeIf, "base", base).firstToken(),
59 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),146 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
60 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),147 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).firstToken(),
148 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(),
149 Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).firstToken(),
150 Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).firstToken(),
151 Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).firstToken(),
152 Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).firstToken(),
61 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(),153 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(),
62 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),154 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),
63 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),155 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).firstToken(),
156 Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).firstToken(),
157 Id.CharLiteral => @fieldParentPtr(NodeCharLiteral, "base", base).firstToken(),
158 Id.BoolLiteral => @fieldParentPtr(NodeBoolLiteral, "base", base).firstToken(),
159 Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).firstToken(),
64 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(),160 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).firstToken(),
161 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).firstToken(),
162 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).firstToken(),
163 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).firstToken(),
164 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).firstToken(),
165 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).firstToken(),
166 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).firstToken(),
167 Id.VarType => @fieldParentPtr(NodeVarType, "base", base).firstToken(),
65 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),168 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
66 Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(),
67 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),169 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
68 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),170 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),
69 };171 };
...@@ -73,18 +175,52 @@ pub const Node = struct {...@@ -73,18 +175,52 @@ pub const Node = struct {
73 return switch (base.id) {175 return switch (base.id) {
74 Id.Root => @fieldParentPtr(NodeRoot, "base", base).lastToken(),176 Id.Root => @fieldParentPtr(NodeRoot, "base", base).lastToken(),
75 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).lastToken(),177 Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).lastToken(),
178 Id.Use => @fieldParentPtr(NodeUse, "base", base).lastToken(),
179 Id.ErrorSetDecl => @fieldParentPtr(NodeErrorSetDecl, "base", base).lastToken(),
180 Id.ContainerDecl => @fieldParentPtr(NodeContainerDecl, "base", base).lastToken(),
181 Id.StructField => @fieldParentPtr(NodeStructField, "base", base).lastToken(),
182 Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).lastToken(),
183 Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).lastToken(),
76 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).lastToken(),184 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).lastToken(),
185 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).lastToken(),
77 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),186 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
78 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),187 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
79 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),188 Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(),
189 Id.Defer => @fieldParentPtr(NodeDefer, "base", base).lastToken(),
190 Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).lastToken(),
191 Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(),
192 Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).lastToken(),
193 Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).lastToken(),
194 Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(),
195 Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(),
196 Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(),
197 Id.SwitchElse => @fieldParentPtr(NodeSwitchElse, "base", base).lastToken(),
198 Id.While => @fieldParentPtr(NodeWhile, "base", base).lastToken(),
199 Id.For => @fieldParentPtr(NodeFor, "base", base).lastToken(),
200 Id.If => @fieldParentPtr(NodeIf, "base", base).lastToken(),
80 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),201 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
81 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),202 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).lastToken(),
203 Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(),
204 Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).lastToken(),
205 Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).lastToken(),
206 Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).lastToken(),
207 Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).lastToken(),
82 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(),208 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(),
83 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),209 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),
84 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),210 Id.StringLiteral => @fieldParentPtr(NodeStringLiteral, "base", base).lastToken(),
211 Id.MultilineStringLiteral => @fieldParentPtr(NodeMultilineStringLiteral, "base", base).lastToken(),
212 Id.CharLiteral => @fieldParentPtr(NodeCharLiteral, "base", base).lastToken(),
213 Id.BoolLiteral => @fieldParentPtr(NodeBoolLiteral, "base", base).lastToken(),
214 Id.NullLiteral => @fieldParentPtr(NodeNullLiteral, "base", base).lastToken(),
85 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),215 Id.UndefinedLiteral => @fieldParentPtr(NodeUndefinedLiteral, "base", base).lastToken(),
216 Id.ThisLiteral => @fieldParentPtr(NodeThisLiteral, "base", base).lastToken(),
217 Id.Asm => @fieldParentPtr(NodeAsm, "base", base).lastToken(),
218 Id.AsmInput => @fieldParentPtr(NodeAsmInput, "base", base).lastToken(),
219 Id.AsmOutput => @fieldParentPtr(NodeAsmOutput, "base", base).lastToken(),
220 Id.Unreachable => @fieldParentPtr(NodeUnreachable, "base", base).lastToken(),
221 Id.ErrorType => @fieldParentPtr(NodeErrorType, "base", base).lastToken(),
222 Id.VarType => @fieldParentPtr(NodeVarType, "base", base).lastToken(),
86 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),223 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
87 Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(),
88 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),224 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
89 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),225 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
90 };226 };
...@@ -160,6 +296,190 @@ pub const NodeVarDecl = struct {...@@ -160,6 +296,190 @@ pub const NodeVarDecl = struct {
160 }296 }
161};297};
162298
299pub const NodeUse = struct {
300 base: Node,
301 visib_token: ?Token,
302 expr: &Node,
303 semicolon_token: Token,
304
305 pub fn iterate(self: &NodeUse, index: usize) ?&Node {
306 var i = index;
307
308 if (i < 1) return self.expr;
309 i -= 1;
310
311 return null;
312 }
313
314 pub fn firstToken(self: &NodeUse) Token {
315 if (self.visib_token) |visib_token| return visib_token;
316 return self.expr.firstToken();
317 }
318
319 pub fn lastToken(self: &NodeUse) Token {
320 return self.semicolon_token;
321 }
322};
323
324pub const NodeErrorSetDecl = struct {
325 base: Node,
326 error_token: Token,
327 decls: ArrayList(&NodeIdentifier),
328 rbrace_token: Token,
329
330 pub fn iterate(self: &NodeErrorSetDecl, index: usize) ?&Node {
331 var i = index;
332
333 if (i < self.decls.len) return &self.decls.at(i).base;
334 i -= self.decls.len;
335
336 return null;
337 }
338
339 pub fn firstToken(self: &NodeErrorSetDecl) Token {
340 return self.error_token;
341 }
342
343 pub fn lastToken(self: &NodeErrorSetDecl) Token {
344 return self.rbrace_token;
345 }
346};
347
348pub const NodeContainerDecl = struct {
349 base: Node,
350 ltoken: Token,
351 layout: Layout,
352 kind: Kind,
353 init_arg_expr: InitArg,
354 fields_and_decls: ArrayList(&Node),
355 rbrace_token: Token,
356
357 const Layout = enum {
358 Auto,
359 Extern,
360 Packed,
361 };
362
363 const Kind = enum {
364 Struct,
365 Enum,
366 Union,
367 };
368
369 const InitArg = union(enum) {
370 None,
371 Enum,
372 Type: &Node,
373 };
374
375 pub fn iterate(self: &NodeContainerDecl, index: usize) ?&Node {
376 var i = index;
377
378 switch (self.init_arg_expr) {
379 InitArg.Type => |t| {
380 if (i < 1) return t;
381 i -= 1;
382 },
383 InitArg.None,
384 InitArg.Enum => { }
385 }
386
387 if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i);
388 i -= self.fields_and_decls.len;
389
390 return null;
391 }
392
393 pub fn firstToken(self: &NodeContainerDecl) Token {
394 return self.ltoken;
395 }
396
397 pub fn lastToken(self: &NodeContainerDecl) Token {
398 return self.rbrace_token;
399 }
400};
401
402pub const NodeStructField = struct {
403 base: Node,
404 name_token: Token,
405 type_expr: &Node,
406
407 pub fn iterate(self: &NodeStructField, index: usize) ?&Node {
408 var i = index;
409
410 if (i < 1) return self.type_expr;
411 i -= 1;
412
413 return null;
414 }
415
416 pub fn firstToken(self: &NodeStructField) Token {
417 return self.name_token;
418 }
419
420 pub fn lastToken(self: &NodeStructField) Token {
421 return self.type_expr.lastToken();
422 }
423};
424
425pub const NodeUnionTag = struct {
426 base: Node,
427 name_token: Token,
428 type_expr: ?&Node,
429
430 pub fn iterate(self: &NodeUnionTag, index: usize) ?&Node {
431 var i = index;
432
433 if (self.type_expr) |type_expr| {
434 if (i < 1) return type_expr;
435 i -= 1;
436 }
437
438 return null;
439 }
440
441 pub fn firstToken(self: &NodeUnionTag) Token {
442 return self.name_token;
443 }
444
445 pub fn lastToken(self: &NodeUnionTag) Token {
446 if (self.type_expr) |type_expr| {
447 return type_expr.lastToken();
448 }
449
450 return self.name_token;
451 }
452};
453
454pub const NodeEnumTag = struct {
455 base: Node,
456 name_token: Token,
457 value: ?&Node,
458
459 pub fn iterate(self: &NodeEnumTag, index: usize) ?&Node {
460 var i = index;
461
462 if (self.value) |value| {
463 if (i < 1) return value;
464 i -= 1;
465 }
466
467 return null;
468 }
469
470 pub fn firstToken(self: &NodeEnumTag) Token {
471 return self.name_token;
472 }
473
474 pub fn lastToken(self: &NodeEnumTag) Token {
475 if (self.value) |value| {
476 return value.lastToken();
477 }
478
479 return self.name_token;
480 }
481};
482
163pub const NodeIdentifier = struct {483pub const NodeIdentifier = struct {
164 base: Node,484 base: Node,
165 name_token: Token,485 name_token: Token,
...@@ -177,6 +497,36 @@ pub const NodeIdentifier = struct {...@@ -177,6 +497,36 @@ pub const NodeIdentifier = struct {
177 }497 }
178};498};
179499
500pub const NodeAsyncAttribute = struct {
501 base: Node,
502 async_token: Token,
503 allocator_type: ?&Node,
504 rangle_bracket: ?Token,
505
506 pub fn iterate(self: &NodeAsyncAttribute, index: usize) ?&Node {
507 var i = index;
508
509 if (self.allocator_type) |allocator_type| {
510 if (i < 1) return allocator_type;
511 i -= 1;
512 }
513
514 return null;
515 }
516
517 pub fn firstToken(self: &NodeAsyncAttribute) Token {
518 return self.async_token;
519 }
520
521 pub fn lastToken(self: &NodeAsyncAttribute) Token {
522 if (self.rangle_bracket) |rangle_bracket| {
523 return rangle_bracket;
524 }
525
526 return self.async_token;
527 }
528};
529
180pub const NodeFnProto = struct {530pub const NodeFnProto = struct {
181 base: Node,531 base: Node,
182 visib_token: ?Token,532 visib_token: ?Token,
...@@ -188,13 +538,13 @@ pub const NodeFnProto = struct {...@@ -188,13 +538,13 @@ pub const NodeFnProto = struct {
188 extern_token: ?Token,538 extern_token: ?Token,
189 inline_token: ?Token,539 inline_token: ?Token,
190 cc_token: ?Token,540 cc_token: ?Token,
541 async_attr: ?&NodeAsyncAttribute,
191 body_node: ?&Node,542 body_node: ?&Node,
192 lib_name: ?&Node, // populated if this is an extern declaration543 lib_name: ?&Node, // populated if this is an extern declaration
193 align_expr: ?&Node, // populated if align(A) is present544 align_expr: ?&Node, // populated if align(A) is present
194545
195 pub const ReturnType = union(enum) {546 pub const ReturnType = union(enum) {
196 Explicit: &Node,547 Explicit: &Node,
197 Infer: Token,
198 InferErrorSet: &Node,548 InferErrorSet: &Node,
199 };549 };
200550
...@@ -216,7 +566,6 @@ pub const NodeFnProto = struct {...@@ -216,7 +566,6 @@ pub const NodeFnProto = struct {
216 if (i < 1) return node;566 if (i < 1) return node;
217 i -= 1;567 i -= 1;
218 },568 },
219 ReturnType.Infer => {},
220 }569 }
221570
222 if (self.align_expr) |align_expr| {571 if (self.align_expr) |align_expr| {
...@@ -250,7 +599,6 @@ pub const NodeFnProto = struct {...@@ -250,7 +599,6 @@ pub const NodeFnProto = struct {
250 // TODO allow this and next prong to share bodies since the types are the same599 // TODO allow this and next prong to share bodies since the types are the same
251 ReturnType.Explicit => |node| return node.lastToken(),600 ReturnType.Explicit => |node| return node.lastToken(),
252 ReturnType.InferErrorSet => |node| return node.lastToken(),601 ReturnType.InferErrorSet => |node| return node.lastToken(),
253 ReturnType.Infer => |token| return token,
254 }602 }
255 }603 }
256};604};
...@@ -287,9 +635,10 @@ pub const NodeParamDecl = struct {...@@ -287,9 +635,10 @@ pub const NodeParamDecl = struct {
287635
288pub const NodeBlock = struct {636pub const NodeBlock = struct {
289 base: Node,637 base: Node,
290 begin_token: Token,638 label: ?Token,
291 end_token: Token,639 lbrace: Token,
292 statements: ArrayList(&Node),640 statements: ArrayList(&Node),
641 rbrace: Token,
293642
294 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {643 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
295 var i = index;644 var i = index;
...@@ -301,11 +650,408 @@ pub const NodeBlock = struct {...@@ -301,11 +650,408 @@ pub const NodeBlock = struct {
301 }650 }
302651
303 pub fn firstToken(self: &NodeBlock) Token {652 pub fn firstToken(self: &NodeBlock) Token {
304 return self.begin_token;653 if (self.label) |label| {
654 return label;
655 }
656
657 return self.lbrace;
305 }658 }
306659
307 pub fn lastToken(self: &NodeBlock) Token {660 pub fn lastToken(self: &NodeBlock) Token {
308 return self.end_token;661 return self.rbrace;
662 }
663};
664
665pub const NodeDefer = struct {
666 base: Node,
667 defer_token: Token,
668 kind: Kind,
669 expr: &Node,
670
671 const Kind = enum {
672 Error,
673 Unconditional,
674 };
675
676 pub fn iterate(self: &NodeDefer, index: usize) ?&Node {
677 var i = index;
678
679 if (i < 1) return self.expr;
680 i -= 1;
681
682 return null;
683 }
684
685 pub fn firstToken(self: &NodeDefer) Token {
686 return self.defer_token;
687 }
688
689 pub fn lastToken(self: &NodeDefer) Token {
690 return self.expr.lastToken();
691 }
692};
693
694pub const NodeComptime = struct {
695 base: Node,
696 comptime_token: Token,
697 expr: &Node,
698
699 pub fn iterate(self: &NodeComptime, index: usize) ?&Node {
700 var i = index;
701
702 if (i < 1) return self.expr;
703 i -= 1;
704
705 return null;
706 }
707
708 pub fn firstToken(self: &NodeComptime) Token {
709 return self.comptime_token;
710 }
711
712 pub fn lastToken(self: &NodeComptime) Token {
713 return self.expr.lastToken();
714 }
715};
716
717pub const NodePayload = struct {
718 base: Node,
719 lpipe: Token,
720 error_symbol: &NodeIdentifier,
721 rpipe: Token,
722
723 pub fn iterate(self: &NodePayload, index: usize) ?&Node {
724 var i = index;
725
726 if (i < 1) return &self.error_symbol.base;
727 i -= 1;
728
729 return null;
730 }
731
732 pub fn firstToken(self: &NodePayload) Token {
733 return self.lpipe;
734 }
735
736 pub fn lastToken(self: &NodePayload) Token {
737 return self.rpipe;
738 }
739};
740
741pub const NodePointerPayload = struct {
742 base: Node,
743 lpipe: Token,
744 is_ptr: bool,
745 value_symbol: &NodeIdentifier,
746 rpipe: Token,
747
748 pub fn iterate(self: &NodePointerPayload, index: usize) ?&Node {
749 var i = index;
750
751 if (i < 1) return &self.value_symbol.base;
752 i -= 1;
753
754 return null;
755 }
756
757 pub fn firstToken(self: &NodePointerPayload) Token {
758 return self.lpipe;
759 }
760
761 pub fn lastToken(self: &NodePointerPayload) Token {
762 return self.rpipe;
763 }
764};
765
766pub const NodePointerIndexPayload = struct {
767 base: Node,
768 lpipe: Token,
769 is_ptr: bool,
770 value_symbol: &NodeIdentifier,
771 index_symbol: ?&NodeIdentifier,
772 rpipe: Token,
773
774 pub fn iterate(self: &NodePointerIndexPayload, index: usize) ?&Node {
775 var i = index;
776
777 if (i < 1) return &self.value_symbol.base;
778 i -= 1;
779
780 if (self.index_symbol) |index_symbol| {
781 if (i < 1) return &index_symbol.base;
782 i -= 1;
783 }
784
785 return null;
786 }
787
788 pub fn firstToken(self: &NodePointerIndexPayload) Token {
789 return self.lpipe;
790 }
791
792 pub fn lastToken(self: &NodePointerIndexPayload) Token {
793 return self.rpipe;
794 }
795};
796
797pub const NodeElse = struct {
798 base: Node,
799 else_token: Token,
800 payload: ?&NodePayload,
801 body: &Node,
802
803 pub fn iterate(self: &NodeElse, index: usize) ?&Node {
804 var i = index;
805
806 if (self.payload) |payload| {
807 if (i < 1) return &payload.base;
808 i -= 1;
809 }
810
811 if (i < 1) return self.body;
812 i -= 1;
813
814 return null;
815 }
816
817 pub fn firstToken(self: &NodeElse) Token {
818 return self.else_token;
819 }
820
821 pub fn lastToken(self: &NodeElse) Token {
822 return self.body.lastToken();
823 }
824};
825
826pub const NodeSwitch = struct {
827 base: Node,
828 switch_token: Token,
829 expr: &Node,
830 cases: ArrayList(&NodeSwitchCase),
831 rbrace: Token,
832
833 pub fn iterate(self: &NodeSwitch, index: usize) ?&Node {
834 var i = index;
835
836 if (i < 1) return self.expr;
837 i -= 1;
838
839 if (i < self.cases.len) return &self.cases.at(i).base;
840 i -= self.cases.len;
841
842 return null;
843 }
844
845 pub fn firstToken(self: &NodeSwitch) Token {
846 return self.switch_token;
847 }
848
849 pub fn lastToken(self: &NodeSwitch) Token {
850 return self.rbrace;
851 }
852};
853
854pub const NodeSwitchCase = struct {
855 base: Node,
856 items: ArrayList(&Node),
857 payload: ?&NodePointerPayload,
858 expr: &Node,
859
860 pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node {
861 var i = index;
862
863 if (i < self.items.len) return self.items.at(i);
864 i -= self.items.len;
865
866 if (self.payload) |payload| {
867 if (i < 1) return &payload.base;
868 i -= 1;
869 }
870
871 if (i < 1) return self.expr;
872 i -= 1;
873
874 return null;
875 }
876
877 pub fn firstToken(self: &NodeSwitchCase) Token {
878 return self.items.at(0).firstToken();
879 }
880
881 pub fn lastToken(self: &NodeSwitchCase) Token {
882 return self.expr.lastToken();
883 }
884};
885
886pub const NodeSwitchElse = struct {
887 base: Node,
888 token: Token,
889
890 pub fn iterate(self: &NodeSwitchElse, index: usize) ?&Node {
891 return null;
892 }
893
894 pub fn firstToken(self: &NodeSwitchElse) Token {
895 return self.token;
896 }
897
898 pub fn lastToken(self: &NodeSwitchElse) Token {
899 return self.token;
900 }
901};
902
903pub const NodeWhile = struct {
904 base: Node,
905 label: ?Token,
906 inline_token: ?Token,
907 while_token: Token,
908 condition: &Node,
909 payload: ?&NodePointerPayload,
910 continue_expr: ?&Node,
911 body: &Node,
912 @"else": ?&NodeElse,
913
914 pub fn iterate(self: &NodeWhile, index: usize) ?&Node {
915 var i = index;
916
917 if (i < 1) return self.condition;
918 i -= 1;
919
920 if (self.payload) |payload| {
921 if (i < 1) return &payload.base;
922 i -= 1;
923 }
924
925 if (self.continue_expr) |continue_expr| {
926 if (i < 1) return continue_expr;
927 i -= 1;
928 }
929
930 if (i < 1) return self.body;
931 i -= 1;
932
933 if (self.@"else") |@"else"| {
934 if (i < 1) return &@"else".base;
935 i -= 1;
936 }
937
938 return null;
939 }
940
941 pub fn firstToken(self: &NodeWhile) Token {
942 if (self.label) |label| {
943 return label;
944 }
945
946 if (self.inline_token) |inline_token| {
947 return inline_token;
948 }
949
950 return self.while_token;
951 }
952
953 pub fn lastToken(self: &NodeWhile) Token {
954 if (self.@"else") |@"else"| {
955 return @"else".body.lastToken();
956 }
957
958 return self.body.lastToken();
959 }
960};
961
962pub const NodeFor = struct {
963 base: Node,
964 label: ?Token,
965 inline_token: ?Token,
966 for_token: Token,
967 array_expr: &Node,
968 payload: ?&NodePointerIndexPayload,
969 body: &Node,
970 @"else": ?&NodeElse,
971
972 pub fn iterate(self: &NodeFor, index: usize) ?&Node {
973 var i = index;
974
975 if (i < 1) return self.array_expr;
976 i -= 1;
977
978 if (self.payload) |payload| {
979 if (i < 1) return &payload.base;
980 i -= 1;
981 }
982
983 if (i < 1) return self.body;
984 i -= 1;
985
986 if (self.@"else") |@"else"| {
987 if (i < 1) return &@"else".base;
988 i -= 1;
989 }
990
991 return null;
992 }
993
994 pub fn firstToken(self: &NodeFor) Token {
995 if (self.label) |label| {
996 return label;
997 }
998
999 if (self.inline_token) |inline_token| {
1000 return inline_token;
1001 }
1002
1003 return self.for_token;
1004 }
1005
1006 pub fn lastToken(self: &NodeFor) Token {
1007 if (self.@"else") |@"else"| {
1008 return @"else".body.lastToken();
1009 }
1010
1011 return self.body.lastToken();
1012 }
1013};
1014
1015pub const NodeIf = struct {
1016 base: Node,
1017 if_token: Token,
1018 condition: &Node,
1019 payload: ?&NodePointerPayload,
1020 body: &Node,
1021 @"else": ?&NodeElse,
1022
1023 pub fn iterate(self: &NodeIf, index: usize) ?&Node {
1024 var i = index;
1025
1026 if (i < 1) return self.condition;
1027 i -= 1;
1028
1029 if (self.payload) |payload| {
1030 if (i < 1) return &payload.base;
1031 i -= 1;
1032 }
1033
1034 if (i < 1) return self.body;
1035 i -= 1;
1036
1037 if (self.@"else") |@"else"| {
1038 if (i < 1) return &@"else".base;
1039 i -= 1;
1040 }
1041
1042 return null;
1043 }
1044
1045 pub fn firstToken(self: &NodeIf) Token {
1046 return self.if_token;
1047 }
1048
1049 pub fn lastToken(self: &NodeIf) Token {
1050 if (self.@"else") |@"else"| {
1051 return @"else".body.lastToken();
1052 }
1053
1054 return self.body.lastToken();
309 }1055 }
310};1056};
3111057
...@@ -316,7 +1062,7 @@ pub const NodeInfixOp = struct {...@@ -316,7 +1062,7 @@ pub const NodeInfixOp = struct {
316 op: InfixOp,1062 op: InfixOp,
317 rhs: &Node,1063 rhs: &Node,
3181064
319 const InfixOp = enum {1065 const InfixOp = union(enum) {
320 Add,1066 Add,
321 AddWrap,1067 AddWrap,
322 ArrayCat,1068 ArrayCat,
...@@ -343,6 +1089,7 @@ pub const NodeInfixOp = struct {...@@ -343,6 +1089,7 @@ pub const NodeInfixOp = struct {
343 BitXor,1089 BitXor,
344 BoolAnd,1090 BoolAnd,
345 BoolOr,1091 BoolOr,
1092 Catch: ?&NodePayload,
346 Div,1093 Div,
347 EqualEqual,1094 EqualEqual,
348 ErrorUnion,1095 ErrorUnion,
...@@ -355,6 +1102,7 @@ pub const NodeInfixOp = struct {...@@ -355,6 +1102,7 @@ pub const NodeInfixOp = struct {
355 Mult,1102 Mult,
356 MultWrap,1103 MultWrap,
357 Period,1104 Period,
1105 Range,
358 Sub,1106 Sub,
359 SubWrap,1107 SubWrap,
360 UnwrapMaybe,1108 UnwrapMaybe,
...@@ -367,6 +1115,13 @@ pub const NodeInfixOp = struct {...@@ -367,6 +1115,13 @@ pub const NodeInfixOp = struct {
367 i -= 1;1115 i -= 1;
3681116
369 switch (self.op) {1117 switch (self.op) {
1118 InfixOp.Catch => |maybe_payload| {
1119 if (maybe_payload) |payload| {
1120 if (i < 1) return &payload.base;
1121 i -= 1;
1122 }
1123 },
1124
370 InfixOp.Add,1125 InfixOp.Add,
371 InfixOp.AddWrap,1126 InfixOp.AddWrap,
372 InfixOp.ArrayCat,1127 InfixOp.ArrayCat,
...@@ -405,83 +1160,310 @@ pub const NodeInfixOp = struct {...@@ -405,83 +1160,310 @@ pub const NodeInfixOp = struct {
405 InfixOp.Mult,1160 InfixOp.Mult,
406 InfixOp.MultWrap,1161 InfixOp.MultWrap,
407 InfixOp.Period,1162 InfixOp.Period,
1163 InfixOp.Range,
408 InfixOp.Sub,1164 InfixOp.Sub,
409 InfixOp.SubWrap,1165 InfixOp.SubWrap,
410 InfixOp.UnwrapMaybe => {},1166 InfixOp.UnwrapMaybe => {},
411 }1167 }
4121168
413 if (i < 1) return self.rhs;1169 if (i < 1) return self.rhs;
1170 i -= 1;
1171
1172 return null;
1173 }
1174
1175 pub fn firstToken(self: &NodeInfixOp) Token {
1176 return self.lhs.firstToken();
1177 }
1178
1179 pub fn lastToken(self: &NodeInfixOp) Token {
1180 return self.rhs.lastToken();
1181 }
1182};
1183
1184pub const NodePrefixOp = struct {
1185 base: Node,
1186 op_token: Token,
1187 op: PrefixOp,
1188 rhs: &Node,
1189
1190 const PrefixOp = union(enum) {
1191 AddrOf: AddrOfInfo,
1192 ArrayType: &Node,
1193 Await,
1194 BitNot,
1195 BoolNot,
1196 Cancel,
1197 Deref,
1198 MaybeType,
1199 Negation,
1200 NegationWrap,
1201 Resume,
1202 SliceType: AddrOfInfo,
1203 Try,
1204 UnwrapMaybe,
1205 };
1206
1207 const AddrOfInfo = struct {
1208 align_expr: ?&Node,
1209 bit_offset_start_token: ?Token,
1210 bit_offset_end_token: ?Token,
1211 const_token: ?Token,
1212 volatile_token: ?Token,
1213 };
1214
1215 pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node {
1216 var i = index;
1217
1218 switch (self.op) {
1219 PrefixOp.SliceType => |addr_of_info| {
1220 if (addr_of_info.align_expr) |align_expr| {
1221 if (i < 1) return align_expr;
1222 i -= 1;
1223 }
1224 },
1225 PrefixOp.AddrOf => |addr_of_info| {
1226 if (addr_of_info.align_expr) |align_expr| {
1227 if (i < 1) return align_expr;
1228 i -= 1;
1229 }
1230 },
1231 PrefixOp.ArrayType => |size_expr| {
1232 if (i < 1) return size_expr;
1233 i -= 1;
1234 },
1235 PrefixOp.Await,
1236 PrefixOp.BitNot,
1237 PrefixOp.BoolNot,
1238 PrefixOp.Cancel,
1239 PrefixOp.Deref,
1240 PrefixOp.MaybeType,
1241 PrefixOp.Negation,
1242 PrefixOp.NegationWrap,
1243 PrefixOp.Try,
1244 PrefixOp.Resume,
1245 PrefixOp.UnwrapMaybe => {},
1246 }
1247
1248 if (i < 1) return self.rhs;
1249 i -= 1;
1250
1251 return null;
1252 }
1253
1254 pub fn firstToken(self: &NodePrefixOp) Token {
1255 return self.op_token;
1256 }
1257
1258 pub fn lastToken(self: &NodePrefixOp) Token {
1259 return self.rhs.lastToken();
1260 }
1261};
1262
1263pub const NodeFieldInitializer = struct {
1264 base: Node,
1265 period_token: Token,
1266 name_token: Token,
1267 expr: &Node,
1268
1269 pub fn iterate(self: &NodeFieldInitializer, index: usize) ?&Node {
1270 var i = index;
1271
1272 if (i < 1) return self.expr;
1273 i -= 1;
1274
1275 return null;
1276 }
1277
1278 pub fn firstToken(self: &NodeFieldInitializer) Token {
1279 return self.period_token;
1280 }
1281
1282 pub fn lastToken(self: &NodeFieldInitializer) Token {
1283 return self.expr.lastToken();
1284 }
1285};
1286
1287pub const NodeSuffixOp = struct {
1288 base: Node,
1289 lhs: &Node,
1290 op: SuffixOp,
1291 rtoken: Token,
1292
1293 const SuffixOp = union(enum) {
1294 Call: CallInfo,
1295 ArrayAccess: &Node,
1296 Slice: SliceRange,
1297 ArrayInitializer: ArrayList(&Node),
1298 StructInitializer: ArrayList(&NodeFieldInitializer),
1299 };
1300
1301 const CallInfo = struct {
1302 params: ArrayList(&Node),
1303 async_attr: ?&NodeAsyncAttribute,
1304 };
1305
1306 const SliceRange = struct {
1307 start: &Node,
1308 end: ?&Node,
1309 };
1310
1311 pub fn iterate(self: &NodeSuffixOp, index: usize) ?&Node {
1312 var i = index;
1313
1314 if (i < 1) return self.lhs;
1315 i -= 1;
1316
1317 switch (self.op) {
1318 SuffixOp.Call => |call_info| {
1319 if (i < call_info.params.len) return call_info.params.at(i);
1320 i -= call_info.params.len;
1321 },
1322 SuffixOp.ArrayAccess => |index_expr| {
1323 if (i < 1) return index_expr;
1324 i -= 1;
1325 },
1326 SuffixOp.Slice => |range| {
1327 if (i < 1) return range.start;
1328 i -= 1;
1329
1330 if (range.end) |end| {
1331 if (i < 1) return end;
1332 i -= 1;
1333 }
1334 },
1335 SuffixOp.ArrayInitializer => |exprs| {
1336 if (i < exprs.len) return exprs.at(i);
1337 i -= exprs.len;
1338 },
1339 SuffixOp.StructInitializer => |fields| {
1340 if (i < fields.len) return &fields.at(i).base;
1341 i -= fields.len;
1342 },
1343 }
1344
1345 return null;
1346 }
1347
1348 pub fn firstToken(self: &NodeSuffixOp) Token {
1349 return self.lhs.firstToken();
1350 }
1351
1352 pub fn lastToken(self: &NodeSuffixOp) Token {
1353 return self.rtoken;
1354 }
1355};
1356
1357pub const NodeGroupedExpression = struct {
1358 base: Node,
1359 lparen: Token,
1360 expr: &Node,
1361 rparen: Token,
1362
1363 pub fn iterate(self: &NodeGroupedExpression, index: usize) ?&Node {
1364 var i = index;
1365
1366 if (i < 1) return self.expr;
414 i -= 1;1367 i -= 1;
4151368
416 return null;1369 return null;
417 }1370 }
4181371
419 pub fn firstToken(self: &NodeInfixOp) Token {1372 pub fn firstToken(self: &NodeGroupedExpression) Token {
420 return self.lhs.firstToken();1373 return self.lparen;
421 }1374 }
4221375
423 pub fn lastToken(self: &NodeInfixOp) Token {1376 pub fn lastToken(self: &NodeGroupedExpression) Token {
424 return self.rhs.lastToken();1377 return self.rparen;
425 }1378 }
426};1379};
4271380
428pub const NodePrefixOp = struct {1381pub const NodeControlFlowExpression = struct {
429 base: Node,1382 base: Node,
430 op_token: Token,1383 ltoken: Token,
431 op: PrefixOp,1384 kind: Kind,
432 rhs: &Node,1385 rhs: ?&Node,
4331386
434 const PrefixOp = union(enum) {1387 const Kind = union(enum) {
435 AddrOf: AddrOfInfo,1388 Break: ?Token,
436 BitNot,1389 Continue: ?Token,
437 BoolNot,
438 Deref,
439 Negation,
440 NegationWrap,
441 Return,1390 Return,
442 Try,
443 UnwrapMaybe,
444 };
445 const AddrOfInfo = struct {
446 align_expr: ?&Node,
447 bit_offset_start_token: ?Token,
448 bit_offset_end_token: ?Token,
449 const_token: ?Token,
450 volatile_token: ?Token,
451 };1391 };
4521392
453 pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node {1393 pub fn iterate(self: &NodeControlFlowExpression, index: usize) ?&Node {
454 var i = index;1394 var i = index;
4551395
456 switch (self.op) {1396 if (self.rhs) |rhs| {
457 PrefixOp.AddrOf => |addr_of_info| {1397 if (i < 1) return rhs;
458 if (addr_of_info.align_expr) |align_expr| {1398 i -= 1;
459 if (i < 1) return align_expr;1399 }
460 i -= 1;1400
1401 return null;
1402 }
1403
1404 pub fn firstToken(self: &NodeControlFlowExpression) Token {
1405 return self.ltoken;
1406 }
1407
1408 pub fn lastToken(self: &NodeControlFlowExpression) Token {
1409 if (self.rhs) |rhs| {
1410 return rhs.lastToken();
1411 }
1412
1413 switch (self.kind) {
1414 Kind.Break => |maybe_blk_token| {
1415 if (maybe_blk_token) |blk_token| {
1416 return blk_token;
461 }1417 }
462 },1418 },
463 PrefixOp.BitNot,1419 Kind.Continue => |maybe_blk_token| {
464 PrefixOp.BoolNot,1420 if (maybe_blk_token) |blk_token| {
465 PrefixOp.Deref,1421 return blk_token;
466 PrefixOp.Negation,1422 }
467 PrefixOp.NegationWrap,1423 },
468 PrefixOp.Return,1424 Kind.Return => return self.ltoken,
469 PrefixOp.Try,
470 PrefixOp.UnwrapMaybe => {},
471 }1425 }
4721426
473 if (i < 1) return self.rhs;1427 return self.ltoken;
474 i -= 1;1428 }
1429};
1430
1431pub const NodeSuspend = struct {
1432 base: Node,
1433 suspend_token: Token,
1434 payload: ?&NodePayload,
1435 body: ?&Node,
1436
1437 pub fn iterate(self: &NodeSuspend, index: usize) ?&Node {
1438 var i = index;
1439
1440 if (self.payload) |payload| {
1441 if (i < 1) return &payload.base;
1442 i -= 1;
1443 }
1444
1445 if (self.body) |body| {
1446 if (i < 1) return body;
1447 i -= 1;
1448 }
4751449
476 return null;1450 return null;
477 }1451 }
4781452
479 pub fn firstToken(self: &NodePrefixOp) Token {1453 pub fn firstToken(self: &NodeSuspend) Token {
480 return self.op_token;1454 return self.suspend_token;
481 }1455 }
4821456
483 pub fn lastToken(self: &NodePrefixOp) Token {1457 pub fn lastToken(self: &NodeSuspend) Token {
484 return self.rhs.lastToken();1458 if (self.body) |body| {
1459 return body.lastToken();
1460 }
1461
1462 if (self.payload) |payload| {
1463 return payload.lastToken();
1464 }
1465
1466 return self.suspend_token;
485 }1467 }
486};1468};
4871469
...@@ -543,46 +1525,87 @@ pub const NodeBuiltinCall = struct {...@@ -543,46 +1525,87 @@ pub const NodeBuiltinCall = struct {
543 }1525 }
544};1526};
5451527
546pub const NodeCall = struct {1528pub const NodeStringLiteral = struct {
547 base: Node,1529 base: Node,
548 callee: &Node,1530 token: Token,
549 params: ArrayList(&Node),
550 rparen_token: Token,
5511531
552 pub fn iterate(self: &NodeCall, index: usize) ?&Node {1532 pub fn iterate(self: &NodeStringLiteral, index: usize) ?&Node {
553 var i = index;1533 return null;
1534 }
5541535
555 if (i < 1) return self.callee;1536 pub fn firstToken(self: &NodeStringLiteral) Token {
556 i -= 1;1537 return self.token;
1538 }
5571539
558 if (i < self.params.len) return self.params.at(i);1540 pub fn lastToken(self: &NodeStringLiteral) Token {
559 i -= self.params.len;1541 return self.token;
1542 }
1543};
1544
1545pub const NodeMultilineStringLiteral = struct {
1546 base: Node,
1547 tokens: ArrayList(Token),
5601548
1549 pub fn iterate(self: &NodeMultilineStringLiteral, index: usize) ?&Node {
561 return null;1550 return null;
562 }1551 }
5631552
564 pub fn firstToken(self: &NodeCall) Token {1553 pub fn firstToken(self: &NodeMultilineStringLiteral) Token {
565 return self.callee.firstToken();1554 return self.tokens.at(0);
566 }1555 }
5671556
568 pub fn lastToken(self: &NodeCall) Token {1557 pub fn lastToken(self: &NodeMultilineStringLiteral) Token {
569 return self.rparen_token;1558 return self.tokens.at(self.tokens.len - 1);
570 }1559 }
571};1560};
5721561
573pub const NodeStringLiteral = struct {1562pub const NodeCharLiteral = struct {
574 base: Node,1563 base: Node,
575 token: Token,1564 token: Token,
5761565
577 pub fn iterate(self: &NodeStringLiteral, index: usize) ?&Node {1566 pub fn iterate(self: &NodeCharLiteral, index: usize) ?&Node {
578 return null;1567 return null;
579 }1568 }
5801569
581 pub fn firstToken(self: &NodeStringLiteral) Token {1570 pub fn firstToken(self: &NodeCharLiteral) Token {
582 return self.token;1571 return self.token;
583 }1572 }
5841573
585 pub fn lastToken(self: &NodeStringLiteral) Token {1574 pub fn lastToken(self: &NodeCharLiteral) Token {
1575 return self.token;
1576 }
1577};
1578
1579pub const NodeBoolLiteral = struct {
1580 base: Node,
1581 token: Token,
1582
1583 pub fn iterate(self: &NodeBoolLiteral, index: usize) ?&Node {
1584 return null;
1585 }
1586
1587 pub fn firstToken(self: &NodeBoolLiteral) Token {
1588 return self.token;
1589 }
1590
1591 pub fn lastToken(self: &NodeBoolLiteral) Token {
1592 return self.token;
1593 }
1594};
1595
1596pub const NodeNullLiteral = struct {
1597 base: Node,
1598 token: Token,
1599
1600 pub fn iterate(self: &NodeNullLiteral, index: usize) ?&Node {
1601 return null;
1602 }
1603
1604 pub fn firstToken(self: &NodeNullLiteral) Token {
1605 return self.token;
1606 }
1607
1608 pub fn lastToken(self: &NodeNullLiteral) Token {
586 return self.token;1609 return self.token;
587 }1610 }
588};1611};
...@@ -604,6 +1627,185 @@ pub const NodeUndefinedLiteral = struct {...@@ -604,6 +1627,185 @@ pub const NodeUndefinedLiteral = struct {
604 }1627 }
605};1628};
6061629
1630pub const NodeThisLiteral = struct {
1631 base: Node,
1632 token: Token,
1633
1634 pub fn iterate(self: &NodeThisLiteral, index: usize) ?&Node {
1635 return null;
1636 }
1637
1638 pub fn firstToken(self: &NodeThisLiteral) Token {
1639 return self.token;
1640 }
1641
1642 pub fn lastToken(self: &NodeThisLiteral) Token {
1643 return self.token;
1644 }
1645};
1646
1647pub const NodeAsmOutput = struct {
1648 base: Node,
1649 symbolic_name: &NodeIdentifier,
1650 constraint: &NodeStringLiteral,
1651 kind: Kind,
1652
1653 const Kind = union(enum) {
1654 Variable: &NodeIdentifier,
1655 Return: &Node
1656 };
1657
1658 pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node {
1659 var i = index;
1660
1661 if (i < 1) return &self.symbolic_name.base;
1662 i -= 1;
1663
1664 if (i < 1) return &self.constraint.base;
1665 i -= 1;
1666
1667 switch (self.kind) {
1668 Kind.Variable => |variable_name| {
1669 if (i < 1) return &variable_name.base;
1670 i -= 1;
1671 },
1672 Kind.Return => |return_type| {
1673 if (i < 1) return return_type;
1674 i -= 1;
1675 }
1676 }
1677
1678 return null;
1679 }
1680
1681 pub fn firstToken(self: &NodeAsmOutput) Token {
1682 return self.symbolic_name.firstToken();
1683 }
1684
1685 pub fn lastToken(self: &NodeAsmOutput) Token {
1686 return switch (self.kind) {
1687 Kind.Variable => |variable_name| variable_name.lastToken(),
1688 Kind.Return => |return_type| return_type.lastToken(),
1689 };
1690 }
1691};
1692
1693pub const NodeAsmInput = struct {
1694 base: Node,
1695 symbolic_name: &NodeIdentifier,
1696 constraint: &NodeStringLiteral,
1697 expr: &Node,
1698
1699 pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node {
1700 var i = index;
1701
1702 if (i < 1) return &self.symbolic_name.base;
1703 i -= 1;
1704
1705 if (i < 1) return &self.constraint.base;
1706 i -= 1;
1707
1708 if (i < 1) return self.expr;
1709 i -= 1;
1710
1711 return null;
1712 }
1713
1714 pub fn firstToken(self: &NodeAsmInput) Token {
1715 return self.symbolic_name.firstToken();
1716 }
1717
1718 pub fn lastToken(self: &NodeAsmInput) Token {
1719 return self.expr.lastToken();
1720 }
1721};
1722
1723pub const NodeAsm = struct {
1724 base: Node,
1725 asm_token: Token,
1726 is_volatile: bool,
1727 template: Token,
1728 //tokens: ArrayList(AsmToken),
1729 outputs: ArrayList(&NodeAsmOutput),
1730 inputs: ArrayList(&NodeAsmInput),
1731 cloppers: ArrayList(&NodeStringLiteral),
1732 rparen: Token,
1733
1734 pub fn iterate(self: &NodeAsm, index: usize) ?&Node {
1735 var i = index;
1736
1737 if (i < self.outputs.len) return &self.outputs.at(index).base;
1738 i -= self.outputs.len;
1739
1740 if (i < self.inputs.len) return &self.inputs.at(index).base;
1741 i -= self.inputs.len;
1742
1743 if (i < self.cloppers.len) return &self.cloppers.at(index).base;
1744 i -= self.cloppers.len;
1745
1746 return null;
1747 }
1748
1749 pub fn firstToken(self: &NodeAsm) Token {
1750 return self.asm_token;
1751 }
1752
1753 pub fn lastToken(self: &NodeAsm) Token {
1754 return self.rparen;
1755 }
1756};
1757
1758pub const NodeUnreachable = struct {
1759 base: Node,
1760 token: Token,
1761
1762 pub fn iterate(self: &NodeUnreachable, index: usize) ?&Node {
1763 return null;
1764 }
1765
1766 pub fn firstToken(self: &NodeUnreachable) Token {
1767 return self.token;
1768 }
1769
1770 pub fn lastToken(self: &NodeUnreachable) Token {
1771 return self.token;
1772 }
1773};
1774
1775pub const NodeErrorType = struct {
1776 base: Node,
1777 token: Token,
1778
1779 pub fn iterate(self: &NodeErrorType, index: usize) ?&Node {
1780 return null;
1781 }
1782
1783 pub fn firstToken(self: &NodeErrorType) Token {
1784 return self.token;
1785 }
1786
1787 pub fn lastToken(self: &NodeErrorType) Token {
1788 return self.token;
1789 }
1790};
1791
1792pub const NodeVarType = struct {
1793 base: Node,
1794 token: Token,
1795
1796 pub fn iterate(self: &NodeVarType, index: usize) ?&Node {
1797 return null;
1798 }
1799
1800 pub fn firstToken(self: &NodeVarType) Token {
1801 return self.token;
1802 }
1803
1804 pub fn lastToken(self: &NodeVarType) Token {
1805 return self.token;
1806 }
1807};
1808
607pub const NodeLineComment = struct {1809pub const NodeLineComment = struct {
608 base: Node,1810 base: Node,
609 lines: ArrayList(Token),1811 lines: ArrayList(Token),
...@@ -624,7 +1826,7 @@ pub const NodeLineComment = struct {...@@ -624,7 +1826,7 @@ pub const NodeLineComment = struct {
624pub const NodeTestDecl = struct {1826pub const NodeTestDecl = struct {
625 base: Node,1827 base: Node,
626 test_token: Token,1828 test_token: Token,
627 name_token: Token,1829 name: &Node,
628 body_node: &Node,1830 body_node: &Node,
6291831
630 pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node {1832 pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node {
...@@ -644,4 +1846,3 @@ pub const NodeTestDecl = struct {...@@ -644,4 +1846,3 @@ pub const NodeTestDecl = struct {
644 return self.body_node.lastToken();1846 return self.body_node.lastToken();
645 }1847 }
646};1848};
647
std/zig/parser.zig+3842-526
...@@ -53,20 +53,33 @@ pub const Parser = struct {...@@ -53,20 +53,33 @@ pub const Parser = struct {
53 }53 }
5454
55 const TopLevelDeclCtx = struct {55 const TopLevelDeclCtx = struct {
56 decls: &ArrayList(&ast.Node),
56 visib_token: ?Token,57 visib_token: ?Token,
57 extern_token: ?Token,58 extern_token: ?Token,
59 lib_name: ?&ast.Node,
60 };
61
62 const ContainerExternCtx = struct {
63 dest_ptr: DestPtr,
64 ltoken: Token,
65 layout: ast.NodeContainerDecl.Layout,
58 };66 };
5967
60 const DestPtr = union(enum) {68 const DestPtr = union(enum) {
61 Field: &&ast.Node,69 Field: &&ast.Node,
62 NullableField: &?&ast.Node,70 NullableField: &?&ast.Node,
63 List: &ArrayList(&ast.Node),
6471
65 pub fn store(self: &const DestPtr, value: &ast.Node) !void {72 pub fn store(self: &const DestPtr, value: &ast.Node) void {
66 switch (*self) {73 switch (*self) {
67 DestPtr.Field => |ptr| *ptr = value,74 DestPtr.Field => |ptr| *ptr = value,
68 DestPtr.NullableField => |ptr| *ptr = value,75 DestPtr.NullableField => |ptr| *ptr = value,
69 DestPtr.List => |list| try list.append(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,
70 }83 }
71 }84 }
72 };85 };
...@@ -76,22 +89,69 @@ pub const Parser = struct {...@@ -76,22 +89,69 @@ pub const Parser = struct {
76 ptr: &Token,89 ptr: &Token,
77 };90 };
7891
92 const RevertState = struct {
93 parser: Parser,
94 tokenizer: Tokenizer,
95
96 // We expect, that if something is optional, then there is a field,
97 // that needs to be set to null, when we revert.
98 ptr: &?&ast.Node,
99 };
100
101 const ExprListCtx = struct {
102 list: &ArrayList(&ast.Node),
103 end: Token.Id,
104 ptr: &Token,
105 };
106
107 const ElseCtx = struct {
108 payload: ?DestPtr,
109 body: DestPtr,
110 };
111
112 fn ListSave(comptime T: type) type {
113 return struct {
114 list: &ArrayList(T),
115 ptr: &Token,
116 };
117 }
118
119 const LabelCtx = struct {
120 label: ?Token,
121 dest_ptr: DestPtr,
122 };
123
124 const InlineCtx = struct {
125 label: ?Token,
126 inline_token: ?Token,
127 dest_ptr: DestPtr,
128 };
129
130 const LoopCtx = struct {
131 label: ?Token,
132 inline_token: ?Token,
133 loop_token: Token,
134 dest_ptr: DestPtr,
135 };
136
137 const AsyncEndCtx = struct {
138 dest_ptr: DestPtr,
139 attribute: &ast.NodeAsyncAttribute,
140 };
141
79 const State = union(enum) {142 const State = union(enum) {
80 TopLevel,143 TopLevel,
81 TopLevelExtern: ?Token,144 TopLevelExtern: TopLevelDeclCtx,
82 TopLevelDecl: TopLevelDeclCtx,145 TopLevelDecl: TopLevelDeclCtx,
83 Expression: DestPtr,146 ContainerExtern: ContainerExternCtx,
84 ExpectOperand,147 ContainerDecl: &ast.NodeContainerDecl,
85 Operand: &ast.Node,148 SliceOrArrayAccess: &ast.NodeSuffixOp,
86 AfterOperand,
87 InfixOp: &ast.NodeInfixOp,
88 PrefixOp: &ast.NodePrefixOp,
89 SuffixOp: &ast.Node,
90 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,149 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
91 TypeExpr: DestPtr,
92 VarDecl: &ast.NodeVarDecl,150 VarDecl: &ast.NodeVarDecl,
93 VarDeclAlign: &ast.NodeVarDecl,151 VarDeclAlign: &ast.NodeVarDecl,
94 VarDeclEq: &ast.NodeVarDecl,152 VarDeclEq: &ast.NodeVarDecl,
153 IfToken: @TagType(Token.Id),
154 IfTokenSave: ExpectTokenSave,
95 ExpectToken: @TagType(Token.Id),155 ExpectToken: @TagType(Token.Id),
96 ExpectTokenSave: ExpectTokenSave,156 ExpectTokenSave: ExpectTokenSave,
97 FnProto: &ast.NodeFnProto,157 FnProto: &ast.NodeFnProto,
...@@ -100,10 +160,73 @@ pub const Parser = struct {...@@ -100,10 +160,73 @@ pub const Parser = struct {
100 ParamDecl: &ast.NodeFnProto,160 ParamDecl: &ast.NodeFnProto,
101 ParamDeclComma,161 ParamDeclComma,
102 FnDef: &ast.NodeFnProto,162 FnDef: &ast.NodeFnProto,
163 LabeledExpression: LabelCtx,
164 Inline: InlineCtx,
165 While: LoopCtx,
166 For: LoopCtx,
103 Block: &ast.NodeBlock,167 Block: &ast.NodeBlock,
168 Else: &?&ast.NodeElse,
169 WhileContinueExpr: &?&ast.Node,
104 Statement: &ast.NodeBlock,170 Statement: &ast.NodeBlock,
105 ExprListItemOrEnd: &ArrayList(&ast.Node),171 Semicolon: &const &const ast.Node,
106 ExprListCommaOrEnd: &ArrayList(&ast.Node),172 AsmOutputItems: &ArrayList(&ast.NodeAsmOutput),
173 AsmInputItems: &ArrayList(&ast.NodeAsmInput),
174 AsmClopperItems: &ArrayList(&ast.NodeStringLiteral),
175 ExprListItemOrEnd: ExprListCtx,
176 ExprListCommaOrEnd: ExprListCtx,
177 FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer),
178 FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer),
179 FieldListCommaOrEnd: &ast.NodeContainerDecl,
180 SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase),
181 SuspendBody: &ast.NodeSuspend,
182 AsyncEnd: AsyncEndCtx,
183 Payload: &?&ast.NodePayload,
184 PointerPayload: &?&ast.NodePointerPayload,
185 PointerIndexPayload: &?&ast.NodePointerIndexPayload,
186 SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase),
187 SwitchCaseItem: &ArrayList(&ast.Node),
188 SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node),
189
190 /// A state that can be appended before any other State. If an error occures,
191 /// the parser will first try looking for the closest optional state. If an
192 /// optional state is found, the parser will revert to the state it was in
193 /// when the optional was added. This will polute the arena allocator with
194 /// "leaked" nodes. TODO: Figure out if it's nessesary to handle leaked nodes.
195 Optional: RevertState,
196
197 Expression: DestPtr,
198 RangeExpressionBegin: DestPtr,
199 RangeExpressionEnd: DestPtr,
200 AssignmentExpressionBegin: DestPtr,
201 AssignmentExpressionEnd: DestPtr,
202 UnwrapExpressionBegin: DestPtr,
203 UnwrapExpressionEnd: DestPtr,
204 BoolOrExpressionBegin: DestPtr,
205 BoolOrExpressionEnd: DestPtr,
206 BoolAndExpressionBegin: DestPtr,
207 BoolAndExpressionEnd: DestPtr,
208 ComparisonExpressionBegin: DestPtr,
209 ComparisonExpressionEnd: DestPtr,
210 BinaryOrExpressionBegin: DestPtr,
211 BinaryOrExpressionEnd: DestPtr,
212 BinaryXorExpressionBegin: DestPtr,
213 BinaryXorExpressionEnd: DestPtr,
214 BinaryAndExpressionBegin: DestPtr,
215 BinaryAndExpressionEnd: DestPtr,
216 BitShiftExpressionBegin: DestPtr,
217 BitShiftExpressionEnd: DestPtr,
218 AdditionExpressionBegin: DestPtr,
219 AdditionExpressionEnd: DestPtr,
220 MultiplyExpressionBegin: DestPtr,
221 MultiplyExpressionEnd: DestPtr,
222 CurlySuffixExpressionBegin: DestPtr,
223 CurlySuffixExpressionEnd: DestPtr,
224 TypeExprBegin: DestPtr,
225 TypeExprEnd: DestPtr,
226 PrefixOpExpression: DestPtr,
227 SuffixOpExpressionBegin: DestPtr,
228 SuffixOpExpressionEnd: DestPtr,
229 PrimaryExpression: DestPtr,
107 };230 };
108231
109 /// Returns an AST tree, allocated with the parser's allocator.232 /// Returns an AST tree, allocated with the parser's allocator.
...@@ -168,104 +291,199 @@ pub const Parser = struct {...@@ -168,104 +291,199 @@ pub const Parser = struct {
168 State.TopLevel => {291 State.TopLevel => {
169 const token = self.getNextToken();292 const token = self.getNextToken();
170 switch (token.id) {293 switch (token.id) {
171 Token.Id.Keyword_pub, Token.Id.Keyword_export => {
172 stack.append(State { .TopLevelExtern = token }) catch unreachable;
173 continue;
174 },
175 Token.Id.Keyword_test => {294 Token.Id.Keyword_test => {
176 stack.append(State.TopLevel) catch unreachable;295 stack.append(State.TopLevel) catch unreachable;
177296
178 const name_token = self.getNextToken();297 const name_token = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
179 if (name_token.id != Token.Id.StringLiteral)298 const lbrace = (try self.eatToken(&stack, Token.Id.LBrace)) ?? continue;
180 return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.StringLiteral), @tagName(name_token.id));
181
182 const lbrace = self.getNextToken();
183 if (lbrace.id != Token.Id.LBrace)
184 return self.parseError(token, "expected {}, found {}", @tagName(Token.Id.LBrace), @tagName(name_token.id));
185299
186 const block = try self.createBlock(arena, token);300 const name = try self.createStringLiteral(arena, name_token);
187 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, name_token, block);301 const block = try self.createBlock(arena, (?Token)(null), token);
188 try stack.append(State { .Block = block });302 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
303 stack.append(State { .Block = block }) catch unreachable;
189 continue;304 continue;
190 },305 },
191 Token.Id.Eof => {306 Token.Id.Eof => {
192 root_node.eof_token = token;307 root_node.eof_token = token;
193 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};308 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};
194 },309 },
310 Token.Id.Keyword_pub, Token.Id.Keyword_export => {
311 stack.append(State.TopLevel) catch unreachable;
312 try stack.append(State {
313 .TopLevelExtern = TopLevelDeclCtx {
314 .decls = &root_node.decls,
315 .visib_token = token,
316 .extern_token = null,
317 .lib_name = null,
318 }
319 });
320 continue;
321 },
322 Token.Id.Keyword_comptime => {
323 const node = try arena.create(ast.NodeComptime);
324 *node = ast.NodeComptime {
325 .base = self.initNode(ast.Node.Id.Comptime),
326 .comptime_token = token,
327 .expr = undefined,
328 };
329 try root_node.decls.append(&node.base);
330 stack.append(State.TopLevel) catch unreachable;
331 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
332 continue;
333 },
195 else => {334 else => {
196 self.putBackToken(token);335 self.putBackToken(token);
197 stack.append(State { .TopLevelExtern = null }) catch unreachable;336 stack.append(State.TopLevel) catch unreachable;
337 try stack.append(State {
338 .TopLevelExtern = TopLevelDeclCtx {
339 .decls = &root_node.decls,
340 .visib_token = null,
341 .extern_token = null,
342 .lib_name = null,
343 }
344 });
198 continue;345 continue;
199 },346 },
200 }347 }
201 },348 },
202 State.TopLevelExtern => |visib_token| {349 State.TopLevelExtern => |ctx| {
203 const token = self.getNextToken();350 const token = self.getNextToken();
204 if (token.id == Token.Id.Keyword_extern) {351 switch (token.id) {
205 stack.append(State {352 Token.Id.Keyword_use => {
206 .TopLevelDecl = TopLevelDeclCtx {353 const node = try arena.create(ast.NodeUse);
207 .visib_token = visib_token,354 *node = ast.NodeUse {
208 .extern_token = token,355 .base = self.initNode(ast.Node.Id.Use),
209 },356 .visib_token = ctx.visib_token,
210 }) catch unreachable;357 .expr = undefined,
211 continue;358 .semicolon_token = undefined,
212 }359 };
213 self.putBackToken(token);360 try ctx.decls.append(&node.base);
214 stack.append(State {361
215 .TopLevelDecl = TopLevelDeclCtx {362 stack.append(State {
216 .visib_token = visib_token,363 .ExpectTokenSave = ExpectTokenSave {
217 .extern_token = null,364 .id = Token.Id.Semicolon,
365 .ptr = &node.semicolon_token,
366 }
367 }) catch unreachable;
368 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
369 continue;
218 },370 },
219 }) catch unreachable;371 Token.Id.Keyword_extern => {
220 continue;372 const lib_name_token = self.getNextToken();
373 const lib_name = blk: {
374 if (lib_name_token.id == Token.Id.StringLiteral) {
375 const res = try self.createStringLiteral(arena, lib_name_token);
376 break :blk &res.base;
377 } else {
378 self.putBackToken(lib_name_token);
379 break :blk null;
380 }
381 };
382
383 stack.append(State {
384 .TopLevelDecl = TopLevelDeclCtx {
385 .decls = ctx.decls,
386 .visib_token = ctx.visib_token,
387 .extern_token = token,
388 .lib_name = lib_name,
389 },
390 }) catch unreachable;
391 continue;
392 },
393 else => {
394 self.putBackToken(token);
395 stack.append(State { .TopLevelDecl = ctx }) catch unreachable;
396 continue;
397 }
398 }
221 },399 },
222 State.TopLevelDecl => |ctx| {400 State.TopLevelDecl => |ctx| {
223 const token = self.getNextToken();401 const token = self.getNextToken();
224 switch (token.id) {402 switch (token.id) {
225 Token.Id.Keyword_var, Token.Id.Keyword_const => {403 Token.Id.Keyword_var, Token.Id.Keyword_const => {
226 stack.append(State.TopLevel) catch unreachable;
227 // TODO shouldn't need these casts404 // TODO shouldn't need these casts
228 const var_decl_node = try self.createAttachVarDecl(arena, &root_node.decls, ctx.visib_token,405 const var_decl_node = try self.createAttachVarDecl(arena, ctx.decls, ctx.visib_token,
229 token, (?Token)(null), ctx.extern_token);406 token, (?Token)(null), ctx.extern_token, ctx.lib_name);
230 try stack.append(State { .VarDecl = var_decl_node });407 stack.append(State { .VarDecl = var_decl_node }) catch unreachable;
231 continue;408 continue;
232 },409 },
233 Token.Id.Keyword_fn => {410 Token.Id.Keyword_fn => {
234 stack.append(State.TopLevel) catch unreachable;
235 // TODO shouldn't need these casts411 // TODO shouldn't need these casts
236 const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, token,412 const fn_proto = try self.createAttachFnProto(arena, ctx.decls, token,
237 ctx.extern_token, (?Token)(null), ctx.visib_token, (?Token)(null));413 ctx.extern_token, ctx.lib_name, (?Token)(null), ctx.visib_token, (?Token)(null));
238 try stack.append(State { .FnDef = fn_proto });414 stack.append(State { .FnDef = fn_proto }) catch unreachable;
239 try stack.append(State { .FnProto = fn_proto });415 try stack.append(State { .FnProto = fn_proto });
240 continue;416 continue;
241 },417 },
242 Token.Id.StringLiteral => {
243 @panic("TODO extern with string literal");
244 },
245 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {418 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
246 stack.append(State.TopLevel) catch unreachable;
247 const fn_token = try self.eatToken(Token.Id.Keyword_fn);
248 // TODO shouldn't need this cast419 // TODO shouldn't need this cast
249 const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, fn_token,420 const fn_proto = try self.createAttachFnProto(arena, ctx.decls, Token(undefined),
250 ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null));421 ctx.extern_token, ctx.lib_name, (?Token)(token), (?Token)(null), (?Token)(null));
251 try stack.append(State { .FnDef = fn_proto });422 stack.append(State { .FnDef = fn_proto }) catch unreachable;
423 try stack.append(State { .FnProto = fn_proto });
424 try stack.append(State {
425 .ExpectTokenSave = ExpectTokenSave {
426 .id = Token.Id.Keyword_fn,
427 .ptr = &fn_proto.fn_token,
428 }
429 });
430 continue;
431 },
432 Token.Id.Keyword_async => {
433 // TODO shouldn't need this cast
434 const fn_proto = try self.createAttachFnProto(arena, ctx.decls, Token(undefined),
435 ctx.extern_token, ctx.lib_name, (?Token)(null), (?Token)(null), (?Token)(null));
436
437 const async_node = try arena.create(ast.NodeAsyncAttribute);
438 *async_node = ast.NodeAsyncAttribute {
439 .base = self.initNode(ast.Node.Id.AsyncAttribute),
440 .async_token = token,
441 .allocator_type = null,
442 .rangle_bracket = null,
443 };
444
445 fn_proto.async_attr = async_node;
446 stack.append(State { .FnDef = fn_proto }) catch unreachable;
252 try stack.append(State { .FnProto = fn_proto });447 try stack.append(State { .FnProto = fn_proto });
448 try stack.append(State {
449 .ExpectTokenSave = ExpectTokenSave {
450 .id = Token.Id.Keyword_fn,
451 .ptr = &fn_proto.fn_token,
452 }
453 });
454
455 const langle_bracket = self.getNextToken();
456 if (langle_bracket.id != Token.Id.AngleBracketLeft) {
457 self.putBackToken(langle_bracket);
458 continue;
459 }
460
461 async_node.rangle_bracket = Token(undefined);
462 try stack.append(State {
463 .ExpectTokenSave = ExpectTokenSave {
464 .id = Token.Id.AngleBracketRight,
465 .ptr = &??async_node.rangle_bracket,
466 }
467 });
468 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } });
469 continue;
470 },
471 else => {
472 try self.parseError(&stack, token, "expected variable declaration or function, found {}", @tagName(token.id));
253 continue;473 continue;
254 },474 },
255 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),
256 }475 }
257 },476 },
258 State.VarDecl => |var_decl| {477 State.VarDecl => |var_decl| {
259 var_decl.name_token = try self.eatToken(Token.Id.Identifier);
260 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;478 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
261479 try stack.append(State { .TypeExprBegin = DestPtr {.NullableField = &var_decl.type_node} });
262 const next_token = self.getNextToken();480 try stack.append(State { .IfToken = Token.Id.Colon });
263 if (next_token.id == Token.Id.Colon) {481 try stack.append(State {
264 try stack.append(State { .TypeExpr = DestPtr {.NullableField = &var_decl.type_node} });482 .ExpectTokenSave = ExpectTokenSave {
265 continue;483 .id = Token.Id.Identifier,
266 }484 .ptr = &var_decl.name_token,
267485 }
268 self.putBackToken(next_token);486 });
269 continue;487 continue;
270 },488 },
271 State.VarDeclAlign => |var_decl| {489 State.VarDeclAlign => |var_decl| {
...@@ -273,9 +491,9 @@ pub const Parser = struct {...@@ -273,9 +491,9 @@ pub const Parser = struct {
273491
274 const next_token = self.getNextToken();492 const next_token = self.getNextToken();
275 if (next_token.id == Token.Id.Keyword_align) {493 if (next_token.id == Token.Id.Keyword_align) {
276 _ = try self.eatToken(Token.Id.LParen);
277 try stack.append(State { .ExpectToken = Token.Id.RParen });494 try stack.append(State { .ExpectToken = Token.Id.RParen });
278 try stack.append(State { .Expression = DestPtr{.NullableField = &var_decl.align_node} });495 try stack.append(State { .Expression = DestPtr{.NullableField = &var_decl.align_node} });
496 try stack.append(State { .ExpectToken = Token.Id.LParen });
279 continue;497 continue;
280 }498 }
281499
...@@ -301,243 +519,1617 @@ pub const Parser = struct {...@@ -301,243 +519,1617 @@ pub const Parser = struct {
301 var_decl.semicolon_token = token;519 var_decl.semicolon_token = token;
302 continue;520 continue;
303 }521 }
304 return self.parseError(token, "expected '=' or ';', found {}", @tagName(token.id));522 try self.parseError(&stack, token, "expected '=' or ';', found {}", @tagName(token.id));
523 continue;
524 },
525
526 State.ContainerExtern => |ctx| {
527 const token = self.getNextToken();
528
529 const node = try arena.create(ast.NodeContainerDecl);
530 *node = ast.NodeContainerDecl {
531 .base = self.initNode(ast.Node.Id.ContainerDecl),
532 .ltoken = ctx.ltoken,
533 .layout = ctx.layout,
534 .kind = switch (token.id) {
535 Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct,
536 Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union,
537 Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum,
538 else => {
539 try self.parseError(&stack, token, "expected {}, {} or {}, found {}",
540 @tagName(Token.Id.Keyword_struct),
541 @tagName(Token.Id.Keyword_union),
542 @tagName(Token.Id.Keyword_enum),
543 @tagName(token.id));
544 continue;
545 },
546 },
547 .init_arg_expr = undefined,
548 .fields_and_decls = ArrayList(&ast.Node).init(arena),
549 .rbrace_token = undefined,
550 };
551 ctx.dest_ptr.store(&node.base);
552
553 stack.append(State { .ContainerDecl = node }) catch unreachable;
554 try stack.append(State { .ExpectToken = Token.Id.LBrace });
555
556 const lparen = self.getNextToken();
557 if (lparen.id != Token.Id.LParen) {
558 self.putBackToken(lparen);
559 node.init_arg_expr = ast.NodeContainerDecl.InitArg.None;
560 continue;
561 }
562
563 try stack.append(State { .ExpectToken = Token.Id.RParen });
564
565 const init_arg_token = self.getNextToken();
566 switch (init_arg_token.id) {
567 Token.Id.Keyword_enum => {
568 node.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum;
569 },
570 else => {
571 self.putBackToken(init_arg_token);
572 node.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined };
573 try stack.append(State {
574 .Expression = DestPtr {
575 .Field = &node.init_arg_expr.Type
576 }
577 });
578 },
579 }
580 continue;
581 },
582
583 State.ContainerDecl => |container_decl| {
584 const token = self.getNextToken();
585
586 switch (token.id) {
587 Token.Id.Identifier => {
588 switch (container_decl.kind) {
589 ast.NodeContainerDecl.Kind.Struct => {
590 const node = try arena.create(ast.NodeStructField);
591 *node = ast.NodeStructField {
592 .base = self.initNode(ast.Node.Id.StructField),
593 .name_token = token,
594 .type_expr = undefined,
595 };
596 try container_decl.fields_and_decls.append(&node.base);
597
598 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
599 try stack.append(State { .Expression = DestPtr { .Field = &node.type_expr } });
600 try stack.append(State { .ExpectToken = Token.Id.Colon });
601 continue;
602 },
603 ast.NodeContainerDecl.Kind.Union => {
604 const node = try arena.create(ast.NodeUnionTag);
605 *node = ast.NodeUnionTag {
606 .base = self.initNode(ast.Node.Id.UnionTag),
607 .name_token = token,
608 .type_expr = null,
609 };
610 try container_decl.fields_and_decls.append(&node.base);
611
612 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
613
614 const next = self.getNextToken();
615 if (next.id != Token.Id.Colon) {
616 self.putBackToken(next);
617 continue;
618 }
619
620 try stack.append(State { .Expression = DestPtr { .NullableField = &node.type_expr } });
621 continue;
622 },
623 ast.NodeContainerDecl.Kind.Enum => {
624 const node = try arena.create(ast.NodeEnumTag);
625 *node = ast.NodeEnumTag {
626 .base = self.initNode(ast.Node.Id.EnumTag),
627 .name_token = token,
628 .value = null,
629 };
630 try container_decl.fields_and_decls.append(&node.base);
631
632 stack.append(State { .FieldListCommaOrEnd = container_decl }) catch unreachable;
633
634 const next = self.getNextToken();
635 if (next.id != Token.Id.Equal) {
636 self.putBackToken(next);
637 continue;
638 }
639
640 try stack.append(State { .Expression = DestPtr { .NullableField = &node.value } });
641 continue;
642 },
643 }
644 },
645 Token.Id.Keyword_pub, Token.Id.Keyword_export => {
646 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
647 try stack.append(State {
648 .TopLevelExtern = TopLevelDeclCtx {
649 .decls = &container_decl.fields_and_decls,
650 .visib_token = token,
651 .extern_token = null,
652 .lib_name = null,
653 }
654 });
655 continue;
656 },
657 Token.Id.RBrace => {
658 container_decl.rbrace_token = token;
659 continue;
660 },
661 else => {
662 self.putBackToken(token);
663 stack.append(State{ .ContainerDecl = container_decl }) catch unreachable;
664 try stack.append(State {
665 .TopLevelExtern = TopLevelDeclCtx {
666 .decls = &container_decl.fields_and_decls,
667 .visib_token = null,
668 .extern_token = null,
669 .lib_name = null,
670 }
671 });
672 continue;
673 }
674 }
305 },675 },
676
306 State.ExpectToken => |token_id| {677 State.ExpectToken => |token_id| {
307 _ = try self.eatToken(token_id);678 _ = (try self.eatToken(&stack, token_id)) ?? continue;
308 continue;679 continue;
309 },680 },
310681
311 State.ExpectTokenSave => |expect_token_save| {682 State.ExpectTokenSave => |expect_token_save| {
312 *expect_token_save.ptr = try self.eatToken(expect_token_save.id);683 *expect_token_save.ptr = (try self.eatToken(&stack, expect_token_save.id)) ?? continue;
313 continue;684 continue;
314 },685 },
315686
316 State.Expression => |dest_ptr| {687 State.IfToken => |token_id| {
317 // save the dest_ptr for later688 const token = self.getNextToken();
318 stack.append(state) catch unreachable;689 if (@TagType(Token.Id)(token.id) != token_id) {
319 try stack.append(State.ExpectOperand);690 self.putBackToken(token);
691 _ = stack.pop();
692 continue;
693 }
694 continue;
695 },
696
697 State.IfTokenSave => |if_token_save| {
698 const token = self.getNextToken();
699 if (@TagType(Token.Id)(token.id) != if_token_save.id) {
700 self.putBackToken(token);
701 _ = stack.pop();
702 continue;
703 }
704
705 *if_token_save.ptr = token;
320 continue;706 continue;
321 },707 },
322 State.ExpectOperand => {708
323 // we'll either get an operand (like 1 or x),709 State.Optional => { },
324 // or a prefix operator (like ~ or return).710
711 State.Expression => |dest_ptr| {
325 const token = self.getNextToken();712 const token = self.getNextToken();
326 switch (token.id) {713 switch (token.id) {
327 Token.Id.Keyword_return => {
328 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
329 ast.NodePrefixOp.PrefixOp.Return) });
330 try stack.append(State.ExpectOperand);
331 continue;
332 },
333 Token.Id.Keyword_try => {714 Token.Id.Keyword_try => {
334 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,715 const node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Try);
335 ast.NodePrefixOp.PrefixOp.Try) });716 dest_ptr.store(&node.base);
336 try stack.append(State.ExpectOperand);717
718 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
337 continue;719 continue;
338 },720 },
339 Token.Id.Minus => {721 Token.Id.Keyword_return => {
340 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,722 const node = try self.createControlFlowExpr(arena, token, ast.NodeControlFlowExpression.Kind.Return);
341 ast.NodePrefixOp.PrefixOp.Negation) });723 dest_ptr.store(&node.base);
342 try stack.append(State.ExpectOperand);724
725 stack.append(State {
726 .Optional = RevertState {
727 .parser = *self,
728 .tokenizer = *self.tokenizer,
729 .ptr = &node.rhs,
730 }
731 }) catch unreachable;
732 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });
343 continue;733 continue;
344 },734 },
345 Token.Id.MinusPercent => {735 Token.Id.Keyword_break => {
346 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,736 const label = blk: {
347 ast.NodePrefixOp.PrefixOp.NegationWrap) });737 const colon = self.getNextToken();
348 try stack.append(State.ExpectOperand);738 if (colon.id != Token.Id.Colon) {
739 self.putBackToken(colon);
740 break :blk null;
741 }
742
743 break :blk (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
744 };
745
746 const node = try self.createControlFlowExpr(arena, token,
747 ast.NodeControlFlowExpression.Kind {
748 .Break = label,
749 }
750 );
751 dest_ptr.store(&node.base);
752
753 stack.append(State {
754 .Optional = RevertState {
755 .parser = *self,
756 .tokenizer = *self.tokenizer,
757 .ptr = &node.rhs,
758 }
759 }) catch unreachable;
760 try stack.append(State { .Expression = DestPtr { .NullableField = &node.rhs } });
349 continue;761 continue;
350 },762 },
351 Token.Id.Tilde => {763 Token.Id.Keyword_continue => {
352 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,764 const label = blk: {
353 ast.NodePrefixOp.PrefixOp.BitNot) });765 const colon = self.getNextToken();
354 try stack.append(State.ExpectOperand);766 if (colon.id != Token.Id.Colon) {
767 self.putBackToken(colon);
768 break :blk null;
769 }
770
771 break :blk (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
772 };
773
774 const node = try self.createControlFlowExpr(arena, token,
775 ast.NodeControlFlowExpression.Kind {
776 .Continue = label,
777 }
778 );
779 dest_ptr.store(&node.base);
355 continue;780 continue;
356 },781 },
357 Token.Id.QuestionMarkQuestionMark => {782 Token.Id.Keyword_cancel => {
358 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,783 const cancel_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Cancel);
359 ast.NodePrefixOp.PrefixOp.UnwrapMaybe) });784 dest_ptr.store(&cancel_node.base);
360 try stack.append(State.ExpectOperand);785 stack.append(State { .Expression = DestPtr { .Field = &cancel_node.rhs } }) catch unreachable;
361 continue;
362 },786 },
363 Token.Id.Bang => {787 Token.Id.Keyword_resume => {
364 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,788 const resume_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Resume);
365 ast.NodePrefixOp.PrefixOp.BoolNot) });789 dest_ptr.store(&resume_node.base);
366 try stack.append(State.ExpectOperand);790 stack.append(State { .Expression = DestPtr { .Field = &resume_node.rhs } }) catch unreachable;
791 },
792 Token.Id.Keyword_suspend => {
793 const node = try arena.create(ast.NodeSuspend);
794 *node = ast.NodeSuspend {
795 .base = self.initNode(ast.Node.Id.Suspend),
796 .suspend_token = token,
797 .payload = null,
798 .body = null,
799 };
800 dest_ptr.store(&node.base);
801 stack.append(State { .SuspendBody = node }) catch unreachable;
802 try stack.append(State { .Payload = &node.payload });
367 continue;803 continue;
368 },804 },
369 Token.Id.Asterisk => {805 Token.Id.Keyword_if => {
370 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,806 const node = try arena.create(ast.NodeIf);
371 ast.NodePrefixOp.PrefixOp.Deref) });807 *node = ast.NodeIf {
372 try stack.append(State.ExpectOperand);808 .base = self.initNode(ast.Node.Id.If),
809 .if_token = token,
810 .condition = undefined,
811 .payload = null,
812 .body = undefined,
813 .@"else" = null,
814 };
815 dest_ptr.store(&node.base);
816
817 stack.append(State { .Else = &node.@"else" }) catch unreachable;
818 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
819 try stack.append(State { .PointerPayload = &node.payload });
820 try stack.append(State { .ExpectToken = Token.Id.RParen });
821 try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
822 try stack.append(State { .ExpectToken = Token.Id.LParen });
373 continue;823 continue;
374 },824 },
375 Token.Id.Ampersand => {825 Token.Id.Keyword_while => {
376 const prefix_op = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{826 stack.append(State {
377 .AddrOf = ast.NodePrefixOp.AddrOfInfo {827 .While = LoopCtx {
378 .align_expr = null,828 .label = null,
379 .bit_offset_start_token = null,829 .inline_token = null,
380 .bit_offset_end_token = null,830 .loop_token = token,
381 .const_token = null,831 .dest_ptr = dest_ptr,
382 .volatile_token = null,
383 }832 }
384 });833 }) catch unreachable;
385 try stack.append(State { .PrefixOp = prefix_op });
386 try stack.append(State.ExpectOperand);
387 try stack.append(State { .AddrOfModifiers = &prefix_op.op.AddrOf });
388 continue;834 continue;
389 },835 },
390 Token.Id.Identifier => {836 Token.Id.Keyword_for => {
391 try stack.append(State {837 stack.append(State {
392 .Operand = &(try self.createIdentifier(arena, token)).base838 .For = LoopCtx {
393 });839 .label = null,
394 try stack.append(State.AfterOperand);840 .inline_token = null,
841 .loop_token = token,
842 .dest_ptr = dest_ptr,
843 }
844 }) catch unreachable;
395 continue;845 continue;
396 },846 },
397 Token.Id.IntegerLiteral => {847 Token.Id.Keyword_switch => {
398 try stack.append(State {848 const node = try arena.create(ast.NodeSwitch);
399 .Operand = &(try self.createIntegerLiteral(arena, token)).base849 *node = ast.NodeSwitch {
400 });850 .base = self.initNode(ast.Node.Id.Switch),
401 try stack.append(State.AfterOperand);851 .switch_token = token,
402 continue;852 .expr = undefined,
853 .cases = ArrayList(&ast.NodeSwitchCase).init(arena),
854 .rbrace = undefined,
855 };
856 dest_ptr.store(&node.base);
857
858 stack.append(State {
859 .SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) {
860 .list = &node.cases,
861 .ptr = &node.rbrace,
862 },
863 }) catch unreachable;
864 try stack.append(State { .ExpectToken = Token.Id.LBrace });
865 try stack.append(State { .ExpectToken = Token.Id.RParen });
866 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
867 try stack.append(State { .ExpectToken = Token.Id.LParen });
403 },868 },
404 Token.Id.FloatLiteral => {869 Token.Id.Keyword_comptime => {
405 try stack.append(State {870 const node = try arena.create(ast.NodeComptime);
406 .Operand = &(try self.createFloatLiteral(arena, token)).base871 *node = ast.NodeComptime {
407 });872 .base = self.initNode(ast.Node.Id.Comptime),
408 try stack.append(State.AfterOperand);873 .comptime_token = token,
874 .expr = undefined,
875 };
876 dest_ptr.store(&node.base);
877 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
409 continue;878 continue;
410 },879 },
411 Token.Id.Keyword_undefined => {880 Token.Id.LBrace => {
412 try stack.append(State {881 const block = try self.createBlock(arena, (?Token)(null), token);
413 .Operand = &(try self.createUndefined(arena, token)).base882 dest_ptr.store(&block.base);
414 });883
415 try stack.append(State.AfterOperand);884 stack.append(State { .Block = block }) catch unreachable;
416 continue;885 continue;
417 },886 },
418 Token.Id.Builtin => {887 else => {
419 const node = try arena.create(ast.NodeBuiltinCall);888 self.putBackToken(token);
420 *node = ast.NodeBuiltinCall {889 stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable;
421 .base = self.initNode(ast.Node.Id.BuiltinCall),890 continue;
422 .builtin_token = token,891 }
423 .params = ArrayList(&ast.Node).init(arena),892 }
424 .rparen_token = undefined,893 },
425 };894
895 State.RangeExpressionBegin => |dest_ptr| {
896 stack.append(State { .RangeExpressionEnd = dest_ptr }) catch unreachable;
897 try stack.append(State { .Expression = dest_ptr });
898 continue;
899 },
900
901 State.RangeExpressionEnd => |dest_ptr| {
902 const token = self.getNextToken();
903 if (token.id == Token.Id.Ellipsis3) {
904 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.Range);
905 node.lhs = dest_ptr.get();
906 dest_ptr.store(&node.base);
907
908 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
909 continue;
910 } else {
911 self.putBackToken(token);
912 continue;
913 }
914 },
915
916 State.AssignmentExpressionBegin => |dest_ptr| {
917 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
918 try stack.append(State { .Expression = dest_ptr });
919 continue;
920 },
921
922 State.AssignmentExpressionEnd => |dest_ptr| {
923 const token = self.getNextToken();
924 if (tokenIdToAssignment(token.id)) |ass_id| {
925 const node = try self.createInfixOp(arena, token, ass_id);
926 node.lhs = dest_ptr.get();
927 dest_ptr.store(&node.base);
928
929 stack.append(State { .AssignmentExpressionEnd = dest_ptr }) catch unreachable;
930 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
931 continue;
932 } else {
933 self.putBackToken(token);
934 continue;
935 }
936 },
937
938 State.UnwrapExpressionBegin => |dest_ptr| {
939 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
940 try stack.append(State { .BoolOrExpressionBegin = dest_ptr });
941 continue;
942 },
943
944 State.UnwrapExpressionEnd => |dest_ptr| {
945 const token = self.getNextToken();
946 switch (token.id) {
947 Token.Id.Keyword_catch => {
948 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp { .Catch = null });
949 node.lhs = dest_ptr.get();
950 dest_ptr.store(&node.base);
951
952 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
953 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
954 try stack.append(State { .Payload = &node.op.Catch });
955 continue;
956 },
957 Token.Id.QuestionMarkQuestionMark => {
958 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.UnwrapMaybe);
959 node.lhs = dest_ptr.get();
960 dest_ptr.store(&node.base);
961
962 stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable;
963 try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } });
964 continue;
965 },
966 else => {
967 self.putBackToken(token);
968 continue;
969 },
970 }
971 },
972
973 State.BoolOrExpressionBegin => |dest_ptr| {
974 stack.append(State { .BoolOrExpressionEnd = dest_ptr }) catch unreachable;
975 try stack.append(State { .BoolAndExpressionBegin = dest_ptr });
976 continue;
977 },
978
979 State.BoolOrExpressionEnd => |dest_ptr| {
980 const token = self.getNextToken();
981 switch (token.id) {
982 Token.Id.Keyword_or => {
983 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BoolOr);
984 node.lhs = dest_ptr.get();
985 dest_ptr.store(&node.base);
986
987 stack.append(State { .BoolOrExpressionEnd = dest_ptr }) catch unreachable;
988 try stack.append(State { .BoolAndExpressionBegin = DestPtr { .Field = &node.rhs } });
989 continue;
990 },
991 else => {
992 self.putBackToken(token);
993 continue;
994 },
995 }
996 },
997
998 State.BoolAndExpressionBegin => |dest_ptr| {
999 stack.append(State { .BoolAndExpressionEnd = dest_ptr }) catch unreachable;
1000 try stack.append(State { .ComparisonExpressionBegin = dest_ptr });
1001 continue;
1002 },
1003
1004 State.BoolAndExpressionEnd => |dest_ptr| {
1005 const token = self.getNextToken();
1006 switch (token.id) {
1007 Token.Id.Keyword_and => {
1008 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BoolAnd);
1009 node.lhs = dest_ptr.get();
1010 dest_ptr.store(&node.base);
1011
1012 stack.append(State { .BoolAndExpressionEnd = dest_ptr }) catch unreachable;
1013 try stack.append(State { .ComparisonExpressionBegin = DestPtr { .Field = &node.rhs } });
1014 continue;
1015 },
1016 else => {
1017 self.putBackToken(token);
1018 continue;
1019 },
1020 }
1021 },
1022
1023 State.ComparisonExpressionBegin => |dest_ptr| {
1024 stack.append(State { .ComparisonExpressionEnd = dest_ptr }) catch unreachable;
1025 try stack.append(State { .BinaryOrExpressionBegin = dest_ptr });
1026 continue;
1027 },
1028
1029 State.ComparisonExpressionEnd => |dest_ptr| {
1030 const token = self.getNextToken();
1031 if (tokenIdToComparison(token.id)) |comp_id| {
1032 const node = try self.createInfixOp(arena, token, comp_id);
1033 node.lhs = dest_ptr.get();
1034 dest_ptr.store(&node.base);
1035
1036 stack.append(State { .ComparisonExpressionEnd = dest_ptr }) catch unreachable;
1037 try stack.append(State { .BinaryOrExpressionBegin = DestPtr { .Field = &node.rhs } });
1038 continue;
1039 } else {
1040 self.putBackToken(token);
1041 continue;
1042 }
1043 },
1044
1045 State.BinaryOrExpressionBegin => |dest_ptr| {
1046 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;
1047 try stack.append(State { .BinaryXorExpressionBegin = dest_ptr });
1048 continue;
1049 },
1050
1051 State.BinaryOrExpressionEnd => |dest_ptr| {
1052 const token = self.getNextToken();
1053 switch (token.id) {
1054 Token.Id.Pipe => {
1055 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BitOr);
1056 node.lhs = dest_ptr.get();
1057 dest_ptr.store(&node.base);
1058
1059 stack.append(State { .BinaryOrExpressionEnd = dest_ptr }) catch unreachable;
1060 try stack.append(State { .BinaryXorExpressionBegin = DestPtr { .Field = &node.rhs } });
1061 continue;
1062 },
1063 else => {
1064 self.putBackToken(token);
1065 continue;
1066 },
1067 }
1068 },
1069
1070 State.BinaryXorExpressionBegin => |dest_ptr| {
1071 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;
1072 try stack.append(State { .BinaryAndExpressionBegin = dest_ptr });
1073 continue;
1074 },
1075
1076 State.BinaryXorExpressionEnd => |dest_ptr| {
1077 const token = self.getNextToken();
1078 switch (token.id) {
1079 Token.Id.Caret => {
1080 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BitXor);
1081 node.lhs = dest_ptr.get();
1082 dest_ptr.store(&node.base);
1083
1084 stack.append(State { .BinaryXorExpressionEnd = dest_ptr }) catch unreachable;
1085 try stack.append(State { .BinaryAndExpressionBegin = DestPtr { .Field = &node.rhs } });
1086 continue;
1087 },
1088 else => {
1089 self.putBackToken(token);
1090 continue;
1091 },
1092 }
1093 },
1094
1095 State.BinaryAndExpressionBegin => |dest_ptr| {
1096 stack.append(State { .BinaryAndExpressionEnd = dest_ptr }) catch unreachable;
1097 try stack.append(State { .BitShiftExpressionBegin = dest_ptr });
1098 continue;
1099 },
1100
1101 State.BinaryAndExpressionEnd => |dest_ptr| {
1102 const token = self.getNextToken();
1103 switch (token.id) {
1104 Token.Id.Ampersand => {
1105 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.BitAnd);
1106 node.lhs = dest_ptr.get();
1107 dest_ptr.store(&node.base);
1108
1109 stack.append(State { .BinaryAndExpressionEnd = dest_ptr }) catch unreachable;
1110 try stack.append(State { .BitShiftExpressionBegin = DestPtr { .Field = &node.rhs } });
1111 continue;
1112 },
1113 else => {
1114 self.putBackToken(token);
1115 continue;
1116 },
1117 }
1118 },
1119
1120 State.BitShiftExpressionBegin => |dest_ptr| {
1121 stack.append(State { .BitShiftExpressionEnd = dest_ptr }) catch unreachable;
1122 try stack.append(State { .AdditionExpressionBegin = dest_ptr });
1123 continue;
1124 },
1125
1126 State.BitShiftExpressionEnd => |dest_ptr| {
1127 const token = self.getNextToken();
1128 if (tokenIdToBitShift(token.id)) |bitshift_id| {
1129 const node = try self.createInfixOp(arena, token, bitshift_id);
1130 node.lhs = dest_ptr.get();
1131 dest_ptr.store(&node.base);
1132
1133 stack.append(State { .BitShiftExpressionEnd = dest_ptr }) catch unreachable;
1134 try stack.append(State { .AdditionExpressionBegin = DestPtr { .Field = &node.rhs } });
1135 continue;
1136 } else {
1137 self.putBackToken(token);
1138 continue;
1139 }
1140 },
1141
1142 State.AdditionExpressionBegin => |dest_ptr| {
1143 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;
1144 try stack.append(State { .MultiplyExpressionBegin = dest_ptr });
1145 continue;
1146 },
1147
1148 State.AdditionExpressionEnd => |dest_ptr| {
1149 const token = self.getNextToken();
1150 if (tokenIdToAddition(token.id)) |add_id| {
1151 const node = try self.createInfixOp(arena, token, add_id);
1152 node.lhs = dest_ptr.get();
1153 dest_ptr.store(&node.base);
1154
1155 stack.append(State { .AdditionExpressionEnd = dest_ptr }) catch unreachable;
1156 try stack.append(State { .MultiplyExpressionBegin = DestPtr { .Field = &node.rhs } });
1157 continue;
1158 } else {
1159 self.putBackToken(token);
1160 continue;
1161 }
1162 },
1163
1164 State.MultiplyExpressionBegin => |dest_ptr| {
1165 stack.append(State { .MultiplyExpressionEnd = dest_ptr }) catch unreachable;
1166 try stack.append(State { .CurlySuffixExpressionBegin = dest_ptr });
1167 continue;
1168 },
1169
1170 State.MultiplyExpressionEnd => |dest_ptr| {
1171 const token = self.getNextToken();
1172 if (tokenIdToMultiply(token.id)) |mult_id| {
1173 const node = try self.createInfixOp(arena, token, mult_id);
1174 node.lhs = dest_ptr.get();
1175 dest_ptr.store(&node.base);
1176
1177 stack.append(State { .MultiplyExpressionEnd = dest_ptr }) catch unreachable;
1178 try stack.append(State { .CurlySuffixExpressionBegin = DestPtr { .Field = &node.rhs } });
1179 continue;
1180 } else {
1181 self.putBackToken(token);
1182 continue;
1183 }
1184 },
1185
1186 State.CurlySuffixExpressionBegin => |dest_ptr| {
1187 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
1188 try stack.append(State { .TypeExprBegin = dest_ptr });
1189 continue;
1190 },
1191
1192 State.CurlySuffixExpressionEnd => |dest_ptr| {
1193 const token = self.getNextToken();
1194 if (token.id != Token.Id.LBrace) {
1195 self.putBackToken(token);
1196 continue;
1197 }
1198
1199 const next = self.getNextToken();
1200 switch (next.id) {
1201 Token.Id.Period => {
1202 const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
1203 .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena),
1204 });
1205 node.lhs = dest_ptr.get();
1206 dest_ptr.store(&node.base);
1207
1208 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
426 try stack.append(State {1209 try stack.append(State {
427 .Operand = &node.base1210 .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) {
1211 .list = &node.op.StructInitializer,
1212 .ptr = &node.rtoken,
1213 }
1214 });
1215 self.putBackToken(next);
1216 continue;
1217 },
1218 else => {
1219 const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
1220 .ArrayInitializer = ArrayList(&ast.Node).init(arena),
428 });1221 });
429 try stack.append(State.AfterOperand);1222 node.lhs = dest_ptr.get();
430 try stack.append(State {.ExprListItemOrEnd = &node.params });1223 dest_ptr.store(&node.base);
1224
1225 stack.append(State { .CurlySuffixExpressionEnd = dest_ptr }) catch unreachable;
1226 try stack.append(State {
1227 .ExprListItemOrEnd = ExprListCtx {
1228 .list = &node.op.ArrayInitializer,
1229 .end = Token.Id.RBrace,
1230 .ptr = &node.rtoken,
1231 }
1232 });
1233 self.putBackToken(next);
1234 continue;
1235 },
1236 }
1237 },
1238
1239 State.TypeExprBegin => |dest_ptr| {
1240 stack.append(State { .TypeExprEnd = dest_ptr }) catch unreachable;
1241 try stack.append(State { .PrefixOpExpression = dest_ptr });
1242 continue;
1243 },
1244
1245 State.TypeExprEnd => |dest_ptr| {
1246 const token = self.getNextToken();
1247 switch (token.id) {
1248 Token.Id.Bang => {
1249 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.ErrorUnion);
1250 node.lhs = dest_ptr.get();
1251 dest_ptr.store(&node.base);
1252
1253 stack.append(State { .TypeExprEnd = dest_ptr }) catch unreachable;
1254 try stack.append(State { .PrefixOpExpression = DestPtr { .Field = &node.rhs } });
1255 continue;
1256 },
1257 else => {
1258 self.putBackToken(token);
1259 continue;
1260 },
1261 }
1262 },
1263
1264 State.PrefixOpExpression => |dest_ptr| {
1265 const token = self.getNextToken();
1266 if (tokenIdToPrefixOp(token.id)) |prefix_id| {
1267 const node = try self.createPrefixOp(arena, token, prefix_id);
1268 dest_ptr.store(&node.base);
1269
1270 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1271 if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) {
1272 try stack.append(State { .AddrOfModifiers = &node.op.AddrOf });
1273 }
1274 continue;
1275 } else {
1276 self.putBackToken(token);
1277 stack.append(State { .SuffixOpExpressionBegin = dest_ptr }) catch unreachable;
1278 continue;
1279 }
1280 },
1281
1282 State.SuffixOpExpressionBegin => |dest_ptr| {
1283 const token = self.getNextToken();
1284 switch (token.id) {
1285 Token.Id.Keyword_async => {
1286 const async_node = try arena.create(ast.NodeAsyncAttribute);
1287 *async_node = ast.NodeAsyncAttribute {
1288 .base = self.initNode(ast.Node.Id.AsyncAttribute),
1289 .async_token = token,
1290 .allocator_type = null,
1291 .rangle_bracket = null,
1292 };
1293
1294 stack.append(State {
1295 .AsyncEnd = AsyncEndCtx {
1296 .dest_ptr = dest_ptr,
1297 .attribute = async_node,
1298 }
1299 }) catch unreachable;
1300 try stack.append(State { .SuffixOpExpressionEnd = dest_ptr });
1301 try stack.append(State { .PrimaryExpression = dest_ptr });
1302
1303 const langle_bracket = self.getNextToken();
1304 if (langle_bracket.id != Token.Id.AngleBracketLeft) {
1305 self.putBackToken(langle_bracket);
1306 continue;
1307 }
1308
1309 async_node.rangle_bracket = Token(undefined);
431 try stack.append(State {1310 try stack.append(State {
432 .ExpectTokenSave = ExpectTokenSave {1311 .ExpectTokenSave = ExpectTokenSave {
433 .id = Token.Id.LParen,1312 .id = Token.Id.AngleBracketRight,
434 .ptr = &node.rparen_token,1313 .ptr = &??async_node.rangle_bracket,
435 },1314 }
436 });1315 });
1316 try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } });
1317 continue;
1318 },
1319 else => {
1320 self.putBackToken(token);
1321 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1322 try stack.append(State { .PrimaryExpression = dest_ptr });
1323 continue;
1324 }
1325 }
1326 },
1327
1328 State.SuffixOpExpressionEnd => |dest_ptr| {
1329 const token = self.getNextToken();
1330 switch (token.id) {
1331 Token.Id.LParen => {
1332 const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp {
1333 .Call = ast.NodeSuffixOp.CallInfo {
1334 .params = ArrayList(&ast.Node).init(arena),
1335 .async_attr = null,
1336 }
1337 });
1338 node.lhs = dest_ptr.get();
1339 dest_ptr.store(&node.base);
1340
1341 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1342 try stack.append(State {
1343 .ExprListItemOrEnd = ExprListCtx {
1344 .list = &node.op.Call.params,
1345 .end = Token.Id.RParen,
1346 .ptr = &node.rtoken,
1347 }
1348 });
1349 continue;
1350 },
1351 Token.Id.LBracket => {
1352 const node = try arena.create(ast.NodeSuffixOp);
1353 *node = ast.NodeSuffixOp {
1354 .base = self.initNode(ast.Node.Id.SuffixOp),
1355 .lhs = undefined,
1356 .op = ast.NodeSuffixOp.SuffixOp {
1357 .ArrayAccess = undefined,
1358 },
1359 .rtoken = undefined,
1360 };
1361 node.lhs = dest_ptr.get();
1362 dest_ptr.store(&node.base);
1363
1364 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1365 try stack.append(State { .SliceOrArrayAccess = node });
1366 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayAccess }});
1367 continue;
1368 },
1369 Token.Id.Period => {
1370 const node = try self.createInfixOp(arena, token, ast.NodeInfixOp.InfixOp.Period);
1371 node.lhs = dest_ptr.get();
1372 dest_ptr.store(&node.base);
1373
1374 stack.append(State { .SuffixOpExpressionEnd = dest_ptr }) catch unreachable;
1375 try stack.append(State { .SuffixOpExpressionBegin = DestPtr { .Field = &node.rhs }});
1376 continue;
1377 },
1378 else => {
1379 self.putBackToken(token);
1380 continue;
1381 },
1382 }
1383 },
1384
1385 State.PrimaryExpression => |dest_ptr| {
1386 const token = self.getNextToken();
1387 switch (token.id) {
1388 Token.Id.IntegerLiteral => {
1389 dest_ptr.store(&(try self.createIntegerLiteral(arena, token)).base);
1390 continue;
1391 },
1392 Token.Id.FloatLiteral => {
1393 dest_ptr.store(&(try self.createFloatLiteral(arena, token)).base);
1394 continue;
1395 },
1396 Token.Id.StringLiteral => {
1397 dest_ptr.store(&(try self.createStringLiteral(arena, token)).base);
1398 continue;
1399 },
1400 Token.Id.CharLiteral => {
1401 const node = try arena.create(ast.NodeCharLiteral);
1402 *node = ast.NodeCharLiteral {
1403 .base = self.initNode(ast.Node.Id.CharLiteral),
1404 .token = token,
1405 };
1406 dest_ptr.store(&node.base);
1407 continue;
1408 },
1409 Token.Id.Keyword_undefined => {
1410 dest_ptr.store(&(try self.createUndefined(arena, token)).base);
1411 continue;
1412 },
1413 Token.Id.Keyword_true, Token.Id.Keyword_false => {
1414 const node = try arena.create(ast.NodeBoolLiteral);
1415 *node = ast.NodeBoolLiteral {
1416 .base = self.initNode(ast.Node.Id.BoolLiteral),
1417 .token = token,
1418 };
1419 dest_ptr.store(&node.base);
1420 continue;
1421 },
1422 Token.Id.Keyword_null => {
1423 const node = try arena.create(ast.NodeNullLiteral);
1424 *node = ast.NodeNullLiteral {
1425 .base = self.initNode(ast.Node.Id.NullLiteral),
1426 .token = token,
1427 };
1428 dest_ptr.store(&node.base);
437 continue;1429 continue;
438 },1430 },
439 Token.Id.StringLiteral => {1431 Token.Id.Keyword_this => {
440 const node = try arena.create(ast.NodeStringLiteral);1432 const node = try arena.create(ast.NodeThisLiteral);
441 *node = ast.NodeStringLiteral {1433 *node = ast.NodeThisLiteral {
442 .base = self.initNode(ast.Node.Id.StringLiteral),1434 .base = self.initNode(ast.Node.Id.ThisLiteral),
443 .token = token,1435 .token = token,
444 };1436 };
445 try stack.append(State {1437 dest_ptr.store(&node.base);
446 .Operand = &node.base1438 continue;
447 });1439 },
448 try stack.append(State.AfterOperand);1440 Token.Id.Keyword_var => {
1441 const node = try arena.create(ast.NodeVarType);
1442 *node = ast.NodeVarType {
1443 .base = self.initNode(ast.Node.Id.VarType),
1444 .token = token,
1445 };
1446 dest_ptr.store(&node.base);
1447 },
1448 Token.Id.Keyword_unreachable => {
1449 const node = try arena.create(ast.NodeUnreachable);
1450 *node = ast.NodeUnreachable {
1451 .base = self.initNode(ast.Node.Id.Unreachable),
1452 .token = token,
1453 };
1454 dest_ptr.store(&node.base);
449 continue;1455 continue;
450 },1456 },
1457 Token.Id.MultilineStringLiteralLine => {
1458 const node = try arena.create(ast.NodeMultilineStringLiteral);
1459 *node = ast.NodeMultilineStringLiteral {
1460 .base = self.initNode(ast.Node.Id.MultilineStringLiteral),
1461 .tokens = ArrayList(Token).init(arena),
1462 };
1463 dest_ptr.store(&node.base);
1464 try node.tokens.append(token);
4511465
452 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),1466 while (true) {
453 }1467 const multiline_str = self.getNextToken();
454 },1468 if (multiline_str.id != Token.Id.MultilineStringLiteralLine) {
1469 self.putBackToken(multiline_str);
1470 break;
1471 }
4551472
456 State.AfterOperand => {1473 try node.tokens.append(multiline_str);
457 // we'll either get an infix operator (like != or ^),1474 }
458 // or a postfix operator (like () or {}),1475 continue;
459 // otherwise this expression is done (like on a ; or else).1476 },
460 var token = self.getNextToken();1477 Token.Id.LParen => {
461 if (tokenIdToInfixOp(token.id)) |infix_id| {1478 const node = try arena.create(ast.NodeGroupedExpression);
462 try stack.append(State {1479 *node = ast.NodeGroupedExpression {
463 .InfixOp = try self.createInfixOp(arena, token, infix_id)1480 .base = self.initNode(ast.Node.Id.GroupedExpression),
464 });1481 .lparen = token,
465 try stack.append(State.ExpectOperand);1482 .expr = undefined,
1483 .rparen = undefined,
1484 };
1485 dest_ptr.store(&node.base);
1486 stack.append(State {
1487 .ExpectTokenSave = ExpectTokenSave {
1488 .id = Token.Id.RParen,
1489 .ptr = &node.rparen,
1490 }
1491 }) catch unreachable;
1492 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1493 continue;
1494 },
1495 Token.Id.Builtin => {
1496 const node = try arena.create(ast.NodeBuiltinCall);
1497 *node = ast.NodeBuiltinCall {
1498 .base = self.initNode(ast.Node.Id.BuiltinCall),
1499 .builtin_token = token,
1500 .params = ArrayList(&ast.Node).init(arena),
1501 .rparen_token = undefined,
1502 };
1503 dest_ptr.store(&node.base);
1504 stack.append(State {
1505 .ExprListItemOrEnd = ExprListCtx {
1506 .list = &node.params,
1507 .end = Token.Id.RParen,
1508 .ptr = &node.rparen_token,
1509 }
1510 }) catch unreachable;
1511 try stack.append(State { .ExpectToken = Token.Id.LParen, });
466 continue;1512 continue;
1513 },
1514 Token.Id.LBracket => {
1515 const rbracket_token = self.getNextToken();
1516 if (rbracket_token.id == Token.Id.RBracket) {
1517 const node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{
1518 .SliceType = ast.NodePrefixOp.AddrOfInfo {
1519 .align_expr = null,
1520 .bit_offset_start_token = null,
1521 .bit_offset_end_token = null,
1522 .const_token = null,
1523 .volatile_token = null,
1524 }
1525 });
1526 dest_ptr.store(&node.base);
1527 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1528 try stack.append(State { .AddrOfModifiers = &node.op.SliceType });
1529 continue;
1530 }
4671531
468 } else if (token.id == Token.Id.LParen) {1532 self.putBackToken(rbracket_token);
469 self.putBackToken(token);
4701533
471 const node = try arena.create(ast.NodeCall);1534 const node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{
472 *node = ast.NodeCall {1535 .ArrayType = undefined,
473 .base = self.initNode(ast.Node.Id.Call),1536 });
474 .callee = undefined,1537 dest_ptr.store(&node.base);
475 .params = ArrayList(&ast.Node).init(arena),1538 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
476 .rparen_token = undefined,1539 try stack.append(State { .ExpectToken = Token.Id.RBracket });
477 };1540 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayType } });
478 try stack.append(State { .SuffixOp = &node.base });
479 try stack.append(State.AfterOperand);
480 try stack.append(State {.ExprListItemOrEnd = &node.params });
481 try stack.append(State {
482 .ExpectTokenSave = ExpectTokenSave {
483 .id = Token.Id.LParen,
484 .ptr = &node.rparen_token,
485 },
486 });
487 continue;
4881541
489 // TODO: Parse postfix operator1542 },
490 } else {1543 Token.Id.Keyword_error => {
491 // no postfix/infix operator after this operand.1544 const next = self.getNextToken();
492 self.putBackToken(token);1545
1546 if (next.id != Token.Id.LBrace) {
1547 self.putBackToken(next);
1548 const node = try arena.create(ast.NodeErrorType);
1549 *node = ast.NodeErrorType {
1550 .base = self.initNode(ast.Node.Id.ErrorType),
1551 .token = token,
1552 };
1553 dest_ptr.store(&node.base);
1554 continue;
1555 }
4931556
494 var expression = popSuffixOp(&stack);1557 const node = try arena.create(ast.NodeErrorSetDecl);
495 while (true) {1558 *node = ast.NodeErrorSetDecl {
496 switch (stack.pop()) {1559 .base = self.initNode(ast.Node.Id.ErrorSetDecl),
497 State.Expression => |dest_ptr| {1560 .error_token = token,
498 // we're done1561 .decls = ArrayList(&ast.NodeIdentifier).init(arena),
499 try dest_ptr.store(expression);1562 .rbrace_token = undefined,
500 break;1563 };
1564 dest_ptr.store(&node.base);
1565
1566 while (true) {
1567 const t = self.getNextToken();
1568 switch (t.id) {
1569 Token.Id.RBrace => {
1570 node.rbrace_token = t;
1571 break;
1572 },
1573 Token.Id.Identifier => {
1574 try node.decls.append(
1575 try self.createIdentifier(arena, t)
1576 );
1577 },
1578 else => {
1579 try self.parseError(&stack, token, "expected {} or {}, found {}",
1580 @tagName(Token.Id.RBrace),
1581 @tagName(Token.Id.Identifier),
1582 @tagName(token.id));
1583 continue;
1584 }
1585 }
1586
1587 const t2 = self.getNextToken();
1588 switch (t2.id) {
1589 Token.Id.RBrace => {
1590 node.rbrace_token = t;
1591 break;
1592 },
1593 Token.Id.Comma => continue,
1594 else => {
1595 try self.parseError(&stack, token, "expected {} or {}, found {}",
1596 @tagName(Token.Id.RBrace),
1597 @tagName(Token.Id.Comma),
1598 @tagName(token.id));
1599 continue;
1600 }
1601 }
1602 }
1603 continue;
1604 },
1605 Token.Id.Keyword_packed => {
1606 stack.append(State {
1607 .ContainerExtern = ContainerExternCtx {
1608 .dest_ptr = dest_ptr,
1609 .ltoken = token,
1610 .layout = ast.NodeContainerDecl.Layout.Packed,
501 },1611 },
502 State.InfixOp => |infix_op| {1612 }) catch unreachable;
503 infix_op.rhs = expression;1613 },
504 infix_op.lhs = popSuffixOp(&stack);1614 Token.Id.Keyword_extern => {
505 expression = &infix_op.base;1615 const next = self.getNextToken();
506 continue;1616 if (next.id == Token.Id.Keyword_fn) {
1617 // TODO shouldn't need this cast
1618 const fn_proto = try self.createFnProto(arena, next,
1619 (?Token)(token), (?&ast.Node)(null), (?Token)(null), (?Token)(null), (?Token)(null));
1620 dest_ptr.store(&fn_proto.base);
1621 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1622 continue;
1623 }
1624
1625 self.putBackToken(next);
1626 stack.append(State {
1627 .ContainerExtern = ContainerExternCtx {
1628 .dest_ptr = dest_ptr,
1629 .ltoken = token,
1630 .layout = ast.NodeContainerDecl.Layout.Extern,
507 },1631 },
508 State.PrefixOp => |prefix_op| {1632 }) catch unreachable;
509 prefix_op.rhs = expression;1633 },
510 expression = &prefix_op.base;1634 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
511 continue;1635 self.putBackToken(token);
1636 stack.append(State {
1637 .ContainerExtern = ContainerExternCtx {
1638 .dest_ptr = dest_ptr,
1639 .ltoken = token,
1640 .layout = ast.NodeContainerDecl.Layout.Auto,
512 },1641 },
513 else => unreachable,1642 }) catch unreachable;
1643 },
1644 Token.Id.Identifier => {
1645 const next = self.getNextToken();
1646 if (next.id != Token.Id.Colon) {
1647 self.putBackToken(next);
1648 dest_ptr.store(&(try self.createIdentifier(arena, token)).base);
1649 continue;
514 }1650 }
1651
1652 stack.append(State {
1653 .LabeledExpression = LabelCtx {
1654 .label = token,
1655 .dest_ptr = dest_ptr
1656 }
1657 }) catch unreachable;
1658 continue;
1659 },
1660 Token.Id.Keyword_fn => {
1661 // TODO shouldn't need these casts
1662 const fn_proto = try self.createFnProto(arena, token,
1663 (?Token)(null), (?&ast.Node)(null), (?Token)(null), (?Token)(null), (?Token)(null));
1664 dest_ptr.store(&fn_proto.base);
1665 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1666 continue;
1667 },
1668 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
1669 const fn_token = (try self.eatToken(&stack, Token.Id.Keyword_fn)) ?? continue;
1670 // TODO shouldn't need this cast
1671 const fn_proto = try self.createFnProto(arena, fn_token,
1672 (?Token)(null), (?&ast.Node)(null), (?Token)(token), (?Token)(null), (?Token)(null));
1673 dest_ptr.store(&fn_proto.base);
1674 stack.append(State { .FnProto = fn_proto }) catch unreachable;
1675 continue;
1676 },
1677 Token.Id.Keyword_asm => {
1678 const is_volatile = blk: {
1679 const volatile_token = self.getNextToken();
1680 if (volatile_token.id != Token.Id.Keyword_volatile) {
1681 self.putBackToken(volatile_token);
1682 break :blk false;
1683 }
1684 break :blk true;
1685 };
1686 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1687 const template = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1688 // TODO parse template
1689
1690 const node = try arena.create(ast.NodeAsm);
1691 *node = ast.NodeAsm {
1692 .base = self.initNode(ast.Node.Id.Asm),
1693 .asm_token = token,
1694 .is_volatile = is_volatile,
1695 .template = template,
1696 //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena),
1697 .outputs = ArrayList(&ast.NodeAsmOutput).init(arena),
1698 .inputs = ArrayList(&ast.NodeAsmInput).init(arena),
1699 .cloppers = ArrayList(&ast.NodeStringLiteral).init(arena),
1700 .rparen = undefined,
1701 };
1702 dest_ptr.store(&node.base);
1703
1704 stack.append(State {
1705 .ExpectTokenSave = ExpectTokenSave {
1706 .id = Token.Id.RParen,
1707 .ptr = &node.rparen,
1708 }
1709 }) catch unreachable;
1710 try stack.append(State { .AsmClopperItems = &node.cloppers });
1711 try stack.append(State { .IfToken = Token.Id.Colon });
1712 try stack.append(State { .AsmInputItems = &node.inputs });
1713 try stack.append(State { .IfToken = Token.Id.Colon });
1714 try stack.append(State { .AsmOutputItems = &node.outputs });
1715 try stack.append(State { .IfToken = Token.Id.Colon });
1716 },
1717 Token.Id.Keyword_inline => {
1718 stack.append(State {
1719 .Inline = InlineCtx {
1720 .label = null,
1721 .inline_token = token,
1722 .dest_ptr = dest_ptr,
1723 }
1724 }) catch unreachable;
1725 continue;
1726 },
1727 else => {
1728 try self.parseError(&stack, token, "expected primary expression, found {}", @tagName(token.id));
1729 continue;
515 }1730 }
516 continue;
517 }1731 }
518 },1732 },
5191733
520 State.ExprListItemOrEnd => |params| {1734 State.SliceOrArrayAccess => |node| {
521 var token = self.getNextToken();1735 var token = self.getNextToken();
1736
522 switch (token.id) {1737 switch (token.id) {
523 Token.Id.RParen => continue,1738 Token.Id.Ellipsis2 => {
1739 const start = node.op.ArrayAccess;
1740 node.op = ast.NodeSuffixOp.SuffixOp {
1741 .Slice = ast.NodeSuffixOp.SliceRange {
1742 .start = start,
1743 .end = undefined,
1744 }
1745 };
1746
1747 const rbracket_token = self.getNextToken();
1748 if (rbracket_token.id != Token.Id.RBracket) {
1749 self.putBackToken(rbracket_token);
1750 stack.append(State {
1751 .ExpectTokenSave = ExpectTokenSave {
1752 .id = Token.Id.RBracket,
1753 .ptr = &node.rtoken,
1754 }
1755 }) catch unreachable;
1756 try stack.append(State { .Expression = DestPtr { .NullableField = &node.op.Slice.end } });
1757 } else {
1758 node.rtoken = rbracket_token;
1759 }
1760 continue;
1761 },
1762 Token.Id.RBracket => {
1763 node.rtoken = token;
1764 continue;
1765 },
524 else => {1766 else => {
525 self.putBackToken(token);1767 try self.parseError(&stack, token, "expected ']' or '..', found {}", @tagName(token.id));
526 stack.append(State { .ExprListCommaOrEnd = params }) catch unreachable;1768 continue;
527 try stack.append(State { .Expression = DestPtr{.List = params} });1769 }
1770 }
1771 },
1772
1773
1774 State.AsmOutputItems => |items| {
1775 const lbracket = self.getNextToken();
1776 if (lbracket.id != Token.Id.LBracket) {
1777 self.putBackToken(lbracket);
1778 continue;
1779 }
1780
1781 stack.append(State { .AsmOutputItems = items }) catch unreachable;
1782 try stack.append(State { .IfToken = Token.Id.Comma });
1783
1784 const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
1785 _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
1786 const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1787
1788 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1789 try stack.append(State { .ExpectToken = Token.Id.RParen });
1790
1791 const node = try arena.create(ast.NodeAsmOutput);
1792 *node = ast.NodeAsmOutput {
1793 .base = self.initNode(ast.Node.Id.AsmOutput),
1794 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1795 .constraint = try self.createStringLiteral(arena, constraint),
1796 .kind = undefined,
1797 };
1798 try items.append(node);
1799
1800 const symbol_or_arrow = self.getNextToken();
1801 switch (symbol_or_arrow.id) {
1802 Token.Id.Identifier => {
1803 node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createIdentifier(arena, symbol_or_arrow) };
1804 },
1805 Token.Id.Arrow => {
1806 node.kind = ast.NodeAsmOutput.Kind { .Return = undefined };
1807 try stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.kind.Return } });
1808 },
1809 else => {
1810 try self.parseError(&stack, symbol_or_arrow, "expected '->' or {}, found {}",
1811 @tagName(Token.Id.Identifier),
1812 @tagName(symbol_or_arrow.id));
1813 continue;
1814 },
1815 }
1816 },
1817
1818 State.AsmInputItems => |items| {
1819 const lbracket = self.getNextToken();
1820 if (lbracket.id != Token.Id.LBracket) {
1821 self.putBackToken(lbracket);
1822 continue;
1823 }
1824
1825 stack.append(State { .AsmInputItems = items }) catch unreachable;
1826 try stack.append(State { .IfToken = Token.Id.Comma });
1827
1828 const symbolic_name = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
1829 _ = (try self.eatToken(&stack, Token.Id.RBracket)) ?? continue;
1830 const constraint = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
1831
1832 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
1833 try stack.append(State { .ExpectToken = Token.Id.RParen });
1834
1835 const node = try arena.create(ast.NodeAsmInput);
1836 *node = ast.NodeAsmInput {
1837 .base = self.initNode(ast.Node.Id.AsmInput),
1838 .symbolic_name = try self.createIdentifier(arena, symbolic_name),
1839 .constraint = try self.createStringLiteral(arena, constraint),
1840 .expr = undefined,
1841 };
1842 try items.append(node);
1843 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
1844 },
1845
1846 State.AsmClopperItems => |items| {
1847 const string = self.getNextToken();
1848 if (string.id != Token.Id.StringLiteral) {
1849 self.putBackToken(string);
1850 continue;
1851 }
1852
1853 try items.append(try self.createStringLiteral(arena, string));
1854 stack.append(State { .AsmClopperItems = items }) catch unreachable;
1855 try stack.append(State { .IfToken = Token.Id.Comma });
1856 },
1857
1858 State.ExprListItemOrEnd => |list_state| {
1859 var token = self.getNextToken();
1860
1861 const IdTag = @TagType(Token.Id);
1862 if (IdTag(list_state.end) == token.id) {
1863 *list_state.ptr = token;
1864 continue;
1865 }
1866
1867 self.putBackToken(token);
1868 stack.append(State { .ExprListCommaOrEnd = list_state }) catch unreachable;
1869 try stack.append(State { .Expression = DestPtr{ .Field = try list_state.list.addOne() } });
1870 },
1871
1872 State.FieldInitListItemOrEnd => |list_state| {
1873 var token = self.getNextToken();
1874
1875 if (token.id == Token.Id.RBrace){
1876 *list_state.ptr = token;
1877 continue;
1878 }
1879
1880 self.putBackToken(token);
1881
1882 const node = try arena.create(ast.NodeFieldInitializer);
1883 *node = ast.NodeFieldInitializer {
1884 .base = self.initNode(ast.Node.Id.FieldInitializer),
1885 .period_token = undefined,
1886 .name_token = undefined,
1887 .expr = undefined,
1888 };
1889 try list_state.list.append(node);
1890
1891 stack.append(State { .FieldInitListCommaOrEnd = list_state }) catch unreachable;
1892 try stack.append(State { .Expression = DestPtr{.Field = &node.expr} });
1893 try stack.append(State { .ExpectToken = Token.Id.Equal });
1894 try stack.append(State {
1895 .ExpectTokenSave = ExpectTokenSave {
1896 .id = Token.Id.Identifier,
1897 .ptr = &node.name_token,
1898 }
1899 });
1900 try stack.append(State {
1901 .ExpectTokenSave = ExpectTokenSave {
1902 .id = Token.Id.Period,
1903 .ptr = &node.period_token,
1904 }
1905 });
1906 },
1907
1908 State.SwitchCaseOrEnd => |list_state| {
1909 var token = self.getNextToken();
1910
1911 if (token.id == Token.Id.RBrace){
1912 *list_state.ptr = token;
1913 continue;
1914 }
1915
1916 self.putBackToken(token);
1917
1918 const node = try arena.create(ast.NodeSwitchCase);
1919 *node = ast.NodeSwitchCase {
1920 .base = self.initNode(ast.Node.Id.SwitchCase),
1921 .items = ArrayList(&ast.Node).init(arena),
1922 .payload = null,
1923 .expr = undefined,
1924 };
1925 try list_state.list.append(node);
1926 stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable;
1927 try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } });
1928 try stack.append(State { .PointerPayload = &node.payload });
1929
1930 const maybe_else = self.getNextToken();
1931 if (maybe_else.id == Token.Id.Keyword_else) {
1932 const else_node = try arena.create(ast.NodeSwitchElse);
1933 *else_node = ast.NodeSwitchElse {
1934 .base = self.initNode(ast.Node.Id.SwitchElse),
1935 .token = maybe_else,
1936 };
1937 try node.items.append(&else_node.base);
1938 try stack.append(State { .ExpectToken = Token.Id.EqualAngleBracketRight });
1939 continue;
1940 } else {
1941 self.putBackToken(maybe_else);
1942 try stack.append(State { .SwitchCaseItem = &node.items });
1943 continue;
1944 }
1945 },
1946
1947 State.SwitchCaseItem => |case_items| {
1948 stack.append(State { .SwitchCaseItemCommaOrEnd = case_items }) catch unreachable;
1949 try stack.append(State { .RangeExpressionBegin = DestPtr{ .Field = try case_items.addOne() } });
1950 },
1951
1952 State.ExprListCommaOrEnd => |list_state| {
1953 try self.commaOrEnd(&stack, list_state.end, list_state.ptr, State { .ExprListItemOrEnd = list_state });
1954 continue;
1955 },
1956
1957 State.FieldInitListCommaOrEnd => |list_state| {
1958 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .FieldInitListItemOrEnd = list_state });
1959 continue;
1960 },
1961
1962 State.FieldListCommaOrEnd => |container_decl| {
1963 try self.commaOrEnd(&stack, Token.Id.RBrace, &container_decl.rbrace_token,
1964 State { .ContainerDecl = container_decl });
1965 continue;
1966 },
1967
1968 State.SwitchCaseCommaOrEnd => |list_state| {
1969 try self.commaOrEnd(&stack, Token.Id.RBrace, list_state.ptr, State { .SwitchCaseOrEnd = list_state });
1970 continue;
1971 },
1972
1973 State.SwitchCaseItemCommaOrEnd => |case_items| {
1974 try self.commaOrEnd(&stack, Token.Id.EqualAngleBracketRight, null, State { .SwitchCaseItem = case_items });
1975 continue;
1976 },
1977
1978 State.Else => |dest| {
1979 const else_token = self.getNextToken();
1980 if (else_token.id != Token.Id.Keyword_else) {
1981 self.putBackToken(else_token);
1982 continue;
1983 }
1984
1985 const node = try arena.create(ast.NodeElse);
1986 *node = ast.NodeElse {
1987 .base = self.initNode(ast.Node.Id.Else),
1988 .else_token = else_token,
1989 .payload = null,
1990 .body = undefined,
1991 };
1992 *dest = node;
1993
1994 stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable;
1995 try stack.append(State { .Payload = &node.payload });
1996 },
1997
1998 State.WhileContinueExpr => |dest| {
1999 const colon = self.getNextToken();
2000 if (colon.id != Token.Id.Colon) {
2001 self.putBackToken(colon);
2002 continue;
2003 }
2004
2005 _ = (try self.eatToken(&stack, Token.Id.LParen)) ?? continue;
2006 stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
2007 try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = dest } });
2008 },
2009
2010 State.SuspendBody => |suspend_node| {
2011 if (suspend_node.payload != null) {
2012 try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = &suspend_node.body } });
2013 }
2014 continue;
2015 },
2016
2017 State.AsyncEnd => |ctx| {
2018 const node = ctx.dest_ptr.get();
2019
2020 switch (node.id) {
2021 ast.Node.Id.FnProto => {
2022 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node);
2023 fn_proto.async_attr = ctx.attribute;
528 },2024 },
2025 ast.Node.Id.SuffixOp => {
2026 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node);
2027 if (suffix_op.op == ast.NodeSuffixOp.SuffixOp.Call) {
2028 suffix_op.op.Call.async_attr = ctx.attribute;
2029 continue;
2030 }
2031
2032 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",
2033 @tagName(suffix_op.op));
2034 continue;
2035 },
2036 else => {
2037 try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.",
2038 @tagName(node.id));
2039 continue;
2040 }
2041 }
2042 },
2043
2044 State.Payload => |dest| {
2045 const lpipe = self.getNextToken();
2046 if (lpipe.id != Token.Id.Pipe) {
2047 self.putBackToken(lpipe);
2048 continue;
2049 }
2050
2051 const error_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
2052 const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
2053 const node = try arena.create(ast.NodePayload);
2054 *node = ast.NodePayload {
2055 .base = self.initNode(ast.Node.Id.Payload),
2056 .lpipe = lpipe,
2057 .error_symbol = try self.createIdentifier(arena, error_symbol),
2058 .rpipe = rpipe
2059 };
2060 *dest = node;
2061 },
2062
2063 State.PointerPayload => |dest| {
2064 const lpipe = self.getNextToken();
2065 if (lpipe.id != Token.Id.Pipe) {
2066 self.putBackToken(lpipe);
2067 continue;
529 }2068 }
2069
2070 const is_ptr = blk: {
2071 const asterik = self.getNextToken();
2072 if (asterik.id == Token.Id.Asterisk) {
2073 break :blk true;
2074 } else {
2075 self.putBackToken(asterik);
2076 break :blk false;
2077 }
2078 };
2079
2080 const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
2081 const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
2082 const node = try arena.create(ast.NodePointerPayload);
2083 *node = ast.NodePointerPayload {
2084 .base = self.initNode(ast.Node.Id.PointerPayload),
2085 .lpipe = lpipe,
2086 .is_ptr = is_ptr,
2087 .value_symbol = try self.createIdentifier(arena, value_symbol),
2088 .rpipe = rpipe
2089 };
2090 *dest = node;
530 },2091 },
5312092
532 State.ExprListCommaOrEnd => |params| {2093 State.PointerIndexPayload => |dest| {
533 var token = self.getNextToken();2094 const lpipe = self.getNextToken();
534 switch (token.id) {2095 if (lpipe.id != Token.Id.Pipe) {
535 Token.Id.Comma => {2096 self.putBackToken(lpipe);
536 stack.append(State { .ExprListItemOrEnd = params }) catch unreachable;2097 continue;
537 },
538 Token.Id.RParen => continue,
539 else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)),
540 }2098 }
2099
2100 const is_ptr = blk: {
2101 const asterik = self.getNextToken();
2102 if (asterik.id == Token.Id.Asterisk) {
2103 break :blk true;
2104 } else {
2105 self.putBackToken(asterik);
2106 break :blk false;
2107 }
2108 };
2109
2110 const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
2111 const index_symbol = blk: {
2112 const comma = self.getNextToken();
2113 if (comma.id != Token.Id.Comma) {
2114 self.putBackToken(comma);
2115 break :blk null;
2116 }
2117
2118 const symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue;
2119 break :blk try self.createIdentifier(arena, symbol);
2120 };
2121
2122 const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue;
2123 const node = try arena.create(ast.NodePointerIndexPayload);
2124 *node = ast.NodePointerIndexPayload {
2125 .base = self.initNode(ast.Node.Id.PointerIndexPayload),
2126 .lpipe = lpipe,
2127 .is_ptr = is_ptr,
2128 .value_symbol = try self.createIdentifier(arena, value_symbol),
2129 .index_symbol = index_symbol,
2130 .rpipe = rpipe
2131 };
2132 *dest = node;
541 },2133 },
5422134
543 State.AddrOfModifiers => |addr_of_info| {2135 State.AddrOfModifiers => |addr_of_info| {
...@@ -545,21 +2137,30 @@ pub const Parser = struct {...@@ -545,21 +2137,30 @@ pub const Parser = struct {
545 switch (token.id) {2137 switch (token.id) {
546 Token.Id.Keyword_align => {2138 Token.Id.Keyword_align => {
547 stack.append(state) catch unreachable;2139 stack.append(state) catch unreachable;
548 if (addr_of_info.align_expr != null) return self.parseError(token, "multiple align qualifiers");2140 if (addr_of_info.align_expr != null) {
549 _ = try self.eatToken(Token.Id.LParen);2141 try self.parseError(&stack, token, "multiple align qualifiers");
2142 continue;
2143 }
550 try stack.append(State { .ExpectToken = Token.Id.RParen });2144 try stack.append(State { .ExpectToken = Token.Id.RParen });
551 try stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });2145 try stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });
2146 try stack.append(State { .ExpectToken = Token.Id.LParen });
552 continue;2147 continue;
553 },2148 },
554 Token.Id.Keyword_const => {2149 Token.Id.Keyword_const => {
555 stack.append(state) catch unreachable;2150 stack.append(state) catch unreachable;
556 if (addr_of_info.const_token != null) return self.parseError(token, "duplicate qualifier: const");2151 if (addr_of_info.const_token != null) {
2152 try self.parseError(&stack, token, "duplicate qualifier: const");
2153 continue;
2154 }
557 addr_of_info.const_token = token;2155 addr_of_info.const_token = token;
558 continue;2156 continue;
559 },2157 },
560 Token.Id.Keyword_volatile => {2158 Token.Id.Keyword_volatile => {
561 stack.append(state) catch unreachable;2159 stack.append(state) catch unreachable;
562 if (addr_of_info.volatile_token != null) return self.parseError(token, "duplicate qualifier: volatile");2160 if (addr_of_info.volatile_token != null) {
2161 try self.parseError(&stack, token, "duplicate qualifier: volatile");
2162 continue;
2163 }
563 addr_of_info.volatile_token = token;2164 addr_of_info.volatile_token = token;
564 continue;2165 continue;
565 },2166 },
...@@ -570,17 +2171,6 @@ pub const Parser = struct {...@@ -570,17 +2171,6 @@ pub const Parser = struct {
570 }2171 }
571 },2172 },
5722173
573 State.TypeExpr => |dest_ptr| {
574 const token = self.getNextToken();
575 if (token.id == Token.Id.Keyword_var) {
576 @panic("TODO param with type var");
577 }
578 self.putBackToken(token);
579
580 stack.append(State { .Expression = dest_ptr }) catch unreachable;
581 continue;
582 },
583
584 State.FnProto => |fn_proto| {2174 State.FnProto => |fn_proto| {
585 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;2175 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
586 try stack.append(State { .ParamDecl = fn_proto });2176 try stack.append(State { .ParamDecl = fn_proto });
...@@ -610,20 +2200,17 @@ pub const Parser = struct {...@@ -610,20 +2200,17 @@ pub const Parser = struct {
610 State.FnProtoReturnType => |fn_proto| {2200 State.FnProtoReturnType => |fn_proto| {
611 const token = self.getNextToken();2201 const token = self.getNextToken();
612 switch (token.id) {2202 switch (token.id) {
613 Token.Id.Keyword_var => {
614 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Infer = token };
615 },
616 Token.Id.Bang => {2203 Token.Id.Bang => {
617 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };2204 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };
618 stack.append(State {2205 stack.append(State {
619 .TypeExpr = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},2206 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},
620 }) catch unreachable;2207 }) catch unreachable;
621 },2208 },
622 else => {2209 else => {
623 self.putBackToken(token);2210 self.putBackToken(token);
624 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };2211 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
625 stack.append(State {2212 stack.append(State {
626 .TypeExpr = DestPtr {.Field = &fn_proto.return_type.Explicit},2213 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.Explicit},
627 }) catch unreachable;2214 }) catch unreachable;
628 },2215 },
629 }2216 }
...@@ -666,7 +2253,7 @@ pub const Parser = struct {...@@ -666,7 +2253,7 @@ pub const Parser = struct {
666 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;2253 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;
667 try stack.append(State.ParamDeclComma);2254 try stack.append(State.ParamDeclComma);
668 try stack.append(State {2255 try stack.append(State {
669 .TypeExpr = DestPtr {.Field = &param_decl.type_node}2256 .TypeExprBegin = DestPtr {.Field = &param_decl.type_node}
670 });2257 });
671 continue;2258 continue;
672 },2259 },
...@@ -679,7 +2266,10 @@ pub const Parser = struct {...@@ -679,7 +2266,10 @@ pub const Parser = struct {
679 continue;2266 continue;
680 },2267 },
681 Token.Id.Comma => continue,2268 Token.Id.Comma => continue,
682 else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)),2269 else => {
2270 try self.parseError(&stack, token, "expected ',' or ')', found {}", @tagName(token.id));
2271 continue;
2272 },
683 }2273 }
684 },2274 },
6852275
...@@ -687,21 +2277,151 @@ pub const Parser = struct {...@@ -687,21 +2277,151 @@ pub const Parser = struct {
687 const token = self.getNextToken();2277 const token = self.getNextToken();
688 switch(token.id) {2278 switch(token.id) {
689 Token.Id.LBrace => {2279 Token.Id.LBrace => {
690 const block = try self.createBlock(arena, token);2280 const block = try self.createBlock(arena, (?Token)(null), token);
691 fn_proto.body_node = &block.base;2281 fn_proto.body_node = &block.base;
692 stack.append(State { .Block = block }) catch unreachable;2282 stack.append(State { .Block = block }) catch unreachable;
693 continue;2283 continue;
694 },2284 },
695 Token.Id.Semicolon => continue,2285 Token.Id.Semicolon => continue,
696 else => return self.parseError(token, "expected ';' or '{{', found {}", @tagName(token.id)),2286 else => {
2287 try self.parseError(&stack, token, "expected ';' or '{{', found {}", @tagName(token.id));
2288 continue;
2289 },
2290 }
2291 },
2292
2293 State.LabeledExpression => |ctx| {
2294 const token = self.getNextToken();
2295 switch (token.id) {
2296 Token.Id.LBrace => {
2297 const block = try self.createBlock(arena, (?Token)(ctx.label), token);
2298 ctx.dest_ptr.store(&block.base);
2299
2300 stack.append(State { .Block = block }) catch unreachable;
2301 continue;
2302 },
2303 Token.Id.Keyword_while => {
2304 stack.append(State {
2305 .While = LoopCtx {
2306 .label = ctx.label,
2307 .inline_token = null,
2308 .loop_token = token,
2309 .dest_ptr = ctx.dest_ptr,
2310 }
2311 }) catch unreachable;
2312 continue;
2313 },
2314 Token.Id.Keyword_for => {
2315 stack.append(State {
2316 .For = LoopCtx {
2317 .label = ctx.label,
2318 .inline_token = null,
2319 .loop_token = token,
2320 .dest_ptr = ctx.dest_ptr,
2321 }
2322 }) catch unreachable;
2323 continue;
2324 },
2325 Token.Id.Keyword_inline => {
2326 stack.append(State {
2327 .Inline = InlineCtx {
2328 .label = ctx.label,
2329 .inline_token = token,
2330 .dest_ptr = ctx.dest_ptr,
2331 }
2332 }) catch unreachable;
2333 continue;
2334 },
2335 else => {
2336 try self.parseError(&stack, token, "expected 'while', 'for', 'inline' or '{{', found {}", @tagName(token.id));
2337 continue;
2338 },
2339 }
2340 },
2341
2342 State.Inline => |ctx| {
2343 const token = self.getNextToken();
2344 switch (token.id) {
2345 Token.Id.Keyword_while => {
2346 stack.append(State {
2347 .While = LoopCtx {
2348 .inline_token = ctx.inline_token,
2349 .label = ctx.label,
2350 .loop_token = token,
2351 .dest_ptr = ctx.dest_ptr,
2352 }
2353 }) catch unreachable;
2354 continue;
2355 },
2356 Token.Id.Keyword_for => {
2357 stack.append(State {
2358 .For = LoopCtx {
2359 .inline_token = ctx.inline_token,
2360 .label = ctx.label,
2361 .loop_token = token,
2362 .dest_ptr = ctx.dest_ptr,
2363 }
2364 }) catch unreachable;
2365 continue;
2366 },
2367 else => {
2368 try self.parseError(&stack, token, "expected 'while' or 'for', found {}", @tagName(token.id));
2369 continue;
2370 },
697 }2371 }
698 },2372 },
6992373
2374 State.While => |ctx| {
2375 const node = try arena.create(ast.NodeWhile);
2376 *node = ast.NodeWhile {
2377 .base = self.initNode(ast.Node.Id.While),
2378 .label = ctx.label,
2379 .inline_token = ctx.inline_token,
2380 .while_token = ctx.loop_token,
2381 .condition = undefined,
2382 .payload = null,
2383 .continue_expr = null,
2384 .body = undefined,
2385 .@"else" = null,
2386 };
2387 ctx.dest_ptr.store(&node.base);
2388
2389 stack.append(State { .Else = &node.@"else" }) catch unreachable;
2390 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
2391 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
2392 try stack.append(State { .PointerPayload = &node.payload });
2393 try stack.append(State { .ExpectToken = Token.Id.RParen });
2394 try stack.append(State { .Expression = DestPtr { .Field = &node.condition } });
2395 try stack.append(State { .ExpectToken = Token.Id.LParen });
2396 },
2397
2398 State.For => |ctx| {
2399 const node = try arena.create(ast.NodeFor);
2400 *node = ast.NodeFor {
2401 .base = self.initNode(ast.Node.Id.For),
2402 .label = ctx.label,
2403 .inline_token = ctx.inline_token,
2404 .for_token = ctx.loop_token,
2405 .array_expr = undefined,
2406 .payload = null,
2407 .body = undefined,
2408 .@"else" = null,
2409 };
2410 ctx.dest_ptr.store(&node.base);
2411
2412 stack.append(State { .Else = &node.@"else" }) catch unreachable;
2413 try stack.append(State { .Expression = DestPtr { .Field = &node.body } });
2414 try stack.append(State { .PointerIndexPayload = &node.payload });
2415 try stack.append(State { .ExpectToken = Token.Id.RParen });
2416 try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } });
2417 try stack.append(State { .ExpectToken = Token.Id.LParen });
2418 },
2419
700 State.Block => |block| {2420 State.Block => |block| {
701 const token = self.getNextToken();2421 const token = self.getNextToken();
702 switch (token.id) {2422 switch (token.id) {
703 Token.Id.RBrace => {2423 Token.Id.RBrace => {
704 block.end_token = token;2424 block.rbrace = token;
705 continue;2425 continue;
706 },2426 },
707 else => {2427 else => {
...@@ -714,119 +2434,262 @@ pub const Parser = struct {...@@ -714,119 +2434,262 @@ pub const Parser = struct {
714 },2434 },
7152435
716 State.Statement => |block| {2436 State.Statement => |block| {
717 {2437 const next = self.getNextToken();
718 // Look for comptime var, comptime const2438 switch (next.id) {
719 const comptime_token = self.getNextToken();2439 Token.Id.Keyword_comptime => {
720 if (comptime_token.id == Token.Id.Keyword_comptime) {
721 const mut_token = self.getNextToken();2440 const mut_token = self.getNextToken();
722 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {2441 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
723 // TODO shouldn't need these casts2442 // TODO shouldn't need these casts
724 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),2443 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
725 mut_token, (?Token)(comptime_token), (?Token)(null));2444 mut_token, (?Token)(next), (?Token)(null), null);
726 try stack.append(State { .VarDecl = var_decl });2445 stack.append(State { .VarDecl = var_decl }) catch unreachable;
727 continue;2446 continue;
2447 } else {
2448 self.putBackToken(mut_token);
2449 self.putBackToken(next);
2450 const statememt = try block.statements.addOne();
2451 stack.append(State { .Semicolon = statememt }) catch unreachable;
2452 try stack.append(State { .Expression = DestPtr{.Field = statememt } });
728 }2453 }
729 self.putBackToken(mut_token);2454 },
730 }2455 Token.Id.Keyword_var, Token.Id.Keyword_const => {
731 self.putBackToken(comptime_token);
732 }
733 {
734 // Look for const, var
735 const mut_token = self.getNextToken();
736 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
737 // TODO shouldn't need these casts
738 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),2456 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
739 mut_token, (?Token)(null), (?Token)(null));2457 next, (?Token)(null), (?Token)(null), null);
740 try stack.append(State { .VarDecl = var_decl });2458 stack.append(State { .VarDecl = var_decl }) catch unreachable;
2459 continue;
2460 },
2461 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
2462 const node = try arena.create(ast.NodeDefer);
2463 *node = ast.NodeDefer {
2464 .base = self.initNode(ast.Node.Id.Defer),
2465 .defer_token = next,
2466 .kind = switch (next.id) {
2467 Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional,
2468 Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error,
2469 else => unreachable,
2470 },
2471 .expr = undefined,
2472 };
2473 try block.statements.append(&node.base);
2474
2475 stack.append(State { .Semicolon = &node.base }) catch unreachable;
2476 try stack.append(State { .AssignmentExpressionBegin = DestPtr{.Field = &node.expr } });
2477 continue;
2478 },
2479 Token.Id.LBrace => {
2480 const inner_block = try self.createBlock(arena, (?Token)(null), next);
2481 try block.statements.append(&inner_block.base);
2482
2483 stack.append(State { .Block = inner_block }) catch unreachable;
2484 continue;
2485 },
2486 else => {
2487 self.putBackToken(next);
2488 const statememt = try block.statements.addOne();
2489 stack.append(State { .Semicolon = statememt }) catch unreachable;
2490 try stack.append(State { .AssignmentExpressionBegin = DestPtr{.Field = statememt } });
741 continue;2491 continue;
742 }2492 }
743 self.putBackToken(mut_token);
744 }2493 }
7452494
746 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
747 try stack.append(State { .Expression = DestPtr{.List = &block.statements} });
748 continue;
749 },2495 },
7502496
751 // These are data, not control flow.2497 State.Semicolon => |node_ptr| {
752 State.InfixOp => unreachable,2498 const node = *node_ptr;
753 State.PrefixOp => unreachable,2499 if (requireSemiColon(node)) {
754 State.SuffixOp => unreachable,2500 _ = (try self.eatToken(&stack, Token.Id.Semicolon)) ?? continue;
755 State.Operand => unreachable,2501 }
2502 }
756 }2503 }
757 }2504 }
758 }2505 }
7592506
760 fn popSuffixOp(stack: &ArrayList(State)) &ast.Node {2507 fn requireSemiColon(node: &const ast.Node) bool {
761 var expression: &ast.Node = undefined;2508 var n = node;
762 var left_leaf_ptr: &&ast.Node = &expression;
763 while (true) {2509 while (true) {
764 switch (stack.pop()) {2510 switch (n.id) {
765 State.SuffixOp => |suffix_op| {2511 ast.Node.Id.Root,
766 switch (suffix_op.id) {2512 ast.Node.Id.StructField,
767 ast.Node.Id.Call => {2513 ast.Node.Id.UnionTag,
768 const call = @fieldParentPtr(ast.NodeCall, "base", suffix_op);2514 ast.Node.Id.EnumTag,
769 *left_leaf_ptr = &call.base;2515 ast.Node.Id.ParamDecl,
770 left_leaf_ptr = &call.callee;2516 ast.Node.Id.Block,
771 continue;2517 ast.Node.Id.Payload,
772 },2518 ast.Node.Id.PointerPayload,
773 else => unreachable,2519 ast.Node.Id.PointerIndexPayload,
2520 ast.Node.Id.Switch,
2521 ast.Node.Id.SwitchCase,
2522 ast.Node.Id.SwitchElse,
2523 ast.Node.Id.FieldInitializer,
2524 ast.Node.Id.LineComment,
2525 ast.Node.Id.TestDecl => return false,
2526 ast.Node.Id.While => {
2527 const while_node = @fieldParentPtr(ast.NodeWhile, "base", n);
2528 if (while_node.@"else") |@"else"| {
2529 n = @"else".base;
2530 continue;
2531 }
2532
2533 n = while_node.body;
2534 },
2535 ast.Node.Id.For => {
2536 const for_node = @fieldParentPtr(ast.NodeFor, "base", n);
2537 if (for_node.@"else") |@"else"| {
2538 n = @"else".base;
2539 continue;
2540 }
2541
2542 n = for_node.body;
2543 },
2544 ast.Node.Id.If => {
2545 const if_node = @fieldParentPtr(ast.NodeIf, "base", n);
2546 if (if_node.@"else") |@"else"| {
2547 n = @"else".base;
2548 continue;
774 }2549 }
2550
2551 n = if_node.body;
775 },2552 },
776 State.Operand => |operand| {2553 ast.Node.Id.Else => {
777 *left_leaf_ptr = operand;2554 const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
778 break;2555 n = else_node.body;
2556 },
2557 ast.Node.Id.Defer => {
2558 const defer_node = @fieldParentPtr(ast.NodeDefer, "base", n);
2559 n = defer_node.expr;
2560 },
2561 ast.Node.Id.Comptime => {
2562 const comptime_node = @fieldParentPtr(ast.NodeComptime, "base", n);
2563 n = comptime_node.expr;
2564 },
2565 ast.Node.Id.Suspend => {
2566 const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", n);
2567 if (suspend_node.body) |body| {
2568 n = body;
2569 continue;
2570 }
2571
2572 return true;
779 },2573 },
780 else => unreachable,2574 else => return true,
781 }2575 }
782 }2576 }
2577 }
2578
2579 fn commaOrEnd(self: &Parser, stack: &ArrayList(State), end: &const Token.Id, maybe_ptr: ?&Token, state_after_comma: &const State) !void {
2580 var token = self.getNextToken();
2581 switch (token.id) {
2582 Token.Id.Comma => {
2583 stack.append(state_after_comma) catch unreachable;
2584 },
2585 else => {
2586 const IdTag = @TagType(Token.Id);
2587 if (IdTag(*end) == token.id) {
2588 if (maybe_ptr) |ptr| {
2589 *ptr = token;
2590 }
2591 return;
2592 }
2593
2594 try self.parseError(stack, token, "expected ',' or {}, found {}", @tagName(*end), @tagName(token.id));
2595 },
2596 }
2597 }
2598
2599 fn tokenIdToAssignment(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
2600 // TODO: We have to cast all cases because of this:
2601 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
2602 return switch (*id) {
2603 Token.Id.AmpersandEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignBitAnd),
2604 Token.Id.AngleBracketAngleBracketLeftEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignBitShiftLeft),
2605 Token.Id.AngleBracketAngleBracketRightEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignBitShiftRight),
2606 Token.Id.AsteriskEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignTimes),
2607 Token.Id.AsteriskPercentEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignTimesWarp),
2608 Token.Id.CaretEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignBitXor),
2609 Token.Id.Equal => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Assign),
2610 Token.Id.MinusEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignMinus),
2611 Token.Id.MinusPercentEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignMinusWrap),
2612 Token.Id.PercentEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignMod),
2613 Token.Id.PipeEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignBitOr),
2614 Token.Id.PlusEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignPlus),
2615 Token.Id.PlusPercentEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignPlusWrap),
2616 Token.Id.SlashEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AssignDiv),
2617 else => null,
2618 };
2619 }
2620
2621 fn tokenIdToComparison(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
2622 // TODO: We have to cast all cases because of this:
2623 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
2624 return switch (*id) {
2625 Token.Id.BangEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.BangEqual),
2626 Token.Id.EqualEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.EqualEqual),
2627 Token.Id.AngleBracketLeft => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.LessThan),
2628 Token.Id.AngleBracketLeftEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.LessOrEqual),
2629 Token.Id.AngleBracketRight => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.GreaterThan),
2630 Token.Id.AngleBracketRightEqual => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.GreaterOrEqual),
2631 else => null,
2632 };
2633 }
2634
2635 fn tokenIdToBitShift(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
2636 // TODO: We have to cast all cases because of this:
2637 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
2638 return switch (*id) {
2639 Token.Id.AngleBracketAngleBracketLeft => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.BitShiftLeft),
2640 Token.Id.AngleBracketAngleBracketRight => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.BitShiftRight),
2641 else => null,
2642 };
2643 }
2644
2645 fn tokenIdToAddition(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
2646 // TODO: We have to cast all cases because of this:
2647 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
2648 return switch (*id) {
2649 Token.Id.Minus => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Sub),
2650 Token.Id.MinusPercent => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.SubWrap),
2651 Token.Id.Plus => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Add),
2652 Token.Id.PlusPercent => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.AddWrap),
2653 Token.Id.PlusPlus => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.ArrayCat),
2654 else => null,
2655 };
2656 }
7832657
784 return expression;2658 fn tokenIdToMultiply(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {
2659 // TODO: We have to cast all cases because of this:
2660 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
2661 return switch (*id) {
2662 Token.Id.Slash => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Div),
2663 Token.Id.Asterisk => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Mult),
2664 Token.Id.AsteriskAsterisk => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.ArrayMult),
2665 Token.Id.AsteriskPercent => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.MultWrap),
2666 Token.Id.Percent => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.Mod),
2667 Token.Id.PipePipe => (ast.NodeInfixOp.InfixOp)(ast.NodeInfixOp.InfixOp.MergeErrorSets),
2668 else => null,
2669 };
785 }2670 }
7862671
787 fn tokenIdToInfixOp(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp {2672 fn tokenIdToPrefixOp(id: &const Token.Id) ?ast.NodePrefixOp.PrefixOp {
2673 // TODO: We have to cast all cases because of this:
2674 // error: expected type '?InfixOp', found '?@TagType(InfixOp)'
788 return switch (*id) {2675 return switch (*id) {
789 Token.Id.Ampersand => ast.NodeInfixOp.InfixOp.BitAnd,2676 Token.Id.Bang => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.BoolNot),
790 Token.Id.AmpersandEqual => ast.NodeInfixOp.InfixOp.AssignBitAnd,2677 Token.Id.Tilde => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.BitNot),
791 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp.BitShiftLeft,2678 Token.Id.Minus => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Negation),
792 Token.Id.AngleBracketAngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftLeft,2679 Token.Id.MinusPercent => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.NegationWrap),
793 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp.BitShiftRight,2680 Token.Id.Asterisk => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Deref),
794 Token.Id.AngleBracketAngleBracketRightEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftRight,2681 Token.Id.Ampersand => ast.NodePrefixOp.PrefixOp {
795 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp.LessThan,2682 .AddrOf = ast.NodePrefixOp.AddrOfInfo {
796 Token.Id.AngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.LessOrEqual,2683 .align_expr = null,
797 Token.Id.AngleBracketRight => ast.NodeInfixOp.InfixOp.GreaterThan,2684 .bit_offset_start_token = null,
798 Token.Id.AngleBracketRightEqual => ast.NodeInfixOp.InfixOp.GreaterOrEqual,2685 .bit_offset_end_token = null,
799 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp.Mult,2686 .const_token = null,
800 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp.ArrayMult,2687 .volatile_token = null,
801 Token.Id.AsteriskEqual => ast.NodeInfixOp.InfixOp.AssignTimes,2688 },
802 Token.Id.AsteriskPercent => ast.NodeInfixOp.InfixOp.MultWrap,2689 },
803 Token.Id.AsteriskPercentEqual => ast.NodeInfixOp.InfixOp.AssignTimesWarp,2690 Token.Id.QuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.MaybeType),
804 Token.Id.Bang => ast.NodeInfixOp.InfixOp.ErrorUnion,2691 Token.Id.QuestionMarkQuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.UnwrapMaybe),
805 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp.BangEqual,2692 Token.Id.Keyword_await => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Await),
806 Token.Id.Caret => ast.NodeInfixOp.InfixOp.BitXor,
807 Token.Id.CaretEqual => ast.NodeInfixOp.InfixOp.AssignBitXor,
808 Token.Id.Equal => ast.NodeInfixOp.InfixOp.Assign,
809 Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp.EqualEqual,
810 Token.Id.Keyword_and => ast.NodeInfixOp.InfixOp.BoolAnd,
811 Token.Id.Keyword_or => ast.NodeInfixOp.InfixOp.BoolOr,
812 Token.Id.Minus => ast.NodeInfixOp.InfixOp.Sub,
813 Token.Id.MinusEqual => ast.NodeInfixOp.InfixOp.AssignMinus,
814 Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp.SubWrap,
815 Token.Id.MinusPercentEqual => ast.NodeInfixOp.InfixOp.AssignMinusWrap,
816 Token.Id.Percent => ast.NodeInfixOp.InfixOp.Mod,
817 Token.Id.PercentEqual => ast.NodeInfixOp.InfixOp.AssignMod,
818 Token.Id.Period => ast.NodeInfixOp.InfixOp.Period,
819 Token.Id.Pipe => ast.NodeInfixOp.InfixOp.BitOr,
820 Token.Id.PipeEqual => ast.NodeInfixOp.InfixOp.AssignBitOr,
821 Token.Id.PipePipe => ast.NodeInfixOp.InfixOp.MergeErrorSets,
822 Token.Id.Plus => ast.NodeInfixOp.InfixOp.Add,
823 Token.Id.PlusEqual => ast.NodeInfixOp.InfixOp.AssignPlus,
824 Token.Id.PlusPercent => ast.NodeInfixOp.InfixOp.AddWrap,
825 Token.Id.PlusPercentEqual => ast.NodeInfixOp.InfixOp.AssignPlusWrap,
826 Token.Id.PlusPlus => ast.NodeInfixOp.InfixOp.ArrayCat,
827 Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp.UnwrapMaybe,
828 Token.Id.Slash => ast.NodeInfixOp.InfixOp.Div,
829 Token.Id.SlashEqual => ast.NodeInfixOp.InfixOp.AssignDiv,
830 else => null,2693 else => null,
831 };2694 };
832 }2695 }
...@@ -852,7 +2715,7 @@ pub const Parser = struct {...@@ -852,7 +2715,7 @@ pub const Parser = struct {
852 }2715 }
8532716
854 fn createVarDecl(self: &Parser, arena: &mem.Allocator, visib_token: &const ?Token, mut_token: &const Token,2717 fn createVarDecl(self: &Parser, arena: &mem.Allocator, visib_token: &const ?Token, mut_token: &const Token,
855 comptime_token: &const ?Token, extern_token: &const ?Token) !&ast.NodeVarDecl2718 comptime_token: &const ?Token, extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
856 {2719 {
857 const node = try arena.create(ast.NodeVarDecl);2720 const node = try arena.create(ast.NodeVarDecl);
8582721
...@@ -865,7 +2728,7 @@ pub const Parser = struct {...@@ -865,7 +2728,7 @@ pub const Parser = struct {
865 .type_node = null,2728 .type_node = null,
866 .align_node = null,2729 .align_node = null,
867 .init_node = null,2730 .init_node = null,
868 .lib_name = null,2731 .lib_name = lib_name,
869 // initialized later2732 // initialized later
870 .name_token = undefined,2733 .name_token = undefined,
871 .eq_token = undefined,2734 .eq_token = undefined,
...@@ -874,7 +2737,18 @@ pub const Parser = struct {...@@ -874,7 +2737,18 @@ pub const Parser = struct {
874 return node;2737 return node;
875 }2738 }
8762739
877 fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name_token: &const Token,2740 fn createStringLiteral(self: &Parser, arena: &mem.Allocator, token: &const Token) !&ast.NodeStringLiteral {
2741 const node = try arena.create(ast.NodeStringLiteral);
2742
2743 assert(token.id == Token.Id.StringLiteral);
2744 *node = ast.NodeStringLiteral {
2745 .base = self.initNode(ast.Node.Id.StringLiteral),
2746 .token = *token,
2747 };
2748 return node;
2749 }
2750
2751 fn createTestDecl(self: &Parser, arena: &mem.Allocator, test_token: &const Token, name: &ast.Node,
878 block: &ast.NodeBlock) !&ast.NodeTestDecl2752 block: &ast.NodeBlock) !&ast.NodeTestDecl
879 {2753 {
880 const node = try arena.create(ast.NodeTestDecl);2754 const node = try arena.create(ast.NodeTestDecl);
...@@ -882,14 +2756,14 @@ pub const Parser = struct {...@@ -882,14 +2756,14 @@ pub const Parser = struct {
882 *node = ast.NodeTestDecl {2756 *node = ast.NodeTestDecl {
883 .base = self.initNode(ast.Node.Id.TestDecl),2757 .base = self.initNode(ast.Node.Id.TestDecl),
884 .test_token = *test_token,2758 .test_token = *test_token,
885 .name_token = *name_token,2759 .name = name,
886 .body_node = &block.base,2760 .body_node = &block.base,
887 };2761 };
888 return node;2762 return node;
889 }2763 }
8902764
891 fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,2765 fn createFnProto(self: &Parser, arena: &mem.Allocator, fn_token: &const Token, extern_token: &const ?Token,
892 cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto2766 lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
893 {2767 {
894 const node = try arena.create(ast.NodeFnProto);2768 const node = try arena.create(ast.NodeFnProto);
8952769
...@@ -904,8 +2778,9 @@ pub const Parser = struct {...@@ -904,8 +2778,9 @@ pub const Parser = struct {
904 .extern_token = *extern_token,2778 .extern_token = *extern_token,
905 .inline_token = *inline_token,2779 .inline_token = *inline_token,
906 .cc_token = *cc_token,2780 .cc_token = *cc_token,
2781 .async_attr = null,
907 .body_node = null,2782 .body_node = null,
908 .lib_name = null,2783 .lib_name = lib_name,
909 .align_expr = null,2784 .align_expr = null,
910 };2785 };
911 return node;2786 return node;
...@@ -925,14 +2800,28 @@ pub const Parser = struct {...@@ -925,14 +2800,28 @@ pub const Parser = struct {
925 return node;2800 return node;
926 }2801 }
9272802
928 fn createBlock(self: &Parser, arena: &mem.Allocator, begin_token: &const Token) !&ast.NodeBlock {2803 fn createBlock(self: &Parser, arena: &mem.Allocator, label: &const ?Token, lbrace: &const Token) !&ast.NodeBlock {
929 const node = try arena.create(ast.NodeBlock);2804 const node = try arena.create(ast.NodeBlock);
9302805
931 *node = ast.NodeBlock {2806 *node = ast.NodeBlock {
932 .base = self.initNode(ast.Node.Id.Block),2807 .base = self.initNode(ast.Node.Id.Block),
933 .begin_token = *begin_token,2808 .label = *label,
934 .end_token = undefined,2809 .lbrace = *lbrace,
935 .statements = ArrayList(&ast.Node).init(arena),2810 .statements = ArrayList(&ast.Node).init(arena),
2811 .rbrace = undefined,
2812 };
2813 return node;
2814 }
2815
2816 fn createControlFlowExpr(self: &Parser, arena: &mem.Allocator, ltoken: &const Token,
2817 kind: &const ast.NodeControlFlowExpression.Kind) !&ast.NodeControlFlowExpression
2818 {
2819 const node = try arena.create(ast.NodeControlFlowExpression);
2820 *node = ast.NodeControlFlowExpression {
2821 .base = self.initNode(ast.Node.Id.ControlFlowExpression),
2822 .ltoken = *ltoken,
2823 .kind = *kind,
2824 .rhs = null,
936 };2825 };
937 return node;2826 return node;
938 }2827 }
...@@ -962,6 +2851,18 @@ pub const Parser = struct {...@@ -962,6 +2851,18 @@ pub const Parser = struct {
962 return node;2851 return node;
963 }2852 }
9642853
2854 fn createSuffixOp(self: &Parser, arena: &mem.Allocator, op: &const ast.NodeSuffixOp.SuffixOp) !&ast.NodeSuffixOp {
2855 const node = try arena.create(ast.NodeSuffixOp);
2856
2857 *node = ast.NodeSuffixOp {
2858 .base = self.initNode(ast.Node.Id.SuffixOp),
2859 .lhs = undefined,
2860 .op = *op,
2861 .rtoken = undefined,
2862 };
2863 return node;
2864 }
2865
965 fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier {2866 fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier {
966 const node = try arena.create(ast.NodeIdentifier);2867 const node = try arena.create(ast.NodeIdentifier);
9672868
...@@ -1015,62 +2916,78 @@ pub const Parser = struct {...@@ -1015,62 +2916,78 @@ pub const Parser = struct {
1015 }2916 }
10162917
1017 fn createAttachFnProto(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), fn_token: &const Token,2918 fn createAttachFnProto(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node), fn_token: &const Token,
1018 extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token,2919 extern_token: &const ?Token, lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token,
1019 inline_token: &const ?Token) !&ast.NodeFnProto2920 inline_token: &const ?Token) !&ast.NodeFnProto
1020 {2921 {
1021 const node = try self.createFnProto(arena, fn_token, extern_token, cc_token, visib_token, inline_token);2922 const node = try self.createFnProto(arena, fn_token, extern_token, lib_name, cc_token, visib_token, inline_token);
1022 try list.append(&node.base);2923 try list.append(&node.base);
1023 return node;2924 return node;
1024 }2925 }
10252926
1026 fn createAttachVarDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),2927 fn createAttachVarDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
1027 visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,2928 visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
1028 extern_token: &const ?Token) !&ast.NodeVarDecl2929 extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
1029 {2930 {
1030 const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token);2931 const node = try self.createVarDecl(arena, visib_token, mut_token, comptime_token, extern_token, lib_name);
1031 try list.append(&node.base);2932 try list.append(&node.base);
1032 return node;2933 return node;
1033 }2934 }
10342935
1035 fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),2936 fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
1036 test_token: &const Token, name_token: &const Token, block: &ast.NodeBlock) !&ast.NodeTestDecl2937 test_token: &const Token, name: &ast.Node, block: &ast.NodeBlock) !&ast.NodeTestDecl
1037 {2938 {
1038 const node = try self.createTestDecl(arena, test_token, name_token, block);2939 const node = try self.createTestDecl(arena, test_token, name, block);
1039 try list.append(&node.base);2940 try list.append(&node.base);
1040 return node;2941 return node;
1041 }2942 }
10422943
1043 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {2944 fn parseError(self: &Parser, stack: &ArrayList(State), token: &const Token, comptime fmt: []const u8, args: ...) !void {
1044 const loc = self.tokenizer.getTokenLocation(token);2945 // Before reporting an error. We pop the stack to see if our state was optional
1045 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, token.line + 1, token.column + 1, args);2946 self.revertIfOptional(stack) catch {
1046 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);2947 const loc = self.tokenizer.getTokenLocation(0, token);
1047 {2948 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
1048 var i: usize = 0;2949 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
1049 while (i < token.column) : (i += 1) {2950 {
1050 warn(" ");2951 var i: usize = 0;
2952 while (i < loc.column) : (i += 1) {
2953 warn(" ");
2954 }
1051 }2955 }
1052 }2956 {
1053 {2957 const caret_count = token.end - token.start;
1054 const caret_count = token.end - token.start;2958 var i: usize = 0;
1055 var i: usize = 0;2959 while (i < caret_count) : (i += 1) {
1056 while (i < caret_count) : (i += 1) {2960 warn("~");
1057 warn("~");2961 }
1058 }2962 }
1059 }2963 warn("\n");
1060 warn("\n");2964 return error.ParseError;
1061 return error.ParseError;2965 };
1062 }2966 }
10632967
1064 fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) !void {2968 fn eatToken(self: &Parser, stack: &ArrayList(State), id: @TagType(Token.Id)) !?Token {
2969 const token = self.getNextToken();
1065 if (token.id != id) {2970 if (token.id != id) {
1066 return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id));2971 try self.parseError(stack, token, "expected {}, found {}", @tagName(id), @tagName(token.id));
2972 return null;
1067 }2973 }
2974 return token;
1068 }2975 }
10692976
1070 fn eatToken(self: &Parser, id: @TagType(Token.Id)) !Token {2977 fn revertIfOptional(self: &Parser, stack: &ArrayList(State)) !void {
1071 const token = self.getNextToken();2978 while (stack.popOrNull()) |state| {
1072 try self.expectToken(token, id);2979 switch (state) {
1073 return token;2980 State.Optional => |revert| {
2981 *self = revert.parser;
2982 *self.tokenizer = revert.tokenizer;
2983 *revert.ptr = null;
2984 return;
2985 },
2986 else => { }
2987 }
2988 }
2989
2990 return error.NoOptionalStateFound;
1074 }2991 }
10752992
1076 fn putBackToken(self: &Parser, token: &const Token) void {2993 fn putBackToken(self: &Parser, token: &const Token) void {
...@@ -1129,6 +3046,7 @@ pub const Parser = struct {...@@ -1129,6 +3046,7 @@ pub const Parser = struct {
1129 Expression: &ast.Node,3046 Expression: &ast.Node,
1130 VarDecl: &ast.NodeVarDecl,3047 VarDecl: &ast.NodeVarDecl,
1131 Statement: &ast.Node,3048 Statement: &ast.Node,
3049 FieldInitializer: &ast.NodeFieldInitializer,
1132 PrintIndent,3050 PrintIndent,
1133 Indent: usize,3051 Indent: usize,
1134 };3052 };
...@@ -1149,9 +3067,8 @@ pub const Parser = struct {...@@ -1149,9 +3067,8 @@ pub const Parser = struct {
1149 try stack.append(RenderState {3067 try stack.append(RenderState {
1150 .Text = blk: {3068 .Text = blk: {
1151 const prev_node = root_node.decls.at(i - 1);3069 const prev_node = root_node.decls.at(i - 1);
1152 const prev_line_index = prev_node.lastToken().line;3070 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, decl.firstToken());
1153 const this_line_index = decl.firstToken().line;3071 if (loc.line >= 2) {
1154 if (this_line_index - prev_line_index >= 2) {
1155 break :blk "\n\n";3072 break :blk "\n\n";
1156 }3073 }
1157 break :blk "\n";3074 break :blk "\n";
...@@ -1169,38 +3086,24 @@ pub const Parser = struct {...@@ -1169,38 +3086,24 @@ pub const Parser = struct {
1169 switch (decl.id) {3086 switch (decl.id) {
1170 ast.Node.Id.FnProto => {3087 ast.Node.Id.FnProto => {
1171 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl);3088 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl);
1172 if (fn_proto.visib_token) |visib_token| {
1173 switch (visib_token.id) {
1174 Token.Id.Keyword_pub => try stream.print("pub "),
1175 Token.Id.Keyword_export => try stream.print("export "),
1176 else => unreachable,
1177 }
1178 }
1179 if (fn_proto.extern_token) |extern_token| {
1180 try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1181 }
1182 try stream.print("fn");
11833089
1184 if (fn_proto.name_token) |name_token| {3090 if (fn_proto.body_node) |body_node| {
1185 try stream.print(" {}", self.tokenizer.getTokenSlice(name_token));3091 stack.append(RenderState { .Expression = body_node}) catch unreachable;
3092 try stack.append(RenderState { .Text = " "});
3093 } else {
3094 stack.append(RenderState { .Text = ";" }) catch unreachable;
1186 }3095 }
11873096
1188 try stream.print("(");3097 try stack.append(RenderState { .Expression = decl });
11893098 },
1190 if (fn_proto.body_node == null) {3099 ast.Node.Id.Use => {
1191 try stack.append(RenderState { .Text = ";" });3100 const use_decl = @fieldParentPtr(ast.NodeUse, "base", decl);
1192 }3101 if (use_decl.visib_token) |visib_token| {
11933102 try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
1194 try stack.append(RenderState { .FnProtoRParen = fn_proto});
1195 var i = fn_proto.params.len;
1196 while (i != 0) {
1197 i -= 1;
1198 const param_decl_node = fn_proto.params.items[i];
1199 try stack.append(RenderState { .ParamDecl = param_decl_node});
1200 if (i != 0) {
1201 try stack.append(RenderState { .Text = ", " });
1202 }
1203 }3103 }
3104 try stream.print("use ");
3105 try stack.append(RenderState { .Text = ";" });
3106 try stack.append(RenderState { .Expression = use_decl.expr });
1204 },3107 },
1205 ast.Node.Id.VarDecl => {3108 ast.Node.Id.VarDecl => {
1206 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);3109 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
...@@ -1208,29 +3111,51 @@ pub const Parser = struct {...@@ -1208,29 +3111,51 @@ pub const Parser = struct {
1208 },3111 },
1209 ast.Node.Id.TestDecl => {3112 ast.Node.Id.TestDecl => {
1210 const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl);3113 const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl);
1211 try stream.print("test {} ", self.tokenizer.getTokenSlice(test_decl.name_token));3114 try stream.print("test ");
1212 try stack.append(RenderState { .Expression = test_decl.body_node });3115 try stack.append(RenderState { .Expression = test_decl.body_node });
3116 try stack.append(RenderState { .Text = " " });
3117 try stack.append(RenderState { .Expression = test_decl.name });
3118 },
3119 ast.Node.Id.StructField => {
3120 const field = @fieldParentPtr(ast.NodeStructField, "base", decl);
3121 try stream.print("{}: ", self.tokenizer.getTokenSlice(field.name_token));
3122 try stack.append(RenderState { .Expression = field.type_expr});
3123 },
3124 ast.Node.Id.UnionTag => {
3125 const tag = @fieldParentPtr(ast.NodeUnionTag, "base", decl);
3126 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
3127
3128 if (tag.type_expr) |type_expr| {
3129 try stream.print(": ");
3130 try stack.append(RenderState { .Expression = type_expr});
3131 }
3132 },
3133 ast.Node.Id.EnumTag => {
3134 const tag = @fieldParentPtr(ast.NodeEnumTag, "base", decl);
3135 try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token));
3136
3137 if (tag.value) |value| {
3138 try stream.print(" = ");
3139 try stack.append(RenderState { .Expression = value});
3140 }
3141 },
3142 ast.Node.Id.Comptime => {
3143 if (requireSemiColon(decl)) {
3144 try stack.append(RenderState { .Text = ";" });
3145 }
3146 try stack.append(RenderState { .Expression = decl });
1213 },3147 },
1214 else => unreachable,3148 else => unreachable,
1215 }3149 }
1216 },3150 },
12173151
1218 RenderState.VarDecl => |var_decl| {3152 RenderState.FieldInitializer => |field_init| {
1219 if (var_decl.visib_token) |visib_token| {3153 try stream.print(".{}", self.tokenizer.getTokenSlice(field_init.name_token));
1220 try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));3154 try stream.print(" = ");
1221 }3155 try stack.append(RenderState { .Expression = field_init.expr });
1222 if (var_decl.extern_token) |extern_token| {3156 },
1223 try stream.print("{} ", self.tokenizer.getTokenSlice(extern_token));
1224 if (var_decl.lib_name != null) {
1225 @panic("TODO");
1226 }
1227 }
1228 if (var_decl.comptime_token) |comptime_token| {
1229 try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token));
1230 }
1231 try stream.print("{} ", self.tokenizer.getTokenSlice(var_decl.mut_token));
1232 try stream.print("{}", self.tokenizer.getTokenSlice(var_decl.name_token));
12333157
3158 RenderState.VarDecl => |var_decl| {
1234 try stack.append(RenderState { .Text = ";" });3159 try stack.append(RenderState { .Text = ";" });
1235 if (var_decl.init_node) |init_node| {3160 if (var_decl.init_node) |init_node| {
1236 try stack.append(RenderState { .Expression = init_node });3161 try stack.append(RenderState { .Expression = init_node });
...@@ -1241,9 +3166,31 @@ pub const Parser = struct {...@@ -1241,9 +3166,31 @@ pub const Parser = struct {
1241 try stack.append(RenderState { .Expression = align_node });3166 try stack.append(RenderState { .Expression = align_node });
1242 try stack.append(RenderState { .Text = " align(" });3167 try stack.append(RenderState { .Text = " align(" });
1243 }3168 }
1244 if (var_decl.type_node) |type_node| {3169 if (var_decl.type_node) |type_node| {
1245 try stream.print(": ");3170 try stack.append(RenderState { .Expression = type_node });
1246 try stack.append(RenderState { .Expression = type_node });3171 try stack.append(RenderState { .Text = ": " });
3172 }
3173 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.name_token) });
3174 try stack.append(RenderState { .Text = " " });
3175 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(var_decl.mut_token) });
3176
3177 if (var_decl.comptime_token) |comptime_token| {
3178 try stack.append(RenderState { .Text = " " });
3179 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(comptime_token) });
3180 }
3181
3182 if (var_decl.extern_token) |extern_token| {
3183 if (var_decl.lib_name != null) {
3184 try stack.append(RenderState { .Text = " " });
3185 try stack.append(RenderState { .Expression = ??var_decl.lib_name });
3186 }
3187 try stack.append(RenderState { .Text = " " });
3188 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) });
3189 }
3190
3191 if (var_decl.visib_token) |visib_token| {
3192 try stack.append(RenderState { .Text = " " });
3193 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) });
1247 }3194 }
1248 },3195 },
12493196
...@@ -1274,6 +3221,10 @@ pub const Parser = struct {...@@ -1274,6 +3221,10 @@ pub const Parser = struct {
1274 },3221 },
1275 ast.Node.Id.Block => {3222 ast.Node.Id.Block => {
1276 const block = @fieldParentPtr(ast.NodeBlock, "base", base);3223 const block = @fieldParentPtr(ast.NodeBlock, "base", base);
3224 if (block.label) |label| {
3225 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
3226 }
3227
1277 if (block.statements.len == 0) {3228 if (block.statements.len == 0) {
1278 try stream.write("{}");3229 try stream.write("{}");
1279 } else {3230 } else {
...@@ -1292,10 +3243,9 @@ pub const Parser = struct {...@@ -1292,10 +3243,9 @@ pub const Parser = struct {
1292 try stack.append(RenderState {3243 try stack.append(RenderState {
1293 .Text = blk: {3244 .Text = blk: {
1294 if (i != 0) {3245 if (i != 0) {
1295 const prev_statement_node = block.statements.items[i - 1];3246 const prev_node = block.statements.items[i - 1];
1296 const prev_line_index = prev_statement_node.lastToken().line;3247 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, statement_node.firstToken());
1297 const this_line_index = statement_node.firstToken().line;3248 if (loc.line >= 2) {
1298 if (this_line_index - prev_line_index >= 2) {
1299 break :blk "\n\n";3249 break :blk "\n\n";
1300 }3250 }
1301 }3251 }
...@@ -1305,54 +3255,99 @@ pub const Parser = struct {...@@ -1305,54 +3255,99 @@ pub const Parser = struct {
1305 }3255 }
1306 }3256 }
1307 },3257 },
3258 ast.Node.Id.Defer => {
3259 const defer_node = @fieldParentPtr(ast.NodeDefer, "base", base);
3260 try stream.print("{} ", self.tokenizer.getTokenSlice(defer_node.defer_token));
3261 try stack.append(RenderState { .Expression = defer_node.expr });
3262 },
3263 ast.Node.Id.Comptime => {
3264 const comptime_node = @fieldParentPtr(ast.NodeComptime, "base", base);
3265 try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_node.comptime_token));
3266 try stack.append(RenderState { .Expression = comptime_node.expr });
3267 },
3268 ast.Node.Id.AsyncAttribute => {
3269 const async_attr = @fieldParentPtr(ast.NodeAsyncAttribute, "base", base);
3270 try stream.print("{}", self.tokenizer.getTokenSlice(async_attr.async_token));
3271
3272 if (async_attr.allocator_type) |allocator_type| {
3273 try stack.append(RenderState { .Text = ">" });
3274 try stack.append(RenderState { .Expression = allocator_type });
3275 try stack.append(RenderState { .Text = "<" });
3276 }
3277 },
3278 ast.Node.Id.Suspend => {
3279 const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", base);
3280 try stream.print("{}", self.tokenizer.getTokenSlice(suspend_node.suspend_token));
3281
3282 if (suspend_node.body) |body| {
3283 try stack.append(RenderState { .Expression = body });
3284 try stack.append(RenderState { .Text = " " });
3285 }
3286
3287 if (suspend_node.payload) |payload| {
3288 try stack.append(RenderState { .Expression = &payload.base });
3289 try stack.append(RenderState { .Text = " " });
3290 }
3291 },
1308 ast.Node.Id.InfixOp => {3292 ast.Node.Id.InfixOp => {
1309 const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base);3293 const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base);
1310 try stack.append(RenderState { .Expression = prefix_op_node.rhs });3294 try stack.append(RenderState { .Expression = prefix_op_node.rhs });
1311 const text = switch (prefix_op_node.op) {
1312 ast.NodeInfixOp.InfixOp.Add => " + ",
1313 ast.NodeInfixOp.InfixOp.AddWrap => " +% ",
1314 ast.NodeInfixOp.InfixOp.ArrayCat => " ++ ",
1315 ast.NodeInfixOp.InfixOp.ArrayMult => " ** ",
1316 ast.NodeInfixOp.InfixOp.Assign => " = ",
1317 ast.NodeInfixOp.InfixOp.AssignBitAnd => " &= ",
1318 ast.NodeInfixOp.InfixOp.AssignBitOr => " |= ",
1319 ast.NodeInfixOp.InfixOp.AssignBitShiftLeft => " <<= ",
1320 ast.NodeInfixOp.InfixOp.AssignBitShiftRight => " >>= ",
1321 ast.NodeInfixOp.InfixOp.AssignBitXor => " ^= ",
1322 ast.NodeInfixOp.InfixOp.AssignDiv => " /= ",
1323 ast.NodeInfixOp.InfixOp.AssignMinus => " -= ",
1324 ast.NodeInfixOp.InfixOp.AssignMinusWrap => " -%= ",
1325 ast.NodeInfixOp.InfixOp.AssignMod => " %= ",
1326 ast.NodeInfixOp.InfixOp.AssignPlus => " += ",
1327 ast.NodeInfixOp.InfixOp.AssignPlusWrap => " +%= ",
1328 ast.NodeInfixOp.InfixOp.AssignTimes => " *= ",
1329 ast.NodeInfixOp.InfixOp.AssignTimesWarp => " *%= ",
1330 ast.NodeInfixOp.InfixOp.BangEqual => " != ",
1331 ast.NodeInfixOp.InfixOp.BitAnd => " & ",
1332 ast.NodeInfixOp.InfixOp.BitOr => " | ",
1333 ast.NodeInfixOp.InfixOp.BitShiftLeft => " << ",
1334 ast.NodeInfixOp.InfixOp.BitShiftRight => " >> ",
1335 ast.NodeInfixOp.InfixOp.BitXor => " ^ ",
1336 ast.NodeInfixOp.InfixOp.BoolAnd => " and ",
1337 ast.NodeInfixOp.InfixOp.BoolOr => " or ",
1338 ast.NodeInfixOp.InfixOp.Div => " / ",
1339 ast.NodeInfixOp.InfixOp.EqualEqual => " == ",
1340 ast.NodeInfixOp.InfixOp.ErrorUnion => "!",
1341 ast.NodeInfixOp.InfixOp.GreaterOrEqual => " >= ",
1342 ast.NodeInfixOp.InfixOp.GreaterThan => " > ",
1343 ast.NodeInfixOp.InfixOp.LessOrEqual => " <= ",
1344 ast.NodeInfixOp.InfixOp.LessThan => " < ",
1345 ast.NodeInfixOp.InfixOp.MergeErrorSets => " || ",
1346 ast.NodeInfixOp.InfixOp.Mod => " % ",
1347 ast.NodeInfixOp.InfixOp.Mult => " * ",
1348 ast.NodeInfixOp.InfixOp.MultWrap => " *% ",
1349 ast.NodeInfixOp.InfixOp.Period => ".",
1350 ast.NodeInfixOp.InfixOp.Sub => " - ",
1351 ast.NodeInfixOp.InfixOp.SubWrap => " -% ",
1352 ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",
1353 };
13543295
1355 try stack.append(RenderState { .Text = text });3296 if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) {
3297 if (prefix_op_node.op.Catch) |payload| {
3298 try stack.append(RenderState { .Text = " " });
3299 try stack.append(RenderState { .Expression = &payload.base });
3300 }
3301 try stack.append(RenderState { .Text = " catch " });
3302 } else {
3303 const text = switch (prefix_op_node.op) {
3304 ast.NodeInfixOp.InfixOp.Add => " + ",
3305 ast.NodeInfixOp.InfixOp.AddWrap => " +% ",
3306 ast.NodeInfixOp.InfixOp.ArrayCat => " ++ ",
3307 ast.NodeInfixOp.InfixOp.ArrayMult => " ** ",
3308 ast.NodeInfixOp.InfixOp.Assign => " = ",
3309 ast.NodeInfixOp.InfixOp.AssignBitAnd => " &= ",
3310 ast.NodeInfixOp.InfixOp.AssignBitOr => " |= ",
3311 ast.NodeInfixOp.InfixOp.AssignBitShiftLeft => " <<= ",
3312 ast.NodeInfixOp.InfixOp.AssignBitShiftRight => " >>= ",
3313 ast.NodeInfixOp.InfixOp.AssignBitXor => " ^= ",
3314 ast.NodeInfixOp.InfixOp.AssignDiv => " /= ",
3315 ast.NodeInfixOp.InfixOp.AssignMinus => " -= ",
3316 ast.NodeInfixOp.InfixOp.AssignMinusWrap => " -%= ",
3317 ast.NodeInfixOp.InfixOp.AssignMod => " %= ",
3318 ast.NodeInfixOp.InfixOp.AssignPlus => " += ",
3319 ast.NodeInfixOp.InfixOp.AssignPlusWrap => " +%= ",
3320 ast.NodeInfixOp.InfixOp.AssignTimes => " *= ",
3321 ast.NodeInfixOp.InfixOp.AssignTimesWarp => " *%= ",
3322 ast.NodeInfixOp.InfixOp.BangEqual => " != ",
3323 ast.NodeInfixOp.InfixOp.BitAnd => " & ",
3324 ast.NodeInfixOp.InfixOp.BitOr => " | ",
3325 ast.NodeInfixOp.InfixOp.BitShiftLeft => " << ",
3326 ast.NodeInfixOp.InfixOp.BitShiftRight => " >> ",
3327 ast.NodeInfixOp.InfixOp.BitXor => " ^ ",
3328 ast.NodeInfixOp.InfixOp.BoolAnd => " and ",
3329 ast.NodeInfixOp.InfixOp.BoolOr => " or ",
3330 ast.NodeInfixOp.InfixOp.Div => " / ",
3331 ast.NodeInfixOp.InfixOp.EqualEqual => " == ",
3332 ast.NodeInfixOp.InfixOp.ErrorUnion => "!",
3333 ast.NodeInfixOp.InfixOp.GreaterOrEqual => " >= ",
3334 ast.NodeInfixOp.InfixOp.GreaterThan => " > ",
3335 ast.NodeInfixOp.InfixOp.LessOrEqual => " <= ",
3336 ast.NodeInfixOp.InfixOp.LessThan => " < ",
3337 ast.NodeInfixOp.InfixOp.MergeErrorSets => " || ",
3338 ast.NodeInfixOp.InfixOp.Mod => " % ",
3339 ast.NodeInfixOp.InfixOp.Mult => " * ",
3340 ast.NodeInfixOp.InfixOp.MultWrap => " *% ",
3341 ast.NodeInfixOp.InfixOp.Period => ".",
3342 ast.NodeInfixOp.InfixOp.Sub => " - ",
3343 ast.NodeInfixOp.InfixOp.SubWrap => " -% ",
3344 ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ",
3345 ast.NodeInfixOp.InfixOp.Range => " ... ",
3346 ast.NodeInfixOp.InfixOp.Catch => unreachable,
3347 };
3348
3349 try stack.append(RenderState { .Text = text });
3350 }
1356 try stack.append(RenderState { .Expression = prefix_op_node.lhs });3351 try stack.append(RenderState { .Expression = prefix_op_node.lhs });
1357 },3352 },
1358 ast.Node.Id.PrefixOp => {3353 ast.Node.Id.PrefixOp => {
...@@ -1373,15 +3368,179 @@ pub const Parser = struct {...@@ -1373,15 +3368,179 @@ pub const Parser = struct {
1373 try stack.append(RenderState { .Expression = align_expr});3368 try stack.append(RenderState { .Expression = align_expr});
1374 }3369 }
1375 },3370 },
3371 ast.NodePrefixOp.PrefixOp.SliceType => |addr_of_info| {
3372 try stream.write("[]");
3373 if (addr_of_info.volatile_token != null) {
3374 try stack.append(RenderState { .Text = "volatile "});
3375 }
3376 if (addr_of_info.const_token != null) {
3377 try stack.append(RenderState { .Text = "const "});
3378 }
3379 if (addr_of_info.align_expr) |align_expr| {
3380 try stream.print("align(");
3381 try stack.append(RenderState { .Text = ") "});
3382 try stack.append(RenderState { .Expression = align_expr});
3383 }
3384 },
3385 ast.NodePrefixOp.PrefixOp.ArrayType => |array_index| {
3386 try stack.append(RenderState { .Text = "]"});
3387 try stack.append(RenderState { .Expression = array_index});
3388 try stack.append(RenderState { .Text = "["});
3389 },
1376 ast.NodePrefixOp.PrefixOp.BitNot => try stream.write("~"),3390 ast.NodePrefixOp.PrefixOp.BitNot => try stream.write("~"),
1377 ast.NodePrefixOp.PrefixOp.BoolNot => try stream.write("!"),3391 ast.NodePrefixOp.PrefixOp.BoolNot => try stream.write("!"),
1378 ast.NodePrefixOp.PrefixOp.Deref => try stream.write("*"),3392 ast.NodePrefixOp.PrefixOp.Deref => try stream.write("*"),
1379 ast.NodePrefixOp.PrefixOp.Negation => try stream.write("-"),3393 ast.NodePrefixOp.PrefixOp.Negation => try stream.write("-"),
1380 ast.NodePrefixOp.PrefixOp.NegationWrap => try stream.write("-%"),3394 ast.NodePrefixOp.PrefixOp.NegationWrap => try stream.write("-%"),
1381 ast.NodePrefixOp.PrefixOp.Return => try stream.write("return "),
1382 ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "),3395 ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "),
1383 ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"),3396 ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"),
3397 ast.NodePrefixOp.PrefixOp.MaybeType => try stream.write("?"),
3398 ast.NodePrefixOp.PrefixOp.Await => try stream.write("await "),
3399 ast.NodePrefixOp.PrefixOp.Cancel => try stream.write("cancel "),
3400 ast.NodePrefixOp.PrefixOp.Resume => try stream.write("resume "),
3401 }
3402 },
3403 ast.Node.Id.SuffixOp => {
3404 const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", base);
3405
3406 switch (suffix_op.op) {
3407 ast.NodeSuffixOp.SuffixOp.Call => |call_info| {
3408 try stack.append(RenderState { .Text = ")"});
3409 var i = call_info.params.len;
3410 while (i != 0) {
3411 i -= 1;
3412 const param_node = call_info.params.at(i);
3413 try stack.append(RenderState { .Expression = param_node});
3414 if (i != 0) {
3415 try stack.append(RenderState { .Text = ", " });
3416 }
3417 }
3418 try stack.append(RenderState { .Text = "("});
3419 try stack.append(RenderState { .Expression = suffix_op.lhs });
3420
3421 if (call_info.async_attr) |async_attr| {
3422 try stack.append(RenderState { .Text = " "});
3423 try stack.append(RenderState { .Expression = &async_attr.base });
3424 }
3425 },
3426 ast.NodeSuffixOp.SuffixOp.ArrayAccess => |index_expr| {
3427 try stack.append(RenderState { .Text = "]"});
3428 try stack.append(RenderState { .Expression = index_expr});
3429 try stack.append(RenderState { .Text = "["});
3430 try stack.append(RenderState { .Expression = suffix_op.lhs });
3431 },
3432 ast.NodeSuffixOp.SuffixOp.Slice => |range| {
3433 try stack.append(RenderState { .Text = "]"});
3434 if (range.end) |end| {
3435 try stack.append(RenderState { .Expression = end});
3436 }
3437 try stack.append(RenderState { .Text = ".."});
3438 try stack.append(RenderState { .Expression = range.start});
3439 try stack.append(RenderState { .Text = "["});
3440 try stack.append(RenderState { .Expression = suffix_op.lhs });
3441 },
3442 ast.NodeSuffixOp.SuffixOp.StructInitializer => |field_inits| {
3443 try stack.append(RenderState { .Text = " }"});
3444 var i = field_inits.len;
3445 while (i != 0) {
3446 i -= 1;
3447 const field_init = field_inits.at(i);
3448 try stack.append(RenderState { .FieldInitializer = field_init });
3449 try stack.append(RenderState { .Text = " " });
3450 if (i != 0) {
3451 try stack.append(RenderState { .Text = "," });
3452 }
3453 }
3454 try stack.append(RenderState { .Text = "{"});
3455 try stack.append(RenderState { .Expression = suffix_op.lhs });
3456 },
3457 ast.NodeSuffixOp.SuffixOp.ArrayInitializer => |exprs| {
3458 try stack.append(RenderState { .Text = " }"});
3459 var i = exprs.len;
3460 while (i != 0) {
3461 i -= 1;
3462 const expr = exprs.at(i);
3463 try stack.append(RenderState { .Expression = expr });
3464 try stack.append(RenderState { .Text = " " });
3465 if (i != 0) {
3466 try stack.append(RenderState { .Text = "," });
3467 }
3468 }
3469 try stack.append(RenderState { .Text = "{"});
3470 try stack.append(RenderState { .Expression = suffix_op.lhs });
3471 },
3472 }
3473 },
3474 ast.Node.Id.ControlFlowExpression => {
3475 const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base);
3476 switch (flow_expr.kind) {
3477 ast.NodeControlFlowExpression.Kind.Break => |maybe_blk_token| {
3478 try stream.print("break");
3479 if (maybe_blk_token) |blk_token| {
3480 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));
3481 }
3482 },
3483 ast.NodeControlFlowExpression.Kind.Continue => |maybe_blk_token| {
3484 try stream.print("continue");
3485 if (maybe_blk_token) |blk_token| {
3486 try stream.print(" :{}", self.tokenizer.getTokenSlice(blk_token));
3487 }
3488 },
3489 ast.NodeControlFlowExpression.Kind.Return => {
3490 try stream.print("return");
3491 },
3492
3493 }
3494
3495 if (flow_expr.rhs) |rhs| {
3496 try stream.print(" ");
3497 try stack.append(RenderState { .Expression = rhs });
3498 }
3499 },
3500 ast.Node.Id.Payload => {
3501 const payload = @fieldParentPtr(ast.NodePayload, "base", base);
3502 try stack.append(RenderState { .Text = "|"});
3503 try stack.append(RenderState { .Expression = &payload.error_symbol.base });
3504 try stack.append(RenderState { .Text = "|"});
3505 },
3506 ast.Node.Id.PointerPayload => {
3507 const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base);
3508 try stack.append(RenderState { .Text = "|"});
3509 try stack.append(RenderState { .Expression = &payload.value_symbol.base });
3510
3511 if (payload.is_ptr) {
3512 try stack.append(RenderState { .Text = "*"});
3513 }
3514
3515 try stack.append(RenderState { .Text = "|"});
3516 },
3517 ast.Node.Id.PointerIndexPayload => {
3518 const payload = @fieldParentPtr(ast.NodePointerIndexPayload, "base", base);
3519 try stack.append(RenderState { .Text = "|"});
3520
3521 if (payload.index_symbol) |index_symbol| {
3522 try stack.append(RenderState { .Expression = &index_symbol.base });
3523 try stack.append(RenderState { .Text = ", "});
3524 }
3525
3526 try stack.append(RenderState { .Expression = &payload.value_symbol.base });
3527
3528 if (payload.is_ptr) {
3529 try stack.append(RenderState { .Text = "*"});
1384 }3530 }
3531
3532 try stack.append(RenderState { .Text = "|"});
3533 },
3534 ast.Node.Id.GroupedExpression => {
3535 const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base);
3536 try stack.append(RenderState { .Text = ")"});
3537 try stack.append(RenderState { .Expression = grouped_expr.expr });
3538 try stack.append(RenderState { .Text = "("});
3539 },
3540 ast.Node.Id.FieldInitializer => {
3541 const field_init = @fieldParentPtr(ast.NodeFieldInitializer, "base", base);
3542 try stream.print(".{} = ", self.tokenizer.getTokenSlice(field_init.name_token));
3543 try stack.append(RenderState { .Expression = field_init.expr });
1385 },3544 },
1386 ast.Node.Id.IntegerLiteral => {3545 ast.Node.Id.IntegerLiteral => {
1387 const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);3546 const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);
...@@ -1395,6 +3554,147 @@ pub const Parser = struct {...@@ -1395,6 +3554,147 @@ pub const Parser = struct {
1395 const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base);3554 const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base);
1396 try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token));3555 try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token));
1397 },3556 },
3557 ast.Node.Id.CharLiteral => {
3558 const char_literal = @fieldParentPtr(ast.NodeCharLiteral, "base", base);
3559 try stream.print("{}", self.tokenizer.getTokenSlice(char_literal.token));
3560 },
3561 ast.Node.Id.BoolLiteral => {
3562 const bool_literal = @fieldParentPtr(ast.NodeCharLiteral, "base", base);
3563 try stream.print("{}", self.tokenizer.getTokenSlice(bool_literal.token));
3564 },
3565 ast.Node.Id.NullLiteral => {
3566 const null_literal = @fieldParentPtr(ast.NodeNullLiteral, "base", base);
3567 try stream.print("{}", self.tokenizer.getTokenSlice(null_literal.token));
3568 },
3569 ast.Node.Id.ThisLiteral => {
3570 const this_literal = @fieldParentPtr(ast.NodeThisLiteral, "base", base);
3571 try stream.print("{}", self.tokenizer.getTokenSlice(this_literal.token));
3572 },
3573 ast.Node.Id.Unreachable => {
3574 const unreachable_node = @fieldParentPtr(ast.NodeUnreachable, "base", base);
3575 try stream.print("{}", self.tokenizer.getTokenSlice(unreachable_node.token));
3576 },
3577 ast.Node.Id.ErrorType => {
3578 const error_type = @fieldParentPtr(ast.NodeErrorType, "base", base);
3579 try stream.print("{}", self.tokenizer.getTokenSlice(error_type.token));
3580 },
3581 ast.Node.Id.VarType => {
3582 const var_type = @fieldParentPtr(ast.NodeVarType, "base", base);
3583 try stream.print("{}", self.tokenizer.getTokenSlice(var_type.token));
3584 },
3585 ast.Node.Id.ContainerDecl => {
3586 const container_decl = @fieldParentPtr(ast.NodeContainerDecl, "base", base);
3587
3588 switch (container_decl.layout) {
3589 ast.NodeContainerDecl.Layout.Packed => try stream.print("packed "),
3590 ast.NodeContainerDecl.Layout.Extern => try stream.print("extern "),
3591 ast.NodeContainerDecl.Layout.Auto => { },
3592 }
3593
3594 switch (container_decl.kind) {
3595 ast.NodeContainerDecl.Kind.Struct => try stream.print("struct"),
3596 ast.NodeContainerDecl.Kind.Enum => try stream.print("enum"),
3597 ast.NodeContainerDecl.Kind.Union => try stream.print("union"),
3598 }
3599
3600 try stack.append(RenderState { .Text = "}"});
3601 try stack.append(RenderState.PrintIndent);
3602 try stack.append(RenderState { .Indent = indent });
3603 try stack.append(RenderState { .Text = "\n"});
3604
3605 const fields_and_decls = container_decl.fields_and_decls.toSliceConst();
3606 var i = fields_and_decls.len;
3607 while (i != 0) {
3608 i -= 1;
3609 const node = fields_and_decls[i];
3610 try stack.append(RenderState { .TopLevelDecl = node});
3611 try stack.append(RenderState.PrintIndent);
3612 try stack.append(RenderState {
3613 .Text = blk: {
3614 if (i != 0) {
3615 const prev_node = fields_and_decls[i - 1];
3616 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
3617 if (loc.line >= 2) {
3618 break :blk "\n\n";
3619 }
3620 }
3621 break :blk "\n";
3622 },
3623 });
3624
3625 if (i != 0) {
3626 const prev_node = fields_and_decls[i - 1];
3627 switch (prev_node.id) {
3628 ast.Node.Id.StructField,
3629 ast.Node.Id.UnionTag,
3630 ast.Node.Id.EnumTag => {
3631 try stack.append(RenderState { .Text = "," });
3632 },
3633 else => { }
3634 }
3635 }
3636 }
3637 try stack.append(RenderState { .Indent = indent + indent_delta});
3638 try stack.append(RenderState { .Text = "{"});
3639
3640 switch (container_decl.init_arg_expr) {
3641 ast.NodeContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}),
3642 ast.NodeContainerDecl.InitArg.Enum => try stack.append(RenderState { .Text = "(enum) "}),
3643 ast.NodeContainerDecl.InitArg.Type => |type_expr| {
3644 try stack.append(RenderState { .Text = ") "});
3645 try stack.append(RenderState { .Expression = type_expr});
3646 try stack.append(RenderState { .Text = "("});
3647 },
3648 }
3649 },
3650 ast.Node.Id.ErrorSetDecl => {
3651 const err_set_decl = @fieldParentPtr(ast.NodeErrorSetDecl, "base", base);
3652 try stream.print("error ");
3653
3654 try stack.append(RenderState { .Text = "}"});
3655 try stack.append(RenderState.PrintIndent);
3656 try stack.append(RenderState { .Indent = indent });
3657 try stack.append(RenderState { .Text = "\n"});
3658
3659 const decls = err_set_decl.decls.toSliceConst();
3660 var i = decls.len;
3661 while (i != 0) {
3662 i -= 1;
3663 const node = decls[i];
3664 try stack.append(RenderState { .Expression = &node.base});
3665 try stack.append(RenderState.PrintIndent);
3666 try stack.append(RenderState {
3667 .Text = blk: {
3668 if (i != 0) {
3669 const prev_node = decls[i - 1];
3670 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
3671 if (loc.line >= 2) {
3672 break :blk "\n\n";
3673 }
3674 }
3675 break :blk "\n";
3676 },
3677 });
3678
3679 if (i != 0) {
3680 try stack.append(RenderState { .Text = "," });
3681 }
3682 }
3683 try stack.append(RenderState { .Indent = indent + indent_delta});
3684 try stack.append(RenderState { .Text = "{"});
3685 },
3686 ast.Node.Id.MultilineStringLiteral => {
3687 const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base);
3688 try stream.print("\n");
3689
3690 var i : usize = 0;
3691 while (i < multiline_str_literal.tokens.len) : (i += 1) {
3692 const t = multiline_str_literal.tokens.at(i);
3693 try stream.writeByteNTimes(' ', indent + indent_delta);
3694 try stream.print("{}", self.tokenizer.getTokenSlice(t));
3695 }
3696 try stream.writeByteNTimes(' ', indent + indent_delta);
3697 },
1398 ast.Node.Id.UndefinedLiteral => {3698 ast.Node.Id.UndefinedLiteral => {
1399 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);3699 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);
1400 try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token));3700 try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token));
...@@ -1413,26 +3713,419 @@ pub const Parser = struct {...@@ -1413,26 +3713,419 @@ pub const Parser = struct {
1413 }3713 }
1414 }3714 }
1415 },3715 },
1416 ast.Node.Id.Call => {3716 ast.Node.Id.FnProto => {
1417 const call = @fieldParentPtr(ast.NodeCall, "base", base);3717 const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", base);
3718
3719 switch (fn_proto.return_type) {
3720 ast.NodeFnProto.ReturnType.Explicit => |node| {
3721 try stack.append(RenderState { .Expression = node});
3722 },
3723 ast.NodeFnProto.ReturnType.InferErrorSet => |node| {
3724 try stack.append(RenderState { .Expression = node});
3725 try stack.append(RenderState { .Text = "!"});
3726 },
3727 }
3728
3729 if (fn_proto.align_expr != null) {
3730 @panic("TODO");
3731 }
3732
3733 try stack.append(RenderState { .Text = ") " });
3734 var i = fn_proto.params.len;
3735 while (i != 0) {
3736 i -= 1;
3737 const param_decl_node = fn_proto.params.items[i];
3738 try stack.append(RenderState { .ParamDecl = param_decl_node});
3739 if (i != 0) {
3740 try stack.append(RenderState { .Text = ", " });
3741 }
3742 }
3743
3744 try stack.append(RenderState { .Text = "(" });
3745 if (fn_proto.name_token) |name_token| {
3746 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(name_token) });
3747 try stack.append(RenderState { .Text = " " });
3748 }
3749
3750 try stack.append(RenderState { .Text = "fn" });
3751
3752 if (fn_proto.async_attr) |async_attr| {
3753 try stack.append(RenderState { .Text = " " });
3754 try stack.append(RenderState { .Expression = &async_attr.base });
3755 }
3756
3757 if (fn_proto.cc_token) |cc_token| {
3758 try stack.append(RenderState { .Text = " " });
3759 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(cc_token) });
3760 }
3761
3762 if (fn_proto.lib_name) |lib_name| {
3763 try stack.append(RenderState { .Text = " " });
3764 try stack.append(RenderState { .Expression = lib_name });
3765 }
3766 if (fn_proto.extern_token) |extern_token| {
3767 try stack.append(RenderState { .Text = " " });
3768 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(extern_token) });
3769 }
3770
3771 if (fn_proto.visib_token) |visib_token| {
3772 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);
3773 try stack.append(RenderState { .Text = " " });
3774 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(visib_token) });
3775 }
3776 },
3777 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
3778 ast.Node.Id.Switch => {
3779 const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base);
3780 try stream.print("{} (", self.tokenizer.getTokenSlice(switch_node.switch_token));
3781
3782 try stack.append(RenderState { .Text = "}"});
3783 try stack.append(RenderState.PrintIndent);
3784 try stack.append(RenderState { .Indent = indent });
3785 try stack.append(RenderState { .Text = "\n"});
3786
3787 const cases = switch_node.cases.toSliceConst();
3788 var i = cases.len;
3789 while (i != 0) {
3790 i -= 1;
3791 const node = cases[i];
3792 try stack.append(RenderState { .Expression = &node.base});
3793 try stack.append(RenderState.PrintIndent);
3794 try stack.append(RenderState {
3795 .Text = blk: {
3796 if (i != 0) {
3797 const prev_node = cases[i - 1];
3798 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
3799 if (loc.line >= 2) {
3800 break :blk "\n\n";
3801 }
3802 }
3803 break :blk "\n";
3804 },
3805 });
3806
3807 if (i != 0) {
3808 try stack.append(RenderState { .Text = "," });
3809 }
3810 }
3811 try stack.append(RenderState { .Indent = indent + indent_delta});
3812 try stack.append(RenderState { .Text = ") {"});
3813 try stack.append(RenderState { .Expression = switch_node.expr });
3814 },
3815 ast.Node.Id.SwitchCase => {
3816 const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base);
3817
3818 try stack.append(RenderState { .Expression = switch_case.expr });
3819 if (switch_case.payload) |payload| {
3820 try stack.append(RenderState { .Text = " " });
3821 try stack.append(RenderState { .Expression = &payload.base });
3822 }
3823 try stack.append(RenderState { .Text = " => "});
3824
3825 const items = switch_case.items.toSliceConst();
3826 var i = items.len;
3827 while (i != 0) {
3828 i -= 1;
3829 try stack.append(RenderState { .Expression = items[i] });
3830
3831 if (i != 0) {
3832 try stack.append(RenderState { .Text = ", " });
3833 }
3834 }
3835 },
3836 ast.Node.Id.SwitchElse => {
3837 const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base);
3838 try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token));
3839 },
3840 ast.Node.Id.Else => {
3841 const else_node = @fieldParentPtr(ast.NodeElse, "base", base);
3842 try stream.print("{}", self.tokenizer.getTokenSlice(else_node.else_token));
3843
3844 switch (else_node.body.id) {
3845 ast.Node.Id.Block, ast.Node.Id.If,
3846 ast.Node.Id.For, ast.Node.Id.While,
3847 ast.Node.Id.Switch => {
3848 try stream.print(" ");
3849 try stack.append(RenderState { .Expression = else_node.body });
3850 },
3851 else => {
3852 try stack.append(RenderState { .Indent = indent });
3853 try stack.append(RenderState { .Expression = else_node.body });
3854 try stack.append(RenderState.PrintIndent);
3855 try stack.append(RenderState { .Indent = indent + indent_delta });
3856 try stack.append(RenderState { .Text = "\n" });
3857 }
3858 }
3859
3860 if (else_node.payload) |payload| {
3861 try stack.append(RenderState { .Text = " " });
3862 try stack.append(RenderState { .Expression = &payload.base });
3863 }
3864 },
3865 ast.Node.Id.While => {
3866 const while_node = @fieldParentPtr(ast.NodeWhile, "base", base);
3867 if (while_node.label) |label| {
3868 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
3869 }
3870
3871 if (while_node.inline_token) |inline_token| {
3872 try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token));
3873 }
3874
3875 try stream.print("{} ", self.tokenizer.getTokenSlice(while_node.while_token));
3876
3877 if (while_node.@"else") |@"else"| {
3878 try stack.append(RenderState { .Expression = &@"else".base });
3879
3880 if (while_node.body.id == ast.Node.Id.Block) {
3881 try stack.append(RenderState { .Text = " " });
3882 } else {
3883 try stack.append(RenderState.PrintIndent);
3884 try stack.append(RenderState { .Text = "\n" });
3885 }
3886 }
3887
3888 if (while_node.body.id == ast.Node.Id.Block) {
3889 try stack.append(RenderState { .Expression = while_node.body });
3890 try stack.append(RenderState { .Text = " " });
3891 } else {
3892 try stack.append(RenderState { .Indent = indent });
3893 try stack.append(RenderState { .Expression = while_node.body });
3894 try stack.append(RenderState.PrintIndent);
3895 try stack.append(RenderState { .Indent = indent + indent_delta });
3896 try stack.append(RenderState { .Text = "\n" });
3897 }
3898
3899 if (while_node.continue_expr) |continue_expr| {
3900 try stack.append(RenderState { .Text = ")" });
3901 try stack.append(RenderState { .Expression = continue_expr });
3902 try stack.append(RenderState { .Text = ": (" });
3903 try stack.append(RenderState { .Text = " " });
3904 }
3905
3906 if (while_node.payload) |payload| {
3907 try stack.append(RenderState { .Expression = &payload.base });
3908 try stack.append(RenderState { .Text = " " });
3909 }
3910
3911 try stack.append(RenderState { .Text = ")" });
3912 try stack.append(RenderState { .Expression = while_node.condition });
3913 try stack.append(RenderState { .Text = "(" });
3914 },
3915 ast.Node.Id.For => {
3916 const for_node = @fieldParentPtr(ast.NodeFor, "base", base);
3917 if (for_node.label) |label| {
3918 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
3919 }
3920
3921 if (for_node.inline_token) |inline_token| {
3922 try stream.print("{} ", self.tokenizer.getTokenSlice(inline_token));
3923 }
3924
3925 try stream.print("{} ", self.tokenizer.getTokenSlice(for_node.for_token));
3926
3927 if (for_node.@"else") |@"else"| {
3928 try stack.append(RenderState { .Expression = &@"else".base });
3929
3930 if (for_node.body.id == ast.Node.Id.Block) {
3931 try stack.append(RenderState { .Text = " " });
3932 } else {
3933 try stack.append(RenderState.PrintIndent);
3934 try stack.append(RenderState { .Text = "\n" });
3935 }
3936 }
3937
3938 if (for_node.body.id == ast.Node.Id.Block) {
3939 try stack.append(RenderState { .Expression = for_node.body });
3940 try stack.append(RenderState { .Text = " " });
3941 } else {
3942 try stack.append(RenderState { .Indent = indent });
3943 try stack.append(RenderState { .Expression = for_node.body });
3944 try stack.append(RenderState.PrintIndent);
3945 try stack.append(RenderState { .Indent = indent + indent_delta });
3946 try stack.append(RenderState { .Text = "\n" });
3947 }
3948
3949 if (for_node.payload) |payload| {
3950 try stack.append(RenderState { .Expression = &payload.base });
3951 try stack.append(RenderState { .Text = " " });
3952 }
3953
3954 try stack.append(RenderState { .Text = ")" });
3955 try stack.append(RenderState { .Expression = for_node.array_expr });
3956 try stack.append(RenderState { .Text = "(" });
3957 },
3958 ast.Node.Id.If => {
3959 const if_node = @fieldParentPtr(ast.NodeIf, "base", base);
3960 try stream.print("{} ", self.tokenizer.getTokenSlice(if_node.if_token));
3961
3962 switch (if_node.body.id) {
3963 ast.Node.Id.Block, ast.Node.Id.If,
3964 ast.Node.Id.For, ast.Node.Id.While,
3965 ast.Node.Id.Switch => {
3966 if (if_node.@"else") |@"else"| {
3967 try stack.append(RenderState { .Expression = &@"else".base });
3968
3969 if (if_node.body.id == ast.Node.Id.Block) {
3970 try stack.append(RenderState { .Text = " " });
3971 } else {
3972 try stack.append(RenderState.PrintIndent);
3973 try stack.append(RenderState { .Text = "\n" });
3974 }
3975 }
3976 },
3977 else => {
3978 if (if_node.@"else") |@"else"| {
3979 try stack.append(RenderState { .Expression = @"else".body });
3980
3981 if (@"else".payload) |payload| {
3982 try stack.append(RenderState { .Text = " " });
3983 try stack.append(RenderState { .Expression = &payload.base });
3984 }
3985
3986 try stack.append(RenderState { .Text = " " });
3987 try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(@"else".else_token) });
3988 try stack.append(RenderState { .Text = " " });
3989 }
3990 }
3991 }
3992
3993 try stack.append(RenderState { .Expression = if_node.body });
3994 try stack.append(RenderState { .Text = " " });
3995
3996 if (if_node.payload) |payload| {
3997 try stack.append(RenderState { .Expression = &payload.base });
3998 try stack.append(RenderState { .Text = " " });
3999 }
4000
4001 try stack.append(RenderState { .Text = ")" });
4002 try stack.append(RenderState { .Expression = if_node.condition });
4003 try stack.append(RenderState { .Text = "(" });
4004 },
4005 ast.Node.Id.Asm => {
4006 const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base);
4007 try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token));
4008
4009 if (asm_node.is_volatile) {
4010 try stream.write("volatile ");
4011 }
4012
4013 try stream.print("({}", self.tokenizer.getTokenSlice(asm_node.template));
4014
4015 try stack.append(RenderState { .Indent = indent });
4016 try stack.append(RenderState { .Text = ")" });
4017 {
4018 const cloppers = asm_node.cloppers.toSliceConst();
4019 var i = cloppers.len;
4020 while (i != 0) {
4021 i -= 1;
4022 try stack.append(RenderState { .Expression = &cloppers[i].base });
4023
4024 if (i != 0) {
4025 try stack.append(RenderState { .Text = ", " });
4026 }
4027 }
4028 }
4029 try stack.append(RenderState { .Text = ": " });
4030 try stack.append(RenderState.PrintIndent);
4031 try stack.append(RenderState { .Indent = indent + indent_delta });
4032 try stack.append(RenderState { .Text = "\n" });
4033 {
4034 const inputs = asm_node.inputs.toSliceConst();
4035 var i = inputs.len;
4036 while (i != 0) {
4037 i -= 1;
4038 const node = inputs[i];
4039 try stack.append(RenderState { .Expression = &node.base});
4040
4041 if (i != 0) {
4042 try stack.append(RenderState.PrintIndent);
4043 try stack.append(RenderState {
4044 .Text = blk: {
4045 const prev_node = inputs[i - 1];
4046 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
4047 if (loc.line >= 2) {
4048 break :blk "\n\n";
4049 }
4050 break :blk "\n";
4051 },
4052 });
4053 try stack.append(RenderState { .Text = "," });
4054 }
4055 }
4056 }
4057 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
4058 try stack.append(RenderState { .Text = ": "});
4059 try stack.append(RenderState.PrintIndent);
4060 try stack.append(RenderState { .Indent = indent + indent_delta});
4061 try stack.append(RenderState { .Text = "\n" });
4062 {
4063 const outputs = asm_node.outputs.toSliceConst();
4064 var i = outputs.len;
4065 while (i != 0) {
4066 i -= 1;
4067 const node = outputs[i];
4068 try stack.append(RenderState { .Expression = &node.base});
4069
4070 if (i != 0) {
4071 try stack.append(RenderState.PrintIndent);
4072 try stack.append(RenderState {
4073 .Text = blk: {
4074 const prev_node = outputs[i - 1];
4075 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, node.firstToken());
4076 if (loc.line >= 2) {
4077 break :blk "\n\n";
4078 }
4079 break :blk "\n";
4080 },
4081 });
4082 try stack.append(RenderState { .Text = "," });
4083 }
4084 }
4085 }
4086 try stack.append(RenderState { .Indent = indent + indent_delta + 2});
4087 try stack.append(RenderState { .Text = ": "});
4088 try stack.append(RenderState.PrintIndent);
4089 try stack.append(RenderState { .Indent = indent + indent_delta});
4090 try stack.append(RenderState { .Text = "\n" });
4091 },
4092 ast.Node.Id.AsmInput => {
4093 const asm_input = @fieldParentPtr(ast.NodeAsmInput, "base", base);
4094
1418 try stack.append(RenderState { .Text = ")"});4095 try stack.append(RenderState { .Text = ")"});
1419 var i = call.params.len;4096 try stack.append(RenderState { .Expression = asm_input.expr});
1420 while (i != 0) {4097 try stack.append(RenderState { .Text = " ("});
1421 i -= 1;4098 try stack.append(RenderState { .Expression = &asm_input.constraint.base});
1422 const param_node = call.params.at(i);4099 try stack.append(RenderState { .Text = "] "});
1423 try stack.append(RenderState { .Expression = param_node});4100 try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});
1424 if (i != 0) {4101 try stack.append(RenderState { .Text = "["});
1425 try stack.append(RenderState { .Text = ", " });4102 },
1426 }4103 ast.Node.Id.AsmOutput => {
4104 const asm_output = @fieldParentPtr(ast.NodeAsmOutput, "base", base);
4105
4106 try stack.append(RenderState { .Text = ")"});
4107 switch (asm_output.kind) {
4108 ast.NodeAsmOutput.Kind.Variable => |variable_name| {
4109 try stack.append(RenderState { .Expression = &variable_name.base});
4110 },
4111 ast.NodeAsmOutput.Kind.Return => |return_type| {
4112 try stack.append(RenderState { .Expression = return_type});
4113 try stack.append(RenderState { .Text = "-> "});
4114 },
1427 }4115 }
1428 try stack.append(RenderState { .Text = "("});4116 try stack.append(RenderState { .Text = " ("});
1429 try stack.append(RenderState { .Expression = call.callee });4117 try stack.append(RenderState { .Expression = &asm_output.constraint.base});
4118 try stack.append(RenderState { .Text = "] "});
4119 try stack.append(RenderState { .Expression = &asm_output.symbolic_name.base});
4120 try stack.append(RenderState { .Text = "["});
1430 },4121 },
1431 ast.Node.Id.FnProto => @panic("TODO fn proto in an expression"),
1432 ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"),
14334122
4123 ast.Node.Id.StructField,
4124 ast.Node.Id.UnionTag,
4125 ast.Node.Id.EnumTag,
1434 ast.Node.Id.Root,4126 ast.Node.Id.Root,
1435 ast.Node.Id.VarDecl,4127 ast.Node.Id.VarDecl,
4128 ast.Node.Id.Use,
1436 ast.Node.Id.TestDecl,4129 ast.Node.Id.TestDecl,
1437 ast.Node.Id.ParamDecl => unreachable,4130 ast.Node.Id.ParamDecl => unreachable,
1438 },4131 },
...@@ -1450,9 +4143,6 @@ pub const Parser = struct {...@@ -1450,9 +4143,6 @@ pub const Parser = struct {
1450 ast.NodeFnProto.ReturnType.Explicit => |node| {4143 ast.NodeFnProto.ReturnType.Explicit => |node| {
1451 try stack.append(RenderState { .Expression = node});4144 try stack.append(RenderState { .Expression = node});
1452 },4145 },
1453 ast.NodeFnProto.ReturnType.Infer => {
1454 try stream.print("var");
1455 },
1456 ast.NodeFnProto.ReturnType.InferErrorSet => |node| {4146 ast.NodeFnProto.ReturnType.InferErrorSet => |node| {
1457 try stream.print("!");4147 try stream.print("!");
1458 try stack.append(RenderState { .Expression = node});4148 try stack.append(RenderState { .Expression = node});
...@@ -1472,8 +4162,10 @@ pub const Parser = struct {...@@ -1472,8 +4162,10 @@ pub const Parser = struct {
1472 try stack.append(RenderState { .VarDecl = var_decl});4162 try stack.append(RenderState { .VarDecl = var_decl});
1473 },4163 },
1474 else => {4164 else => {
1475 try stack.append(RenderState { .Text = ";"});4165 if (requireSemiColon(base)) {
1476 try stack.append(RenderState { .Expression = base});4166 try stack.append(RenderState { .Text = ";" });
4167 }
4168 try stack.append(RenderState { .Expression = base });
1477 },4169 },
1478 }4170 }
1479 },4171 },
...@@ -1557,7 +4249,7 @@ fn testCanonical(source: []const u8) !void {...@@ -1557,7 +4249,7 @@ fn testCanonical(source: []const u8) !void {
1557 }4249 }
1558}4250}
15594251
1560test "zig fmt" {4252test "zig fmt: get stdout or fail" {
1561 try testCanonical(4253 try testCanonical(
1562 \\const std = @import("std");4254 \\const std = @import("std");
1563 \\4255 \\
...@@ -1568,7 +4260,9 @@ test "zig fmt" {...@@ -1568,7 +4260,9 @@ test "zig fmt" {
1568 \\}4260 \\}
1569 \\4261 \\
1570 );4262 );
4263}
15714264
4265test "zig fmt: preserve spacing" {
1572 try testCanonical(4266 try testCanonical(
1573 \\const std = @import("std");4267 \\const std = @import("std");
1574 \\4268 \\
...@@ -1581,25 +4275,26 @@ test "zig fmt" {...@@ -1581,25 +4275,26 @@ test "zig fmt" {
1581 \\}4275 \\}
1582 \\4276 \\
1583 );4277 );
4278}
15844279
4280test "zig fmt: return types" {
1585 try testCanonical(4281 try testCanonical(
1586 \\pub fn main() !void {}4282 \\pub fn main() !void {}
1587 \\pub fn main() var {}4283 \\pub fn main() var {}
1588 \\pub fn main() i32 {}4284 \\pub fn main() i32 {}
1589 \\4285 \\
1590 );4286 );
4287}
15914288
4289test "zig fmt: imports" {
1592 try testCanonical(4290 try testCanonical(
1593 \\const std = @import("std");4291 \\const std = @import("std");
1594 \\const std = @import();4292 \\const std = @import();
1595 \\4293 \\
1596 );4294 );
4295}
15974296
1598 try testCanonical(4297test "zig fmt: global declarations" {
1599 \\extern fn puts(s: &const u8) c_int;
1600 \\
1601 );
1602
1603 try testCanonical(4298 try testCanonical(
1604 \\const a = b;4299 \\const a = b;
1605 \\pub const a = b;4300 \\pub const a = b;
...@@ -1609,61 +4304,85 @@ test "zig fmt" {...@@ -1609,61 +4304,85 @@ test "zig fmt" {
1609 \\pub const a: i32 = b;4304 \\pub const a: i32 = b;
1610 \\var a: i32 = b;4305 \\var a: i32 = b;
1611 \\pub var a: i32 = b;4306 \\pub var a: i32 = b;
4307 \\extern const a: i32 = b;
4308 \\pub extern const a: i32 = b;
4309 \\extern var a: i32 = b;
4310 \\pub extern var a: i32 = b;
4311 \\extern "a" const a: i32 = b;
4312 \\pub extern "a" const a: i32 = b;
4313 \\extern "a" var a: i32 = b;
4314 \\pub extern "a" var a: i32 = b;
1612 \\4315 \\
1613 );4316 );
4317}
16144318
4319test "zig fmt: extern declaration" {
1615 try testCanonical(4320 try testCanonical(
1616 \\extern var foo: c_int;4321 \\extern var foo: c_int;
1617 \\4322 \\
1618 );4323 );
4324}
16194325
1620 try testCanonical(4326test "zig fmt: alignment" {
4327 try testCanonical(
1621 \\var foo: c_int align(1);4328 \\var foo: c_int align(1);
1622 \\4329 \\
1623 );4330 );
4331}
16244332
4333test "zig fmt: C main" {
1625 try testCanonical(4334 try testCanonical(
1626 \\fn main(argc: c_int, argv: &&u8) c_int {4335 \\fn main(argc: c_int, argv: &&u8) c_int {
1627 \\ const a = b;4336 \\ const a = b;
1628 \\}4337 \\}
1629 \\4338 \\
1630 );4339 );
4340}
16314341
4342test "zig fmt: return" {
1632 try testCanonical(4343 try testCanonical(
1633 \\fn foo(argc: c_int, argv: &&u8) c_int {4344 \\fn foo(argc: c_int, argv: &&u8) c_int {
1634 \\ return 0;4345 \\ return 0;
1635 \\}4346 \\}
1636 \\4347 \\
1637 );4348 \\fn bar() void {
16384349 \\ return;
1639 try testCanonical(4350 \\}
1640 \\extern fn f1(s: &align(&u8) u8) c_int;
1641 \\4351 \\
1642 );4352 );
4353}
16434354
4355test "zig fmt: pointer attributes" {
1644 try testCanonical(4356 try testCanonical(
1645 \\extern fn f1(s: &&align(1) &const &volatile u8) c_int;4357 \\extern fn f1(s: &align(&u8) u8) c_int;
1646 \\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) c_int;4358 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
1647 \\extern fn f3(s: &align(1) const volatile u8) c_int;4359 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
4360 \\extern fn f4(s: &align(1) const volatile u8) c_int;
1648 \\4361 \\
1649 );4362 );
4363}
16504364
4365test "zig fmt: slice attributes" {
1651 try testCanonical(4366 try testCanonical(
1652 \\fn f1(a: bool, b: bool) bool {4367 \\extern fn f1(s: &align(&u8) u8) c_int;
1653 \\ a != b;4368 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
1654 \\ return a == b;4369 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
1655 \\}4370 \\extern fn f4(s: &align(1) const volatile u8) c_int;
1656 \\4371 \\
1657 );4372 );
4373}
16584374
1659 try testCanonical(4375test "zig fmt: test declaration" {
4376 try testCanonical(
1660 \\test "test name" {4377 \\test "test name" {
1661 \\ const a = 1;4378 \\ const a = 1;
1662 \\ var b = 1;4379 \\ var b = 1;
1663 \\}4380 \\}
1664 \\4381 \\
1665 );4382 );
4383}
16664384
4385test "zig fmt: infix operators" {
1667 try testCanonical(4386 try testCanonical(
1668 \\test "infix operators" {4387 \\test "infix operators" {
1669 \\ var i = undefined;4388 \\ var i = undefined;
...@@ -1713,14 +4432,49 @@ test "zig fmt" {...@@ -1713,14 +4432,49 @@ test "zig fmt" {
1713 \\}4432 \\}
1714 \\4433 \\
1715 );4434 );
4435}
4436
4437test "zig fmt: precedence" {
4438 try testCanonical(
4439 \\test "precedence" {
4440 \\ a!b();
4441 \\ (a!b)();
4442 \\ !a!b;
4443 \\ !(a!b);
4444 \\ !a{ };
4445 \\ !(a{ });
4446 \\ a + b{ };
4447 \\ (a + b){ };
4448 \\ a << b + c;
4449 \\ (a << b) + c;
4450 \\ a & b << c;
4451 \\ (a & b) << c;
4452 \\ a ^ b & c;
4453 \\ (a ^ b) & c;
4454 \\ a | b ^ c;
4455 \\ (a | b) ^ c;
4456 \\ a == b | c;
4457 \\ (a == b) | c;
4458 \\ a and b == c;
4459 \\ (a and b) == c;
4460 \\ a or b and c;
4461 \\ (a or b) and c;
4462 \\ (a or b) and c;
4463 \\}
4464 \\
4465 );
4466}
17164467
4468test "zig fmt: prefix operators" {
1717 try testCanonical(4469 try testCanonical(
1718 \\test "prefix operators" {4470 \\test "prefix operators" {
1719 \\ --%~??!*&0;4471 \\ try return --%~??!*&0;
1720 \\}4472 \\}
1721 \\4473 \\
1722 );4474 );
4475}
17234476
4477test "zig fmt: call expression" {
1724 try testCanonical(4478 try testCanonical(
1725 \\test "test calls" {4479 \\test "test calls" {
1726 \\ a();4480 \\ a();
...@@ -1731,3 +4485,565 @@ test "zig fmt" {...@@ -1731,3 +4485,565 @@ test "zig fmt" {
1731 \\4485 \\
1732 );4486 );
1733}4487}
4488
4489test "zig fmt: var args" {
4490 try testCanonical(
4491 \\fn print(args: ...) void {}
4492 \\
4493 );
4494}
4495
4496test "zig fmt: var type" {
4497 try testCanonical(
4498 \\fn print(args: var) var {}
4499 \\const Var = var;
4500 \\const i: var = 0;
4501 \\
4502 );
4503}
4504
4505test "zig fmt: extern function" {
4506 try testCanonical(
4507 \\extern fn puts(s: &const u8) c_int;
4508 \\extern "c" fn puts(s: &const u8) c_int;
4509 \\
4510 );
4511}
4512
4513test "zig fmt: multiline string" {
4514 try testCanonical(
4515 \\const s =
4516 \\ \\ something
4517 \\ \\ something else
4518 \\ ;
4519 \\
4520 );
4521}
4522
4523test "zig fmt: values" {
4524 try testCanonical(
4525 \\test "values" {
4526 \\ 1;
4527 \\ 1.0;
4528 \\ "string";
4529 \\ c"cstring";
4530 \\ 'c';
4531 \\ true;
4532 \\ false;
4533 \\ null;
4534 \\ undefined;
4535 \\ error;
4536 \\ this;
4537 \\ unreachable;
4538 \\}
4539 \\
4540 );
4541}
4542
4543test "zig fmt: indexing" {
4544 try testCanonical(
4545 \\test "test index" {
4546 \\ a[0];
4547 \\ a[0 + 5];
4548 \\ a[0..];
4549 \\ a[0..5];
4550 \\ a[a[0]];
4551 \\ a[a[0..]];
4552 \\ a[a[0..5]];
4553 \\ a[a[0]..];
4554 \\ a[a[0..5]..];
4555 \\ a[a[0]..a[0]];
4556 \\ a[a[0..5]..a[0]];
4557 \\ a[a[0..5]..a[0..5]];
4558 \\}
4559 \\
4560 );
4561}
4562
4563test "zig fmt: struct declaration" {
4564 try testCanonical(
4565 \\const S = struct {
4566 \\ const Self = this;
4567 \\ f1: u8,
4568 \\
4569 \\ fn method(self: &Self) Self {
4570 \\ return *self;
4571 \\ }
4572 \\
4573 \\ f2: u8
4574 \\};
4575 \\
4576 \\const Ps = packed struct {
4577 \\ a: u8,
4578 \\ b: u8,
4579 \\
4580 \\ c: u8
4581 \\};
4582 \\
4583 \\const Es = extern struct {
4584 \\ a: u8,
4585 \\ b: u8,
4586 \\
4587 \\ c: u8
4588 \\};
4589 \\
4590 );
4591}
4592
4593test "zig fmt: enum declaration" {
4594 try testCanonical(
4595 \\const E = enum {
4596 \\ Ok,
4597 \\ SomethingElse = 0
4598 \\};
4599 \\
4600 \\const E2 = enum(u8) {
4601 \\ Ok,
4602 \\ SomethingElse = 255,
4603 \\ SomethingThird
4604 \\};
4605 \\
4606 \\const Ee = extern enum {
4607 \\ Ok,
4608 \\ SomethingElse,
4609 \\ SomethingThird
4610 \\};
4611 \\
4612 \\const Ep = packed enum {
4613 \\ Ok,
4614 \\ SomethingElse,
4615 \\ SomethingThird
4616 \\};
4617 \\
4618 );
4619}
4620
4621test "zig fmt: union declaration" {
4622 try testCanonical(
4623 \\const U = union {
4624 \\ Int: u8,
4625 \\ Float: f32,
4626 \\ None,
4627 \\ Bool: bool
4628 \\};
4629 \\
4630 \\const Ue = union(enum) {
4631 \\ Int: u8,
4632 \\ Float: f32,
4633 \\ None,
4634 \\ Bool: bool
4635 \\};
4636 \\
4637 \\const E = enum {
4638 \\ Int,
4639 \\ Float,
4640 \\ None,
4641 \\ Bool
4642 \\};
4643 \\
4644 \\const Ue2 = union(E) {
4645 \\ Int: u8,
4646 \\ Float: f32,
4647 \\ None,
4648 \\ Bool: bool
4649 \\};
4650 \\
4651 \\const Eu = extern union {
4652 \\ Int: u8,
4653 \\ Float: f32,
4654 \\ None,
4655 \\ Bool: bool
4656 \\};
4657 \\
4658 );
4659}
4660
4661test "zig fmt: error set declaration" {
4662 try testCanonical(
4663 \\const E = error {
4664 \\ A,
4665 \\ B,
4666 \\
4667 \\ C
4668 \\};
4669 \\
4670 );
4671}
4672
4673test "zig fmt: arrays" {
4674 try testCanonical(
4675 \\test "test array" {
4676 \\ const a: [2]u8 = [2]u8{ 1, 2 };
4677 \\ const a: [2]u8 = []u8{ 1, 2 };
4678 \\ const a: [0]u8 = []u8{ };
4679 \\}
4680 \\
4681 );
4682}
4683
4684test "zig fmt: container initializers" {
4685 try testCanonical(
4686 \\const a1 = []u8{ };
4687 \\const a2 = []u8{ 1, 2, 3, 4 };
4688 \\const s1 = S{ };
4689 \\const s2 = S{ .a = 1, .b = 2 };
4690 \\
4691 );
4692}
4693
4694test "zig fmt: catch" {
4695 try testCanonical(
4696 \\test "catch" {
4697 \\ const a: error!u8 = 0;
4698 \\ _ = a catch return;
4699 \\ _ = a catch |err| return;
4700 \\}
4701 \\
4702 );
4703}
4704
4705test "zig fmt: blocks" {
4706 try testCanonical(
4707 \\test "blocks" {
4708 \\ {
4709 \\ const a = 0;
4710 \\ const b = 0;
4711 \\ }
4712 \\
4713 \\ blk: {
4714 \\ const a = 0;
4715 \\ const b = 0;
4716 \\ }
4717 \\
4718 \\ const r = blk: {
4719 \\ const a = 0;
4720 \\ const b = 0;
4721 \\ };
4722 \\}
4723 \\
4724 );
4725}
4726
4727test "zig fmt: switch" {
4728 try testCanonical(
4729 \\test "switch" {
4730 \\ switch (0) {
4731 \\ 0 => {},
4732 \\ 1 => unreachable,
4733 \\ 2, 3 => {},
4734 \\ 4 ... 7 => {},
4735 \\ 1 + 4 * 3 + 22 => {},
4736 \\ else => {
4737 \\ const a = 1;
4738 \\ const b = a;
4739 \\ }
4740 \\ }
4741 \\
4742 \\ const res = switch (0) {
4743 \\ 0 => 0,
4744 \\ 1 => 2,
4745 \\ else => 4
4746 \\ };
4747 \\
4748 \\ const Union = union(enum) {
4749 \\ Int: i64,
4750 \\ Float: f64
4751 \\ };
4752 \\
4753 \\ const u = Union{ .Int = 0 };
4754 \\ switch (u) {
4755 \\ Union.Int => |int| {},
4756 \\ Union.Float => |*float| unreachable
4757 \\ }
4758 \\}
4759 \\
4760 );
4761}
4762
4763test "zig fmt: while" {
4764 try testCanonical(
4765 \\test "while" {
4766 \\ while (10 < 1) {
4767 \\ unreachable;
4768 \\ }
4769 \\
4770 \\ while (10 < 1)
4771 \\ unreachable;
4772 \\
4773 \\ var i: usize = 0;
4774 \\ while (i < 10) : (i += 1) {
4775 \\ continue;
4776 \\ }
4777 \\
4778 \\ i = 0;
4779 \\ while (i < 10) : (i += 1)
4780 \\ continue;
4781 \\
4782 \\ i = 0;
4783 \\ var j: usize = 0;
4784 \\ while (i < 10) : ({
4785 \\ i += 1;
4786 \\ j += 1;
4787 \\ }) {
4788 \\ continue;
4789 \\ }
4790 \\
4791 \\ var a: ?u8 = 2;
4792 \\ while (a) |v| : (a = null) {
4793 \\ continue;
4794 \\ }
4795 \\
4796 \\ while (a) |v| : (a = null)
4797 \\ unreachable;
4798 \\
4799 \\ label: while (10 < 0) {
4800 \\ unreachable;
4801 \\ }
4802 \\
4803 \\ const res = while (0 < 10) {
4804 \\ break 7;
4805 \\ } else {
4806 \\ unreachable;
4807 \\ };
4808 \\
4809 \\ const res = while (0 < 10)
4810 \\ break 7
4811 \\ else
4812 \\ unreachable;
4813 \\
4814 \\ var a: error!u8 = 0;
4815 \\ while (a) |v| {
4816 \\ a = error.Err;
4817 \\ } else |err| {
4818 \\ i = 1;
4819 \\ }
4820 \\
4821 \\ comptime var k: usize = 0;
4822 \\ inline while (i < 10) : (i += 1)
4823 \\ j += 2;
4824 \\}
4825 \\
4826 );
4827}
4828
4829test "zig fmt: for" {
4830 try testCanonical(
4831 \\test "for" {
4832 \\ const a = []u8{ 1, 2, 3 };
4833 \\ for (a) |v| {
4834 \\ continue;
4835 \\ }
4836 \\
4837 \\ for (a) |v|
4838 \\ continue;
4839 \\
4840 \\ for (a) |*v|
4841 \\ continue;
4842 \\
4843 \\ for (a) |v, i| {
4844 \\ continue;
4845 \\ }
4846 \\
4847 \\ for (a) |v, i|
4848 \\ continue;
4849 \\
4850 \\ const res = for (a) |v, i| {
4851 \\ break v;
4852 \\ } else {
4853 \\ unreachable;
4854 \\ };
4855 \\
4856 \\ var num: usize = 0;
4857 \\ inline for (a) |v, i| {
4858 \\ num += v;
4859 \\ num += i;
4860 \\ }
4861 \\}
4862 \\
4863 );
4864}
4865
4866test "zig fmt: if" {
4867 try testCanonical(
4868 \\test "if" {
4869 \\ if (10 < 0) {
4870 \\ unreachable;
4871 \\ }
4872 \\
4873 \\ if (10 < 0) unreachable;
4874 \\
4875 \\ if (10 < 0) {
4876 \\ unreachable;
4877 \\ } else {
4878 \\ const a = 20;
4879 \\ }
4880 \\
4881 \\ if (10 < 0) {
4882 \\ unreachable;
4883 \\ } else if (5 < 0) {
4884 \\ unreachable;
4885 \\ } else {
4886 \\ const a = 20;
4887 \\ }
4888 \\
4889 \\ const is_world_broken = if (10 < 0) true else false;
4890 \\
4891 \\ const a: ?u8 = 10;
4892 \\ const b: ?u8 = null;
4893 \\ if (a) |v| {
4894 \\ const some = v;
4895 \\ } else if (b) |*v| {
4896 \\ unreachable;
4897 \\ } else {
4898 \\ const some = 10;
4899 \\ }
4900 \\
4901 \\ const non_null_a = if (a) |v| v else 0;
4902 \\
4903 \\ const a_err: error!u8 = 0;
4904 \\ if (a_err) |v| {
4905 \\ const p = v;
4906 \\ } else |err| {
4907 \\ unreachable;
4908 \\ }
4909 \\}
4910 \\
4911 );
4912}
4913
4914test "zig fmt: defer" {
4915 try testCanonical(
4916 \\test "defer" {
4917 \\ var i: usize = 0;
4918 \\ defer i = 1;
4919 \\ defer {
4920 \\ i += 2;
4921 \\ i *= i;
4922 \\ }
4923 \\
4924 \\ errdefer i += 3;
4925 \\ errdefer {
4926 \\ i += 2;
4927 \\ i /= i;
4928 \\ }
4929 \\}
4930 \\
4931 );
4932}
4933
4934test "zig fmt: comptime" {
4935 try testCanonical(
4936 \\fn a() u8 {
4937 \\ return 5;
4938 \\}
4939 \\
4940 \\fn b(comptime i: u8) u8 {
4941 \\ return i;
4942 \\}
4943 \\
4944 \\const av = comptime a();
4945 \\const av2 = comptime blk: {
4946 \\ var res = a();
4947 \\ res *= b(2);
4948 \\ break :blk res;
4949 \\};
4950 \\
4951 \\comptime {
4952 \\ _ = a();
4953 \\}
4954 \\
4955 \\test "comptime" {
4956 \\ const av3 = comptime a();
4957 \\ const av4 = comptime blk: {
4958 \\ var res = a();
4959 \\ res *= a();
4960 \\ break :blk res;
4961 \\ };
4962 \\
4963 \\ comptime var i = 0;
4964 \\ comptime {
4965 \\ i = a();
4966 \\ i += b(i);
4967 \\ }
4968 \\}
4969 \\
4970 );
4971}
4972
4973test "zig fmt: fn type" {
4974 try testCanonical(
4975 \\fn a(i: u8) u8 {
4976 \\ return i + 1;
4977 \\}
4978 \\
4979 \\const a: fn(u8) u8 = undefined;
4980 \\const b: extern fn(u8) u8 = undefined;
4981 \\const c: nakedcc fn(u8) u8 = undefined;
4982 \\const ap: fn(u8) u8 = a;
4983 \\
4984 );
4985}
4986
4987test "zig fmt: inline asm" {
4988 try testCanonical(
4989 \\pub fn syscall1(number: usize, arg1: usize) usize {
4990 \\ return asm volatile ("syscall"
4991 \\ : [ret] "={rax}" (-> usize)
4992 \\ : [number] "{rax}" (number),
4993 \\ [arg1] "{rdi}" (arg1)
4994 \\ : "rcx", "r11");
4995 \\}
4996 \\
4997 );
4998}
4999
5000test "zig fmt: coroutines" {
5001 try testCanonical(
5002 \\async fn simpleAsyncFn() void {
5003 \\ x += 1;
5004 \\ suspend;
5005 \\ x += 1;
5006 \\ suspend |p| {}
5007 \\ const p = async simpleAsyncFn() catch unreachable;
5008 \\ await p;
5009 \\}
5010 \\
5011 \\test "coroutine suspend, resume, cancel" {
5012 \\ const p = try async<std.debug.global_allocator> testAsyncSeq();
5013 \\ resume p;
5014 \\ cancel p;
5015 \\}
5016 \\
5017 );
5018}
5019
5020test "zig fmt: Block after if" {
5021 try testCanonical(
5022 \\test "Block after if" {
5023 \\ if (true) {
5024 \\ const a = 0;
5025 \\ }
5026 \\
5027 \\ {
5028 \\ const a = 0;
5029 \\ }
5030 \\}
5031 \\
5032 );
5033}
5034
5035test "zig fmt: use" {
5036 try testCanonical(
5037 \\use @import("std");
5038 \\pub use @import("std");
5039 \\
5040 );
5041}
5042
5043test "zig fmt: string identifier" {
5044 try testCanonical(
5045 \\const @"a b" = @"c d".@"e f";
5046 \\fn @"g h"() void {}
5047 \\
5048 );
5049}
std/zig/tokenizer.zig+146-33
...@@ -5,8 +5,6 @@ pub const Token = struct {...@@ -5,8 +5,6 @@ pub const Token = struct {
5 id: Id,5 id: Id,
6 start: usize,6 start: usize,
7 end: usize,7 end: usize,
8 line: usize,
9 column: usize,
108
11 const KeywordId = struct {9 const KeywordId = struct {
12 bytes: []const u8,10 bytes: []const u8,
...@@ -17,14 +15,18 @@ pub const Token = struct {...@@ -17,14 +15,18 @@ pub const Token = struct {
17 KeywordId{.bytes="align", .id = Id.Keyword_align},15 KeywordId{.bytes="align", .id = Id.Keyword_align},
18 KeywordId{.bytes="and", .id = Id.Keyword_and},16 KeywordId{.bytes="and", .id = Id.Keyword_and},
19 KeywordId{.bytes="asm", .id = Id.Keyword_asm},17 KeywordId{.bytes="asm", .id = Id.Keyword_asm},
18 KeywordId{.bytes="async", .id = Id.Keyword_async},
19 KeywordId{.bytes="await", .id = Id.Keyword_await},
20 KeywordId{.bytes="break", .id = Id.Keyword_break},20 KeywordId{.bytes="break", .id = Id.Keyword_break},
21 KeywordId{.bytes="catch", .id = Id.Keyword_catch},21 KeywordId{.bytes="catch", .id = Id.Keyword_catch},
22 KeywordId{.bytes="cancel", .id = Id.Keyword_cancel},
22 KeywordId{.bytes="comptime", .id = Id.Keyword_comptime},23 KeywordId{.bytes="comptime", .id = Id.Keyword_comptime},
23 KeywordId{.bytes="const", .id = Id.Keyword_const},24 KeywordId{.bytes="const", .id = Id.Keyword_const},
24 KeywordId{.bytes="continue", .id = Id.Keyword_continue},25 KeywordId{.bytes="continue", .id = Id.Keyword_continue},
25 KeywordId{.bytes="defer", .id = Id.Keyword_defer},26 KeywordId{.bytes="defer", .id = Id.Keyword_defer},
26 KeywordId{.bytes="else", .id = Id.Keyword_else},27 KeywordId{.bytes="else", .id = Id.Keyword_else},
27 KeywordId{.bytes="enum", .id = Id.Keyword_enum},28 KeywordId{.bytes="enum", .id = Id.Keyword_enum},
29 KeywordId{.bytes="errdefer", .id = Id.Keyword_errdefer},
28 KeywordId{.bytes="error", .id = Id.Keyword_error},30 KeywordId{.bytes="error", .id = Id.Keyword_error},
29 KeywordId{.bytes="export", .id = Id.Keyword_export},31 KeywordId{.bytes="export", .id = Id.Keyword_export},
30 KeywordId{.bytes="extern", .id = Id.Keyword_extern},32 KeywordId{.bytes="extern", .id = Id.Keyword_extern},
...@@ -39,10 +41,12 @@ pub const Token = struct {...@@ -39,10 +41,12 @@ pub const Token = struct {
39 KeywordId{.bytes="or", .id = Id.Keyword_or},41 KeywordId{.bytes="or", .id = Id.Keyword_or},
40 KeywordId{.bytes="packed", .id = Id.Keyword_packed},42 KeywordId{.bytes="packed", .id = Id.Keyword_packed},
41 KeywordId{.bytes="pub", .id = Id.Keyword_pub},43 KeywordId{.bytes="pub", .id = Id.Keyword_pub},
44 KeywordId{.bytes="resume", .id = Id.Keyword_resume},
42 KeywordId{.bytes="return", .id = Id.Keyword_return},45 KeywordId{.bytes="return", .id = Id.Keyword_return},
43 KeywordId{.bytes="section", .id = Id.Keyword_section},46 KeywordId{.bytes="section", .id = Id.Keyword_section},
44 KeywordId{.bytes="stdcallcc", .id = Id.Keyword_stdcallcc},47 KeywordId{.bytes="stdcallcc", .id = Id.Keyword_stdcallcc},
45 KeywordId{.bytes="struct", .id = Id.Keyword_struct},48 KeywordId{.bytes="struct", .id = Id.Keyword_struct},
49 KeywordId{.bytes="suspend", .id = Id.Keyword_suspend},
46 KeywordId{.bytes="switch", .id = Id.Keyword_switch},50 KeywordId{.bytes="switch", .id = Id.Keyword_switch},
47 KeywordId{.bytes="test", .id = Id.Keyword_test},51 KeywordId{.bytes="test", .id = Id.Keyword_test},
48 KeywordId{.bytes="this", .id = Id.Keyword_this},52 KeywordId{.bytes="this", .id = Id.Keyword_this},
...@@ -72,7 +76,8 @@ pub const Token = struct {...@@ -72,7 +76,8 @@ pub const Token = struct {
72 Invalid,76 Invalid,
73 Identifier,77 Identifier,
74 StringLiteral: StrLitKind,78 StringLiteral: StrLitKind,
75 StringIdentifier,79 MultilineStringLiteralLine: StrLitKind,
80 CharLiteral,
76 Eof,81 Eof,
77 Builtin,82 Builtin,
78 Bang,83 Bang,
...@@ -81,6 +86,7 @@ pub const Token = struct {...@@ -81,6 +86,7 @@ pub const Token = struct {
81 PipeEqual,86 PipeEqual,
82 Equal,87 Equal,
83 EqualEqual,88 EqualEqual,
89 EqualAngleBracketRight,
84 BangEqual,90 BangEqual,
85 LParen,91 LParen,
86 RParen,92 RParen,
...@@ -89,6 +95,8 @@ pub const Token = struct {...@@ -89,6 +95,8 @@ pub const Token = struct {
89 PercentEqual,95 PercentEqual,
90 LBrace,96 LBrace,
91 RBrace,97 RBrace,
98 LBracket,
99 RBracket,
92 Period,100 Period,
93 Ellipsis2,101 Ellipsis2,
94 Ellipsis3,102 Ellipsis3,
...@@ -132,7 +140,10 @@ pub const Token = struct {...@@ -132,7 +140,10 @@ pub const Token = struct {
132 Keyword_align,140 Keyword_align,
133 Keyword_and,141 Keyword_and,
134 Keyword_asm,142 Keyword_asm,
143 Keyword_async,
144 Keyword_await,
135 Keyword_break,145 Keyword_break,
146 Keyword_cancel,
136 Keyword_catch,147 Keyword_catch,
137 Keyword_comptime,148 Keyword_comptime,
138 Keyword_const,149 Keyword_const,
...@@ -140,6 +151,7 @@ pub const Token = struct {...@@ -140,6 +151,7 @@ pub const Token = struct {
140 Keyword_defer,151 Keyword_defer,
141 Keyword_else,152 Keyword_else,
142 Keyword_enum,153 Keyword_enum,
154 Keyword_errdefer,
143 Keyword_error,155 Keyword_error,
144 Keyword_export,156 Keyword_export,
145 Keyword_extern,157 Keyword_extern,
...@@ -154,10 +166,12 @@ pub const Token = struct {...@@ -154,10 +166,12 @@ pub const Token = struct {
154 Keyword_or,166 Keyword_or,
155 Keyword_packed,167 Keyword_packed,
156 Keyword_pub,168 Keyword_pub,
169 Keyword_resume,
157 Keyword_return,170 Keyword_return,
158 Keyword_section,171 Keyword_section,
159 Keyword_stdcallcc,172 Keyword_stdcallcc,
160 Keyword_struct,173 Keyword_struct,
174 Keyword_suspend,
161 Keyword_switch,175 Keyword_switch,
162 Keyword_test,176 Keyword_test,
163 Keyword_this,177 Keyword_this,
...@@ -176,28 +190,34 @@ pub const Token = struct {...@@ -176,28 +190,34 @@ pub const Token = struct {
176pub const Tokenizer = struct {190pub const Tokenizer = struct {
177 buffer: []const u8,191 buffer: []const u8,
178 index: usize,192 index: usize,
179 line: usize,
180 column: usize,
181 pending_invalid_token: ?Token,193 pending_invalid_token: ?Token,
182194
183 pub const LineLocation = struct {195 pub const Location = struct {
196 line: usize,
197 column: usize,
184 line_start: usize,198 line_start: usize,
185 line_end: usize,199 line_end: usize,
186 };200 };
187201
188 pub fn getTokenLocation(self: &Tokenizer, token: &const Token) LineLocation {202 pub fn getTokenLocation(self: &Tokenizer, start_index: usize, token: &const Token) Location {
189 var loc = LineLocation {203 var loc = Location {
190 .line_start = 0,204 .line = 0,
205 .column = 0,
206 .line_start = start_index,
191 .line_end = self.buffer.len,207 .line_end = self.buffer.len,
192 };208 };
193 for (self.buffer) |c, i| {209 for (self.buffer[start_index..]) |c, i| {
194 if (i == token.start) {210 if (i + start_index == token.start) {
195 loc.line_end = i;211 loc.line_end = i + start_index;
196 while (loc.line_end < self.buffer.len and self.buffer[loc.line_end] != '\n') : (loc.line_end += 1) {}212 while (loc.line_end < self.buffer.len and self.buffer[loc.line_end] != '\n') : (loc.line_end += 1) {}
197 return loc;213 return loc;
198 }214 }
199 if (c == '\n') {215 if (c == '\n') {
216 loc.line += 1;
217 loc.column = 0;
200 loc.line_start = i + 1;218 loc.line_start = i + 1;
219 } else {
220 loc.column += 1;
201 }221 }
202 }222 }
203 return loc;223 return loc;
...@@ -212,8 +232,6 @@ pub const Tokenizer = struct {...@@ -212,8 +232,6 @@ pub const Tokenizer = struct {
212 return Tokenizer {232 return Tokenizer {
213 .buffer = buffer,233 .buffer = buffer,
214 .index = 0,234 .index = 0,
215 .line = 0,
216 .column = 0,
217 .pending_invalid_token = null,235 .pending_invalid_token = null,
218 };236 };
219 }237 }
...@@ -225,6 +243,12 @@ pub const Tokenizer = struct {...@@ -225,6 +243,12 @@ pub const Tokenizer = struct {
225 C,243 C,
226 StringLiteral,244 StringLiteral,
227 StringLiteralBackslash,245 StringLiteralBackslash,
246 MultilineStringLiteralLine,
247 MultilineStringLiteralLineBackslash,
248 CharLiteral,
249 CharLiteralBackslash,
250 CharLiteralEnd,
251 Backslash,
228 Equal,252 Equal,
229 Bang,253 Bang,
230 Pipe,254 Pipe,
...@@ -261,26 +285,22 @@ pub const Tokenizer = struct {...@@ -261,26 +285,22 @@ pub const Tokenizer = struct {
261 self.pending_invalid_token = null;285 self.pending_invalid_token = null;
262 return token;286 return token;
263 }287 }
288 const start_index = self.index;
264 var state = State.Start;289 var state = State.Start;
265 var result = Token {290 var result = Token {
266 .id = Token.Id.Eof,291 .id = Token.Id.Eof,
267 .start = self.index,292 .start = self.index,
268 .end = undefined,293 .end = undefined,
269 .line = self.line,
270 .column = self.column,
271 };294 };
272 while (self.index < self.buffer.len) {295 while (self.index < self.buffer.len) : (self.index += 1) {
273 const c = self.buffer[self.index];296 const c = self.buffer[self.index];
274 switch (state) {297 switch (state) {
275 State.Start => switch (c) {298 State.Start => switch (c) {
276 ' ' => {299 ' ' => {
277 result.start = self.index + 1;300 result.start = self.index + 1;
278 result.column += 1;
279 },301 },
280 '\n' => {302 '\n' => {
281 result.start = self.index + 1;303 result.start = self.index + 1;
282 result.line += 1;
283 result.column = 0;
284 },304 },
285 'c' => {305 'c' => {
286 state = State.C;306 state = State.C;
...@@ -290,6 +310,9 @@ pub const Tokenizer = struct {...@@ -290,6 +310,9 @@ pub const Tokenizer = struct {
290 state = State.StringLiteral;310 state = State.StringLiteral;
291 result.id = Token.Id { .StringLiteral = Token.StrLitKind.Normal };311 result.id = Token.Id { .StringLiteral = Token.StrLitKind.Normal };
292 },312 },
313 '\'' => {
314 state = State.CharLiteral;
315 },
293 'a'...'b', 'd'...'z', 'A'...'Z', '_' => {316 'a'...'b', 'd'...'z', 'A'...'Z', '_' => {
294 state = State.Identifier;317 state = State.Identifier;
295 result.id = Token.Id.Identifier;318 result.id = Token.Id.Identifier;
...@@ -316,6 +339,16 @@ pub const Tokenizer = struct {...@@ -316,6 +339,16 @@ pub const Tokenizer = struct {
316 self.index += 1;339 self.index += 1;
317 break;340 break;
318 },341 },
342 '[' => {
343 result.id = Token.Id.LBracket;
344 self.index += 1;
345 break;
346 },
347 ']' => {
348 result.id = Token.Id.RBracket;
349 self.index += 1;
350 break;
351 },
319 ';' => {352 ';' => {
320 result.id = Token.Id.Semicolon;353 result.id = Token.Id.Semicolon;
321 self.index += 1;354 self.index += 1;
...@@ -352,6 +385,10 @@ pub const Tokenizer = struct {...@@ -352,6 +385,10 @@ pub const Tokenizer = struct {
352 '^' => {385 '^' => {
353 state = State.Caret;386 state = State.Caret;
354 },387 },
388 '\\' => {
389 state = State.Backslash;
390 result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.Normal };
391 },
355 '{' => {392 '{' => {
356 result.id = Token.Id.LBrace;393 result.id = Token.Id.LBrace;
357 self.index += 1;394 self.index += 1;
...@@ -396,7 +433,7 @@ pub const Tokenizer = struct {...@@ -396,7 +433,7 @@ pub const Tokenizer = struct {
396433
397 State.SawAtSign => switch (c) {434 State.SawAtSign => switch (c) {
398 '"' => {435 '"' => {
399 result.id = Token.Id.StringIdentifier;436 result.id = Token.Id.Identifier;
400 state = State.StringLiteral;437 state = State.StringLiteral;
401 },438 },
402 else => {439 else => {
...@@ -532,8 +569,17 @@ pub const Tokenizer = struct {...@@ -532,8 +569,17 @@ pub const Tokenizer = struct {
532 'a'...'z', 'A'...'Z', '_', '0'...'9' => {},569 'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
533 else => break,570 else => break,
534 },571 },
572 State.Backslash => switch (c) {
573 '\\' => {
574 state = State.MultilineStringLiteralLine;
575 },
576 else => break,
577 },
535 State.C => switch (c) {578 State.C => switch (c) {
536 '\\' => @panic("TODO"),579 '\\' => {
580 state = State.Backslash;
581 result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.C };
582 },
537 '"' => {583 '"' => {
538 state = State.StringLiteral;584 state = State.StringLiteral;
539 result.id = Token.Id { .StringLiteral = Token.StrLitKind.C };585 result.id = Token.Id { .StringLiteral = Token.StrLitKind.C };
...@@ -562,6 +608,64 @@ pub const Tokenizer = struct {...@@ -562,6 +608,64 @@ pub const Tokenizer = struct {
562 },608 },
563 },609 },
564610
611 State.CharLiteral => switch (c) {
612 '\\' => {
613 state = State.CharLiteralBackslash;
614 },
615 '\'' => {
616 result.id = Token.Id.Invalid;
617 break;
618 },
619 else => {
620 if (c < 0x20 or c == 0x7f) {
621 result.id = Token.Id.Invalid;
622 break;
623 }
624
625 state = State.CharLiteralEnd;
626 }
627 },
628
629 State.CharLiteralBackslash => switch (c) {
630 '\n' => {
631 result.id = Token.Id.Invalid;
632 break;
633 },
634 else => {
635 state = State.CharLiteralEnd;
636 },
637 },
638
639 State.CharLiteralEnd => switch (c) {
640 '\'' => {
641 result.id = Token.Id.CharLiteral;
642 self.index += 1;
643 break;
644 },
645 else => {
646 result.id = Token.Id.Invalid;
647 break;
648 },
649 },
650
651 State.MultilineStringLiteralLine => switch (c) {
652 '\\' => {
653 state = State.MultilineStringLiteralLineBackslash;
654 },
655 '\n' => {
656 self.index += 1;
657 break;
658 },
659 else => self.checkLiteralCharacter(),
660 },
661
662 State.MultilineStringLiteralLineBackslash => switch (c) {
663 '\n' => break, // Look for this error later.
664 else => {
665 state = State.MultilineStringLiteralLine;
666 },
667 },
668
565 State.Bang => switch (c) {669 State.Bang => switch (c) {
566 '=' => {670 '=' => {
567 result.id = Token.Id.BangEqual;671 result.id = Token.Id.BangEqual;
...@@ -597,6 +701,11 @@ pub const Tokenizer = struct {...@@ -597,6 +701,11 @@ pub const Tokenizer = struct {
597 self.index += 1;701 self.index += 1;
598 break;702 break;
599 },703 },
704 '>' => {
705 result.id = Token.Id.EqualAngleBracketRight;
706 self.index += 1;
707 break;
708 },
600 else => {709 else => {
601 result.id = Token.Id.Equal;710 result.id = Token.Id.Equal;
602 break;711 break;
...@@ -794,14 +903,6 @@ pub const Tokenizer = struct {...@@ -794,14 +903,6 @@ pub const Tokenizer = struct {
794 else => break,903 else => break,
795 },904 },
796 }905 }
797
798 self.index += 1;
799 if (c == '\n') {
800 self.line += 1;
801 self.column = 0;
802 } else {
803 self.column += 1;
804 }
805 } else if (self.index == self.buffer.len) {906 } else if (self.index == self.buffer.len) {
806 switch (state) {907 switch (state) {
807 State.Start,908 State.Start,
...@@ -811,6 +912,7 @@ pub const Tokenizer = struct {...@@ -811,6 +912,7 @@ pub const Tokenizer = struct {
811 State.FloatFraction,912 State.FloatFraction,
812 State.FloatExponentNumber,913 State.FloatExponentNumber,
813 State.StringLiteral, // find this error later914 State.StringLiteral, // find this error later
915 State.MultilineStringLiteralLine,
814 State.Builtin => {},916 State.Builtin => {},
815917
816 State.Identifier => {918 State.Identifier => {
...@@ -825,6 +927,11 @@ pub const Tokenizer = struct {...@@ -825,6 +927,11 @@ pub const Tokenizer = struct {
825 State.NumberDot,927 State.NumberDot,
826 State.FloatExponentUnsigned,928 State.FloatExponentUnsigned,
827 State.SawAtSign,929 State.SawAtSign,
930 State.Backslash,
931 State.MultilineStringLiteralLineBackslash,
932 State.CharLiteral,
933 State.CharLiteralBackslash,
934 State.CharLiteralEnd,
828 State.StringLiteralBackslash => {935 State.StringLiteralBackslash => {
829 result.id = Token.Id.Invalid;936 result.id = Token.Id.Invalid;
830 },937 },
...@@ -894,6 +1001,7 @@ pub const Tokenizer = struct {...@@ -894,6 +1001,7 @@ pub const Tokenizer = struct {
894 },1001 },
895 }1002 }
896 }1003 }
1004
897 if (result.id == Token.Id.Eof) {1005 if (result.id == Token.Id.Eof) {
898 if (self.pending_invalid_token) |token| {1006 if (self.pending_invalid_token) |token| {
899 self.pending_invalid_token = null;1007 self.pending_invalid_token = null;
...@@ -917,8 +1025,6 @@ pub const Tokenizer = struct {...@@ -917,8 +1025,6 @@ pub const Tokenizer = struct {
917 .id = Token.Id.Invalid,1025 .id = Token.Id.Invalid,
918 .start = self.index,1026 .start = self.index,
919 .end = self.index + invalid_length,1027 .end = self.index + invalid_length,
920 .line = self.line,
921 .column = self.column,
922 };1028 };
923 }1029 }
9241030
...@@ -968,9 +1074,16 @@ test "tokenizer" {...@@ -968,9 +1074,16 @@ test "tokenizer" {
968 });1074 });
969}1075}
9701076
1077test "tokenizer - chars" {
1078 testTokenize("'c'", []Token.Id {Token.Id.CharLiteral});
1079}
1080
971test "tokenizer - invalid token characters" {1081test "tokenizer - invalid token characters" {
972 testTokenize("#", []Token.Id{Token.Id.Invalid});1082 testTokenize("#", []Token.Id{Token.Id.Invalid});
973 testTokenize("`", []Token.Id{Token.Id.Invalid});1083 testTokenize("`", []Token.Id{Token.Id.Invalid});
1084 testTokenize("'c", []Token.Id {Token.Id.Invalid});
1085 testTokenize("'", []Token.Id {Token.Id.Invalid});
1086 testTokenize("''", []Token.Id {Token.Id.Invalid, Token.Id.Invalid});
974}1087}
9751088
976test "tokenizer - invalid literal/comment characters" {1089test "tokenizer - invalid literal/comment characters" {
...@@ -1022,7 +1135,7 @@ test "tokenizer - string identifier and builtin fns" {...@@ -1022,7 +1135,7 @@ test "tokenizer - string identifier and builtin fns" {
1022 ,1135 ,
1023 []Token.Id{1136 []Token.Id{
1024 Token.Id.Keyword_const,1137 Token.Id.Keyword_const,
1025 Token.Id.StringIdentifier,1138 Token.Id.Identifier,
1026 Token.Id.Equal,1139 Token.Id.Equal,
1027 Token.Id.Builtin,1140 Token.Id.Builtin,
1028 Token.Id.LParen,1141 Token.Id.LParen,