authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 15:15:55+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-01-05 20:25:51+02:00
logf934f9b41938ee6208d7cdd8a26687bffbe171cf
tree86b7a259399f765054b85b0379eaff2ebf76324d
parent46f292982d6035c7d57ae8d637c770a121c40e37
signature Commit is signed but in an unrecognized format.

std-c parser fndef and static assert


2 files changed, 132 insertions(+), 46 deletions(-)

lib/std/c/ast.zig+27-3
...@@ -32,6 +32,8 @@ pub const Error = union(enum) {...@@ -32,6 +32,8 @@ pub const Error = union(enum) {
32 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),32 ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
33 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),33 ExpectedStmt: SingleTokenError("expected statement, found '{}'"),
34 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),34 ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
35 ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
36 ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
35 InvalidTypeSpecifier: InvalidTypeSpecifier,37 InvalidTypeSpecifier: InvalidTypeSpecifier,
36 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),38 DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
37 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),39 DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
...@@ -43,6 +45,8 @@ pub const Error = union(enum) {...@@ -43,6 +45,8 @@ pub const Error = union(enum) {
43 .ExpectedExpr => |*x| return x.render(tokens, stream),45 .ExpectedExpr => |*x| return x.render(tokens, stream),
44 .ExpectedStmt => |*x| return x.render(tokens, stream),46 .ExpectedStmt => |*x| return x.render(tokens, stream),
45 .ExpectedTypeName => |*x| return x.render(tokens, stream),47 .ExpectedTypeName => |*x| return x.render(tokens, stream),
48 .ExpectedDeclarator => |*x| return x.render(tokens, stream),
49 .ExpectedFnBody => |*x| return x.render(tokens, stream),
46 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),50 .InvalidTypeSpecifier => |*x| return x.render(tokens, stream),
47 .DuplicateQualifier => |*x| return x.render(tokens, stream),51 .DuplicateQualifier => |*x| return x.render(tokens, stream),
48 .DuplicateSpecifier => |*x| return x.render(tokens, stream),52 .DuplicateSpecifier => |*x| return x.render(tokens, stream),
...@@ -56,6 +60,8 @@ pub const Error = union(enum) {...@@ -56,6 +60,8 @@ pub const Error = union(enum) {
56 .ExpectedExpr => |x| return x.token,60 .ExpectedExpr => |x| return x.token,
57 .ExpectedStmt => |x| return x.token,61 .ExpectedStmt => |x| return x.token,
58 .ExpectedTypeName => |x| return x.token,62 .ExpectedTypeName => |x| return x.token,
63 .ExpectedDeclarator => |x| return x.token,
64 .ExpectedFnBody => |x| return x.token,
59 .InvalidTypeSpecifier => |x| return x.token,65 .InvalidTypeSpecifier => |x| return x.token,
60 .DuplicateQualifier => |x| return x.token,66 .DuplicateQualifier => |x| return x.token,
61 .DuplicateSpecifier => |x| return x.token,67 .DuplicateSpecifier => |x| return x.token,
...@@ -85,7 +91,7 @@ pub const Error = union(enum) {...@@ -85,7 +91,7 @@ pub const Error = union(enum) {
85 try stream.write("invalid type specifier '");91 try stream.write("invalid type specifier '");
86 try type_spec.spec.print(tokens, stream);92 try type_spec.spec.print(tokens, stream);
87 const token_name = tokens.at(self.token).id.symbol();93 const token_name = tokens.at(self.token).id.symbol();
88 return stream.print("{}'", .{ token_name });94 return stream.print("{}'", .{token_name});
89 }95 }
90 };96 };
9197
...@@ -111,10 +117,12 @@ pub const Node = struct {...@@ -111,10 +117,12 @@ pub const Node = struct {
111 Label,117 Label,
112 CompoundStmt,118 CompoundStmt,
113 IfStmt,119 IfStmt,
120 StaticAssert,
121 FnDef,
114 };122 };
115123
116 pub const Root = struct {124 pub const Root = struct {
117 base: Node,125 base: Node = Node{ .id = .Root },
118 decls: DeclList,126 decls: DeclList,
119 eof: TokenIndex,127 eof: TokenIndex,
120128
...@@ -230,7 +238,6 @@ pub const Node = struct {...@@ -230,7 +238,6 @@ pub const Node = struct {
230 pub const Label = struct {238 pub const Label = struct {
231 base: Node = Node{ .id = .Label },239 base: Node = Node{ .id = .Label },
232 identifier: TokenIndex,240 identifier: TokenIndex,
233 colon: TokenIndex,
234 };241 };
235242
236 pub const CompoundStmt = struct {243 pub const CompoundStmt = struct {
...@@ -251,4 +258,21 @@ pub const Node = struct {...@@ -251,4 +258,21 @@ pub const Node = struct {
251 stmt: *Node,258 stmt: *Node,
252 },259 },
253 };260 };
261
262 pub const StaticAssert = struct {
263 base: Node = Node{ .id = .StaticAssert },
264 assert: TokenIndex,
265 expr: *Node,
266 semicolon: TokenIndex,
267 };
268
269 pub const FnDef = struct {
270 base: Node = Node{ .id = .FnDef },
271 decl_spec: *DeclSpec,
272 declarator: *Node,
273 old_decls: OldDeclList,
274 body: *CompoundStmt,
275
276 pub const OldDeclList = SegmentedList(*Node, 0);
277 };
254};278};
lib/std/c/parse.zig+105-43
...@@ -78,10 +78,10 @@ const Parser = struct {...@@ -78,10 +78,10 @@ const Parser = struct {
78 }78 }
7979
80 /// Root <- ExternalDeclaration* eof80 /// 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 }
10196
102 /// ExternalDeclaration97 /// ExternalDeclaration
103 /// <- DeclSpec Declarator Declaration* CompoundStmt98 /// <- DeclSpec Declarator Declaration* CompoundStmt
104 /// / DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON99 /// / 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 }
110136
111 /// Declaration137 /// Declaration
112 /// <- DeclSpec (Declarator (EQUAL Initializer)?)* SEMICOLON138 /// <- DeclSpec (Declarator (EQUAL Initializer)? COMMA)* SEMICOLON
113 /// / StaticAssert139 /// / 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 }
115154
116 /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON155 /// 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 }
118174
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 {}
539595
540 /// ConstExpr <- ConditionalExpr596 /// 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 {}
543601
...@@ -613,19 +671,19 @@ const Parser = struct {...@@ -613,19 +671,19 @@ const Parser = struct {
613 /// / PERIOD IDENTIFIER671 /// / PERIOD IDENTIFIER
614 fn designator(parser: *Parser) !*Node {}672 fn designator(parser: *Parser) !*Node {}
615673
616 /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE674 /// 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 }
630688
631 /// Stmt689 /// Stmt
...@@ -643,15 +701,15 @@ const Parser = struct {...@@ -643,15 +701,15 @@ const Parser = struct {
643 /// / Keyword_return Expr? SEMICOLON701 /// / Keyword_return Expr? SEMICOLON
644 /// / IDENTIFIER COLON Stmt702 /// / IDENTIFIER COLON Stmt
645 /// / ExprStmt703 /// / 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 }
725782
726 /// ExprStmt <- Expr? SEMICOLON783 /// 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 }