| ... | ... | @@ -78,10 +78,10 @@ const Parser = struct { |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | /// Root <- ExternalDeclaration* eof |
| 81 | | fn root(parser: *Parser) Allocator.Error!*Node { |
| 82 | | const node = try arena.create(ast.Root); |
| 81 | fn root(parser: *Parser) Allocator.Error!*Node.Root { |
| 82 | const node = try parser.arena.create(Node.Root); |
| 83 | 83 | node.* = .{ |
| 84 | | .decls = ast.Node.DeclList.init(arena), |
| 84 | .decls = Node.Root.DeclList.init(parser.arena), |
| 85 | 85 | .eof = undefined, |
| 86 | 86 | }; |
| 87 | 87 | while (parser.externalDeclarations() catch |err| switch (err) { |
| ... | ... | @@ -90,31 +90,87 @@ const Parser = struct { |
| 90 | 90 | }) |decl| { |
| 91 | 91 | try node.decls.push(decl); |
| 92 | 92 | } |
| 93 | | node.eof = eatToken(it, .Eof) orelse { |
| 94 | | try tree.errors.push(.{ |
| 95 | | .ExpectedDecl = .{ .token = it.index }, |
| 96 | | }); |
| 97 | | return node; |
| 98 | | }; |
| 93 | node.eof = parser.eatToken(.Eof) orelse return node; |
| 99 | 94 | return node; |
| 100 | 95 | } |
| 101 | 96 | |
| 102 | 97 | /// ExternalDeclaration |
| 103 | 98 | /// <- DeclSpec Declarator Declaration* CompoundStmt |
| 104 | | /// / DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON |
| 105 | | /// / StaticAssert |
| 99 | /// / Declaration |
| 106 | 100 | fn externalDeclarations(parser: *Parser) !?*Node { |
| 107 | | if (try Declaration(parser)) |decl| {} |
| 108 | | return null; |
| 101 | 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 | }); |
| 108 | // TODO disallow auto and register |
| 109 | const next_tok = parser.it.peek().?; |
| 110 | switch (next_tok.id) { |
| 111 | .Semicolon, |
| 112 | .Equal, |
| 113 | .Comma, |
| 114 | .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; |
| 109 | 135 | } |
| 110 | 136 | |
| 111 | 137 | /// Declaration |
| 112 | | /// <- DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON |
| 138 | /// <- DeclSpec (Declarator (EQUAL Initializer)? COMMA)* SEMICOLON |
| 113 | 139 | /// / StaticAssert |
| 114 | | fn declaration(parser: *Parser) !?*Node {} |
| 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 | } |
| 151 | |
| 152 | fn declarationExtra(parser: *Parser, ds: *Node.DeclSpec, dr: ?*Node, local: bool) !?*Node { |
| 153 | } |
| 115 | 154 | |
| 116 | 155 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON |
| 117 | | fn StaticAssert(parser: *Parser) !?*Node {} |
| 156 | fn staticAssert(parser: *Parser) !?*Node { |
| 157 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; |
| 158 | _ = try parser.expectToken(.LParen); |
| 159 | const const_expr = try parser.expect(constExpr, .{ |
| 160 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 161 | }); |
| 162 | _ = try parser.expectToken(.Comma); |
| 163 | const str = try parser.expectToken(.StringLiteral); |
| 164 | _ = try parser.expectToken(.RParen); |
| 165 | const semicolon = try parser.expectToken(.Semicolon); |
| 166 | const node = try parser.arena.create(Node.StaticAssert); |
| 167 | node.* = .{ |
| 168 | .assert = tok, |
| 169 | .expr = const_expr, |
| 170 | .semicolon = semicolon, |
| 171 | }; |
| 172 | return &node.base; |
| 173 | } |
| 118 | 174 | |
| 119 | 175 | /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)* |
| 120 | 176 | fn declSpec(parser: *Parser) !*Node.DeclSpec { |
| ... | ... | @@ -455,7 +511,7 @@ const Parser = struct { |
| 455 | 511 | fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { |
| 456 | 512 | if (parser.eatToken(.Keyword_alignas)) |tok| { |
| 457 | 513 | _ = try parser.expectToken(.LParen); |
| 458 | | const node = (try parser.typeName()) orelse (try parser.expect(conditionalExpr, .{ |
| 514 | const node = (try parser.typeName()) orelse (try parser.expect(constExpr, .{ |
| 459 | 515 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 460 | 516 | })); |
| 461 | 517 | if (ds.align_spec != null) { |
| ... | ... | @@ -538,6 +594,8 @@ const Parser = struct { |
| 538 | 594 | fn assignmentExpr(parser: *Parser) !*Node {} |
| 539 | 595 | |
| 540 | 596 | /// ConstExpr <- ConditionalExpr |
| 597 | const constExpr = conditionalExpr; |
| 598 | |
| 541 | 599 | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? |
| 542 | 600 | fn conditionalExpr(parser: *Parser) !*Node {} |
| 543 | 601 | |
| ... | ... | @@ -613,19 +671,19 @@ const Parser = struct { |
| 613 | 671 | /// / PERIOD IDENTIFIER |
| 614 | 672 | fn designator(parser: *Parser) !*Node {} |
| 615 | 673 | |
| 616 | | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE |
| 617 | | fn compoundStmt(parser: *Parser) !?*Node { |
| 674 | /// CompoundStmt <- LBRACE (Stmt / Declaration)* RBRACE |
| 675 | fn compoundStmt(parser: *Parser) Error!?*Node { |
| 618 | 676 | const lbrace = parser.eatToken(.LBrace) orelse return null; |
| 619 | | const node = try parser.arena.create(Node.CompoundStmt); |
| 620 | | node.* = .{ |
| 677 | const body_node = try parser.arena.create(Node.CompoundStmt); |
| 678 | body_node.* = .{ |
| 621 | 679 | .lbrace = lbrace, |
| 622 | | .statements = Node.JumpStmt.StmtList.init(parser.arena), |
| 680 | .statements = Node.CompoundStmt.StmtList.init(parser.arena), |
| 623 | 681 | .rbrace = undefined, |
| 624 | 682 | }; |
| 625 | | while (parser.declaration() orelse parser.stmt()) |node| |
| 626 | | try node.statements.push(node); |
| 627 | | node.rbrace = try parser.expectToken(.RBrace); |
| 628 | | return &node.base; |
| 683 | while ((try parser.stmt()) orelse (try parser.declaration())) |node| |
| 684 | try body_node.statements.push(node); |
| 685 | body_node.rbrace = try parser.expectToken(.RBrace); |
| 686 | return &body_node.base; |
| 629 | 687 | } |
| 630 | 688 | |
| 631 | 689 | /// Stmt |
| ... | ... | @@ -643,15 +701,15 @@ const Parser = struct { |
| 643 | 701 | /// / Keyword_return Expr? SEMICOLON |
| 644 | 702 | /// / IDENTIFIER COLON Stmt |
| 645 | 703 | /// / ExprStmt |
| 646 | | fn stmt(parser: *Parser) !?*Node { |
| 647 | | if (parser.compoundStmt()) |node| return node; |
| 704 | fn stmt(parser: *Parser) Error!?*Node { |
| 705 | if (try parser.compoundStmt()) |node| return node; |
| 648 | 706 | if (parser.eatToken(.Keyword_if)) |tok| { |
| 649 | 707 | const node = try parser.arena.create(Node.IfStmt); |
| 650 | 708 | _ = try parser.expectToken(.LParen); |
| 651 | 709 | node.* = .{ |
| 652 | 710 | .@"if" = tok, |
| 653 | 711 | .cond = try parser.expect(expr, .{ |
| 654 | | .ExpectedExpr = .{ .token = it.index }, |
| 712 | .ExpectedExpr = .{ .token = parser.it.index }, |
| 655 | 713 | }), |
| 656 | 714 | .@"else" = null, |
| 657 | 715 | }; |
| ... | ... | @@ -659,8 +717,8 @@ const Parser = struct { |
| 659 | 717 | if (parser.eatToken(.Keyword_else)) |else_tok| { |
| 660 | 718 | node.@"else" = .{ |
| 661 | 719 | .tok = else_tok, |
| 662 | | .stmt = try parser.stmt(expr, .{ |
| 663 | | .ExpectedStmt = .{ .token = it.index }, |
| 720 | .stmt = try parser.expect(stmt, .{ |
| 721 | .ExpectedStmt = .{ .token = parser.it.index }, |
| 664 | 722 | }), |
| 665 | 723 | }; |
| 666 | 724 | } |
| ... | ... | @@ -676,8 +734,8 @@ const Parser = struct { |
| 676 | 734 | const node = try parser.arena.create(Node.JumpStmt); |
| 677 | 735 | node.* = .{ |
| 678 | 736 | .ltoken = tok, |
| 679 | | .kind = .Goto, |
| 680 | | .semicolon = parser.expectToken(.Semicolon), |
| 737 | .kind = .{ .Goto = tok }, |
| 738 | .semicolon = try parser.expectToken(.Semicolon), |
| 681 | 739 | }; |
| 682 | 740 | return &node.base; |
| 683 | 741 | } |
| ... | ... | @@ -686,7 +744,7 @@ const Parser = struct { |
| 686 | 744 | node.* = .{ |
| 687 | 745 | .ltoken = tok, |
| 688 | 746 | .kind = .Continue, |
| 689 | | .semicolon = parser.expectToken(.Semicolon), |
| 747 | .semicolon = try parser.expectToken(.Semicolon), |
| 690 | 748 | }; |
| 691 | 749 | return &node.base; |
| 692 | 750 | } |
| ... | ... | @@ -695,7 +753,7 @@ const Parser = struct { |
| 695 | 753 | node.* = .{ |
| 696 | 754 | .ltoken = tok, |
| 697 | 755 | .kind = .Break, |
| 698 | | .semicolon = parser.expectToken(.Semicolon), |
| 756 | .semicolon = try parser.expectToken(.Semicolon), |
| 699 | 757 | }; |
| 700 | 758 | return &node.base; |
| 701 | 759 | } |
| ... | ... | @@ -704,31 +762,35 @@ const Parser = struct { |
| 704 | 762 | node.* = .{ |
| 705 | 763 | .ltoken = tok, |
| 706 | 764 | .kind = .{ .Return = try parser.expr() }, |
| 707 | | .semicolon = parser.expectToken(.Semicolon), |
| 765 | .semicolon = try parser.expectToken(.Semicolon), |
| 708 | 766 | }; |
| 709 | 767 | return &node.base; |
| 710 | 768 | } |
| 711 | 769 | if (parser.eatToken(.Identifier)) |tok| { |
| 712 | | if (parser.eatToken(.Colon)) |col| { |
| 770 | if (parser.eatToken(.Colon)) |_| { |
| 713 | 771 | const node = try parser.arena.create(Node.Label); |
| 714 | 772 | node.* = .{ |
| 715 | 773 | .identifier = tok, |
| 716 | | .semicolon = parser.expectToken(.Colon), |
| 717 | 774 | }; |
| 718 | 775 | return &node.base; |
| 719 | 776 | } |
| 720 | | putBackToken(tok); |
| 777 | parser.putBackToken(tok); |
| 721 | 778 | } |
| 722 | | if (parser.exprStmt()) |node| return node; |
| 779 | if (try parser.exprStmt()) |node| return node; |
| 723 | 780 | return null; |
| 724 | 781 | } |
| 725 | 782 | |
| 726 | 783 | /// ExprStmt <- Expr? SEMICOLON |
| 727 | | fn exprStmt(parser: *Parser) !*Node { |
| 784 | fn exprStmt(parser: *Parser) !?*Node { |
| 728 | 785 | const node = try parser.arena.create(Node.ExprStmt); |
| 786 | const expr_node = try parser.expr(); |
| 787 | const semicolon = if (expr_node != null) |
| 788 | try parser.expectToken(.Semicolon) |
| 789 | else |
| 790 | parser.eatToken(.Semicolon) orelse return null; |
| 729 | 791 | node.* = .{ |
| 730 | | .expr = try parser.expr(), |
| 731 | | .semicolon = parser.expectToken(.Semicolon), |
| 792 | .expr = expr_node, |
| 793 | .semicolon = semicolon, |
| 732 | 794 | }; |
| 733 | 795 | return &node.base; |
| 734 | 796 | } |