| ... | @@ -105,6 +105,10 @@ const Parser = struct { | ... | @@ -105,6 +105,10 @@ const Parser = struct { |
| 105 | return null; | 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 | /// Root <- ExternalDeclaration* eof | 112 | /// Root <- ExternalDeclaration* eof |
| 109 | fn root(parser: *Parser) Allocator.Error!*Node.Root { | 113 | fn root(parser: *Parser) Allocator.Error!*Node.Root { |
| 110 | const node = try parser.arena.create(Node.Root); | 114 | const node = try parser.arena.create(Node.Root); |
| ... | @@ -140,77 +144,127 @@ const Parser = struct { | ... | @@ -140,77 +144,127 @@ const Parser = struct { |
| 140 | | 144 | |
| 141 | fn declarationExtra(parser: *Parser, local: bool) !?*Node { | 145 | fn declarationExtra(parser: *Parser, local: bool) !?*Node { |
| 142 | if (try parser.staticAssert()) |decl| return decl; | 146 | if (try parser.staticAssert()) |decl| return decl; |
| | 147 | const begin = parser.it.index + 1; |
| 143 | var ds = Node.DeclSpec{}; | 148 | var ds = Node.DeclSpec{}; |
| 144 | const got_ds = try parser.declSpec(&ds); | 149 | const got_ds = try parser.declSpec(&ds); |
| 145 | if (local and !got_ds) { | 150 | if (local and !got_ds) { |
| 146 | // not a declaration | 151 | // not a declaration |
| 147 | return null; | 152 | return null; |
| 148 | } | 153 | } |
| 149 | var dr = try parser.declarator(); | 154 | switch (ds.storage_class) { |
| 150 | // TODO disallow auto and register | 155 | .Auto, .Register => |tok| return parser.err(.{ |
| 151 | const next_tok = parser.it.peek().?; | 156 | .InvalidStorageClass = .{ .token = tok }, |
| 152 | if (next_tok.id == .Eof and !got_ds and dr == null) { | 157 | }), |
| 153 | return null; | 158 | .Typedef => { |
| 154 | } | 159 | const node = try parser.arena.create(Node.Typedef); |
| 155 | switch (next_tok.id) { | 160 | node.* = .{ |
| 156 | .Semicolon, | 161 | .decl_spec = ds, |
| 157 | .Equal, | 162 | .declarators = Node.Typedef.DeclaratorList.init(parser.arena), |
| 158 | .Comma, | 163 | .semicolon = undefined, |
| 159 | .Eof, | 164 | }; |
| 160 | => { | 165 | while (true) { |
| 161 | while (dr != null) { | 166 | const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ |
| 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(.{ | | |
| 170 | .ExpectedDeclarator = .{ .token = parser.it.index }, | 167 | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 171 | }); | 168 | })); |
| 172 | // .push(dr); | 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); | 173 | return &node.base; |
| 175 | | | |
| 176 | // TODO VarDecl, TypeDecl, TypeDef | | |
| 177 | return null; | | |
| 178 | }, | 174 | }, |
| 179 | else => { | 175 | else => {}, |
| 180 | if (dr == null) | 176 | } |
| 181 | return parser.err(.{ | 177 | var first_dr = try parser.declarator(.Must); |
| 182 | .ExpectedDeclarator = .{ .token = parser.it.index }, | 178 | if (first_dr != null and declaratorIsFunction(first_dr.?)) { |
| 183 | }); | 179 | const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?); |
| 184 | var old_decls = Node.FnDef.OldDeclList.init(parser.arena); | 180 | try parser.declareSymbol(&ds, dr); |
| 185 | while (true) { | 181 | var old_decls = Node.FnDecl.OldDeclList.init(parser.arena); |
| 186 | var old_ds = Node.DeclSpec{}; | 182 | const body = if (parser.eatToken(.Semicolon)) |_| |
| 187 | if (!(try parser.declSpec(&old_ds))) { | 183 | null |
| 188 | // not old decl | 184 | else blk: { |
| 189 | break; | 185 | // TODO first_dr.is_old |
| 190 | } | 186 | // while (true) { |
| 191 | var old_dr = (try parser.declarator()); | 187 | // var old_ds = Node.DeclSpec{}; |
| 192 | // if (old_dr == null) | 188 | // if (!(try parser.declSpec(&old_ds))) { |
| 193 | // try parser.err(.{ | 189 | // // not old decl |
| 194 | // .NoParamName = .{ .token = parser.it.index }, | 190 | // break; |
| 195 | // }); | 191 | // } |
| 196 | // try old_decls.push(decl); | 192 | // var old_dr = (try parser.declarator(.Must)); |
| 197 | } | 193 | // // if (old_dr == null) |
| 198 | const body = (try parser.compoundStmt()) orelse return parser.err(.{ | 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 | .ExpectedFnBody = .{ .token = parser.it.index }, | 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); | 205 | const node = try parser.arena.create(Node.FnDecl); |
| 203 | node.* = .{ | 206 | node.* = .{ |
| 204 | .decl_spec = ds, | 207 | .decl_spec = ds, |
| 205 | .declarator = dr orelse return null, | 208 | .declarator = dr, |
| 206 | .old_decls = old_decls, | 209 | .old_decls = old_decls, |
| 207 | .body = @fieldParentPtr(Node.CompoundStmt, "base", body), | 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 | return &node.base; | 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 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON | 268 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 215 | fn staticAssert(parser: *Parser) !?*Node { | 269 | fn staticAssert(parser: *Parser) !?*Node { |
| 216 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; | 270 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; |
| ... | @@ -733,7 +787,7 @@ const Parser = struct { | ... | @@ -733,7 +787,7 @@ const Parser = struct { |
| 733 | fn recordDeclarator(parser: *Parser) !*Node {} | 787 | fn recordDeclarator(parser: *Parser) !*Node {} |
| 734 | | 788 | |
| 735 | /// Pointer <- ASTERISK TypeQual* Pointer? | 789 | /// Pointer <- ASTERISK TypeQual* Pointer? |
| 736 | fn pointer(parser: *Parser) Error!?*Node { | 790 | fn pointer(parser: *Parser) Error!?*Node.Pointer { |
| 737 | const asterisk = parser.eatToken(.Asterisk) orelse return null; | 791 | const asterisk = parser.eatToken(.Asterisk) orelse return null; |
| 738 | const node = try parser.arena.create(Node.Pointer); | 792 | const node = try parser.arena.create(Node.Pointer); |
| 739 | node.* = .{ | 793 | node.* = .{ |
| ... | @@ -743,7 +797,7 @@ const Parser = struct { | ... | @@ -743,7 +797,7 @@ const Parser = struct { |
| 743 | }; | 797 | }; |
| 744 | while (try parser.typeQual(&node.qual)) {} | 798 | while (try parser.typeQual(&node.qual)) {} |
| 745 | node.pointer = try parser.pointer(); | 799 | node.pointer = try parser.pointer(); |
| 746 | return &node.base; | 800 | return node; |
| 747 | } | 801 | } |
| 748 | | 802 | |
| 749 | const Named = enum { | 803 | const Named = enum { |
| ... | @@ -772,7 +826,7 @@ const Parser = struct { | ... | @@ -772,7 +826,7 @@ const Parser = struct { |
| 772 | node.* = .{ | 826 | node.* = .{ |
| 773 | .pointer = ptr, | 827 | .pointer = ptr, |
| 774 | .prefix = .{ | 828 | .prefix = .{ |
| 775 | .Comples = .{ | 829 | .Complex = .{ |
| 776 | .lparen = lparen, | 830 | .lparen = lparen, |
| 777 | .inner = inner, | 831 | .inner = inner, |
| 778 | .rparen = try parser.expectToken(.RParen), | 832 | .rparen = try parser.expectToken(.RParen), |
| ... | @@ -785,7 +839,7 @@ const Parser = struct { | ... | @@ -785,7 +839,7 @@ const Parser = struct { |
| 785 | node = try parser.arena.create(Node.Declarator); | 839 | node = try parser.arena.create(Node.Declarator); |
| 786 | node.* = .{ | 840 | node.* = .{ |
| 787 | .pointer = ptr, | 841 | .pointer = ptr, |
| 788 | .prefix = .{ .Simple = tok }, | 842 | .prefix = .{ .Identifer = tok }, |
| 789 | .suffix = .None, | 843 | .suffix = .None, |
| 790 | }; | 844 | }; |
| 791 | } else if (named == .Must) { | 845 | } else if (named == .Must) { |
| ... | @@ -793,7 +847,9 @@ const Parser = struct { | ... | @@ -793,7 +847,9 @@ const Parser = struct { |
| 793 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier }, | 847 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier }, |
| 794 | }); | 848 | }); |
| 795 | } else { | 849 | } else { |
| 796 | return ptr; | 850 | if (ptr) |some| |
| | 851 | return &some.base; |
| | 852 | return null; |
| 797 | } | 853 | } |
| 798 | } else { | 854 | } else { |
| 799 | node = try parser.arena.create(Node.Declarator); | 855 | node = try parser.arena.create(Node.Declarator); |
| ... | @@ -808,16 +864,16 @@ const Parser = struct { | ... | @@ -808,16 +864,16 @@ const Parser = struct { |
| 808 | node.suffix = .{ | 864 | node.suffix = .{ |
| 809 | .Fn = .{ | 865 | .Fn = .{ |
| 810 | .lparen = lparen, | 866 | .lparen = lparen, |
| 811 | .params = .Node.Declarator.Params.init(parser.arena), | 867 | .params = Node.Declarator.Params.init(parser.arena), |
| 812 | .rparen = undefined, | 868 | .rparen = undefined, |
| 813 | }, | 869 | }, |
| 814 | }; | 870 | }; |
| 815 | try parser.ParamDecl(node); | 871 | try parser.paramDecl(node); |
| 816 | node.suffix.Fn.rparen = try parser.expectToken(.RParen); | 872 | node.suffix.Fn.rparen = try parser.expectToken(.RParen); |
| 817 | } else { | 873 | } else { |
| 818 | while (parser.arrayDeclarator()) |arr| { | 874 | while (try parser.arrayDeclarator()) |arr| { |
| 819 | if (node.suffix == .None) | 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 | try node.suffix.Array.push(arr); | 877 | try node.suffix.Array.push(arr); |
| 822 | } | 878 | } |
| 823 | } | 879 | } |
| ... | @@ -825,7 +881,7 @@ const Parser = struct { | ... | @@ -825,7 +881,7 @@ const Parser = struct { |
| 825 | return parser.err(.{ | 881 | return parser.err(.{ |
| 826 | .InvalidDeclarator = .{ .token = tok }, | 882 | .InvalidDeclarator = .{ .token = tok }, |
| 827 | }); | 883 | }); |
| 828 | return node; | 884 | return &node.base; |
| 829 | } | 885 | } |
| 830 | | 886 | |
| 831 | /// ArrayDeclarator | 887 | /// ArrayDeclarator |
| ... | @@ -834,11 +890,11 @@ const Parser = struct { | ... | @@ -834,11 +890,11 @@ const Parser = struct { |
| 834 | /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr) | 890 | /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr) |
| 835 | /// / TypeQual+ AssignmentExpr? | 891 | /// / TypeQual+ AssignmentExpr? |
| 836 | /// / AssignmentExpr | 892 | /// / AssignmentExpr |
| 837 | fn arrayDeclarator(parser: *Parser, dr: *Node.Declarator) !?*Node.Array { | 893 | fn arrayDeclarator(parser: *Parser) !?*Node.Array { |
| 838 | const lbracket = parser.eatToken(.LBracket) orelse return null; | 894 | const lbracket = parser.eatToken(.LBracket) orelse return null; |
| 839 | const arr = try parser.arena.create(Node.Array); | 895 | const arr = try parser.arena.create(Node.Array); |
| 840 | arr.* = .{ | 896 | arr.* = .{ |
| 841 | .lbracket = lbarcket, | 897 | .lbracket = lbracket, |
| 842 | .inner = .Inferred, | 898 | .inner = .Inferred, |
| 843 | .rbracket = undefined, | 899 | .rbracket = undefined, |
| 844 | }; | 900 | }; |
| ... | @@ -856,12 +912,12 @@ const Parser = struct { | ... | @@ -856,12 +912,12 @@ const Parser = struct { |
| 856 | fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void { | 912 | fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void { |
| 857 | var old_style = false; | 913 | var old_style = false; |
| 858 | while (true) { | 914 | while (true) { |
| 859 | var ds = Node.DeclSpec; | 915 | var ds = Node.DeclSpec{}; |
| 860 | if (try parser.declSpec(&ds)) { | 916 | if (try parser.declSpec(&ds)) { |
| 861 | //TODO | 917 | //TODO |
| 862 | } else if (parser.eatToken(.Identifier)) { | 918 | } else if (parser.eatToken(.Identifier)) |tok| { |
| 863 | old_style = true; | 919 | old_style = true; |
| 864 | } else if (parser.eatToken(.Ellipsis)) { | 920 | } else if (parser.eatToken(.Ellipsis)) |tok| { |
| 865 | // TODO | 921 | // TODO |
| 866 | } | 922 | } |
| 867 | } | 923 | } |