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
signaturebadge-question-mark 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
1414 }
1515}
1616
17// Note that memset does not return `dest`, like the libc API.
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 {
17export fn memset(dest: ?&u8, c: u8, n: usize) ?&u8 {
2118 @setRuntimeSafety(false);
2219
2320 var index: usize = 0;
2421 while (index != n) : (index += 1)
2522 (??dest)[index] = c;
23
24 return dest;
2625}
2726
28// Note that memcpy does not return `dest`, like the libc API.
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 {
27export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) ?&u8 {
3228 @setRuntimeSafety(false);
3329
3430 var index: usize = 0;
3531 while (index != n) : (index += 1)
3632 (??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;
3754}
3855
3956comptime {
std/zig/ast.zig+1278-77
......@@ -11,18 +11,52 @@ pub const Node = struct {
1111 pub const Id = enum {
1212 Root,
1313 VarDecl,
14 Use,
15 ErrorSetDecl,
16 ContainerDecl,
17 StructField,
18 UnionTag,
19 EnumTag,
1420 Identifier,
21 AsyncAttribute,
1522 FnProto,
1623 ParamDecl,
1724 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,
1837 InfixOp,
1938 PrefixOp,
39 SuffixOp,
40 GroupedExpression,
41 ControlFlowExpression,
42 Suspend,
43 FieldInitializer,
2044 IntegerLiteral,
2145 FloatLiteral,
2246 StringLiteral,
47 MultilineStringLiteral,
48 CharLiteral,
49 BoolLiteral,
50 NullLiteral,
2351 UndefinedLiteral,
52 ThisLiteral,
53 Asm,
54 AsmInput,
55 AsmOutput,
56 Unreachable,
57 ErrorType,
58 VarType,
2459 BuiltinCall,
25 Call,
2660 LineComment,
2761 TestDecl,
2862 };
......@@ -31,18 +65,52 @@ pub const Node = struct {
3165 return switch (base.id) {
3266 Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index),
3367 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),
3474 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index),
75 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).iterate(index),
3576 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
3677 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
3778 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),
3891 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
3992 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),
4098 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
4199 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
42100 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),
43105 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),
44113 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).iterate(index),
45 Id.Call => @fieldParentPtr(NodeCall, "base", base).iterate(index),
46114 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).iterate(index),
47115 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).iterate(index),
48116 };
......@@ -52,18 +120,52 @@ pub const Node = struct {
52120 return switch (base.id) {
53121 Id.Root => @fieldParentPtr(NodeRoot, "base", base).firstToken(),
54122 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(),
55129 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).firstToken(),
130 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).firstToken(),
56131 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(),
57132 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(),
58133 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(),
59146 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).firstToken(),
60147 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(),
61153 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(),
62154 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(),
63155 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(),
64160 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(),
65168 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).firstToken(),
66 Id.Call => @fieldParentPtr(NodeCall, "base", base).firstToken(),
67169 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).firstToken(),
68170 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).firstToken(),
69171 };
......@@ -73,18 +175,52 @@ pub const Node = struct {
73175 return switch (base.id) {
74176 Id.Root => @fieldParentPtr(NodeRoot, "base", base).lastToken(),
75177 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(),
76184 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).lastToken(),
185 Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).lastToken(),
77186 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(),
78187 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(),
79188 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(),
80201 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).lastToken(),
81202 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(),
82208 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(),
83209 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(),
84210 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(),
85215 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(),
86223 Id.BuiltinCall => @fieldParentPtr(NodeBuiltinCall, "base", base).lastToken(),
87 Id.Call => @fieldParentPtr(NodeCall, "base", base).lastToken(),
88224 Id.LineComment => @fieldParentPtr(NodeLineComment, "base", base).lastToken(),
89225 Id.TestDecl => @fieldParentPtr(NodeTestDecl, "base", base).lastToken(),
90226 };
......@@ -160,6 +296,190 @@ pub const NodeVarDecl = struct {
160296 }
161297};
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
163483pub const NodeIdentifier = struct {
164484 base: Node,
165485 name_token: Token,
......@@ -177,6 +497,36 @@ pub const NodeIdentifier = struct {
177497 }
178498};
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
180530pub const NodeFnProto = struct {
181531 base: Node,
182532 visib_token: ?Token,
......@@ -188,13 +538,13 @@ pub const NodeFnProto = struct {
188538 extern_token: ?Token,
189539 inline_token: ?Token,
190540 cc_token: ?Token,
541 async_attr: ?&NodeAsyncAttribute,
191542 body_node: ?&Node,
192543 lib_name: ?&Node, // populated if this is an extern declaration
193544 align_expr: ?&Node, // populated if align(A) is present
194545
195546 pub const ReturnType = union(enum) {
196547 Explicit: &Node,
197 Infer: Token,
198548 InferErrorSet: &Node,
199549 };
200550
......@@ -216,7 +566,6 @@ pub const NodeFnProto = struct {
216566 if (i < 1) return node;
217567 i -= 1;
218568 },
219 ReturnType.Infer => {},
220569 }
221570
222571 if (self.align_expr) |align_expr| {
......@@ -250,7 +599,6 @@ pub const NodeFnProto = struct {
250599 // TODO allow this and next prong to share bodies since the types are the same
251600 ReturnType.Explicit => |node| return node.lastToken(),
252601 ReturnType.InferErrorSet => |node| return node.lastToken(),
253 ReturnType.Infer => |token| return token,
254602 }
255603 }
256604};
......@@ -287,9 +635,10 @@ pub const NodeParamDecl = struct {
287635
288636pub const NodeBlock = struct {
289637 base: Node,
290 begin_token: Token,
291 end_token: Token,
638 label: ?Token,
639 lbrace: Token,
292640 statements: ArrayList(&Node),
641 rbrace: Token,
293642
294643 pub fn iterate(self: &NodeBlock, index: usize) ?&Node {
295644 var i = index;
......@@ -301,11 +650,408 @@ pub const NodeBlock = struct {
301650 }
302651
303652 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;
305658 }
306659
307660 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();
3091055 }
3101056};
3111057
......@@ -316,7 +1062,7 @@ pub const NodeInfixOp = struct {
3161062 op: InfixOp,
3171063 rhs: &Node,
3181064
319 const InfixOp = enum {
1065 const InfixOp = union(enum) {
3201066 Add,
3211067 AddWrap,
3221068 ArrayCat,
......@@ -343,6 +1089,7 @@ pub const NodeInfixOp = struct {
3431089 BitXor,
3441090 BoolAnd,
3451091 BoolOr,
1092 Catch: ?&NodePayload,
3461093 Div,
3471094 EqualEqual,
3481095 ErrorUnion,
......@@ -355,6 +1102,7 @@ pub const NodeInfixOp = struct {
3551102 Mult,
3561103 MultWrap,
3571104 Period,
1105 Range,
3581106 Sub,
3591107 SubWrap,
3601108 UnwrapMaybe,
......@@ -367,6 +1115,13 @@ pub const NodeInfixOp = struct {
3671115 i -= 1;
3681116
3691117 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
3701125 InfixOp.Add,
3711126 InfixOp.AddWrap,
3721127 InfixOp.ArrayCat,
......@@ -405,83 +1160,310 @@ pub const NodeInfixOp = struct {
4051160 InfixOp.Mult,
4061161 InfixOp.MultWrap,
4071162 InfixOp.Period,
1163 InfixOp.Range,
4081164 InfixOp.Sub,
4091165 InfixOp.SubWrap,
4101166 InfixOp.UnwrapMaybe => {},
4111167 }
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;
4141367 i -= 1;
4151368
4161369 return null;
4171370 }
4181371
419 pub fn firstToken(self: &NodeInfixOp) Token {
420 return self.lhs.firstToken();
1372 pub fn firstToken(self: &NodeGroupedExpression) Token {
1373 return self.lparen;
4211374 }
4221375
423 pub fn lastToken(self: &NodeInfixOp) Token {
424 return self.rhs.lastToken();
1376 pub fn lastToken(self: &NodeGroupedExpression) Token {
1377 return self.rparen;
4251378 }
4261379};
4271380
428pub const NodePrefixOp = struct {
1381pub const NodeControlFlowExpression = struct {
4291382 base: Node,
430 op_token: Token,
431 op: PrefixOp,
432 rhs: &Node,
1383 ltoken: Token,
1384 kind: Kind,
1385 rhs: ?&Node,
4331386
434 const PrefixOp = union(enum) {
435 AddrOf: AddrOfInfo,
436 BitNot,
437 BoolNot,
438 Deref,
439 Negation,
440 NegationWrap,
1387 const Kind = union(enum) {
1388 Break: ?Token,
1389 Continue: ?Token,
4411390 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,
4511391 };
4521392
453 pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node {
1393 pub fn iterate(self: &NodeControlFlowExpression, index: usize) ?&Node {
4541394 var i = index;
4551395
456 switch (self.op) {
457 PrefixOp.AddrOf => |addr_of_info| {
458 if (addr_of_info.align_expr) |align_expr| {
459 if (i < 1) return align_expr;
460 i -= 1;
1396 if (self.rhs) |rhs| {
1397 if (i < 1) return rhs;
1398 i -= 1;
1399 }
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;
4611417 }
4621418 },
463 PrefixOp.BitNot,
464 PrefixOp.BoolNot,
465 PrefixOp.Deref,
466 PrefixOp.Negation,
467 PrefixOp.NegationWrap,
468 PrefixOp.Return,
469 PrefixOp.Try,
470 PrefixOp.UnwrapMaybe => {},
1419 Kind.Continue => |maybe_blk_token| {
1420 if (maybe_blk_token) |blk_token| {
1421 return blk_token;
1422 }
1423 },
1424 Kind.Return => return self.ltoken,
4711425 }
4721426
473 if (i < 1) return self.rhs;
474 i -= 1;
1427 return self.ltoken;
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
4761450 return null;
4771451 }
4781452
479 pub fn firstToken(self: &NodePrefixOp) Token {
480 return self.op_token;
1453 pub fn firstToken(self: &NodeSuspend) Token {
1454 return self.suspend_token;
4811455 }
4821456
483 pub fn lastToken(self: &NodePrefixOp) Token {
484 return self.rhs.lastToken();
1457 pub fn lastToken(self: &NodeSuspend) Token {
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;
4851467 }
4861468};
4871469
......@@ -543,46 +1525,87 @@ pub const NodeBuiltinCall = struct {
5431525 }
5441526};
5451527
546pub const NodeCall = struct {
1528pub const NodeStringLiteral = struct {
5471529 base: Node,
548 callee: &Node,
549 params: ArrayList(&Node),
550 rparen_token: Token,
1530 token: Token,
5511531
552 pub fn iterate(self: &NodeCall, index: usize) ?&Node {
553 var i = index;
1532 pub fn iterate(self: &NodeStringLiteral, index: usize) ?&Node {
1533 return null;
1534 }
5541535
555 if (i < 1) return self.callee;
556 i -= 1;
1536 pub fn firstToken(self: &NodeStringLiteral) Token {
1537 return self.token;
1538 }
5571539
558 if (i < self.params.len) return self.params.at(i);
559 i -= self.params.len;
1540 pub fn lastToken(self: &NodeStringLiteral) Token {
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 {
5611550 return null;
5621551 }
5631552
564 pub fn firstToken(self: &NodeCall) Token {
565 return self.callee.firstToken();
1553 pub fn firstToken(self: &NodeMultilineStringLiteral) Token {
1554 return self.tokens.at(0);
5661555 }
5671556
568 pub fn lastToken(self: &NodeCall) Token {
569 return self.rparen_token;
1557 pub fn lastToken(self: &NodeMultilineStringLiteral) Token {
1558 return self.tokens.at(self.tokens.len - 1);
5701559 }
5711560};
5721561
573pub const NodeStringLiteral = struct {
1562pub const NodeCharLiteral = struct {
5741563 base: Node,
5751564 token: Token,
5761565
577 pub fn iterate(self: &NodeStringLiteral, index: usize) ?&Node {
1566 pub fn iterate(self: &NodeCharLiteral, index: usize) ?&Node {
5781567 return null;
5791568 }
5801569
581 pub fn firstToken(self: &NodeStringLiteral) Token {
1570 pub fn firstToken(self: &NodeCharLiteral) Token {
5821571 return self.token;
5831572 }
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 {
5861609 return self.token;
5871610 }
5881611};
......@@ -604,6 +1627,185 @@ pub const NodeUndefinedLiteral = struct {
6041627 }
6051628};
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
6071809pub const NodeLineComment = struct {
6081810 base: Node,
6091811 lines: ArrayList(Token),
......@@ -624,7 +1826,7 @@ pub const NodeLineComment = struct {
6241826pub const NodeTestDecl = struct {
6251827 base: Node,
6261828 test_token: Token,
627 name_token: Token,
1829 name: &Node,
6281830 body_node: &Node,
6291831
6301832 pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node {
......@@ -644,4 +1846,3 @@ pub const NodeTestDecl = struct {
6441846 return self.body_node.lastToken();
6451847 }
6461848};
647
std/zig/parser.zig+3842-526
......@@ -53,20 +53,33 @@ pub const Parser = struct {
5353 }
5454
5555 const TopLevelDeclCtx = struct {
56 decls: &ArrayList(&ast.Node),
5657 visib_token: ?Token,
5758 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,
5866 };
5967
6068 const DestPtr = union(enum) {
6169 Field: &&ast.Node,
6270 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 {
6673 switch (*self) {
6774 DestPtr.Field => |ptr| *ptr = value,
6875 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,
7083 }
7184 }
7285 };
......@@ -76,22 +89,69 @@ pub const Parser = struct {
7689 ptr: &Token,
7790 };
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
79142 const State = union(enum) {
80143 TopLevel,
81 TopLevelExtern: ?Token,
144 TopLevelExtern: TopLevelDeclCtx,
82145 TopLevelDecl: TopLevelDeclCtx,
83 Expression: DestPtr,
84 ExpectOperand,
85 Operand: &ast.Node,
86 AfterOperand,
87 InfixOp: &ast.NodeInfixOp,
88 PrefixOp: &ast.NodePrefixOp,
89 SuffixOp: &ast.Node,
146 ContainerExtern: ContainerExternCtx,
147 ContainerDecl: &ast.NodeContainerDecl,
148 SliceOrArrayAccess: &ast.NodeSuffixOp,
90149 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
91 TypeExpr: DestPtr,
92150 VarDecl: &ast.NodeVarDecl,
93151 VarDeclAlign: &ast.NodeVarDecl,
94152 VarDeclEq: &ast.NodeVarDecl,
153 IfToken: @TagType(Token.Id),
154 IfTokenSave: ExpectTokenSave,
95155 ExpectToken: @TagType(Token.Id),
96156 ExpectTokenSave: ExpectTokenSave,
97157 FnProto: &ast.NodeFnProto,
......@@ -100,10 +160,73 @@ pub const Parser = struct {
100160 ParamDecl: &ast.NodeFnProto,
101161 ParamDeclComma,
102162 FnDef: &ast.NodeFnProto,
163 LabeledExpression: LabelCtx,
164 Inline: InlineCtx,
165 While: LoopCtx,
166 For: LoopCtx,
103167 Block: &ast.NodeBlock,
168 Else: &?&ast.NodeElse,
169 WhileContinueExpr: &?&ast.Node,
104170 Statement: &ast.NodeBlock,
105 ExprListItemOrEnd: &ArrayList(&ast.Node),
106 ExprListCommaOrEnd: &ArrayList(&ast.Node),
171 Semicolon: &const &const 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,
107230 };
108231
109232 /// Returns an AST tree, allocated with the parser's allocator.
......@@ -168,104 +291,199 @@ pub const Parser = struct {
168291 State.TopLevel => {
169292 const token = self.getNextToken();
170293 switch (token.id) {
171 Token.Id.Keyword_pub, Token.Id.Keyword_export => {
172 stack.append(State { .TopLevelExtern = token }) catch unreachable;
173 continue;
174 },
175294 Token.Id.Keyword_test => {
176295 stack.append(State.TopLevel) catch unreachable;
177296
178 const name_token = self.getNextToken();
179 if (name_token.id != Token.Id.StringLiteral)
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));
297 const name_token = (try self.eatToken(&stack, Token.Id.StringLiteral)) ?? continue;
298 const lbrace = (try self.eatToken(&stack, Token.Id.LBrace)) ?? continue;
185299
186 const block = try self.createBlock(arena, token);
187 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, name_token, block);
188 try stack.append(State { .Block = block });
300 const name = try self.createStringLiteral(arena, name_token);
301 const block = try self.createBlock(arena, (?Token)(null), token);
302 const test_decl = try self.createAttachTestDecl(arena, &root_node.decls, token, &name.base, block);
303 stack.append(State { .Block = block }) catch unreachable;
189304 continue;
190305 },
191306 Token.Id.Eof => {
192307 root_node.eof_token = token;
193308 return Tree {.root_node = root_node, .arena_allocator = arena_allocator};
194309 },
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 },
195334 else => {
196335 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 });
198345 continue;
199346 },
200347 }
201348 },
202 State.TopLevelExtern => |visib_token| {
349 State.TopLevelExtern => |ctx| {
203350 const token = self.getNextToken();
204 if (token.id == Token.Id.Keyword_extern) {
205 stack.append(State {
206 .TopLevelDecl = TopLevelDeclCtx {
207 .visib_token = visib_token,
208 .extern_token = token,
209 },
210 }) catch unreachable;
211 continue;
212 }
213 self.putBackToken(token);
214 stack.append(State {
215 .TopLevelDecl = TopLevelDeclCtx {
216 .visib_token = visib_token,
217 .extern_token = null,
351 switch (token.id) {
352 Token.Id.Keyword_use => {
353 const node = try arena.create(ast.NodeUse);
354 *node = ast.NodeUse {
355 .base = self.initNode(ast.Node.Id.Use),
356 .visib_token = ctx.visib_token,
357 .expr = undefined,
358 .semicolon_token = undefined,
359 };
360 try ctx.decls.append(&node.base);
361
362 stack.append(State {
363 .ExpectTokenSave = ExpectTokenSave {
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;
218370 },
219 }) catch unreachable;
220 continue;
371 Token.Id.Keyword_extern => {
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 }
221399 },
222400 State.TopLevelDecl => |ctx| {
223401 const token = self.getNextToken();
224402 switch (token.id) {
225403 Token.Id.Keyword_var, Token.Id.Keyword_const => {
226 stack.append(State.TopLevel) catch unreachable;
227404 // TODO shouldn't need these casts
228 const var_decl_node = try self.createAttachVarDecl(arena, &root_node.decls, ctx.visib_token,
229 token, (?Token)(null), ctx.extern_token);
230 try stack.append(State { .VarDecl = var_decl_node });
405 const var_decl_node = try self.createAttachVarDecl(arena, ctx.decls, ctx.visib_token,
406 token, (?Token)(null), ctx.extern_token, ctx.lib_name);
407 stack.append(State { .VarDecl = var_decl_node }) catch unreachable;
231408 continue;
232409 },
233410 Token.Id.Keyword_fn => {
234 stack.append(State.TopLevel) catch unreachable;
235411 // TODO shouldn't need these casts
236 const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, token,
237 ctx.extern_token, (?Token)(null), ctx.visib_token, (?Token)(null));
238 try stack.append(State { .FnDef = fn_proto });
412 const fn_proto = try self.createAttachFnProto(arena, ctx.decls, token,
413 ctx.extern_token, ctx.lib_name, (?Token)(null), ctx.visib_token, (?Token)(null));
414 stack.append(State { .FnDef = fn_proto }) catch unreachable;
239415 try stack.append(State { .FnProto = fn_proto });
240416 continue;
241417 },
242 Token.Id.StringLiteral => {
243 @panic("TODO extern with string literal");
244 },
245418 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);
248419 // TODO shouldn't need this cast
249 const fn_proto = try self.createAttachFnProto(arena, &root_node.decls, fn_token,
250 ctx.extern_token, (?Token)(token), (?Token)(null), (?Token)(null));
251 try stack.append(State { .FnDef = fn_proto });
420 const fn_proto = try self.createAttachFnProto(arena, ctx.decls, Token(undefined),
421 ctx.extern_token, ctx.lib_name, (?Token)(token), (?Token)(null), (?Token)(null));
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;
252447 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));
253473 continue;
254474 },
255 else => return self.parseError(token, "expected variable declaration or function, found {}", @tagName(token.id)),
256475 }
257476 },
258477 State.VarDecl => |var_decl| {
259 var_decl.name_token = try self.eatToken(Token.Id.Identifier);
260478 stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
261
262 const next_token = self.getNextToken();
263 if (next_token.id == Token.Id.Colon) {
264 try stack.append(State { .TypeExpr = DestPtr {.NullableField = &var_decl.type_node} });
265 continue;
266 }
267
268 self.putBackToken(next_token);
479 try stack.append(State { .TypeExprBegin = DestPtr {.NullableField = &var_decl.type_node} });
480 try stack.append(State { .IfToken = Token.Id.Colon });
481 try stack.append(State {
482 .ExpectTokenSave = ExpectTokenSave {
483 .id = Token.Id.Identifier,
484 .ptr = &var_decl.name_token,
485 }
486 });
269487 continue;
270488 },
271489 State.VarDeclAlign => |var_decl| {
......@@ -273,9 +491,9 @@ pub const Parser = struct {
273491
274492 const next_token = self.getNextToken();
275493 if (next_token.id == Token.Id.Keyword_align) {
276 _ = try self.eatToken(Token.Id.LParen);
277494 try stack.append(State { .ExpectToken = Token.Id.RParen });
278495 try stack.append(State { .Expression = DestPtr{.NullableField = &var_decl.align_node} });
496 try stack.append(State { .ExpectToken = Token.Id.LParen });
279497 continue;
280498 }
281499
......@@ -301,243 +519,1617 @@ pub const Parser = struct {
301519 var_decl.semicolon_token = token;
302520 continue;
303521 }
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 }
305675 },
676
306677 State.ExpectToken => |token_id| {
307 _ = try self.eatToken(token_id);
678 _ = (try self.eatToken(&stack, token_id)) ?? continue;
308679 continue;
309680 },
310681
311682 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;
313684 continue;
314685 },
315686
316 State.Expression => |dest_ptr| {
317 // save the dest_ptr for later
318 stack.append(state) catch unreachable;
319 try stack.append(State.ExpectOperand);
687 State.IfToken => |token_id| {
688 const token = self.getNextToken();
689 if (@TagType(Token.Id)(token.id) != token_id) {
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;
320706 continue;
321707 },
322 State.ExpectOperand => {
323 // we'll either get an operand (like 1 or x),
324 // or a prefix operator (like ~ or return).
708
709 State.Optional => { },
710
711 State.Expression => |dest_ptr| {
325712 const token = self.getNextToken();
326713 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 },
333714 Token.Id.Keyword_try => {
334 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
335 ast.NodePrefixOp.PrefixOp.Try) });
336 try stack.append(State.ExpectOperand);
715 const node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Try);
716 dest_ptr.store(&node.base);
717
718 stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }) catch unreachable;
337719 continue;
338720 },
339 Token.Id.Minus => {
340 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
341 ast.NodePrefixOp.PrefixOp.Negation) });
342 try stack.append(State.ExpectOperand);
721 Token.Id.Keyword_return => {
722 const node = try self.createControlFlowExpr(arena, token, ast.NodeControlFlowExpression.Kind.Return);
723 dest_ptr.store(&node.base);
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 } });
343733 continue;
344734 },
345 Token.Id.MinusPercent => {
346 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
347 ast.NodePrefixOp.PrefixOp.NegationWrap) });
348 try stack.append(State.ExpectOperand);
735 Token.Id.Keyword_break => {
736 const label = blk: {
737 const colon = self.getNextToken();
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 } });
349761 continue;
350762 },
351 Token.Id.Tilde => {
352 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
353 ast.NodePrefixOp.PrefixOp.BitNot) });
354 try stack.append(State.ExpectOperand);
763 Token.Id.Keyword_continue => {
764 const label = blk: {
765 const colon = self.getNextToken();
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);
355780 continue;
356781 },
357 Token.Id.QuestionMarkQuestionMark => {
358 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
359 ast.NodePrefixOp.PrefixOp.UnwrapMaybe) });
360 try stack.append(State.ExpectOperand);
361 continue;
782 Token.Id.Keyword_cancel => {
783 const cancel_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Cancel);
784 dest_ptr.store(&cancel_node.base);
785 stack.append(State { .Expression = DestPtr { .Field = &cancel_node.rhs } }) catch unreachable;
362786 },
363 Token.Id.Bang => {
364 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
365 ast.NodePrefixOp.PrefixOp.BoolNot) });
366 try stack.append(State.ExpectOperand);
787 Token.Id.Keyword_resume => {
788 const resume_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Resume);
789 dest_ptr.store(&resume_node.base);
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 });
367803 continue;
368804 },
369 Token.Id.Asterisk => {
370 try stack.append(State { .PrefixOp = try self.createPrefixOp(arena, token,
371 ast.NodePrefixOp.PrefixOp.Deref) });
372 try stack.append(State.ExpectOperand);
805 Token.Id.Keyword_if => {
806 const node = try arena.create(ast.NodeIf);
807 *node = ast.NodeIf {
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 });
373823 continue;
374824 },
375 Token.Id.Ampersand => {
376 const prefix_op = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{
377 .AddrOf = ast.NodePrefixOp.AddrOfInfo {
378 .align_expr = null,
379 .bit_offset_start_token = null,
380 .bit_offset_end_token = null,
381 .const_token = null,
382 .volatile_token = null,
825 Token.Id.Keyword_while => {
826 stack.append(State {
827 .While = LoopCtx {
828 .label = null,
829 .inline_token = null,
830 .loop_token = token,
831 .dest_ptr = dest_ptr,
383832 }
384 });
385 try stack.append(State { .PrefixOp = prefix_op });
386 try stack.append(State.ExpectOperand);
387 try stack.append(State { .AddrOfModifiers = &prefix_op.op.AddrOf });
833 }) catch unreachable;
388834 continue;
389835 },
390 Token.Id.Identifier => {
391 try stack.append(State {
392 .Operand = &(try self.createIdentifier(arena, token)).base
393 });
394 try stack.append(State.AfterOperand);
836 Token.Id.Keyword_for => {
837 stack.append(State {
838 .For = LoopCtx {
839 .label = null,
840 .inline_token = null,
841 .loop_token = token,
842 .dest_ptr = dest_ptr,
843 }
844 }) catch unreachable;
395845 continue;
396846 },
397 Token.Id.IntegerLiteral => {
398 try stack.append(State {
399 .Operand = &(try self.createIntegerLiteral(arena, token)).base
400 });
401 try stack.append(State.AfterOperand);
402 continue;
847 Token.Id.Keyword_switch => {
848 const node = try arena.create(ast.NodeSwitch);
849 *node = ast.NodeSwitch {
850 .base = self.initNode(ast.Node.Id.Switch),
851 .switch_token = token,
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 });
403868 },
404 Token.Id.FloatLiteral => {
405 try stack.append(State {
406 .Operand = &(try self.createFloatLiteral(arena, token)).base
407 });
408 try stack.append(State.AfterOperand);
869 Token.Id.Keyword_comptime => {
870 const node = try arena.create(ast.NodeComptime);
871 *node = ast.NodeComptime {
872 .base = self.initNode(ast.Node.Id.Comptime),
873 .comptime_token = token,
874 .expr = undefined,
875 };
876 dest_ptr.store(&node.base);
877 try stack.append(State { .Expression = DestPtr { .Field = &node.expr } });
409878 continue;
410879 },
411 Token.Id.Keyword_undefined => {
412 try stack.append(State {
413 .Operand = &(try self.createUndefined(arena, token)).base
414 });
415 try stack.append(State.AfterOperand);
880 Token.Id.LBrace => {
881 const block = try self.createBlock(arena, (?Token)(null), token);
882 dest_ptr.store(&block.base);
883
884 stack.append(State { .Block = block }) catch unreachable;
416885 continue;
417886 },
418 Token.Id.Builtin => {
419 const node = try arena.create(ast.NodeBuiltinCall);
420 *node = ast.NodeBuiltinCall {
421 .base = self.initNode(ast.Node.Id.BuiltinCall),
422 .builtin_token = token,
423 .params = ArrayList(&ast.Node).init(arena),
424 .rparen_token = undefined,
425 };
887 else => {
888 self.putBackToken(token);
889 stack.append(State { .UnwrapExpressionBegin = dest_ptr }) catch unreachable;
890 continue;
891 }
892 }
893 },
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;
4261209 try stack.append(State {
427 .Operand = &node.base
1210 .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),
4281221 });
429 try stack.append(State.AfterOperand);
430 try stack.append(State {.ExprListItemOrEnd = &node.params });
1222 node.lhs = dest_ptr.get();
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);
4311310 try stack.append(State {
4321311 .ExpectTokenSave = ExpectTokenSave {
433 .id = Token.Id.LParen,
434 .ptr = &node.rparen_token,
435 },
1312 .id = Token.Id.AngleBracketRight,
1313 .ptr = &??async_node.rangle_bracket,
1314 }
4361315 });
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);
4371429 continue;
4381430 },
439 Token.Id.StringLiteral => {
440 const node = try arena.create(ast.NodeStringLiteral);
441 *node = ast.NodeStringLiteral {
442 .base = self.initNode(ast.Node.Id.StringLiteral),
1431 Token.Id.Keyword_this => {
1432 const node = try arena.create(ast.NodeThisLiteral);
1433 *node = ast.NodeThisLiteral {
1434 .base = self.initNode(ast.Node.Id.ThisLiteral),
4431435 .token = token,
4441436 };
445 try stack.append(State {
446 .Operand = &node.base
447 });
448 try stack.append(State.AfterOperand);
1437 dest_ptr.store(&node.base);
1438 continue;
1439 },
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);
4491455 continue;
4501456 },
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)),
453 }
454 },
1466 while (true) {
1467 const multiline_str = self.getNextToken();
1468 if (multiline_str.id != Token.Id.MultilineStringLiteralLine) {
1469 self.putBackToken(multiline_str);
1470 break;
1471 }
4551472
456 State.AfterOperand => {
457 // we'll either get an infix operator (like != or ^),
458 // or a postfix operator (like () or {}),
459 // otherwise this expression is done (like on a ; or else).
460 var token = self.getNextToken();
461 if (tokenIdToInfixOp(token.id)) |infix_id| {
462 try stack.append(State {
463 .InfixOp = try self.createInfixOp(arena, token, infix_id)
464 });
465 try stack.append(State.ExpectOperand);
1473 try node.tokens.append(multiline_str);
1474 }
1475 continue;
1476 },
1477 Token.Id.LParen => {
1478 const node = try arena.create(ast.NodeGroupedExpression);
1479 *node = ast.NodeGroupedExpression {
1480 .base = self.initNode(ast.Node.Id.GroupedExpression),
1481 .lparen = token,
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, });
4661512 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) {
469 self.putBackToken(token);
1532 self.putBackToken(rbracket_token);
4701533
471 const node = try arena.create(ast.NodeCall);
472 *node = ast.NodeCall {
473 .base = self.initNode(ast.Node.Id.Call),
474 .callee = undefined,
475 .params = ArrayList(&ast.Node).init(arena),
476 .rparen_token = undefined,
477 };
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;
1534 const node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp{
1535 .ArrayType = undefined,
1536 });
1537 dest_ptr.store(&node.base);
1538 stack.append(State { .TypeExprBegin = DestPtr { .Field = &node.rhs } }) catch unreachable;
1539 try stack.append(State { .ExpectToken = Token.Id.RBracket });
1540 try stack.append(State { .Expression = DestPtr { .Field = &node.op.ArrayType } });
4881541
489 // TODO: Parse postfix operator
490 } else {
491 // no postfix/infix operator after this operand.
492 self.putBackToken(token);
1542 },
1543 Token.Id.Keyword_error => {
1544 const next = self.getNextToken();
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);
495 while (true) {
496 switch (stack.pop()) {
497 State.Expression => |dest_ptr| {
498 // we're done
499 try dest_ptr.store(expression);
500 break;
1557 const node = try arena.create(ast.NodeErrorSetDecl);
1558 *node = ast.NodeErrorSetDecl {
1559 .base = self.initNode(ast.Node.Id.ErrorSetDecl),
1560 .error_token = token,
1561 .decls = ArrayList(&ast.NodeIdentifier).init(arena),
1562 .rbrace_token = undefined,
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,
5011611 },
502 State.InfixOp => |infix_op| {
503 infix_op.rhs = expression;
504 infix_op.lhs = popSuffixOp(&stack);
505 expression = &infix_op.base;
506 continue;
1612 }) catch unreachable;
1613 },
1614 Token.Id.Keyword_extern => {
1615 const next = self.getNextToken();
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,
5071631 },
508 State.PrefixOp => |prefix_op| {
509 prefix_op.rhs = expression;
510 expression = &prefix_op.base;
511 continue;
1632 }) catch unreachable;
1633 },
1634 Token.Id.Keyword_struct, Token.Id.Keyword_union, Token.Id.Keyword_enum => {
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,
5121641 },
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;
5141650 }
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;
5151730 }
516 continue;
5171731 }
5181732 },
5191733
520 State.ExprListItemOrEnd => |params| {
1734 State.SliceOrArrayAccess => |node| {
5211735 var token = self.getNextToken();
1736
5221737 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 },
5241766 else => {
525 self.putBackToken(token);
526 stack.append(State { .ExprListCommaOrEnd = params }) catch unreachable;
527 try stack.append(State { .Expression = DestPtr{.List = params} });
1767 try self.parseError(&stack, token, "expected ']' or '..', found {}", @tagName(token.id));
1768 continue;
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;
5282024 },
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;
5292068 }
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;
5302091 },
5312092
532 State.ExprListCommaOrEnd => |params| {
533 var token = self.getNextToken();
534 switch (token.id) {
535 Token.Id.Comma => {
536 stack.append(State { .ExprListItemOrEnd = params }) catch unreachable;
537 },
538 Token.Id.RParen => continue,
539 else => return self.parseError(token, "expected ',' or ')', found {}", @tagName(token.id)),
2093 State.PointerIndexPayload => |dest| {
2094 const lpipe = self.getNextToken();
2095 if (lpipe.id != Token.Id.Pipe) {
2096 self.putBackToken(lpipe);
2097 continue;
5402098 }
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;
5412133 },
5422134
5432135 State.AddrOfModifiers => |addr_of_info| {
......@@ -545,21 +2137,30 @@ pub const Parser = struct {
5452137 switch (token.id) {
5462138 Token.Id.Keyword_align => {
5472139 stack.append(state) catch unreachable;
548 if (addr_of_info.align_expr != null) return self.parseError(token, "multiple align qualifiers");
549 _ = try self.eatToken(Token.Id.LParen);
2140 if (addr_of_info.align_expr != null) {
2141 try self.parseError(&stack, token, "multiple align qualifiers");
2142 continue;
2143 }
5502144 try stack.append(State { .ExpectToken = Token.Id.RParen });
5512145 try stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });
2146 try stack.append(State { .ExpectToken = Token.Id.LParen });
5522147 continue;
5532148 },
5542149 Token.Id.Keyword_const => {
5552150 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 }
5572155 addr_of_info.const_token = token;
5582156 continue;
5592157 },
5602158 Token.Id.Keyword_volatile => {
5612159 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 }
5632164 addr_of_info.volatile_token = token;
5642165 continue;
5652166 },
......@@ -570,17 +2171,6 @@ pub const Parser = struct {
5702171 }
5712172 },
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
5842174 State.FnProto => |fn_proto| {
5852175 stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
5862176 try stack.append(State { .ParamDecl = fn_proto });
......@@ -610,20 +2200,17 @@ pub const Parser = struct {
6102200 State.FnProtoReturnType => |fn_proto| {
6112201 const token = self.getNextToken();
6122202 switch (token.id) {
613 Token.Id.Keyword_var => {
614 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Infer = token };
615 },
6162203 Token.Id.Bang => {
6172204 fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined };
6182205 stack.append(State {
619 .TypeExpr = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},
2206 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.InferErrorSet},
6202207 }) catch unreachable;
6212208 },
6222209 else => {
6232210 self.putBackToken(token);
6242211 fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined };
6252212 stack.append(State {
626 .TypeExpr = DestPtr {.Field = &fn_proto.return_type.Explicit},
2213 .TypeExprBegin = DestPtr {.Field = &fn_proto.return_type.Explicit},
6272214 }) catch unreachable;
6282215 },
6292216 }
......@@ -666,7 +2253,7 @@ pub const Parser = struct {
6662253 stack.append(State { .ParamDecl = fn_proto }) catch unreachable;
6672254 try stack.append(State.ParamDeclComma);
6682255 try stack.append(State {
669 .TypeExpr = DestPtr {.Field = &param_decl.type_node}
2256 .TypeExprBegin = DestPtr {.Field = &param_decl.type_node}
6702257 });
6712258 continue;
6722259 },
......@@ -679,7 +2266,10 @@ pub const Parser = struct {
6792266 continue;
6802267 },
6812268 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 },
6832273 }
6842274 },
6852275
......@@ -687,21 +2277,151 @@ pub const Parser = struct {
6872277 const token = self.getNextToken();
6882278 switch(token.id) {
6892279 Token.Id.LBrace => {
690 const block = try self.createBlock(arena, token);
2280 const block = try self.createBlock(arena, (?Token)(null), token);
6912281 fn_proto.body_node = &block.base;
6922282 stack.append(State { .Block = block }) catch unreachable;
6932283 continue;
6942284 },
6952285 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 },
6972371 }
6982372 },
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
7002420 State.Block => |block| {
7012421 const token = self.getNextToken();
7022422 switch (token.id) {
7032423 Token.Id.RBrace => {
704 block.end_token = token;
2424 block.rbrace = token;
7052425 continue;
7062426 },
7072427 else => {
......@@ -714,119 +2434,262 @@ pub const Parser = struct {
7142434 },
7152435
7162436 State.Statement => |block| {
717 {
718 // Look for comptime var, comptime const
719 const comptime_token = self.getNextToken();
720 if (comptime_token.id == Token.Id.Keyword_comptime) {
2437 const next = self.getNextToken();
2438 switch (next.id) {
2439 Token.Id.Keyword_comptime => {
7212440 const mut_token = self.getNextToken();
7222441 if (mut_token.id == Token.Id.Keyword_var or mut_token.id == Token.Id.Keyword_const) {
7232442 // TODO shouldn't need these casts
7242443 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
725 mut_token, (?Token)(comptime_token), (?Token)(null));
726 try stack.append(State { .VarDecl = var_decl });
2444 mut_token, (?Token)(next), (?Token)(null), null);
2445 stack.append(State { .VarDecl = var_decl }) catch unreachable;
7272446 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 } });
7282453 }
729 self.putBackToken(mut_token);
730 }
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
2454 },
2455 Token.Id.Keyword_var, Token.Id.Keyword_const => {
7382456 const var_decl = try self.createAttachVarDecl(arena, &block.statements, (?Token)(null),
739 mut_token, (?Token)(null), (?Token)(null));
740 try stack.append(State { .VarDecl = var_decl });
2457 next, (?Token)(null), (?Token)(null), null);
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 } });
7412491 continue;
7422492 }
743 self.putBackToken(mut_token);
7442493 }
7452494
746 stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
747 try stack.append(State { .Expression = DestPtr{.List = &block.statements} });
748 continue;
7492495 },
7502496
751 // These are data, not control flow.
752 State.InfixOp => unreachable,
753 State.PrefixOp => unreachable,
754 State.SuffixOp => unreachable,
755 State.Operand => unreachable,
2497 State.Semicolon => |node_ptr| {
2498 const node = *node_ptr;
2499 if (requireSemiColon(node)) {
2500 _ = (try self.eatToken(&stack, Token.Id.Semicolon)) ?? continue;
2501 }
2502 }
7562503 }
7572504 }
7582505 }
7592506
760 fn popSuffixOp(stack: &ArrayList(State)) &ast.Node {
761 var expression: &ast.Node = undefined;
762 var left_leaf_ptr: &&ast.Node = &expression;
2507 fn requireSemiColon(node: &const ast.Node) bool {
2508 var n = node;
7632509 while (true) {
764 switch (stack.pop()) {
765 State.SuffixOp => |suffix_op| {
766 switch (suffix_op.id) {
767 ast.Node.Id.Call => {
768 const call = @fieldParentPtr(ast.NodeCall, "base", suffix_op);
769 *left_leaf_ptr = &call.base;
770 left_leaf_ptr = &call.callee;
771 continue;
772 },
773 else => unreachable,
2510 switch (n.id) {
2511 ast.Node.Id.Root,
2512 ast.Node.Id.StructField,
2513 ast.Node.Id.UnionTag,
2514 ast.Node.Id.EnumTag,
2515 ast.Node.Id.ParamDecl,
2516 ast.Node.Id.Block,
2517 ast.Node.Id.Payload,
2518 ast.Node.Id.PointerPayload,
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;
7742549 }
2550
2551 n = if_node.body;
7752552 },
776 State.Operand => |operand| {
777 *left_leaf_ptr = operand;
778 break;
2553 ast.Node.Id.Else => {
2554 const else_node = @fieldParentPtr(ast.NodeElse, "base", n);
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;
7792573 },
780 else => unreachable,
2574 else => return true,
7812575 }
7822576 }
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 };
7852670 }
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)'
7882675 return switch (*id) {
789 Token.Id.Ampersand => ast.NodeInfixOp.InfixOp.BitAnd,
790 Token.Id.AmpersandEqual => ast.NodeInfixOp.InfixOp.AssignBitAnd,
791 Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp.BitShiftLeft,
792 Token.Id.AngleBracketAngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftLeft,
793 Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp.BitShiftRight,
794 Token.Id.AngleBracketAngleBracketRightEqual => ast.NodeInfixOp.InfixOp.AssignBitShiftRight,
795 Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp.LessThan,
796 Token.Id.AngleBracketLeftEqual => ast.NodeInfixOp.InfixOp.LessOrEqual,
797 Token.Id.AngleBracketRight => ast.NodeInfixOp.InfixOp.GreaterThan,
798 Token.Id.AngleBracketRightEqual => ast.NodeInfixOp.InfixOp.GreaterOrEqual,
799 Token.Id.Asterisk => ast.NodeInfixOp.InfixOp.Mult,
800 Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp.ArrayMult,
801 Token.Id.AsteriskEqual => ast.NodeInfixOp.InfixOp.AssignTimes,
802 Token.Id.AsteriskPercent => ast.NodeInfixOp.InfixOp.MultWrap,
803 Token.Id.AsteriskPercentEqual => ast.NodeInfixOp.InfixOp.AssignTimesWarp,
804 Token.Id.Bang => ast.NodeInfixOp.InfixOp.ErrorUnion,
805 Token.Id.BangEqual => ast.NodeInfixOp.InfixOp.BangEqual,
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,
2676 Token.Id.Bang => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.BoolNot),
2677 Token.Id.Tilde => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.BitNot),
2678 Token.Id.Minus => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Negation),
2679 Token.Id.MinusPercent => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.NegationWrap),
2680 Token.Id.Asterisk => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Deref),
2681 Token.Id.Ampersand => ast.NodePrefixOp.PrefixOp {
2682 .AddrOf = ast.NodePrefixOp.AddrOfInfo {
2683 .align_expr = null,
2684 .bit_offset_start_token = null,
2685 .bit_offset_end_token = null,
2686 .const_token = null,
2687 .volatile_token = null,
2688 },
2689 },
2690 Token.Id.QuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.MaybeType),
2691 Token.Id.QuestionMarkQuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.UnwrapMaybe),
2692 Token.Id.Keyword_await => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Await),
8302693 else => null,
8312694 };
8322695 }
......@@ -852,7 +2715,7 @@ pub const Parser = struct {
8522715 }
8532716
8542717 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.NodeVarDecl
2718 comptime_token: &const ?Token, extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
8562719 {
8572720 const node = try arena.create(ast.NodeVarDecl);
8582721
......@@ -865,7 +2728,7 @@ pub const Parser = struct {
8652728 .type_node = null,
8662729 .align_node = null,
8672730 .init_node = null,
868 .lib_name = null,
2731 .lib_name = lib_name,
8692732 // initialized later
8702733 .name_token = undefined,
8712734 .eq_token = undefined,
......@@ -874,7 +2737,18 @@ pub const Parser = struct {
8742737 return node;
8752738 }
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,
8782752 block: &ast.NodeBlock) !&ast.NodeTestDecl
8792753 {
8802754 const node = try arena.create(ast.NodeTestDecl);
......@@ -882,14 +2756,14 @@ pub const Parser = struct {
8822756 *node = ast.NodeTestDecl {
8832757 .base = self.initNode(ast.Node.Id.TestDecl),
8842758 .test_token = *test_token,
885 .name_token = *name_token,
2759 .name = name,
8862760 .body_node = &block.base,
8872761 };
8882762 return node;
8892763 }
8902764
8912765 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.NodeFnProto
2766 lib_name: ?&ast.Node, cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) !&ast.NodeFnProto
8932767 {
8942768 const node = try arena.create(ast.NodeFnProto);
8952769
......@@ -904,8 +2778,9 @@ pub const Parser = struct {
9042778 .extern_token = *extern_token,
9052779 .inline_token = *inline_token,
9062780 .cc_token = *cc_token,
2781 .async_attr = null,
9072782 .body_node = null,
908 .lib_name = null,
2783 .lib_name = lib_name,
9092784 .align_expr = null,
9102785 };
9112786 return node;
......@@ -925,14 +2800,28 @@ pub const Parser = struct {
9252800 return node;
9262801 }
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 {
9292804 const node = try arena.create(ast.NodeBlock);
9302805
9312806 *node = ast.NodeBlock {
9322807 .base = self.initNode(ast.Node.Id.Block),
933 .begin_token = *begin_token,
934 .end_token = undefined,
2808 .label = *label,
2809 .lbrace = *lbrace,
9352810 .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,
9362825 };
9372826 return node;
9382827 }
......@@ -962,6 +2851,18 @@ pub const Parser = struct {
9622851 return node;
9632852 }
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
9652866 fn createIdentifier(self: &Parser, arena: &mem.Allocator, name_token: &const Token) !&ast.NodeIdentifier {
9662867 const node = try arena.create(ast.NodeIdentifier);
9672868
......@@ -1015,62 +2916,78 @@ pub const Parser = struct {
10152916 }
10162917
10172918 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,
10192920 inline_token: &const ?Token) !&ast.NodeFnProto
10202921 {
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);
10222923 try list.append(&node.base);
10232924 return node;
10242925 }
10252926
10262927 fn createAttachVarDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
10272928 visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token,
1028 extern_token: &const ?Token) !&ast.NodeVarDecl
2929 extern_token: &const ?Token, lib_name: ?&ast.Node) !&ast.NodeVarDecl
10292930 {
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);
10312932 try list.append(&node.base);
10322933 return node;
10332934 }
10342935
10352936 fn createAttachTestDecl(self: &Parser, arena: &mem.Allocator, list: &ArrayList(&ast.Node),
1036 test_token: &const Token, name_token: &const Token, block: &ast.NodeBlock) !&ast.NodeTestDecl
2937 test_token: &const Token, name: &ast.Node, block: &ast.NodeBlock) !&ast.NodeTestDecl
10372938 {
1038 const node = try self.createTestDecl(arena, test_token, name_token, block);
2939 const node = try self.createTestDecl(arena, test_token, name, block);
10392940 try list.append(&node.base);
10402941 return node;
10412942 }
10422943
1043 fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) (error{ParseError}) {
1044 const loc = self.tokenizer.getTokenLocation(token);
1045 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, token.line + 1, token.column + 1, args);
1046 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
1047 {
1048 var i: usize = 0;
1049 while (i < token.column) : (i += 1) {
1050 warn(" ");
2944 fn parseError(self: &Parser, stack: &ArrayList(State), token: &const Token, comptime fmt: []const u8, args: ...) !void {
2945 // Before reporting an error. We pop the stack to see if our state was optional
2946 self.revertIfOptional(stack) catch {
2947 const loc = self.tokenizer.getTokenLocation(0, token);
2948 warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args);
2949 warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]);
2950 {
2951 var i: usize = 0;
2952 while (i < loc.column) : (i += 1) {
2953 warn(" ");
2954 }
10512955 }
1052 }
1053 {
1054 const caret_count = token.end - token.start;
1055 var i: usize = 0;
1056 while (i < caret_count) : (i += 1) {
1057 warn("~");
2956 {
2957 const caret_count = token.end - token.start;
2958 var i: usize = 0;
2959 while (i < caret_count) : (i += 1) {
2960 warn("~");
2961 }
10582962 }
1059 }
1060 warn("\n");
1061 return error.ParseError;
2963 warn("\n");
2964 return error.ParseError;
2965 };
10622966 }
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();
10652970 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;
10672973 }
2974 return token;
10682975 }
10692976
1070 fn eatToken(self: &Parser, id: @TagType(Token.Id)) !Token {
1071 const token = self.getNextToken();
1072 try self.expectToken(token, id);
1073 return token;
2977 fn revertIfOptional(self: &Parser, stack: &ArrayList(State)) !void {
2978 while (stack.popOrNull()) |state| {
2979 switch (state) {
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;
10742991 }
10752992
10762993 fn putBackToken(self: &Parser, token: &const Token) void {
......@@ -1129,6 +3046,7 @@ pub const Parser = struct {
11293046 Expression: &ast.Node,
11303047 VarDecl: &ast.NodeVarDecl,
11313048 Statement: &ast.Node,
3049 FieldInitializer: &ast.NodeFieldInitializer,
11323050 PrintIndent,
11333051 Indent: usize,
11343052 };
......@@ -1149,9 +3067,8 @@ pub const Parser = struct {
11493067 try stack.append(RenderState {
11503068 .Text = blk: {
11513069 const prev_node = root_node.decls.at(i - 1);
1152 const prev_line_index = prev_node.lastToken().line;
1153 const this_line_index = decl.firstToken().line;
1154 if (this_line_index - prev_line_index >= 2) {
3070 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, decl.firstToken());
3071 if (loc.line >= 2) {
11553072 break :blk "\n\n";
11563073 }
11573074 break :blk "\n";
......@@ -1169,38 +3086,24 @@ pub const Parser = struct {
11693086 switch (decl.id) {
11703087 ast.Node.Id.FnProto => {
11713088 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| {
1185 try stream.print(" {}", self.tokenizer.getTokenSlice(name_token));
3090 if (fn_proto.body_node) |body_node| {
3091 stack.append(RenderState { .Expression = body_node}) catch unreachable;
3092 try stack.append(RenderState { .Text = " "});
3093 } else {
3094 stack.append(RenderState { .Text = ";" }) catch unreachable;
11863095 }
11873096
1188 try stream.print("(");
1189
1190 if (fn_proto.body_node == null) {
1191 try stack.append(RenderState { .Text = ";" });
1192 }
1193
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 }
3097 try stack.append(RenderState { .Expression = decl });
3098 },
3099 ast.Node.Id.Use => {
3100 const use_decl = @fieldParentPtr(ast.NodeUse, "base", decl);
3101 if (use_decl.visib_token) |visib_token| {
3102 try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
12033103 }
3104 try stream.print("use ");
3105 try stack.append(RenderState { .Text = ";" });
3106 try stack.append(RenderState { .Expression = use_decl.expr });
12043107 },
12053108 ast.Node.Id.VarDecl => {
12063109 const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl);
......@@ -1208,29 +3111,51 @@ pub const Parser = struct {
12083111 },
12093112 ast.Node.Id.TestDecl => {
12103113 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 ");
12123115 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 });
12133147 },
12143148 else => unreachable,
12153149 }
12163150 },
12173151
1218 RenderState.VarDecl => |var_decl| {
1219 if (var_decl.visib_token) |visib_token| {
1220 try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token));
1221 }
1222 if (var_decl.extern_token) |extern_token| {
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));
3152 RenderState.FieldInitializer => |field_init| {
3153 try stream.print(".{}", self.tokenizer.getTokenSlice(field_init.name_token));
3154 try stream.print(" = ");
3155 try stack.append(RenderState { .Expression = field_init.expr });
3156 },
12333157
3158 RenderState.VarDecl => |var_decl| {
12343159 try stack.append(RenderState { .Text = ";" });
12353160 if (var_decl.init_node) |init_node| {
12363161 try stack.append(RenderState { .Expression = init_node });
......@@ -1241,9 +3166,31 @@ pub const Parser = struct {
12413166 try stack.append(RenderState { .Expression = align_node });
12423167 try stack.append(RenderState { .Text = " align(" });
12433168 }
1244 if (var_decl.type_node) |type_node| {
1245 try stream.print(": ");
1246 try stack.append(RenderState { .Expression = type_node });
3169 if (var_decl.type_node) |type_node| {
3170 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) });
12473194 }
12483195 },
12493196
......@@ -1274,6 +3221,10 @@ pub const Parser = struct {
12743221 },
12753222 ast.Node.Id.Block => {
12763223 const block = @fieldParentPtr(ast.NodeBlock, "base", base);
3224 if (block.label) |label| {
3225 try stream.print("{}: ", self.tokenizer.getTokenSlice(label));
3226 }
3227
12773228 if (block.statements.len == 0) {
12783229 try stream.write("{}");
12793230 } else {
......@@ -1292,10 +3243,9 @@ pub const Parser = struct {
12923243 try stack.append(RenderState {
12933244 .Text = blk: {
12943245 if (i != 0) {
1295 const prev_statement_node = block.statements.items[i - 1];
1296 const prev_line_index = prev_statement_node.lastToken().line;
1297 const this_line_index = statement_node.firstToken().line;
1298 if (this_line_index - prev_line_index >= 2) {
3246 const prev_node = block.statements.items[i - 1];
3247 const loc = self.tokenizer.getTokenLocation(prev_node.lastToken().end, statement_node.firstToken());
3248 if (loc.line >= 2) {
12993249 break :blk "\n\n";
13003250 }
13013251 }
......@@ -1305,54 +3255,99 @@ pub const Parser = struct {
13053255 }
13063256 }
13073257 },
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 },
13083292 ast.Node.Id.InfixOp => {
13093293 const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base);
13103294 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 }
13563351 try stack.append(RenderState { .Expression = prefix_op_node.lhs });
13573352 },
13583353 ast.Node.Id.PrefixOp => {
......@@ -1373,15 +3368,179 @@ pub const Parser = struct {
13733368 try stack.append(RenderState { .Expression = align_expr});
13743369 }
13753370 },
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 },
13763390 ast.NodePrefixOp.PrefixOp.BitNot => try stream.write("~"),
13773391 ast.NodePrefixOp.PrefixOp.BoolNot => try stream.write("!"),
13783392 ast.NodePrefixOp.PrefixOp.Deref => try stream.write("*"),
13793393 ast.NodePrefixOp.PrefixOp.Negation => try stream.write("-"),
13803394 ast.NodePrefixOp.PrefixOp.NegationWrap => try stream.write("-%"),
1381 ast.NodePrefixOp.PrefixOp.Return => try stream.write("return "),
13823395 ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "),
13833396 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 = "*"});
13843530 }
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 });
13853544 },
13863545 ast.Node.Id.IntegerLiteral => {
13873546 const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);
......@@ -1395,6 +3554,147 @@ pub const Parser = struct {
13953554 const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base);
13963555 try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token));
13973556 },
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 },
13983698 ast.Node.Id.UndefinedLiteral => {
13993699 const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base);
14003700 try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token));
......@@ -1413,26 +3713,419 @@ pub const Parser = struct {
14133713 }
14143714 }
14153715 },
1416 ast.Node.Id.Call => {
1417 const call = @fieldParentPtr(ast.NodeCall, "base", base);
3716 ast.Node.Id.FnProto => {
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
14184095 try stack.append(RenderState { .Text = ")"});
1419 var i = call.params.len;
1420 while (i != 0) {
1421 i -= 1;
1422 const param_node = call.params.at(i);
1423 try stack.append(RenderState { .Expression = param_node});
1424 if (i != 0) {
1425 try stack.append(RenderState { .Text = ", " });
1426 }
4096 try stack.append(RenderState { .Expression = asm_input.expr});
4097 try stack.append(RenderState { .Text = " ("});
4098 try stack.append(RenderState { .Expression = &asm_input.constraint.base});
4099 try stack.append(RenderState { .Text = "] "});
4100 try stack.append(RenderState { .Expression = &asm_input.symbolic_name.base});
4101 try stack.append(RenderState { .Text = "["});
4102 },
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 },
14274115 }
1428 try stack.append(RenderState { .Text = "("});
1429 try stack.append(RenderState { .Expression = call.callee });
4116 try stack.append(RenderState { .Text = " ("});
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 = "["});
14304121 },
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,
14344126 ast.Node.Id.Root,
14354127 ast.Node.Id.VarDecl,
4128 ast.Node.Id.Use,
14364129 ast.Node.Id.TestDecl,
14374130 ast.Node.Id.ParamDecl => unreachable,
14384131 },
......@@ -1450,9 +4143,6 @@ pub const Parser = struct {
14504143 ast.NodeFnProto.ReturnType.Explicit => |node| {
14514144 try stack.append(RenderState { .Expression = node});
14524145 },
1453 ast.NodeFnProto.ReturnType.Infer => {
1454 try stream.print("var");
1455 },
14564146 ast.NodeFnProto.ReturnType.InferErrorSet => |node| {
14574147 try stream.print("!");
14584148 try stack.append(RenderState { .Expression = node});
......@@ -1472,8 +4162,10 @@ pub const Parser = struct {
14724162 try stack.append(RenderState { .VarDecl = var_decl});
14734163 },
14744164 else => {
1475 try stack.append(RenderState { .Text = ";"});
1476 try stack.append(RenderState { .Expression = base});
4165 if (requireSemiColon(base)) {
4166 try stack.append(RenderState { .Text = ";" });
4167 }
4168 try stack.append(RenderState { .Expression = base });
14774169 },
14784170 }
14794171 },
......@@ -1557,7 +4249,7 @@ fn testCanonical(source: []const u8) !void {
15574249 }
15584250}
15594251
1560test "zig fmt" {
4252test "zig fmt: get stdout or fail" {
15614253 try testCanonical(
15624254 \\const std = @import("std");
15634255 \\
......@@ -1568,7 +4260,9 @@ test "zig fmt" {
15684260 \\}
15694261 \\
15704262 );
4263}
15714264
4265test "zig fmt: preserve spacing" {
15724266 try testCanonical(
15734267 \\const std = @import("std");
15744268 \\
......@@ -1581,25 +4275,26 @@ test "zig fmt" {
15814275 \\}
15824276 \\
15834277 );
4278}
15844279
4280test "zig fmt: return types" {
15854281 try testCanonical(
15864282 \\pub fn main() !void {}
15874283 \\pub fn main() var {}
15884284 \\pub fn main() i32 {}
15894285 \\
15904286 );
4287}
15914288
4289test "zig fmt: imports" {
15924290 try testCanonical(
15934291 \\const std = @import("std");
15944292 \\const std = @import();
15954293 \\
15964294 );
4295}
15974296
1598 try testCanonical(
1599 \\extern fn puts(s: &const u8) c_int;
1600 \\
1601 );
1602
4297test "zig fmt: global declarations" {
16034298 try testCanonical(
16044299 \\const a = b;
16054300 \\pub const a = b;
......@@ -1609,61 +4304,85 @@ test "zig fmt" {
16094304 \\pub const a: i32 = b;
16104305 \\var a: i32 = b;
16114306 \\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;
16124315 \\
16134316 );
4317}
16144318
4319test "zig fmt: extern declaration" {
16154320 try testCanonical(
16164321 \\extern var foo: c_int;
16174322 \\
16184323 );
4324}
16194325
1620 try testCanonical(
4326test "zig fmt: alignment" {
4327 try testCanonical(
16214328 \\var foo: c_int align(1);
16224329 \\
16234330 );
4331}
16244332
4333test "zig fmt: C main" {
16254334 try testCanonical(
16264335 \\fn main(argc: c_int, argv: &&u8) c_int {
16274336 \\ const a = b;
16284337 \\}
16294338 \\
16304339 );
4340}
16314341
4342test "zig fmt: return" {
16324343 try testCanonical(
16334344 \\fn foo(argc: c_int, argv: &&u8) c_int {
16344345 \\ return 0;
16354346 \\}
16364347 \\
1637 );
1638
1639 try testCanonical(
1640 \\extern fn f1(s: &align(&u8) u8) c_int;
4348 \\fn bar() void {
4349 \\ return;
4350 \\}
16414351 \\
16424352 );
4353}
16434354
4355test "zig fmt: pointer attributes" {
16444356 try testCanonical(
1645 \\extern fn f1(s: &&align(1) &const &volatile u8) c_int;
1646 \\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
1647 \\extern fn f3(s: &align(1) const volatile u8) c_int;
4357 \\extern fn f1(s: &align(&u8) u8) c_int;
4358 \\extern fn f2(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;
16484361 \\
16494362 );
4363}
16504364
4365test "zig fmt: slice attributes" {
16514366 try testCanonical(
1652 \\fn f1(a: bool, b: bool) bool {
1653 \\ a != b;
1654 \\ return a == b;
1655 \\}
4367 \\extern fn f1(s: &align(&u8) u8) c_int;
4368 \\extern fn f2(s: &&align(1) &const &volatile u8) c_int;
4369 \\extern fn f3(s: &align(1) const &align(1) volatile &const volatile u8) c_int;
4370 \\extern fn f4(s: &align(1) const volatile u8) c_int;
16564371 \\
16574372 );
4373}
16584374
1659 try testCanonical(
4375test "zig fmt: test declaration" {
4376 try testCanonical(
16604377 \\test "test name" {
16614378 \\ const a = 1;
16624379 \\ var b = 1;
16634380 \\}
16644381 \\
16654382 );
4383}
16664384
4385test "zig fmt: infix operators" {
16674386 try testCanonical(
16684387 \\test "infix operators" {
16694388 \\ var i = undefined;
......@@ -1713,14 +4432,49 @@ test "zig fmt" {
17134432 \\}
17144433 \\
17154434 );
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" {
17174469 try testCanonical(
17184470 \\test "prefix operators" {
1719 \\ --%~??!*&0;
4471 \\ try return --%~??!*&0;
17204472 \\}
17214473 \\
17224474 );
4475}
17234476
4477test "zig fmt: call expression" {
17244478 try testCanonical(
17254479 \\test "test calls" {
17264480 \\ a();
......@@ -1731,3 +4485,565 @@ test "zig fmt" {
17314485 \\
17324486 );
17334487}
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 {
55 id: Id,
66 start: usize,
77 end: usize,
8 line: usize,
9 column: usize,
108
119 const KeywordId = struct {
1210 bytes: []const u8,
......@@ -17,14 +15,18 @@ pub const Token = struct {
1715 KeywordId{.bytes="align", .id = Id.Keyword_align},
1816 KeywordId{.bytes="and", .id = Id.Keyword_and},
1917 KeywordId{.bytes="asm", .id = Id.Keyword_asm},
18 KeywordId{.bytes="async", .id = Id.Keyword_async},
19 KeywordId{.bytes="await", .id = Id.Keyword_await},
2020 KeywordId{.bytes="break", .id = Id.Keyword_break},
2121 KeywordId{.bytes="catch", .id = Id.Keyword_catch},
22 KeywordId{.bytes="cancel", .id = Id.Keyword_cancel},
2223 KeywordId{.bytes="comptime", .id = Id.Keyword_comptime},
2324 KeywordId{.bytes="const", .id = Id.Keyword_const},
2425 KeywordId{.bytes="continue", .id = Id.Keyword_continue},
2526 KeywordId{.bytes="defer", .id = Id.Keyword_defer},
2627 KeywordId{.bytes="else", .id = Id.Keyword_else},
2728 KeywordId{.bytes="enum", .id = Id.Keyword_enum},
29 KeywordId{.bytes="errdefer", .id = Id.Keyword_errdefer},
2830 KeywordId{.bytes="error", .id = Id.Keyword_error},
2931 KeywordId{.bytes="export", .id = Id.Keyword_export},
3032 KeywordId{.bytes="extern", .id = Id.Keyword_extern},
......@@ -39,10 +41,12 @@ pub const Token = struct {
3941 KeywordId{.bytes="or", .id = Id.Keyword_or},
4042 KeywordId{.bytes="packed", .id = Id.Keyword_packed},
4143 KeywordId{.bytes="pub", .id = Id.Keyword_pub},
44 KeywordId{.bytes="resume", .id = Id.Keyword_resume},
4245 KeywordId{.bytes="return", .id = Id.Keyword_return},
4346 KeywordId{.bytes="section", .id = Id.Keyword_section},
4447 KeywordId{.bytes="stdcallcc", .id = Id.Keyword_stdcallcc},
4548 KeywordId{.bytes="struct", .id = Id.Keyword_struct},
49 KeywordId{.bytes="suspend", .id = Id.Keyword_suspend},
4650 KeywordId{.bytes="switch", .id = Id.Keyword_switch},
4751 KeywordId{.bytes="test", .id = Id.Keyword_test},
4852 KeywordId{.bytes="this", .id = Id.Keyword_this},
......@@ -72,7 +76,8 @@ pub const Token = struct {
7276 Invalid,
7377 Identifier,
7478 StringLiteral: StrLitKind,
75 StringIdentifier,
79 MultilineStringLiteralLine: StrLitKind,
80 CharLiteral,
7681 Eof,
7782 Builtin,
7883 Bang,
......@@ -81,6 +86,7 @@ pub const Token = struct {
8186 PipeEqual,
8287 Equal,
8388 EqualEqual,
89 EqualAngleBracketRight,
8490 BangEqual,
8591 LParen,
8692 RParen,
......@@ -89,6 +95,8 @@ pub const Token = struct {
8995 PercentEqual,
9096 LBrace,
9197 RBrace,
98 LBracket,
99 RBracket,
92100 Period,
93101 Ellipsis2,
94102 Ellipsis3,
......@@ -132,7 +140,10 @@ pub const Token = struct {
132140 Keyword_align,
133141 Keyword_and,
134142 Keyword_asm,
143 Keyword_async,
144 Keyword_await,
135145 Keyword_break,
146 Keyword_cancel,
136147 Keyword_catch,
137148 Keyword_comptime,
138149 Keyword_const,
......@@ -140,6 +151,7 @@ pub const Token = struct {
140151 Keyword_defer,
141152 Keyword_else,
142153 Keyword_enum,
154 Keyword_errdefer,
143155 Keyword_error,
144156 Keyword_export,
145157 Keyword_extern,
......@@ -154,10 +166,12 @@ pub const Token = struct {
154166 Keyword_or,
155167 Keyword_packed,
156168 Keyword_pub,
169 Keyword_resume,
157170 Keyword_return,
158171 Keyword_section,
159172 Keyword_stdcallcc,
160173 Keyword_struct,
174 Keyword_suspend,
161175 Keyword_switch,
162176 Keyword_test,
163177 Keyword_this,
......@@ -176,28 +190,34 @@ pub const Token = struct {
176190pub const Tokenizer = struct {
177191 buffer: []const u8,
178192 index: usize,
179 line: usize,
180 column: usize,
181193 pending_invalid_token: ?Token,
182194
183 pub const LineLocation = struct {
195 pub const Location = struct {
196 line: usize,
197 column: usize,
184198 line_start: usize,
185199 line_end: usize,
186200 };
187201
188 pub fn getTokenLocation(self: &Tokenizer, token: &const Token) LineLocation {
189 var loc = LineLocation {
190 .line_start = 0,
202 pub fn getTokenLocation(self: &Tokenizer, start_index: usize, token: &const Token) Location {
203 var loc = Location {
204 .line = 0,
205 .column = 0,
206 .line_start = start_index,
191207 .line_end = self.buffer.len,
192208 };
193 for (self.buffer) |c, i| {
194 if (i == token.start) {
195 loc.line_end = i;
209 for (self.buffer[start_index..]) |c, i| {
210 if (i + start_index == token.start) {
211 loc.line_end = i + start_index;
196212 while (loc.line_end < self.buffer.len and self.buffer[loc.line_end] != '\n') : (loc.line_end += 1) {}
197213 return loc;
198214 }
199215 if (c == '\n') {
216 loc.line += 1;
217 loc.column = 0;
200218 loc.line_start = i + 1;
219 } else {
220 loc.column += 1;
201221 }
202222 }
203223 return loc;
......@@ -212,8 +232,6 @@ pub const Tokenizer = struct {
212232 return Tokenizer {
213233 .buffer = buffer,
214234 .index = 0,
215 .line = 0,
216 .column = 0,
217235 .pending_invalid_token = null,
218236 };
219237 }
......@@ -225,6 +243,12 @@ pub const Tokenizer = struct {
225243 C,
226244 StringLiteral,
227245 StringLiteralBackslash,
246 MultilineStringLiteralLine,
247 MultilineStringLiteralLineBackslash,
248 CharLiteral,
249 CharLiteralBackslash,
250 CharLiteralEnd,
251 Backslash,
228252 Equal,
229253 Bang,
230254 Pipe,
......@@ -261,26 +285,22 @@ pub const Tokenizer = struct {
261285 self.pending_invalid_token = null;
262286 return token;
263287 }
288 const start_index = self.index;
264289 var state = State.Start;
265290 var result = Token {
266291 .id = Token.Id.Eof,
267292 .start = self.index,
268293 .end = undefined,
269 .line = self.line,
270 .column = self.column,
271294 };
272 while (self.index < self.buffer.len) {
295 while (self.index < self.buffer.len) : (self.index += 1) {
273296 const c = self.buffer[self.index];
274297 switch (state) {
275298 State.Start => switch (c) {
276299 ' ' => {
277300 result.start = self.index + 1;
278 result.column += 1;
279301 },
280302 '\n' => {
281303 result.start = self.index + 1;
282 result.line += 1;
283 result.column = 0;
284304 },
285305 'c' => {
286306 state = State.C;
......@@ -290,6 +310,9 @@ pub const Tokenizer = struct {
290310 state = State.StringLiteral;
291311 result.id = Token.Id { .StringLiteral = Token.StrLitKind.Normal };
292312 },
313 '\'' => {
314 state = State.CharLiteral;
315 },
293316 'a'...'b', 'd'...'z', 'A'...'Z', '_' => {
294317 state = State.Identifier;
295318 result.id = Token.Id.Identifier;
......@@ -316,6 +339,16 @@ pub const Tokenizer = struct {
316339 self.index += 1;
317340 break;
318341 },
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 },
319352 ';' => {
320353 result.id = Token.Id.Semicolon;
321354 self.index += 1;
......@@ -352,6 +385,10 @@ pub const Tokenizer = struct {
352385 '^' => {
353386 state = State.Caret;
354387 },
388 '\\' => {
389 state = State.Backslash;
390 result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.Normal };
391 },
355392 '{' => {
356393 result.id = Token.Id.LBrace;
357394 self.index += 1;
......@@ -396,7 +433,7 @@ pub const Tokenizer = struct {
396433
397434 State.SawAtSign => switch (c) {
398435 '"' => {
399 result.id = Token.Id.StringIdentifier;
436 result.id = Token.Id.Identifier;
400437 state = State.StringLiteral;
401438 },
402439 else => {
......@@ -532,8 +569,17 @@ pub const Tokenizer = struct {
532569 'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
533570 else => break,
534571 },
572 State.Backslash => switch (c) {
573 '\\' => {
574 state = State.MultilineStringLiteralLine;
575 },
576 else => break,
577 },
535578 State.C => switch (c) {
536 '\\' => @panic("TODO"),
579 '\\' => {
580 state = State.Backslash;
581 result.id = Token.Id { .MultilineStringLiteralLine = Token.StrLitKind.C };
582 },
537583 '"' => {
538584 state = State.StringLiteral;
539585 result.id = Token.Id { .StringLiteral = Token.StrLitKind.C };
......@@ -562,6 +608,64 @@ pub const Tokenizer = struct {
562608 },
563609 },
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
565669 State.Bang => switch (c) {
566670 '=' => {
567671 result.id = Token.Id.BangEqual;
......@@ -597,6 +701,11 @@ pub const Tokenizer = struct {
597701 self.index += 1;
598702 break;
599703 },
704 '>' => {
705 result.id = Token.Id.EqualAngleBracketRight;
706 self.index += 1;
707 break;
708 },
600709 else => {
601710 result.id = Token.Id.Equal;
602711 break;
......@@ -794,14 +903,6 @@ pub const Tokenizer = struct {
794903 else => break,
795904 },
796905 }
797
798 self.index += 1;
799 if (c == '\n') {
800 self.line += 1;
801 self.column = 0;
802 } else {
803 self.column += 1;
804 }
805906 } else if (self.index == self.buffer.len) {
806907 switch (state) {
807908 State.Start,
......@@ -811,6 +912,7 @@ pub const Tokenizer = struct {
811912 State.FloatFraction,
812913 State.FloatExponentNumber,
813914 State.StringLiteral, // find this error later
915 State.MultilineStringLiteralLine,
814916 State.Builtin => {},
815917
816918 State.Identifier => {
......@@ -825,6 +927,11 @@ pub const Tokenizer = struct {
825927 State.NumberDot,
826928 State.FloatExponentUnsigned,
827929 State.SawAtSign,
930 State.Backslash,
931 State.MultilineStringLiteralLineBackslash,
932 State.CharLiteral,
933 State.CharLiteralBackslash,
934 State.CharLiteralEnd,
828935 State.StringLiteralBackslash => {
829936 result.id = Token.Id.Invalid;
830937 },
......@@ -894,6 +1001,7 @@ pub const Tokenizer = struct {
8941001 },
8951002 }
8961003 }
1004
8971005 if (result.id == Token.Id.Eof) {
8981006 if (self.pending_invalid_token) |token| {
8991007 self.pending_invalid_token = null;
......@@ -917,8 +1025,6 @@ pub const Tokenizer = struct {
9171025 .id = Token.Id.Invalid,
9181026 .start = self.index,
9191027 .end = self.index + invalid_length,
920 .line = self.line,
921 .column = self.column,
9221028 };
9231029 }
9241030
......@@ -968,9 +1074,16 @@ test "tokenizer" {
9681074 });
9691075}
9701076
1077test "tokenizer - chars" {
1078 testTokenize("'c'", []Token.Id {Token.Id.CharLiteral});
1079}
1080
9711081test "tokenizer - invalid token characters" {
9721082 testTokenize("#", []Token.Id{Token.Id.Invalid});
9731083 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});
9741087}
9751088
9761089test "tokenizer - invalid literal/comment characters" {
......@@ -1022,7 +1135,7 @@ test "tokenizer - string identifier and builtin fns" {
10221135 ,
10231136 []Token.Id{
10241137 Token.Id.Keyword_const,
1025 Token.Id.StringIdentifier,
1138 Token.Id.Identifier,
10261139 Token.Id.Equal,
10271140 Token.Id.Builtin,
10281141 Token.Id.LParen,