authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-12-12 22:41:21-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-12-17 11:16:55-07:00
logab44939941215a753ca51f7b2d84a90d52bfebcf
tree0764925c68e694a4ecbdbb9346bb3a5a9acf81d9
parent39e96d933ec3611017edccfdd443fece826a7207

roughly parsing infix operators


3 files changed, 274 insertions(+), 144 deletions(-)

src-self-hosted/ast.zig+63-35
...@@ -13,9 +13,9 @@ pub const Node = struct {...@@ -13,9 +13,9 @@ pub const Node = struct {
13 Identifier,13 Identifier,
14 FnProto,14 FnProto,
15 ParamDecl,15 ParamDecl,
16 AddrOfExpr,
17 Block,16 Block,
18 Return,17 InfixOp,
18 PrefixOp,
19 IntegerLiteral,19 IntegerLiteral,
20 FloatLiteral,20 FloatLiteral,
21 };21 };
...@@ -27,9 +27,9 @@ pub const Node = struct {...@@ -27,9 +27,9 @@ pub const Node = struct {
27 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index),27 Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index),
28 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),28 Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index),
29 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),29 Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index),
30 Id.AddrOfExpr => @fieldParentPtr(NodeAddrOfExpr, "base", base).iterate(index),
31 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),30 Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index),
32 Id.Return => @fieldParentPtr(NodeReturn, "base", base).iterate(index),31 Id.InfixOp => @fieldParentPtr(NodeInfixOp, "base", base).iterate(index),
32 Id.PrefixOp => @fieldParentPtr(NodePrefixOp, "base", base).iterate(index),
33 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),33 Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index),
34 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),34 Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index),
35 };35 };
...@@ -42,9 +42,9 @@ pub const Node = struct {...@@ -42,9 +42,9 @@ pub const Node = struct {
42 Id.Identifier => allocator.destroy(@fieldParentPtr(NodeIdentifier, "base", base)),42 Id.Identifier => allocator.destroy(@fieldParentPtr(NodeIdentifier, "base", base)),
43 Id.FnProto => allocator.destroy(@fieldParentPtr(NodeFnProto, "base", base)),43 Id.FnProto => allocator.destroy(@fieldParentPtr(NodeFnProto, "base", base)),
44 Id.ParamDecl => allocator.destroy(@fieldParentPtr(NodeParamDecl, "base", base)),44 Id.ParamDecl => allocator.destroy(@fieldParentPtr(NodeParamDecl, "base", base)),
45 Id.AddrOfExpr => allocator.destroy(@fieldParentPtr(NodeAddrOfExpr, "base", base)),
46 Id.Block => allocator.destroy(@fieldParentPtr(NodeBlock, "base", base)),45 Id.Block => allocator.destroy(@fieldParentPtr(NodeBlock, "base", base)),
47 Id.Return => allocator.destroy(@fieldParentPtr(NodeReturn, "base", base)),46 Id.InfixOp => allocator.destroy(@fieldParentPtr(NodeInfixOp, "base", base)),
47 Id.PrefixOp => allocator.destroy(@fieldParentPtr(NodePrefixOp, "base", base)),
48 Id.IntegerLiteral => allocator.destroy(@fieldParentPtr(NodeIntegerLiteral, "base", base)),48 Id.IntegerLiteral => allocator.destroy(@fieldParentPtr(NodeIntegerLiteral, "base", base)),
49 Id.FloatLiteral => allocator.destroy(@fieldParentPtr(NodeFloatLiteral, "base", base)),49 Id.FloatLiteral => allocator.destroy(@fieldParentPtr(NodeFloatLiteral, "base", base)),
50 };50 };
...@@ -170,56 +170,84 @@ pub const NodeParamDecl = struct {...@@ -170,56 +170,84 @@ pub const NodeParamDecl = struct {
170 }170 }
171};171};
172172
173pub const NodeAddrOfExpr = struct {173pub const NodeBlock = struct {
174 base: Node,174 base: Node,
175 op_token: Token,175 begin_token: Token,
176 align_expr: ?&Node,176 end_token: Token,
177 bit_offset_start_token: ?Token,177 statements: ArrayList(&Node),
178 bit_offset_end_token: ?Token,
179 const_token: ?Token,
180 volatile_token: ?Token,
181 op_expr: &Node,
182
183 pub fn iterate(self: &NodeAddrOfExpr, index: usize) -> ?&Node {
184 var i = index;
185178
186 if (self.align_expr) |align_expr| {179 pub fn iterate(self: &NodeBlock, index: usize) -> ?&Node {
187 if (i < 1) return align_expr;180 var i = index;
188 i -= 1;
189 }
190181
191 if (i < 1) return self.op_expr;182 if (i < self.statements.len) return self.statements.items[i];
192 i -= 1;183 i -= self.statements.len;
193184
194 return null;185 return null;
195 }186 }
196};187};
197188
198pub const NodeBlock = struct {189pub const NodeInfixOp = struct {
199 base: Node,190 base: Node,
200 begin_token: Token,191 op_token: Token,
201 end_token: Token,192 lhs: &Node,
202 statements: ArrayList(&Node),193 op: InfixOp,
194 rhs: &Node,
203195
204 pub fn iterate(self: &NodeBlock, index: usize) -> ?&Node {196 const InfixOp = enum {
197 EqualEqual,
198 BangEqual,
199 };
200
201 pub fn iterate(self: &NodeInfixOp, index: usize) -> ?&Node {
205 var i = index;202 var i = index;
206203
207 if (i < self.statements.len) return self.statements.items[i];204 if (i < 1) return self.lhs;
208 i -= self.statements.len;205 i -= 1;
206
207 switch (self.op) {
208 InfixOp.EqualEqual => {},
209 InfixOp.BangEqual => {},
210 }
211
212 if (i < 1) return self.rhs;
213 i -= 1;
209214
210 return null;215 return null;
211 }216 }
212};217};
213218
214pub const NodeReturn = struct {219pub const NodePrefixOp = struct {
215 base: Node,220 base: Node,
216 return_token: Token,221 op_token: Token,
217 expr: &Node,222 op: PrefixOp,
223 rhs: &Node,
218224
219 pub fn iterate(self: &NodeReturn, index: usize) -> ?&Node {225 const PrefixOp = union(enum) {
226 Return,
227 AddrOf: AddrOfInfo,
228 };
229 const AddrOfInfo = struct {
230 align_expr: ?&Node,
231 bit_offset_start_token: ?Token,
232 bit_offset_end_token: ?Token,
233 const_token: ?Token,
234 volatile_token: ?Token,
235 };
236
237 pub fn iterate(self: &NodePrefixOp, index: usize) -> ?&Node {
220 var i = index;238 var i = index;
221239
222 if (i < 1) return self.expr;240 switch (self.op) {
241 PrefixOp.Return => {},
242 PrefixOp.AddrOf => |addr_of_info| {
243 if (addr_of_info.align_expr) |align_expr| {
244 if (i < 1) return align_expr;
245 i -= 1;
246 }
247 },
248 }
249
250 if (i < 1) return self.rhs;
223 i -= 1;251 i -= 1;
224252
225 return null;253 return null;
src-self-hosted/parser.zig+178-106
...@@ -68,7 +68,12 @@ pub const Parser = struct {...@@ -68,7 +68,12 @@ pub const Parser = struct {
68 TopLevelExtern: ?Token,68 TopLevelExtern: ?Token,
69 TopLevelDecl: TopLevelDeclCtx,69 TopLevelDecl: TopLevelDeclCtx,
70 Expression: DestPtr,70 Expression: DestPtr,
71 AddrOfModifiers: &ast.NodeAddrOfExpr,71 ExpectOperand,
72 Operand: &ast.Node,
73 AfterOperand,
74 InfixOp: &ast.NodeInfixOp,
75 PrefixOp: &ast.NodePrefixOp,
76 AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo,
72 TypeExpr: DestPtr,77 TypeExpr: DestPtr,
73 VarDecl: &ast.NodeVarDecl,78 VarDecl: &ast.NodeVarDecl,
74 VarDeclAlign: &ast.NodeVarDecl,79 VarDeclAlign: &ast.NodeVarDecl,
...@@ -265,63 +270,140 @@ pub const Parser = struct {...@@ -265,63 +270,140 @@ pub const Parser = struct {
265 _ = %return self.eatToken(token_id);270 _ = %return self.eatToken(token_id);
266 continue;271 continue;
267 },272 },
273
268 State.Expression => |dest_ptr| {274 State.Expression => |dest_ptr| {
275 // save the dest_ptr for later
276 stack.append(state) %% unreachable;
277 %return stack.append(State.ExpectOperand);
278 continue;
279 },
280 State.ExpectOperand => {
281 // we'll either get an operand (like 1 or x),
282 // or a prefix operator (like ~ or return).
269 const token = self.getNextToken();283 const token = self.getNextToken();
270 switch (token.id) {284 switch (token.id) {
271 Token.Id.Keyword_return => {285 Token.Id.Keyword_return => {
272 const return_node = %return self.createAttachReturn(dest_ptr, token);286 %return stack.append(State { .PrefixOp = %return self.createPrefixOp(token,
273 stack.append(State {.Expression = DestPtr {.Field = &return_node.expr} }) %% unreachable;287 ast.NodePrefixOp.PrefixOp.Return) });
288 %return stack.append(State.ExpectOperand);
289 continue;
290 },
291 Token.Id.Ampersand => {
292 const prefix_op = %return self.createPrefixOp(token, ast.NodePrefixOp.PrefixOp{
293 .AddrOf = ast.NodePrefixOp.AddrOfInfo {
294 .align_expr = null,
295 .bit_offset_start_token = null,
296 .bit_offset_end_token = null,
297 .const_token = null,
298 .volatile_token = null,
299 }
300 });
301 %return stack.append(State { .PrefixOp = prefix_op });
302 %return stack.append(State.ExpectOperand);
303 %return stack.append(State { .AddrOfModifiers = &prefix_op.op.AddrOf });
274 continue;304 continue;
275 },305 },
276 Token.Id.Identifier => {306 Token.Id.Identifier => {
277 _ = %return self.createAttachIdentifier(dest_ptr, token);307 %return stack.append(State {
308 .Operand = &(%return self.createIdentifier(token)).base
309 });
310 %return stack.append(State.AfterOperand);
278 continue;311 continue;
279 },312 },
280 Token.Id.IntegerLiteral => {313 Token.Id.IntegerLiteral => {
281 _ = %return self.createAttachIntegerLiteral(dest_ptr, token);314 %return stack.append(State {
315 .Operand = &(%return self.createIntegerLiteral(token)).base
316 });
317 %return stack.append(State.AfterOperand);
282 continue;318 continue;
283 },319 },
284 Token.Id.FloatLiteral => {320 Token.Id.FloatLiteral => {
285 _ = %return self.createAttachFloatLiteral(dest_ptr, token);321 %return stack.append(State {
322 .Operand = &(%return self.createFloatLiteral(token)).base
323 });
324 %return stack.append(State.AfterOperand);
286 continue;325 continue;
287 },326 },
288 Token.Id.Ampersand => {327 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
289 const addr_of_expr = %return self.createAttachAddrOfExpr(dest_ptr, token);328 }
290 stack.append(State { .AddrOfModifiers = addr_of_expr }) %% unreachable;329 },
330
331 State.AfterOperand => {
332 // we'll either get an infix operator (like != or ^),
333 // or a postfix operator (like () or {}),
334 // otherwise this expression is done (like on a ; or else).
335 var token = self.getNextToken();
336 switch (token.id) {
337 Token.Id.EqualEqual => {
338 %return stack.append(State {
339 .InfixOp = %return self.createInfixOp(token, ast.NodeInfixOp.InfixOp.EqualEqual)
340 });
341 %return stack.append(State.ExpectOperand);
342 continue;
343 },
344 Token.Id.BangEqual => {
345 %return stack.append(State {
346 .InfixOp = %return self.createInfixOp(token, ast.NodeInfixOp.InfixOp.BangEqual)
347 });
348 %return stack.append(State.ExpectOperand);
349 continue;
350 },
351 else => {
352 // no postfix/infix operator after this operand.
353 self.putBackToken(token);
354 // reduce the stack
355 var expression: &ast.Node = stack.pop().Operand;
356 while (true) {
357 switch (stack.pop()) {
358 State.Expression => |dest_ptr| {
359 // we're done
360 %return dest_ptr.store(expression);
361 break;
362 },
363 State.InfixOp => |infix_op| {
364 infix_op.rhs = expression;
365 infix_op.lhs = stack.pop().Operand;
366 expression = &infix_op.base;
367 continue;
368 },
369 State.PrefixOp => |prefix_op| {
370 prefix_op.rhs = expression;
371 expression = &prefix_op.base;
372 continue;
373 },
374 else => unreachable,
375 }
376 }
291 continue;377 continue;
292 },378 },
293 else => return self.parseError(token, "expected primary expression, found {}", @tagName(token.id)),
294 }379 }
295 },380 },
296381
297 State.AddrOfModifiers => |addr_of_expr| {382 State.AddrOfModifiers => |addr_of_info| {
298 var token = self.getNextToken();383 var token = self.getNextToken();
299 switch (token.id) {384 switch (token.id) {
300 Token.Id.Keyword_align => {385 Token.Id.Keyword_align => {
301 stack.append(State { .AddrOfModifiers = addr_of_expr }) %% unreachable;386 stack.append(state) %% unreachable;
302 if (addr_of_expr.align_expr != null) return self.parseError(token, "multiple align qualifiers");387 if (addr_of_info.align_expr != null) return self.parseError(token, "multiple align qualifiers");
303 _ = %return self.eatToken(Token.Id.LParen);388 _ = %return self.eatToken(Token.Id.LParen);
304 %return stack.append(State { .ExpectToken = Token.Id.RParen });389 %return stack.append(State { .ExpectToken = Token.Id.RParen });
305 %return stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_expr.align_expr} });390 %return stack.append(State { .Expression = DestPtr{.NullableField = &addr_of_info.align_expr} });
306 continue;391 continue;
307 },392 },
308 Token.Id.Keyword_const => {393 Token.Id.Keyword_const => {
309 if (addr_of_expr.const_token != null) return self.parseError(token, "duplicate qualifier: const");394 stack.append(state) %% unreachable;
310 addr_of_expr.const_token = token;395 if (addr_of_info.const_token != null) return self.parseError(token, "duplicate qualifier: const");
311 stack.append(State { .AddrOfModifiers = addr_of_expr }) %% unreachable;396 addr_of_info.const_token = token;
312 continue;397 continue;
313 },398 },
314 Token.Id.Keyword_volatile => {399 Token.Id.Keyword_volatile => {
315 if (addr_of_expr.volatile_token != null) return self.parseError(token, "duplicate qualifier: volatile");400 stack.append(state) %% unreachable;
316 addr_of_expr.volatile_token = token;401 if (addr_of_info.volatile_token != null) return self.parseError(token, "duplicate qualifier: volatile");
317 stack.append(State { .AddrOfModifiers = addr_of_expr }) %% unreachable;402 addr_of_info.volatile_token = token;
318 continue;403 continue;
319 },404 },
320 else => {405 else => {
321 self.putBackToken(token);406 self.putBackToken(token);
322 stack.append(State {
323 .Expression = DestPtr { .Field = &addr_of_expr.op_expr},
324 }) %% unreachable;
325 continue;407 continue;
326 },408 },
327 }409 }
...@@ -482,8 +564,14 @@ pub const Parser = struct {...@@ -482,8 +564,14 @@ pub const Parser = struct {
482 %return stack.append(State { .Expression = DestPtr{.List = &block.statements} });564 %return stack.append(State { .Expression = DestPtr{.List = &block.statements} });
483 continue;565 continue;
484 },566 },
567
568 // These are data, not control flow.
569 State.InfixOp => unreachable,
570 State.PrefixOp => unreachable,
571 State.Operand => unreachable,
485 }572 }
486 unreachable;573 @import("std").debug.panic("{}", @tagName(state));
574 //unreachable;
487 }575 }
488 }576 }
489577
...@@ -560,23 +648,6 @@ pub const Parser = struct {...@@ -560,23 +648,6 @@ pub const Parser = struct {
560 return node;648 return node;
561 }649 }
562650
563 fn createAddrOfExpr(self: &Parser, op_token: &const Token) -> %&ast.NodeAddrOfExpr {
564 const node = %return self.allocator.create(ast.NodeAddrOfExpr);
565 %defer self.allocator.destroy(node);
566
567 *node = ast.NodeAddrOfExpr {
568 .base = ast.Node {.id = ast.Node.Id.AddrOfExpr},
569 .align_expr = null,
570 .op_token = *op_token,
571 .bit_offset_start_token = null,
572 .bit_offset_end_token = null,
573 .const_token = null,
574 .volatile_token = null,
575 .op_expr = undefined,
576 };
577 return node;
578 }
579
580 fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock {651 fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock {
581 const node = %return self.allocator.create(ast.NodeBlock);652 const node = %return self.allocator.create(ast.NodeBlock);
582 %defer self.allocator.destroy(node);653 %defer self.allocator.destroy(node);
...@@ -590,14 +661,29 @@ pub const Parser = struct {...@@ -590,14 +661,29 @@ pub const Parser = struct {
590 return node;661 return node;
591 }662 }
592663
593 fn createReturn(self: &Parser, return_token: &const Token) -> %&ast.NodeReturn {664 fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) -> %&ast.NodeInfixOp {
594 const node = %return self.allocator.create(ast.NodeReturn);665 const node = %return self.allocator.create(ast.NodeInfixOp);
666 %defer self.allocator.destroy(node);
667
668 *node = ast.NodeInfixOp {
669 .base = ast.Node {.id = ast.Node.Id.InfixOp},
670 .op_token = *op_token,
671 .lhs = undefined,
672 .op = *op,
673 .rhs = undefined,
674 };
675 return node;
676 }
677
678 fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) -> %&ast.NodePrefixOp {
679 const node = %return self.allocator.create(ast.NodePrefixOp);
595 %defer self.allocator.destroy(node);680 %defer self.allocator.destroy(node);
596681
597 *node = ast.NodeReturn {682 *node = ast.NodePrefixOp {
598 .base = ast.Node {.id = ast.Node.Id.Return},683 .base = ast.Node {.id = ast.Node.Id.PrefixOp},
599 .return_token = *return_token,684 .op_token = *op_token,
600 .expr = undefined,685 .op = *op,
686 .rhs = undefined,
601 };687 };
602 return node;688 return node;
603 }689 }
...@@ -635,20 +721,6 @@ pub const Parser = struct {...@@ -635,20 +721,6 @@ pub const Parser = struct {
635 return node;721 return node;
636 }722 }
637723
638 fn createAttachFloatLiteral(self: &Parser, dest_ptr: &const DestPtr, token: &const Token) -> %&ast.NodeFloatLiteral {
639 const node = %return self.createFloatLiteral(token);
640 %defer self.allocator.destroy(node);
641 %return dest_ptr.store(&node.base);
642 return node;
643 }
644
645 fn createAttachIntegerLiteral(self: &Parser, dest_ptr: &const DestPtr, token: &const Token) -> %&ast.NodeIntegerLiteral {
646 const node = %return self.createIntegerLiteral(token);
647 %defer self.allocator.destroy(node);
648 %return dest_ptr.store(&node.base);
649 return node;
650 }
651
652 fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier {724 fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier {
653 const node = %return self.createIdentifier(name_token);725 const node = %return self.createIdentifier(name_token);
654 %defer self.allocator.destroy(node);726 %defer self.allocator.destroy(node);
...@@ -656,20 +728,6 @@ pub const Parser = struct {...@@ -656,20 +728,6 @@ pub const Parser = struct {
656 return node;728 return node;
657 }729 }
658730
659 fn createAttachReturn(self: &Parser, dest_ptr: &const DestPtr, return_token: &const Token) -> %&ast.NodeReturn {
660 const node = %return self.createReturn(return_token);
661 %defer self.allocator.destroy(node);
662 %return dest_ptr.store(&node.base);
663 return node;
664 }
665
666 fn createAttachAddrOfExpr(self: &Parser, dest_ptr: &const DestPtr, op_token: &const Token) -> %&ast.NodeAddrOfExpr {
667 const node = %return self.createAddrOfExpr(op_token);
668 %defer self.allocator.destroy(node);
669 %return dest_ptr.store(&node.base);
670 return node;
671 }
672
673 fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl {731 fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl {
674 const node = %return self.createParamDecl();732 const node = %return self.createParamDecl();
675 %defer self.allocator.destroy(node);733 %defer self.allocator.destroy(node);
...@@ -783,7 +841,6 @@ pub const Parser = struct {...@@ -783,7 +841,6 @@ pub const Parser = struct {
783 ParamDecl: &ast.Node,841 ParamDecl: &ast.Node,
784 Text: []const u8,842 Text: []const u8,
785 Expression: &ast.Node,843 Expression: &ast.Node,
786 AddrOfExprBit: &ast.NodeAddrOfExpr,
787 VarDecl: &ast.NodeVarDecl,844 VarDecl: &ast.NodeVarDecl,
788 Statement: &ast.Node,845 Statement: &ast.Node,
789 PrintIndent,846 PrintIndent,
...@@ -912,17 +969,6 @@ pub const Parser = struct {...@@ -912,17 +969,6 @@ pub const Parser = struct {
912 const identifier = @fieldParentPtr(ast.NodeIdentifier, "base", base);969 const identifier = @fieldParentPtr(ast.NodeIdentifier, "base", base);
913 %return stream.print("{}", self.tokenizer.getTokenSlice(identifier.name_token));970 %return stream.print("{}", self.tokenizer.getTokenSlice(identifier.name_token));
914 },971 },
915 ast.Node.Id.AddrOfExpr => {
916 const addr_of_expr = @fieldParentPtr(ast.NodeAddrOfExpr, "base", base);
917 %return stream.print("{}", self.tokenizer.getTokenSlice(addr_of_expr.op_token));
918 %return stack.append(RenderState { .AddrOfExprBit = addr_of_expr});
919
920 if (addr_of_expr.align_expr) |align_expr| {
921 %return stream.print("align(");
922 %return stack.append(RenderState { .Text = ") "});
923 %return stack.append(RenderState { .Expression = align_expr});
924 }
925 },
926 ast.Node.Id.Block => {972 ast.Node.Id.Block => {
927 const block = @fieldParentPtr(ast.NodeBlock, "base", base);973 const block = @fieldParentPtr(ast.NodeBlock, "base", base);
928 %return stream.write("{");974 %return stream.write("{");
...@@ -940,10 +986,43 @@ pub const Parser = struct {...@@ -940,10 +986,43 @@ pub const Parser = struct {
940 %return stack.append(RenderState { .Text = "\n" });986 %return stack.append(RenderState { .Text = "\n" });
941 }987 }
942 },988 },
943 ast.Node.Id.Return => {989 ast.Node.Id.InfixOp => {
944 const return_node = @fieldParentPtr(ast.NodeReturn, "base", base);990 const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base);
945 %return stream.write("return ");991 %return stack.append(RenderState { .Expression = prefix_op_node.rhs });
946 %return stack.append(RenderState { .Expression = return_node.expr });992 switch (prefix_op_node.op) {
993 ast.NodeInfixOp.InfixOp.EqualEqual => {
994 %return stack.append(RenderState { .Text = " == "});
995 },
996 ast.NodeInfixOp.InfixOp.BangEqual => {
997 %return stack.append(RenderState { .Text = " != "});
998 },
999 else => unreachable,
1000 }
1001 %return stack.append(RenderState { .Expression = prefix_op_node.lhs });
1002 },
1003 ast.Node.Id.PrefixOp => {
1004 const prefix_op_node = @fieldParentPtr(ast.NodePrefixOp, "base", base);
1005 %return stack.append(RenderState { .Expression = prefix_op_node.rhs });
1006 switch (prefix_op_node.op) {
1007 ast.NodePrefixOp.PrefixOp.Return => {
1008 %return stream.write("return ");
1009 },
1010 ast.NodePrefixOp.PrefixOp.AddrOf => |addr_of_info| {
1011 %return stream.write("&");
1012 if (addr_of_info.volatile_token != null) {
1013 %return stack.append(RenderState { .Text = "volatile "});
1014 }
1015 if (addr_of_info.const_token != null) {
1016 %return stack.append(RenderState { .Text = "const "});
1017 }
1018 if (addr_of_info.align_expr) |align_expr| {
1019 %return stream.print("align(");
1020 %return stack.append(RenderState { .Text = ") "});
1021 %return stack.append(RenderState { .Expression = align_expr});
1022 }
1023 },
1024 else => unreachable,
1025 }
947 },1026 },
948 ast.Node.Id.IntegerLiteral => {1027 ast.Node.Id.IntegerLiteral => {
949 const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);1028 const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base);
...@@ -955,21 +1034,6 @@ pub const Parser = struct {...@@ -955,21 +1034,6 @@ pub const Parser = struct {
955 },1034 },
956 else => unreachable,1035 else => unreachable,
957 },1036 },
958 RenderState.AddrOfExprBit => |addr_of_expr| {
959 if (addr_of_expr.bit_offset_start_token) |bit_offset_start_token| {
960 %return stream.print("{} ", self.tokenizer.getTokenSlice(bit_offset_start_token));
961 }
962 if (addr_of_expr.bit_offset_end_token) |bit_offset_end_token| {
963 %return stream.print("{} ", self.tokenizer.getTokenSlice(bit_offset_end_token));
964 }
965 if (addr_of_expr.const_token) |const_token| {
966 %return stream.print("{} ", self.tokenizer.getTokenSlice(const_token));
967 }
968 if (addr_of_expr.volatile_token) |volatile_token| {
969 %return stream.print("{} ", self.tokenizer.getTokenSlice(volatile_token));
970 }
971 %return stack.append(RenderState { .Expression = addr_of_expr.op_expr});
972 },
973 RenderState.FnProtoRParen => |fn_proto| {1037 RenderState.FnProtoRParen => |fn_proto| {
974 %return stream.print(")");1038 %return stream.print(")");
975 if (fn_proto.align_expr != null) {1039 if (fn_proto.align_expr != null) {
...@@ -1128,4 +1192,12 @@ test "zig fmt" {...@@ -1128,4 +1192,12 @@ test "zig fmt" {
1128 \\extern fn f3(s: &align(1) const volatile u8) -> c_int;1192 \\extern fn f3(s: &align(1) const volatile u8) -> c_int;
1129 \\1193 \\
1130 );1194 );
1195
1196 testCanonical(
1197 \\fn f1(a: bool, b: bool) -> bool {
1198 \\ a != b;
1199 \\ return a == b;
1200 \\}
1201 \\
1202 );
1131}1203}
src-self-hosted/tokenizer.zig+33-3
...@@ -71,7 +71,10 @@ pub const Token = struct {...@@ -71,7 +71,10 @@ pub const Token = struct {
71 StringLiteral: StrLitKind,71 StringLiteral: StrLitKind,
72 Eof,72 Eof,
73 Builtin,73 Builtin,
74 Bang,
74 Equal,75 Equal,
76 EqualEqual,
77 BangEqual,
75 LParen,78 LParen,
76 RParen,79 RParen,
77 Semicolon,80 Semicolon,
...@@ -187,6 +190,8 @@ pub const Tokenizer = struct {...@@ -187,6 +190,8 @@ pub const Tokenizer = struct {
187 C,190 C,
188 StringLiteral,191 StringLiteral,
189 StringLiteralBackslash,192 StringLiteralBackslash,
193 Equal,
194 Bang,
190 Minus,195 Minus,
191 Slash,196 Slash,
192 LineComment,197 LineComment,
...@@ -232,9 +237,10 @@ pub const Tokenizer = struct {...@@ -232,9 +237,10 @@ pub const Tokenizer = struct {
232 result.id = Token.Id.Builtin;237 result.id = Token.Id.Builtin;
233 },238 },
234 '=' => {239 '=' => {
235 result.id = Token.Id.Equal;240 state = State.Equal;
236 self.index += 1;241 },
237 break;242 '!' => {
243 state = State.Bang;
238 },244 },
239 '(' => {245 '(' => {
240 result.id = Token.Id.LParen;246 result.id = Token.Id.LParen;
...@@ -356,6 +362,30 @@ pub const Tokenizer = struct {...@@ -356,6 +362,30 @@ pub const Tokenizer = struct {
356 },362 },
357 },363 },
358364
365 State.Bang => switch (c) {
366 '=' => {
367 result.id = Token.Id.BangEqual;
368 self.index += 1;
369 break;
370 },
371 else => {
372 result.id = Token.Id.Bang;
373 break;
374 },
375 },
376
377 State.Equal => switch (c) {
378 '=' => {
379 result.id = Token.Id.EqualEqual;
380 self.index += 1;
381 break;
382 },
383 else => {
384 result.id = Token.Id.Equal;
385 break;
386 },
387 },
388
359 State.Minus => switch (c) {389 State.Minus => switch (c) {
360 '>' => {390 '>' => {
361 result.id = Token.Id.Arrow;391 result.id = Token.Id.Arrow;