| ... | ... | @@ -105,6 +105,10 @@ const Parser = struct { |
| 105 | 105 | return null; |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | fn declareSymbol(parser: *Parser, decl_spec: *Node.DeclSpec, dr: *Node.Declarator) Error!void { |
| 109 | return; // TODO |
| 110 | } |
| 111 | |
| 108 | 112 | /// Root <- ExternalDeclaration* eof |
| 109 | 113 | fn root(parser: *Parser) Allocator.Error!*Node.Root { |
| 110 | 114 | const node = try parser.arena.create(Node.Root); |
| ... | ... | @@ -140,77 +144,127 @@ const Parser = struct { |
| 140 | 144 | |
| 141 | 145 | fn declarationExtra(parser: *Parser, local: bool) !?*Node { |
| 142 | 146 | if (try parser.staticAssert()) |decl| return decl; |
| 147 | const begin = parser.it.index + 1; |
| 143 | 148 | var ds = Node.DeclSpec{}; |
| 144 | 149 | const got_ds = try parser.declSpec(&ds); |
| 145 | 150 | if (local and !got_ds) { |
| 146 | 151 | // not a declaration |
| 147 | 152 | return null; |
| 148 | 153 | } |
| 149 | | var dr = try parser.declarator(); |
| 150 | | // TODO disallow auto and register |
| 151 | | const next_tok = parser.it.peek().?; |
| 152 | | if (next_tok.id == .Eof and !got_ds and dr == null) { |
| 153 | | return null; |
| 154 | | } |
| 155 | | switch (next_tok.id) { |
| 156 | | .Semicolon, |
| 157 | | .Equal, |
| 158 | | .Comma, |
| 159 | | .Eof, |
| 160 | | => { |
| 161 | | while (dr != null) { |
| 162 | | if (parser.eatToken(.Equal)) |tok| { |
| 163 | | // TODO typedef |
| 164 | | // dr.?.init = try parser.expect(initializer, .{ |
| 165 | | // .ExpectedInitializer = .{ .token = parser.it.index }, |
| 166 | | // }); |
| 167 | | } |
| 168 | | if (parser.eatToken(.Comma) != null) break; |
| 169 | | dr = (try parser.declarator()) orelse return parser.err(.{ |
| 154 | switch (ds.storage_class) { |
| 155 | .Auto, .Register => |tok| return parser.err(.{ |
| 156 | .InvalidStorageClass = .{ .token = tok }, |
| 157 | }), |
| 158 | .Typedef => { |
| 159 | const node = try parser.arena.create(Node.Typedef); |
| 160 | node.* = .{ |
| 161 | .decl_spec = ds, |
| 162 | .declarators = Node.Typedef.DeclaratorList.init(parser.arena), |
| 163 | .semicolon = undefined, |
| 164 | }; |
| 165 | while (true) { |
| 166 | const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ |
| 170 | 167 | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 171 | | }); |
| 172 | | // .push(dr); |
| 168 | })); |
| 169 | try parser.declareSymbol(&ds, dr); |
| 170 | try node.declarators.push(&dr.base); |
| 171 | if (parser.eatToken(.Comma)) |_| {} else break; |
| 173 | 172 | } |
| 174 | | const semicolon = try parser.expectToken(.Semicolon); |
| 175 | | |
| 176 | | // TODO VarDecl, TypeDecl, TypeDef |
| 177 | | return null; |
| 173 | return &node.base; |
| 178 | 174 | }, |
| 179 | | else => { |
| 180 | | if (dr == null) |
| 181 | | return parser.err(.{ |
| 182 | | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 183 | | }); |
| 184 | | var old_decls = Node.FnDef.OldDeclList.init(parser.arena); |
| 185 | | while (true) { |
| 186 | | var old_ds = Node.DeclSpec{}; |
| 187 | | if (!(try parser.declSpec(&old_ds))) { |
| 188 | | // not old decl |
| 189 | | break; |
| 190 | | } |
| 191 | | var old_dr = (try parser.declarator()); |
| 192 | | // if (old_dr == null) |
| 193 | | // try parser.err(.{ |
| 194 | | // .NoParamName = .{ .token = parser.it.index }, |
| 195 | | // }); |
| 196 | | // try old_decls.push(decl); |
| 197 | | } |
| 198 | | const body = (try parser.compoundStmt()) orelse return parser.err(.{ |
| 175 | else => {}, |
| 176 | } |
| 177 | var first_dr = try parser.declarator(.Must); |
| 178 | if (first_dr != null and declaratorIsFunction(first_dr.?)) { |
| 179 | const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?); |
| 180 | try parser.declareSymbol(&ds, dr); |
| 181 | var old_decls = Node.FnDecl.OldDeclList.init(parser.arena); |
| 182 | const body = if (parser.eatToken(.Semicolon)) |_| |
| 183 | null |
| 184 | else blk: { |
| 185 | // TODO first_dr.is_old |
| 186 | // while (true) { |
| 187 | // var old_ds = Node.DeclSpec{}; |
| 188 | // if (!(try parser.declSpec(&old_ds))) { |
| 189 | // // not old decl |
| 190 | // break; |
| 191 | // } |
| 192 | // var old_dr = (try parser.declarator(.Must)); |
| 193 | // // if (old_dr == null) |
| 194 | // // try parser.err(.{ |
| 195 | // // .NoParamName = .{ .token = parser.it.index }, |
| 196 | // // }); |
| 197 | // // try old_decls.push(decl); |
| 198 | // } |
| 199 | const body_node = (try parser.compoundStmt()) orelse return parser.err(.{ |
| 199 | 200 | .ExpectedFnBody = .{ .token = parser.it.index }, |
| 200 | 201 | }); |
| 202 | break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node); |
| 203 | }; |
| 201 | 204 | |
| 202 | | const node = try parser.arena.create(Node.FnDef); |
| 203 | | node.* = .{ |
| 204 | | .decl_spec = ds, |
| 205 | | .declarator = dr orelse return null, |
| 206 | | .old_decls = old_decls, |
| 207 | | .body = @fieldParentPtr(Node.CompoundStmt, "base", body), |
| 205 | const node = try parser.arena.create(Node.FnDecl); |
| 206 | node.* = .{ |
| 207 | .decl_spec = ds, |
| 208 | .declarator = dr, |
| 209 | .old_decls = old_decls, |
| 210 | .body = body, |
| 211 | }; |
| 212 | return &node.base; |
| 213 | } else { |
| 214 | switch (ds.fn_spec) { |
| 215 | .Inline, .Noreturn => |tok| return parser.err(.{ |
| 216 | .FnSpecOnNonFn = .{ .token = tok }, |
| 217 | }), |
| 218 | else => {}, |
| 219 | } |
| 220 | // TODO threadlocal without static or extern on local variable |
| 221 | const node = try parser.arena.create(Node.VarDecl); |
| 222 | node.* = .{ |
| 223 | .decl_spec = ds, |
| 224 | .initializers = Node.VarDecl.Initializers.init(parser.arena), |
| 225 | .semicolon = undefined, |
| 226 | }; |
| 227 | if (first_dr == null) { |
| 228 | node.semicolon = try parser.expectToken(.Semicolon); |
| 229 | const ok = switch (ds.type_spec.spec) { |
| 230 | .Enum => |e| e.name != null, |
| 231 | .Record => |r| r.name != null, |
| 232 | else => false, |
| 208 | 233 | }; |
| 234 | const q = ds.type_spec.qual; |
| 235 | if (!ok) |
| 236 | try parser.warn(.{ |
| 237 | .NothingDeclared = .{ .token = begin }, |
| 238 | }) |
| 239 | else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok| |
| 240 | try parser.warn(.{ |
| 241 | .QualifierIgnored = .{ .token = tok }, |
| 242 | }); |
| 209 | 243 | return &node.base; |
| 210 | | }, |
| 244 | } |
| 245 | var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?); |
| 246 | while (true) { |
| 247 | try parser.declareSymbol(&ds, dr); |
| 248 | if (parser.eatToken(.Equal)) |tok| { |
| 249 | try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{ |
| 250 | .ExpectedInitializer = .{ .token = parser.it.index }, |
| 251 | })); |
| 252 | } else |
| 253 | try node.initializers.push(&dr.base); |
| 254 | if (parser.eatToken(.Comma) != null) break; |
| 255 | dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ |
| 256 | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 257 | })); |
| 258 | } |
| 259 | node.semicolon = try parser.expectToken(.Semicolon); |
| 260 | return &node.base; |
| 211 | 261 | } |
| 212 | 262 | } |
| 213 | 263 | |
| 264 | fn declaratorIsFunction(dr: *Node) bool { |
| 265 | return false; // TODO |
| 266 | } |
| 267 | |
| 214 | 268 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 215 | 269 | fn staticAssert(parser: *Parser) !?*Node { |
| 216 | 270 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; |
| ... | ... | @@ -733,7 +787,7 @@ const Parser = struct { |
| 733 | 787 | fn recordDeclarator(parser: *Parser) !*Node {} |
| 734 | 788 | |
| 735 | 789 | /// Pointer <- ASTERISK TypeQual* Pointer? |
| 736 | | fn pointer(parser: *Parser) Error!?*Node { |
| 790 | fn pointer(parser: *Parser) Error!?*Node.Pointer { |
| 737 | 791 | const asterisk = parser.eatToken(.Asterisk) orelse return null; |
| 738 | 792 | const node = try parser.arena.create(Node.Pointer); |
| 739 | 793 | node.* = .{ |
| ... | ... | @@ -743,7 +797,7 @@ const Parser = struct { |
| 743 | 797 | }; |
| 744 | 798 | while (try parser.typeQual(&node.qual)) {} |
| 745 | 799 | node.pointer = try parser.pointer(); |
| 746 | | return &node.base; |
| 800 | return node; |
| 747 | 801 | } |
| 748 | 802 | |
| 749 | 803 | const Named = enum { |
| ... | ... | @@ -772,7 +826,7 @@ const Parser = struct { |
| 772 | 826 | node.* = .{ |
| 773 | 827 | .pointer = ptr, |
| 774 | 828 | .prefix = .{ |
| 775 | | .Comples = .{ |
| 829 | .Complex = .{ |
| 776 | 830 | .lparen = lparen, |
| 777 | 831 | .inner = inner, |
| 778 | 832 | .rparen = try parser.expectToken(.RParen), |
| ... | ... | @@ -785,7 +839,7 @@ const Parser = struct { |
| 785 | 839 | node = try parser.arena.create(Node.Declarator); |
| 786 | 840 | node.* = .{ |
| 787 | 841 | .pointer = ptr, |
| 788 | | .prefix = .{ .Simple = tok }, |
| 842 | .prefix = .{ .Identifer = tok }, |
| 789 | 843 | .suffix = .None, |
| 790 | 844 | }; |
| 791 | 845 | } else if (named == .Must) { |
| ... | ... | @@ -793,7 +847,9 @@ const Parser = struct { |
| 793 | 847 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier }, |
| 794 | 848 | }); |
| 795 | 849 | } else { |
| 796 | | return ptr; |
| 850 | if (ptr) |some| |
| 851 | return &some.base; |
| 852 | return null; |
| 797 | 853 | } |
| 798 | 854 | } else { |
| 799 | 855 | node = try parser.arena.create(Node.Declarator); |
| ... | ... | @@ -808,16 +864,16 @@ const Parser = struct { |
| 808 | 864 | node.suffix = .{ |
| 809 | 865 | .Fn = .{ |
| 810 | 866 | .lparen = lparen, |
| 811 | | .params = .Node.Declarator.Params.init(parser.arena), |
| 867 | .params = Node.Declarator.Params.init(parser.arena), |
| 812 | 868 | .rparen = undefined, |
| 813 | 869 | }, |
| 814 | 870 | }; |
| 815 | | try parser.ParamDecl(node); |
| 871 | try parser.paramDecl(node); |
| 816 | 872 | node.suffix.Fn.rparen = try parser.expectToken(.RParen); |
| 817 | 873 | } else { |
| 818 | | while (parser.arrayDeclarator()) |arr| { |
| 874 | while (try parser.arrayDeclarator()) |arr| { |
| 819 | 875 | if (node.suffix == .None) |
| 820 | | node.suffix = .{ .Array = .Node.Declarator.Arrays.init(parser.arena) }; |
| 876 | node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) }; |
| 821 | 877 | try node.suffix.Array.push(arr); |
| 822 | 878 | } |
| 823 | 879 | } |
| ... | ... | @@ -825,7 +881,7 @@ const Parser = struct { |
| 825 | 881 | return parser.err(.{ |
| 826 | 882 | .InvalidDeclarator = .{ .token = tok }, |
| 827 | 883 | }); |
| 828 | | return node; |
| 884 | return &node.base; |
| 829 | 885 | } |
| 830 | 886 | |
| 831 | 887 | /// ArrayDeclarator |
| ... | ... | @@ -834,11 +890,11 @@ const Parser = struct { |
| 834 | 890 | /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr) |
| 835 | 891 | /// / TypeQual+ AssignmentExpr? |
| 836 | 892 | /// / AssignmentExpr |
| 837 | | fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array { |
| 893 | fn arrayDeclarator(parser: *Parser) !?*Node.Array { |
| 838 | 894 | const lbracket = parser.eatToken(.LBracket) orelse return null; |
| 839 | 895 | const arr = try parser.arena.create(Node.Array); |
| 840 | 896 | arr.* = .{ |
| 841 | | .lbracket = lbarcket, |
| 897 | .lbracket = lbracket, |
| 842 | 898 | .inner = .Inferred, |
| 843 | 899 | .rbracket = undefined, |
| 844 | 900 | }; |
| ... | ... | @@ -856,12 +912,12 @@ const Parser = struct { |
| 856 | 912 | fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void { |
| 857 | 913 | var old_style = false; |
| 858 | 914 | while (true) { |
| 859 | | var ds = Node.DeclSpec; |
| 915 | var ds = Node.DeclSpec{}; |
| 860 | 916 | if (try parser.declSpec(&ds)) { |
| 861 | 917 | //TODO |
| 862 | | } else if (parser.eatToken(.Identifier)) { |
| 918 | } else if (parser.eatToken(.Identifier)) |tok| { |
| 863 | 919 | old_style = true; |
| 864 | | } else if (parser.eatToken(.Ellipsis)) { |
| 920 | } else if (parser.eatToken(.Ellipsis)) |tok| { |
| 865 | 921 | // TODO |
| 866 | 922 | } |
| 867 | 923 | } |