@@ -68,7 +68,12 @@ pub const Parser = struct {
6868 TopLevelExtern : ? Token ,
6969 TopLevelDecl : TopLevelDeclCtx ,
7070 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 ,
7277 TypeExpr : DestPtr ,
7378 VarDecl : & ast.NodeVarDecl ,
7479 VarDeclAlign : & ast.NodeVarDecl ,
@@ -265,63 +270,140 @@ pub const Parser = struct {
265270 _ = % return self .eatToken (token_id );
266271 continue ;
267272 },
273+
268274 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).
269283 const token = self .getNextToken ();
270284 switch (token .id ) {
271285 Token .Id .Keyword_return = > {
272- const return_node = % return self .createAttachReturn (dest_ptr , token );
273- stack .append (State {.Expression = DestPtr {.Field = & return_node .expr } }) %% unreachable ;
286+ % return stack .append (State { .PrefixOp = % return self .createPrefixOp (token ,
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 });
274304 continue ;
275305 },
276306 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 );
278311 continue ;
279312 },
280313 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 );
282318 continue ;
283319 },
284320 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 );
286325 continue ;
287326 },
288- Token .Id .Ampersand = > {
289- const addr_of_expr = % return self .createAttachAddrOfExpr (dest_ptr , token );
290- stack .append (State { .AddrOfModifiers = addr_of_expr }) %% unreachable ;
327+ else = > return self .parseError (token , "expected primary expression, found {}" , @tagName (token .id )),
328+ }
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+ }
291377 continue ;
292378 },
293- else = > return self .parseError (token , "expected primary expression, found {}" , @tagName (token .id )),
294379 }
295380 },
296381
297- State .AddrOfModifiers = > | addr_of_expr | {
382+ State .AddrOfModifiers = > | addr_of_info | {
298383 var token = self .getNextToken ();
299384 switch (token .id ) {
300385 Token .Id .Keyword_align = > {
301- stack .append (State { . AddrOfModifiers = addr_of_expr } ) %% unreachable ;
302- if (addr_of_expr .align_expr != null ) return self .parseError (token , "multiple align qualifiers" );
386+ stack .append (state ) %% unreachable ;
387+ if (addr_of_info .align_expr != null ) return self .parseError (token , "multiple align qualifiers" );
303388 _ = % return self .eatToken (Token .Id .LParen );
304389 % 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 } });
306391 continue ;
307392 },
308393 Token .Id .Keyword_const = > {
309- if ( addr_of_expr . const_token != null ) return self . parseError ( token , "duplicate qualifier: const" ) ;
310- addr_of_expr .const_token = token ;
311- stack . append ( State { . AddrOfModifiers = addr_of_expr }) %% unreachable ;
394+ stack . append ( state ) %% unreachable ;
395+ if ( addr_of_info .const_token != null ) return self . parseError ( token , "duplicate qualifier: const" ) ;
396+ addr_of_info . const_token = token ;
312397 continue ;
313398 },
314399 Token .Id .Keyword_volatile = > {
315- if ( addr_of_expr . volatile_token != null ) return self . parseError ( token , "duplicate qualifier: volatile" ) ;
316- addr_of_expr .volatile_token = token ;
317- stack . append ( State { . AddrOfModifiers = addr_of_expr }) %% unreachable ;
400+ stack . append ( state ) %% unreachable ;
401+ if ( addr_of_info .volatile_token != null ) return self . parseError ( token , "duplicate qualifier: volatile" ) ;
402+ addr_of_info . volatile_token = token ;
318403 continue ;
319404 },
320405 else = > {
321406 self .putBackToken (token );
322- stack .append (State {
323- .Expression = DestPtr { .Field = & addr_of_expr .op_expr },
324- }) %% unreachable ;
325407 continue ;
326408 },
327409 }
@@ -482,8 +564,14 @@ pub const Parser = struct {
482564 % return stack .append (State { .Expression = DestPtr {.List = & block .statements } });
483565 continue ;
484566 },
567+
568+ // These are data, not control flow.
569+ State .InfixOp = > unreachable ,
570+ State .PrefixOp = > unreachable ,
571+ State .Operand = > unreachable ,
485572 }
486- unreachable ;
573+ @import ("std" ).debug .panic ("{}" , @tagName (state ));
574+ //unreachable;
487575 }
488576 }
489577
@@ -560,23 +648,6 @@ pub const Parser = struct {
560648 return node ;
561649 }
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-
580651 fn createBlock (self : & Parser , begin_token : & const Token ) - > % & ast.NodeBlock {
581652 const node = % return self .allocator .create (ast .NodeBlock );
582653 % defer self .allocator .destroy (node );
@@ -590,14 +661,29 @@ pub const Parser = struct {
590661 return node ;
591662 }
592663
593- fn createReturn (self : & Parser , return_token : & const Token ) - > % & ast.NodeReturn {
594- const node = % return self .allocator .create (ast .NodeReturn );
664+ fn createInfixOp (self : & Parser , op_token : & const Token , op : & const ast.NodeInfixOp.InfixOp ) - > % & ast.NodeInfixOp {
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 );
595680 % defer self .allocator .destroy (node );
596681
597- * node = ast.NodeReturn {
598- .base = ast.Node {.id = ast .Node .Id .Return },
599- .return_token = * return_token ,
600- .expr = undefined ,
682+ * node = ast.NodePrefixOp {
683+ .base = ast.Node {.id = ast .Node .Id .PrefixOp },
684+ .op_token = * op_token ,
685+ .op = * op ,
686+ .rhs = undefined ,
601687 };
602688 return node ;
603689 }
@@ -635,41 +721,13 @@ pub const Parser = struct {
635721 return node ;
636722 }
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-
652724 fn createAttachIdentifier (self : & Parser , dest_ptr : & const DestPtr , name_token : & const Token ) - > % & ast.NodeIdentifier {
653725 const node = % return self .createIdentifier (name_token );
654726 % defer self .allocator .destroy (node );
655727 % return dest_ptr .store (& node .base );
656728 return node ;
657729 }
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-
673731 fn createAttachParamDecl (self : & Parser , list : & ArrayList (& ast.Node )) - > % & ast.NodeParamDecl {
674732 const node = % return self .createParamDecl ();
675733 % defer self .allocator .destroy (node );
@@ -783,7 +841,6 @@ pub const Parser = struct {
783841 ParamDecl : & ast.Node ,
784842 Text : []const u8 ,
785843 Expression : & ast.Node ,
786- AddrOfExprBit : & ast.NodeAddrOfExpr ,
787844 VarDecl : & ast.NodeVarDecl ,
788845 Statement : & ast.Node ,
789846 PrintIndent ,
@@ -912,17 +969,6 @@ pub const Parser = struct {
912969 const identifier = @fieldParentPtr (ast .NodeIdentifier , "base" , base );
913970 % return stream .print ("{}" , self .tokenizer .getTokenSlice (identifier .name_token ));
914971 },
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- },
926972 ast .Node .Id .Block = > {
927973 const block = @fieldParentPtr (ast .NodeBlock , "base" , base );
928974 % return stream .write ("{" );
@@ -940,10 +986,43 @@ pub const Parser = struct {
940986 % return stack .append (RenderState { .Text = "\n " });
941987 }
942988 },
943- ast .Node .Id .Return = > {
944- const return_node = @fieldParentPtr (ast .NodeReturn , "base" , base );
945- % return stream .write ("return " );
946- % return stack .append (RenderState { .Expression = return_node .expr });
989+ ast .Node .Id .InfixOp = > {
990+ const prefix_op_node = @fieldParentPtr (ast .NodeInfixOp , "base" , base );
991+ % return stack .append (RenderState { .Expression = prefix_op_node .rhs });
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+ }
9471026 },
9481027 ast .Node .Id .IntegerLiteral = > {
9491028 const integer_literal = @fieldParentPtr (ast .NodeIntegerLiteral , "base" , base );
@@ -955,21 +1034,6 @@ pub const Parser = struct {
9551034 },
9561035 else = > unreachable ,
9571036 },
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- },
9731037 RenderState .FnProtoRParen = > | fn_proto | {
9741038 % return stream .print (")" );
9751039 if (fn_proto .align_expr != null ) {
@@ -1128,4 +1192,12 @@ test "zig fmt" {
11281192 \\extern fn f3(s: &align(1) const volatile u8) -> c_int;
11291193 \\
11301194 );
1195+
1196+ testCanonical (
1197+ \\fn f1(a: bool, b: bool) -> bool {
1198+ \\ a != b;
1199+ \\ return a == b;
1200+ \\}
1201+ \\
1202+ );
11311203}
0 commit comments