| ... | ... | @@ -481,6 +481,7 @@ const NoAlias = enum { No, Yes }; |
| 481 | 481 | const Extern = enum { No, Yes }; |
| 482 | 482 | const VarArgs = enum { No, Yes }; |
| 483 | 483 | const Mutability = enum { Const, Var }; |
| 484 | const Volatile = enum { No, Yes }; |
| 484 | 485 | |
| 485 | 486 | const Inline = enum { |
| 486 | 487 | Auto, |
| ... | ... | @@ -511,6 +512,7 @@ const AstNode = struct { |
| 511 | 512 | Identifier, |
| 512 | 513 | FnProto, |
| 513 | 514 | ParamDecl, |
| 515 | AddrOfExpr, |
| 514 | 516 | }; |
| 515 | 517 | |
| 516 | 518 | fn iterate(base: &AstNode, index: usize) -> ?&AstNode { |
| ... | ... | @@ -520,6 +522,7 @@ const AstNode = struct { |
| 520 | 522 | Id.Identifier => @fieldParentPtr(AstNodeIdentifier, "base", base).iterate(index), |
| 521 | 523 | Id.FnProto => @fieldParentPtr(AstNodeFnProto, "base", base).iterate(index), |
| 522 | 524 | Id.ParamDecl => @fieldParentPtr(AstNodeParamDecl, "base", base).iterate(index), |
| 525 | Id.AddrOfExpr => @fieldParentPtr(AstNodeAddrOfExpr, "base", base).iterate(index), |
| 523 | 526 | }; |
| 524 | 527 | } |
| 525 | 528 | }; |
| ... | ... | @@ -643,6 +646,31 @@ const AstNodeParamDecl = struct { |
| 643 | 646 | } |
| 644 | 647 | }; |
| 645 | 648 | |
| 649 | const AstNodeAddrOfExpr = struct { |
| 650 | base: AstNode, |
| 651 | align_expr: ?&AstNode, |
| 652 | op_token: Token, |
| 653 | bit_offset_start_token: ?Token, |
| 654 | bit_offset_end_token: ?Token, |
| 655 | const_token: ?Token, |
| 656 | volatile_token: ?Token, |
| 657 | op_expr: &AstNode, |
| 658 | |
| 659 | fn iterate(self: &AstNodeAddrOfExpr, index: usize) -> ?&AstNode { |
| 660 | var i = index; |
| 661 | |
| 662 | if (self.align_expr) |align_expr| { |
| 663 | if (i < 1) return align_expr; |
| 664 | i -= 1; |
| 665 | } |
| 666 | |
| 667 | if (i < 1) return self.op_expr; |
| 668 | i -= 1; |
| 669 | |
| 670 | return null; |
| 671 | } |
| 672 | }; |
| 673 | |
| 646 | 674 | error ParseError; |
| 647 | 675 | |
| 648 | 676 | const Parser = struct { |
| ... | ... | @@ -796,6 +824,7 @@ const Parser = struct { |
| 796 | 824 | }, |
| 797 | 825 | Token.Id.Keyword_fn => { |
| 798 | 826 | stack.append(State.TopLevel) %% unreachable; |
| 827 | %return stack.append(State { .ExpectToken = Token.Id.Semicolon }); |
| 799 | 828 | const fn_proto_node = %return self.createAttachFnProto(&root_node.decls, token, |
| 800 | 829 | Extern.Yes, CallingConvention.Auto, visib, Inline.Auto); |
| 801 | 830 | %return stack.append(State { .FnProto = fn_proto_node }); |
| ... | ... | @@ -806,6 +835,7 @@ const Parser = struct { |
| 806 | 835 | }, |
| 807 | 836 | Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { |
| 808 | 837 | stack.append(State.TopLevel) %% unreachable; |
| 838 | %return stack.append(State { .ExpectToken = Token.Id.Semicolon }); |
| 809 | 839 | const cc = switch (token.id) { |
| 810 | 840 | Token.Id.Keyword_coldcc => CallingConvention.Cold, |
| 811 | 841 | Token.Id.Keyword_nakedcc => CallingConvention.Naked, |
| ... | ... | @@ -904,7 +934,7 @@ const Parser = struct { |
| 904 | 934 | }, |
| 905 | 935 | |
| 906 | 936 | State.AdditionExpression => |result_ptr| { |
| 907 | | stack.append(State {.AdditionExpression = result_ptr}) %% unreachable; |
| 937 | stack.append(State {.MultiplyExpression = result_ptr}) %% unreachable; |
| 908 | 938 | continue; |
| 909 | 939 | }, |
| 910 | 940 | |
| ... | ... | @@ -919,6 +949,27 @@ const Parser = struct { |
| 919 | 949 | }, |
| 920 | 950 | |
| 921 | 951 | State.PrefixOpExpression => |result_ptr| { |
| 952 | const first_token = self.getNextToken(); |
| 953 | if (first_token.id == Token.Id.Ampersand) { |
| 954 | const addr_of_expr = %return self.createAttachAddrOfExpr(result_ptr, first_token); |
| 955 | var token = self.getNextToken(); |
| 956 | if (token.id == Token.Id.Keyword_align) { |
| 957 | @panic("TODO align"); |
| 958 | } |
| 959 | if (token.id == Token.Id.Keyword_const) { |
| 960 | addr_of_expr.const_token = token; |
| 961 | token = self.getNextToken(); |
| 962 | } |
| 963 | if (token.id == Token.Id.Keyword_volatile) { |
| 964 | addr_of_expr.volatile_token = token; |
| 965 | token = self.getNextToken(); |
| 966 | } |
| 967 | self.putBackToken(token); |
| 968 | stack.append(State { .PrefixOpExpression = &addr_of_expr.op_expr }) %% unreachable; |
| 969 | continue; |
| 970 | } |
| 971 | |
| 972 | self.putBackToken(first_token); |
| 922 | 973 | stack.append(State { .SuffixOpExpression = result_ptr }) %% unreachable; |
| 923 | 974 | continue; |
| 924 | 975 | }, |
| ... | ... | @@ -966,8 +1017,17 @@ const Parser = struct { |
| 966 | 1017 | }, |
| 967 | 1018 | |
| 968 | 1019 | State.FnProtoAlign => |fn_proto| { |
| 969 | | @panic("TODO fn proto align"); |
| 970 | | //continue; |
| 1020 | const token = self.getNextToken(); |
| 1021 | if (token.id == Token.Id.Keyword_align) { |
| 1022 | @panic("TODO fn proto align"); |
| 1023 | } |
| 1024 | if (token.id == Token.Id.Arrow) { |
| 1025 | stack.append(State { .TypeExpr = removeNullCast(&fn_proto.return_type) }) %% unreachable; |
| 1026 | continue; |
| 1027 | } else { |
| 1028 | self.putBackToken(token); |
| 1029 | continue; |
| 1030 | } |
| 971 | 1031 | }, |
| 972 | 1032 | |
| 973 | 1033 | State.ParamDecl => |fn_proto| { |
| ... | ... | @@ -1107,6 +1167,30 @@ const Parser = struct { |
| 1107 | 1167 | return node; |
| 1108 | 1168 | } |
| 1109 | 1169 | |
| 1170 | fn createAddrOfExpr(self: &Parser, op_token: &const Token) -> %&AstNodeAddrOfExpr { |
| 1171 | const node = %return self.allocator.create(AstNodeAddrOfExpr); |
| 1172 | %defer self.allocator.destroy(node); |
| 1173 | |
| 1174 | *node = AstNodeAddrOfExpr { |
| 1175 | .base = AstNode {.id = AstNode.Id.AddrOfExpr}, |
| 1176 | .align_expr = null, |
| 1177 | .op_token = *op_token, |
| 1178 | .bit_offset_start_token = null, |
| 1179 | .bit_offset_end_token = null, |
| 1180 | .const_token = null, |
| 1181 | .volatile_token = null, |
| 1182 | .op_expr = undefined, |
| 1183 | }; |
| 1184 | return node; |
| 1185 | } |
| 1186 | |
| 1187 | fn createAttachAddrOfExpr(self: &Parser, result_ptr: &&AstNode, op_token: &const Token) -> %&AstNodeAddrOfExpr { |
| 1188 | const node = %return self.createAddrOfExpr(op_token); |
| 1189 | %defer self.allocator.destroy(node); |
| 1190 | *result_ptr = &node.base; |
| 1191 | return node; |
| 1192 | } |
| 1193 | |
| 1110 | 1194 | fn createAttachParamDecl(self: &Parser, list: &ArrayList(&AstNode)) -> %&AstNodeParamDecl { |
| 1111 | 1195 | const node = %return self.createParamDecl(); |
| 1112 | 1196 | %defer self.allocator.destroy(node); |