@@ -81,6 +81,7 @@ pub const Parser = struct {
8181 MultiplyExpression : DestPtr ,
8282 BraceSuffixExpression : DestPtr ,
8383 PrefixOpExpression : DestPtr ,
84+ AddrOfModifiers : & ast.NodeAddrOfExpr ,
8485 SuffixOpExpression : DestPtr ,
8586 PrimaryExpression : DestPtr ,
8687 TypeExpr : DestPtr ,
@@ -350,30 +351,51 @@ pub const Parser = struct {
350351
351352 State .PrefixOpExpression = > | dest_ptr | {
352353 const first_token = self .getNextToken ();
353- if (first_token .id == Token .Id .Ampersand ) {
354- const addr_of_expr = % return self .createAttachAddrOfExpr (dest_ptr , first_token );
355- var token = self .getNextToken ();
356- if (token .id == Token .Id .Keyword_align ) {
357- @panic ("TODO align" );
358- }
359- if (token .id == Token .Id .Keyword_const ) {
354+ switch (first_token .id ) {
355+ Token .Id .Ampersand = > {
356+ const addr_of_expr = % return self .createAttachAddrOfExpr (dest_ptr , first_token );
357+ stack .append (State { .AddrOfModifiers = addr_of_expr }) %% unreachable ;
358+ continue ;
359+ },
360+ else = > {
361+ self .putBackToken (first_token );
362+ stack .append (State { .SuffixOpExpression = dest_ptr }) %% unreachable ;
363+ continue ;
364+ },
365+ }
366+ },
367+
368+ State .AddrOfModifiers = > | addr_of_expr | {
369+ var token = self .getNextToken ();
370+ switch (token .id ) {
371+ Token .Id .Keyword_align = > {
372+ stack .append (State { .AddrOfModifiers = addr_of_expr }) %% unreachable ;
373+ if (addr_of_expr .align_expr != null ) return self .parseError (token , "multiple align qualifiers" );
374+ _ = % return self .eatToken (Token .Id .LParen );
375+ % return stack .append (State { .ExpectToken = Token .Id .RParen });
376+ % return stack .append (State { .Expression = DestPtr {.NullableField = & addr_of_expr .align_expr } });
377+ continue ;
378+ },
379+ Token .Id .Keyword_const = > {
380+ if (addr_of_expr .const_token != null ) return self .parseError (token , "duplicate qualifier: const" );
360381 addr_of_expr .const_token = token ;
361- token = self .getNextToken ();
362- }
363- if (token .id == Token .Id .Keyword_volatile ) {
382+ stack .append (State { .AddrOfModifiers = addr_of_expr }) %% unreachable ;
383+ continue ;
384+ },
385+ Token .Id .Keyword_volatile = > {
386+ if (addr_of_expr .volatile_token != null ) return self .parseError (token , "duplicate qualifier: volatile" );
364387 addr_of_expr .volatile_token = token ;
365- token = self .getNextToken ();
366- }
367- self .putBackToken (token );
368- stack .append (State {
369- .PrefixOpExpression = DestPtr { .Field = & addr_of_expr .op_expr },
370- }) %% unreachable ;
371- continue ;
388+ stack .append (State { .AddrOfModifiers = addr_of_expr }) %% unreachable ;
389+ continue ;
390+ },
391+ else = > {
392+ self .putBackToken (token );
393+ stack .append (State {
394+ .PrefixOpExpression = DestPtr { .Field = & addr_of_expr .op_expr },
395+ }) %% unreachable ;
396+ continue ;
397+ },
372398 }
373-
374- self .putBackToken (first_token );
375- stack .append (State { .SuffixOpExpression = dest_ptr }) %% unreachable ;
376- continue ;
377399 },
378400
379401 State .SuffixOpExpression = > | dest_ptr | {
@@ -997,7 +1019,7 @@ pub const Parser = struct {
9971019
9981020 if (addr_of_expr .align_expr ) | align_expr | {
9991021 % return stream .print ("align(" );
1000- % return stack .append (RenderState { .Text = ")" });
1022+ % return stack .append (RenderState { .Text = ") " });
10011023 % return stack .append (RenderState { .Expression = align_expr });
10021024 }
10031025 },
@@ -1189,4 +1211,16 @@ test "zig fmt" {
11891211 \\}
11901212 \\
11911213 );
1214+
1215+ testCanonical (
1216+ \\extern fn f1(s: &align(&u8) u8) -> c_int;
1217+ \\
1218+ );
1219+
1220+ testCanonical (
1221+ \\extern fn f1(s: &&align(1) &const &volatile u8) -> c_int;
1222+ \\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) -> c_int;
1223+ \\extern fn f3(s: &align(1) const volatile u8) -> c_int;
1224+ \\
1225+ );
11921226}
0 commit comments