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