| ... | ... | @@ -70,11 +70,21 @@ const Parser = struct { |
| 70 | 70 | arena: *Allocator, |
| 71 | 71 | it: *TokenIterator, |
| 72 | 72 | tree: *Tree, |
| 73 | | typedefs: std.StringHashMap(void), |
| 74 | 73 | |
| 75 | | fn isTypedef(parser: *Parser, tok: TokenIndex) bool { |
| 76 | | const token = parser.it.list.at(tok); |
| 77 | | return parser.typedefs.contains(token.slice()); |
| 74 | /// only used for scopes |
| 75 | arena_allocator: std.heap.ArenaAllocator, |
| 76 | // scopes: std.SegmentedLists(Scope), |
| 77 | warnings: bool = true, |
| 78 | |
| 79 | // const Scope = struct { |
| 80 | // types: |
| 81 | // syms: |
| 82 | // }; |
| 83 | |
| 84 | fn getTypeDef(parser: *Parser, tok: TokenIndex) bool { |
| 85 | return false; // TODO |
| 86 | // const token = parser.it.list.at(tok); |
| 87 | // return parser.typedefs.contains(token.slice()); |
| 78 | 88 | } |
| 79 | 89 | |
| 80 | 90 | /// Root <- ExternalDeclaration* eof |
| ... | ... | @@ -84,7 +94,7 @@ const Parser = struct { |
| 84 | 94 | .decls = Node.Root.DeclList.init(parser.arena), |
| 85 | 95 | .eof = undefined, |
| 86 | 96 | }; |
| 87 | | while (parser.externalDeclarations() catch |err| switch (err) { |
| 97 | while (parser.externalDeclarations() catch |e| switch (e) { |
| 88 | 98 | error.OutOfMemory => return error.OutOfMemory, |
| 89 | 99 | error.ParseError => return node, |
| 90 | 100 | }) |decl| { |
| ... | ... | @@ -95,70 +105,99 @@ const Parser = struct { |
| 95 | 105 | } |
| 96 | 106 | |
| 97 | 107 | /// ExternalDeclaration |
| 98 | | /// <- DeclSpec Declarator Declaration* CompoundStmt |
| 108 | /// <- DeclSpec Declarator OldStyleDecl* CompoundStmt |
| 99 | 109 | /// / Declaration |
| 110 | /// OldStyleDecl <- DeclSpec Declarator (COMMA Declarator)* SEMICOLON |
| 100 | 111 | fn externalDeclarations(parser: *Parser) !?*Node { |
| 112 | return parser.declarationExtra(false); |
| 113 | } |
| 114 | |
| 115 | /// Declaration |
| 116 | /// <- DeclSpec DeclInit SEMICOLON |
| 117 | /// / StaticAssert |
| 118 | /// DeclInit <- Declarator (EQUAL Initializer)? (COMMA Declarator (EQUAL Initializer)?)* |
| 119 | fn declaration(parser: *Parser) !?*Node { |
| 120 | return parser.declarationExtra(true); |
| 121 | } |
| 122 | |
| 123 | fn declarationExtra(parser: *Parser, local: bool) !?*Node { |
| 101 | 124 | if (try parser.staticAssert()) |decl| return decl; |
| 102 | | const ds = try parser.declSpec(); |
| 103 | | const dr = (try parser.declarator()); |
| 104 | | if (dr == null) |
| 105 | | try parser.warning(.{ |
| 106 | | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 107 | | }); |
| 125 | var ds = Node.DeclSpec{}; |
| 126 | const got_ds = try parser.declSpec(&ds); |
| 127 | if (local and !got_ds) { |
| 128 | // not a declaration |
| 129 | return null; |
| 130 | } |
| 131 | var dr = try parser.declarator(); |
| 108 | 132 | // TODO disallow auto and register |
| 109 | 133 | const next_tok = parser.it.peek().?; |
| 134 | if (next_tok.id == .Eof and !got_ds and dr == null) { |
| 135 | return null; |
| 136 | } |
| 110 | 137 | switch (next_tok.id) { |
| 111 | 138 | .Semicolon, |
| 112 | 139 | .Equal, |
| 113 | 140 | .Comma, |
| 114 | 141 | .Eof, |
| 115 | | => return parser.declarationExtra(ds, dr, false), |
| 116 | | else => {}, |
| 117 | | } |
| 118 | | var old_decls = Node.FnDef.OldDeclList.init(parser.arena); |
| 119 | | while (try parser.declaration()) |decl| { |
| 120 | | // validate declaration |
| 121 | | try old_decls.push(decl); |
| 122 | | } |
| 123 | | const body = try parser.expect(compoundStmt, .{ |
| 124 | | .ExpectedFnBody = .{ .token = parser.it.index }, |
| 125 | | }); |
| 126 | | |
| 127 | | const node = try parser.arena.create(Node.FnDef); |
| 128 | | node.* = .{ |
| 129 | | .decl_spec = ds, |
| 130 | | .declarator = dr orelse return null, |
| 131 | | .old_decls = old_decls, |
| 132 | | .body = @fieldParentPtr(Node.CompoundStmt, "base", body), |
| 133 | | }; |
| 134 | | return &node.base; |
| 135 | | } |
| 142 | => { |
| 143 | while (dr != null) { |
| 144 | if (parser.eatToken(.Equal)) |tok| { |
| 145 | // TODO typedef |
| 146 | // dr.?.init = try parser.expect(initializer, .{ |
| 147 | // .ExpectedInitializer = .{ .token = parser.it.index }, |
| 148 | // }); |
| 149 | } |
| 150 | if (parser.eatToken(.Comma) != null) break; |
| 151 | dr = (try parser.declarator()) orelse return parser.err(.{ |
| 152 | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 153 | }); |
| 154 | // .push(dr); |
| 155 | } |
| 156 | const semicolon = try parser.expectToken(.Semicolon); |
| 136 | 157 | |
| 137 | | /// Declaration |
| 138 | | /// <- DeclSpec (Declarator (EQUAL Initializer)? COMMA)* SEMICOLON |
| 139 | | /// / StaticAssert |
| 140 | | fn declaration(parser: *Parser) !?*Node { |
| 141 | | if (try parser.staticAssert()) |decl| return decl; |
| 142 | | const ds = try parser.declSpec(); |
| 143 | | const dr = (try parser.declarator()); |
| 144 | | if (dr == null) |
| 145 | | try parser.warning(.{ |
| 146 | | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 147 | | }); |
| 148 | | // TODO disallow threadlocal without static or extern |
| 149 | | return parser.declarationExtra(ds, dr, true); |
| 150 | | } |
| 158 | // TODO VarDecl, TypeDecl, TypeDef |
| 159 | return null; |
| 160 | }, |
| 161 | else => { |
| 162 | if (dr == null) |
| 163 | return parser.err(.{ |
| 164 | .ExpectedDeclarator = .{ .token = parser.it.index }, |
| 165 | }); |
| 166 | var old_decls = Node.FnDef.OldDeclList.init(parser.arena); |
| 167 | while (true) { |
| 168 | var old_ds = Node.DeclSpec{}; |
| 169 | if (!(try parser.declSpec(&old_ds))) { |
| 170 | // not old decl |
| 171 | break; |
| 172 | } |
| 173 | var old_dr = (try parser.declarator()); |
| 174 | // if (old_dr == null) |
| 175 | // try parser.err(.{ |
| 176 | // .NoParamName = .{ .token = parser.it.index }, |
| 177 | // }); |
| 178 | // try old_decls.push(decl); |
| 179 | } |
| 180 | const body = (try parser.compoundStmt()) orelse return parser.err(.{ |
| 181 | .ExpectedFnBody = .{ .token = parser.it.index }, |
| 182 | }); |
| 151 | 183 | |
| 152 | | fn declarationExtra(parser: *Parser, ds: *Node.DeclSpec, dr: ?*Node, local: bool) !?*Node { |
| 184 | const node = try parser.arena.create(Node.FnDef); |
| 185 | node.* = .{ |
| 186 | .decl_spec = ds, |
| 187 | .declarator = dr orelse return null, |
| 188 | .old_decls = old_decls, |
| 189 | .body = @fieldParentPtr(Node.CompoundStmt, "base", body), |
| 190 | }; |
| 191 | return &node.base; |
| 192 | }, |
| 193 | } |
| 153 | 194 | } |
| 154 | 195 | |
| 155 | 196 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 156 | 197 | fn staticAssert(parser: *Parser) !?*Node { |
| 157 | 198 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; |
| 158 | 199 | _ = try parser.expectToken(.LParen); |
| 159 | | const const_expr = try parser.expect(constExpr, .{ |
| 160 | | .ExpectedExpr = .{ .token = parser.it.index }, |
| 161 | | }); |
| 200 | const const_expr = try parser.constExpr(); |
| 162 | 201 | _ = try parser.expectToken(.Comma); |
| 163 | 202 | const str = try parser.expectToken(.StringLiteral); |
| 164 | 203 | _ = try parser.expectToken(.RParen); |
| ... | ... | @@ -173,11 +212,13 @@ const Parser = struct { |
| 173 | 212 | } |
| 174 | 213 | |
| 175 | 214 | /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)* |
| 176 | | fn declSpec(parser: *Parser) !*Node.DeclSpec { |
| 177 | | const ds = try parser.arena.create(Node.DeclSpec); |
| 178 | | ds.* = .{}; |
| 179 | | while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {} |
| 180 | | return ds; |
| 215 | /// returns true if any tokens were consumed |
| 216 | fn declSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { |
| 217 | var got = false; |
| 218 | while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) { |
| 219 | got = true; |
| 220 | } |
| 221 | return got; |
| 181 | 222 | } |
| 182 | 223 | |
| 183 | 224 | /// StorageClassSpec |
| ... | ... | @@ -213,7 +254,7 @@ const Parser = struct { |
| 213 | 254 | } else return false; |
| 214 | 255 | return true; |
| 215 | 256 | } |
| 216 | | try parser.warning(.{ |
| 257 | try parser.warn(.{ |
| 217 | 258 | .DuplicateSpecifier = .{ .token = parser.it.index }, |
| 218 | 259 | }); |
| 219 | 260 | return true; |
| ... | ... | @@ -420,7 +461,7 @@ const Parser = struct { |
| 420 | 461 | if (type_spec.spec != .None) |
| 421 | 462 | break :blk; |
| 422 | 463 | _ = try parser.expectToken(.LParen); |
| 423 | | const name = try parser.expect(typeName, .{ |
| 464 | const name = (try parser.typeName()) orelse return parser.err(.{ |
| 424 | 465 | .ExpectedTypeName = .{ .token = parser.it.index }, |
| 425 | 466 | }); |
| 426 | 467 | type_spec.spec.Atomic = .{ |
| ... | ... | @@ -440,7 +481,7 @@ const Parser = struct { |
| 440 | 481 | @panic("TODO record type"); |
| 441 | 482 | // return true; |
| 442 | 483 | } else if (parser.eatToken(.Identifier)) |tok| { |
| 443 | | if (!parser.isTypedef(tok)) { |
| 484 | if (!parser.getTypeDef(tok)) { |
| 444 | 485 | parser.putBackToken(tok); |
| 445 | 486 | return false; |
| 446 | 487 | } |
| ... | ... | @@ -450,13 +491,12 @@ const Parser = struct { |
| 450 | 491 | return true; |
| 451 | 492 | } |
| 452 | 493 | } |
| 453 | | try parser.tree.errors.push(.{ |
| 494 | return parser.err(.{ |
| 454 | 495 | .InvalidTypeSpecifier = .{ |
| 455 | 496 | .token = parser.it.index, |
| 456 | 497 | .type_spec = type_spec, |
| 457 | 498 | }, |
| 458 | 499 | }); |
| 459 | | return error.ParseError; |
| 460 | 500 | } |
| 461 | 501 | |
| 462 | 502 | /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic |
| ... | ... | @@ -481,7 +521,7 @@ const Parser = struct { |
| 481 | 521 | } else return false; |
| 482 | 522 | return true; |
| 483 | 523 | } |
| 484 | | try parser.warning(.{ |
| 524 | try parser.warn(.{ |
| 485 | 525 | .DuplicateQualifier = .{ .token = parser.it.index }, |
| 486 | 526 | }); |
| 487 | 527 | return true; |
| ... | ... | @@ -501,7 +541,7 @@ const Parser = struct { |
| 501 | 541 | } else return false; |
| 502 | 542 | return true; |
| 503 | 543 | } |
| 504 | | try parser.warning(.{ |
| 544 | try parser.warn(.{ |
| 505 | 545 | .DuplicateSpecifier = .{ .token = parser.it.index }, |
| 506 | 546 | }); |
| 507 | 547 | return true; |
| ... | ... | @@ -511,11 +551,9 @@ const Parser = struct { |
| 511 | 551 | fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { |
| 512 | 552 | if (parser.eatToken(.Keyword_alignas)) |tok| { |
| 513 | 553 | _ = try parser.expectToken(.LParen); |
| 514 | | const node = (try parser.typeName()) orelse (try parser.expect(constExpr, .{ |
| 515 | | .ExpectedExpr = .{ .token = parser.it.index }, |
| 516 | | })); |
| 554 | const node = (try parser.typeName()) orelse (try parser.constExpr()); |
| 517 | 555 | if (ds.align_spec != null) { |
| 518 | | try parser.warning(.{ |
| 556 | try parser.warn(.{ |
| 519 | 557 | .DuplicateSpecifier = .{ .token = parser.it.index }, |
| 520 | 558 | }); |
| 521 | 559 | } |
| ... | ... | @@ -594,7 +632,16 @@ const Parser = struct { |
| 594 | 632 | fn assignmentExpr(parser: *Parser) !*Node {} |
| 595 | 633 | |
| 596 | 634 | /// ConstExpr <- ConditionalExpr |
| 597 | | const constExpr = conditionalExpr; |
| 635 | fn constExpr(parser: *Parser) Error!*Node { |
| 636 | const start = parser.it.index; |
| 637 | const expression = try parser.conditionalExpr(); |
| 638 | // TODO |
| 639 | // if (expression == nullor expression.?.value == null) |
| 640 | // return parser.err(.{ |
| 641 | // .ConsExpr = start, |
| 642 | // }); |
| 643 | return expression.?; |
| 644 | } |
| 598 | 645 | |
| 599 | 646 | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? |
| 600 | 647 | fn conditionalExpr(parser: *Parser) !*Node {} |
| ... | ... | @@ -671,7 +718,7 @@ const Parser = struct { |
| 671 | 718 | /// / PERIOD IDENTIFIER |
| 672 | 719 | fn designator(parser: *Parser) !*Node {} |
| 673 | 720 | |
| 674 | | /// CompoundStmt <- LBRACE (Stmt / Declaration)* RBRACE |
| 721 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 675 | 722 | fn compoundStmt(parser: *Parser) Error!?*Node { |
| 676 | 723 | const lbrace = parser.eatToken(.LBrace) orelse return null; |
| 677 | 724 | const body_node = try parser.arena.create(Node.CompoundStmt); |
| ... | ... | @@ -680,7 +727,7 @@ const Parser = struct { |
| 680 | 727 | .statements = Node.CompoundStmt.StmtList.init(parser.arena), |
| 681 | 728 | .rbrace = undefined, |
| 682 | 729 | }; |
| 683 | | while ((try parser.stmt()) orelse (try parser.declaration())) |node| |
| 730 | while ((try parser.declaration()) orelse (try parser.stmt())) |node| |
| 684 | 731 | try body_node.statements.push(node); |
| 685 | 732 | body_node.rbrace = try parser.expectToken(.RBrace); |
| 686 | 733 | return &body_node.base; |
| ... | ... | @@ -708,7 +755,7 @@ const Parser = struct { |
| 708 | 755 | _ = try parser.expectToken(.LParen); |
| 709 | 756 | node.* = .{ |
| 710 | 757 | .@"if" = tok, |
| 711 | | .cond = try parser.expect(expr, .{ |
| 758 | .cond = (try parser.expr()) orelse return parser.err(.{ |
| 712 | 759 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 713 | 760 | }), |
| 714 | 761 | .@"else" = null, |
| ... | ... | @@ -717,7 +764,7 @@ const Parser = struct { |
| 717 | 764 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 718 | 765 | node.@"else" = .{ |
| 719 | 766 | .tok = else_tok, |
| 720 | | .stmt = try parser.expect(stmt, .{ |
| 767 | .stmt = (try parser.stmt()) orelse return parser.err(.{ |
| 721 | 768 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 722 | 769 | }), |
| 723 | 770 | }; |
| ... | ... | @@ -797,7 +844,7 @@ const Parser = struct { |
| 797 | 844 | |
| 798 | 845 | fn eatToken(parser: *Parser, id: @TagType(Token.Id)) ?TokenIndex { |
| 799 | 846 | while (true) { |
| 800 | | switch (parser.it.next() orelse return null) { |
| 847 | switch ((parser.it.next() orelse return null).id) { |
| 801 | 848 | .LineComment, .MultiLineComment, .Nl => continue, |
| 802 | 849 | else => |next_id| if (next_id == id) { |
| 803 | 850 | return parser.it.index; |
| ... | ... | @@ -811,7 +858,7 @@ const Parser = struct { |
| 811 | 858 | |
| 812 | 859 | fn expectToken(parser: *Parser, id: @TagType(Token.Id)) Error!TokenIndex { |
| 813 | 860 | while (true) { |
| 814 | | switch (parser.it.next() orelse return null) { |
| 861 | switch ((parser.it.next() orelse return error.ParseError).id) { |
| 815 | 862 | .LineComment, .MultiLineComment, .Nl => continue, |
| 816 | 863 | else => |next_id| if (next_id != id) { |
| 817 | 864 | return parser.err(.{ |
| ... | ... | @@ -826,9 +873,10 @@ const Parser = struct { |
| 826 | 873 | |
| 827 | 874 | fn putBackToken(parser: *Parser, putting_back: TokenIndex) void { |
| 828 | 875 | while (true) { |
| 829 | | switch (parser.it.next() orelse return null) { |
| 876 | const prev_tok = parser.it.next() orelse return; |
| 877 | switch (prev_tok.id) { |
| 830 | 878 | .LineComment, .MultiLineComment, .Nl => continue, |
| 831 | | else => |next_id| { |
| 879 | else => { |
| 832 | 880 | assert(parser.it.list.at(putting_back) == prev_tok); |
| 833 | 881 | return; |
| 834 | 882 | }, |
| ... | ... | @@ -836,23 +884,26 @@ const Parser = struct { |
| 836 | 884 | } |
| 837 | 885 | } |
| 838 | 886 | |
| 839 | | fn expect( |
| 840 | | parser: *Parser, |
| 841 | | parseFn: fn (*Parser) Error!?*Node, |
| 842 | | err: ast.Error, // if parsing fails |
| 843 | | ) Error!*Node { |
| 844 | | return (try parseFn(parser)) orelse { |
| 845 | | try parser.tree.errors.push(err); |
| 846 | | return error.ParseError; |
| 847 | | }; |
| 887 | fn err(parser: *Parser, msg: ast.Error) Error { |
| 888 | try parser.tree.msgs.push(.{ |
| 889 | .kind = .Error, |
| 890 | .inner = msg, |
| 891 | }); |
| 892 | return error.ParseError; |
| 848 | 893 | } |
| 849 | 894 | |
| 850 | | fn warning(parser: *Parser, err: ast.Error) Error!void { |
| 851 | | if (parser.tree.warnings) |*w| { |
| 852 | | try w.push(err); |
| 853 | | return; |
| 854 | | } |
| 855 | | try parser.tree.errors.push(err); |
| 856 | | return error.ParseError; |
| 895 | fn warn(parser: *Parser, msg: ast.Error) Error!void { |
| 896 | try parser.tree.msgs.push(.{ |
| 897 | .kind = if (parser.warnings) .Warning else .Error, |
| 898 | .inner = msg, |
| 899 | }); |
| 900 | if (!parser.warnings) return error.ParseError; |
| 901 | } |
| 902 | |
| 903 | fn note(parser: *Parser, msg: ast.Error) Error!void { |
| 904 | try parser.tree.msgs.push(.{ |
| 905 | .kind = .Note, |
| 906 | .inner = msg, |
| 907 | }); |
| 857 | 908 | } |
| 858 | 909 | }; |